Version in base suite: 21.0.8+9-1 Base version: openjdk-21_21.0.8+9-1 Target version: openjdk-21_21.0.9+10-1~deb13u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/o/openjdk-21/openjdk-21_21.0.8+9-1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/o/openjdk-21/openjdk-21_21.0.9+10-1~deb13u1.dsc /srv/release.debian.org/tmp/emfaCnEiU2/openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicHTML/4228104/duke.gif |binary /srv/release.debian.org/tmp/emfaCnEiU2/openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/duke.gif |binary /srv/release.debian.org/tmp/emfaCnEiU2/openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/duke.gif |binary openjdk-21-21.0.9+10/.jcheck/conf | 2 openjdk-21-21.0.9+10/debian/changelog | 50 openjdk-21-21.0.9+10/debian/copyright | 2 openjdk-21-21.0.9+10/debian/copyright-generator/copyright-gen.py | 2 openjdk-21-21.0.9+10/debian/patches/default-jvm-cfg.diff | 4 openjdk-21-21.0.9+10/debian/patches/icedtea-override-redirect-compiz.diff | 2 openjdk-21-21.0.9+10/debian/patches/jdk-8307977-proposed.patch | 81 openjdk-21-21.0.9+10/debian/patches/jdk-8334502-proposed.patch | 2 openjdk-21-21.0.9+10/debian/patches/jdk-8359735.patch | 6 openjdk-21-21.0.9+10/debian/patches/jdk-8369450-proposed.patch | 18 openjdk-21-21.0.9+10/debian/patches/jdk-getAccessibleValue.diff | 30 openjdk-21-21.0.9+10/debian/patches/make-debug-print.diff | 2 openjdk-21-21.0.9+10/debian/patches/multiple-pkcs11-library-init.diff | 6 openjdk-21-21.0.9+10/debian/patches/series | 2 openjdk-21-21.0.9+10/debian/patches/zero-alpha-workaround.diff | 2 openjdk-21-21.0.9+10/debian/rules | 11 openjdk-21-21.0.9+10/debian/tests/control | 2 openjdk-21-21.0.9+10/debian/tests/control.in | 2 openjdk-21-21.0.9+10/debian/tests/dependencies.sh | 2 openjdk-21-21.0.9+10/debian/tests/hotspot-autopkgtest.in | 1 openjdk-21-21.0.9+10/debian/tests/hotspot-autopkgtest.sh | 1 openjdk-21-21.0.9+10/debian/tests/jdk-autopkgtest.in | 1 openjdk-21-21.0.9+10/debian/tests/jdk-autopkgtest.sh | 1 openjdk-21-21.0.9+10/debian/tests/problems.csv | 56 openjdk-21-21.0.9+10/debian/tests/skip-large-autopkgtest.txt | 7 openjdk-21-21.0.9+10/doc/building.html | 8 openjdk-21-21.0.9+10/doc/building.md | 6 openjdk-21-21.0.9+10/make/Global.gmk | 3 openjdk-21-21.0.9+10/make/Install.gmk | 43 openjdk-21-21.0.9+10/make/Main.gmk | 8 openjdk-21-21.0.9+10/make/RunTestsPrebuilt.gmk | 6 openjdk-21-21.0.9+10/make/autoconf/build-performance.m4 | 5 openjdk-21-21.0.9+10/make/autoconf/flags-cflags.m4 | 2 openjdk-21-21.0.9+10/make/autoconf/lib-tests.m4 | 2 openjdk-21-21.0.9+10/make/autoconf/spec.gmk.in | 51 openjdk-21-21.0.9+10/make/conf/github-actions.conf | 2 openjdk-21-21.0.9+10/make/conf/jib-profiles.js | 2 openjdk-21-21.0.9+10/make/conf/version-numbers.conf | 4 openjdk-21-21.0.9+10/make/data/hotspot-symbols/symbols-linux | 1 openjdk-21-21.0.9+10/make/modules/java.desktop/lib/Awt2dLibraries.gmk | 10 openjdk-21-21.0.9+10/make/modules/jdk.internal.le/Lib.gmk | 5 openjdk-21-21.0.9+10/make/test/BuildTestLib.gmk | 3 openjdk-21-21.0.9+10/src/hotspot/cpu/aarch64/assembler_aarch64.cpp | 2 openjdk-21-21.0.9+10/src/hotspot/cpu/aarch64/assembler_aarch64.hpp | 2 openjdk-21-21.0.9+10/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp | 2 openjdk-21-21.0.9+10/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp | 4 openjdk-21-21.0.9+10/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp | 12 openjdk-21-21.0.9+10/src/hotspot/cpu/ppc/frame_ppc.cpp | 13 openjdk-21-21.0.9+10/src/hotspot/cpu/ppc/gc/x/xGlobals_ppc.cpp | 12 openjdk-21-21.0.9+10/src/hotspot/cpu/ppc/gc/z/zAddress_ppc.cpp | 13 openjdk-21-21.0.9+10/src/hotspot/cpu/ppc/methodHandles_ppc.cpp | 4 openjdk-21-21.0.9+10/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp | 2 openjdk-21-21.0.9+10/src/hotspot/cpu/riscv/assembler_riscv.hpp | 2 openjdk-21-21.0.9+10/src/hotspot/cpu/riscv/gc/x/xGlobals_riscv.cpp | 8 openjdk-21-21.0.9+10/src/hotspot/cpu/riscv/gc/z/zAddress_riscv.cpp | 8 openjdk-21-21.0.9+10/src/hotspot/cpu/riscv/riscv.ad | 31 openjdk-21-21.0.9+10/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp | 4 openjdk-21-21.0.9+10/src/hotspot/cpu/riscv/templateTable_riscv.cpp | 36 openjdk-21-21.0.9+10/src/hotspot/cpu/x86/gc/z/zAddress_x86.cpp | 4 openjdk-21-21.0.9+10/src/hotspot/cpu/x86/macroAssembler_x86.cpp | 4 openjdk-21-21.0.9+10/src/hotspot/os/aix/os_aix.cpp | 4 openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupSubsystem_linux.cpp | 373 ++- openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupSubsystem_linux.hpp | 291 +- openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupUtil_linux.cpp | 159 + openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupUtil_linux.hpp | 43 openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp | 294 +- openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp | 151 - openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp | 228 + openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp | 131 - openjdk-21-21.0.9+10/src/hotspot/os/linux/osContainer_linux.cpp | 49 openjdk-21-21.0.9+10/src/hotspot/os/linux/osContainer_linux.hpp | 2 openjdk-21-21.0.9+10/src/hotspot/os/linux/os_linux.cpp | 2 openjdk-21-21.0.9+10/src/hotspot/os/posix/signals_posix.cpp | 10 openjdk-21-21.0.9+10/src/hotspot/os_cpu/aix_ppc/javaThread_aix_ppc.cpp | 19 openjdk-21-21.0.9+10/src/hotspot/os_cpu/linux_ppc/javaThread_linux_ppc.cpp | 19 openjdk-21-21.0.9+10/src/hotspot/share/adlc/output_h.cpp | 3 openjdk-21-21.0.9+10/src/hotspot/share/c1/c1_Compilation.cpp | 8 openjdk-21-21.0.9+10/src/hotspot/share/cds/classListParser.cpp | 4 openjdk-21-21.0.9+10/src/hotspot/share/cds/classListWriter.cpp | 2 openjdk-21-21.0.9+10/src/hotspot/share/cds/filemap.cpp | 2 openjdk-21-21.0.9+10/src/hotspot/share/ci/ciEnv.cpp | 9 openjdk-21-21.0.9+10/src/hotspot/share/classfile/classLoader.cpp | 48 openjdk-21-21.0.9+10/src/hotspot/share/classfile/classLoader.hpp | 2 openjdk-21-21.0.9+10/src/hotspot/share/classfile/classLoaderExt.cpp | 10 openjdk-21-21.0.9+10/src/hotspot/share/classfile/javaClasses.cpp | 41 openjdk-21-21.0.9+10/src/hotspot/share/classfile/javaClasses.hpp | 38 openjdk-21-21.0.9+10/src/hotspot/share/classfile/javaClasses.inline.hpp | 4 openjdk-21-21.0.9+10/src/hotspot/share/classfile/javaClassesImpl.hpp | 2 openjdk-21-21.0.9+10/src/hotspot/share/classfile/stackMapTable.cpp | 10 openjdk-21-21.0.9+10/src/hotspot/share/classfile/stackMapTable.hpp | 2 openjdk-21-21.0.9+10/src/hotspot/share/classfile/verifier.cpp | 35 openjdk-21-21.0.9+10/src/hotspot/share/classfile/vmClassMacros.hpp | 1 openjdk-21-21.0.9+10/src/hotspot/share/classfile/vmSymbols.hpp | 2 openjdk-21-21.0.9+10/src/hotspot/share/code/dependencyContext.cpp | 18 openjdk-21-21.0.9+10/src/hotspot/share/code/dependencyContext.hpp | 5 openjdk-21-21.0.9+10/src/hotspot/share/compiler/compilationLog.cpp | 6 openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1CardTableEntryClosure.hpp | 6 openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp | 50 openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp | 2 openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp | 2 openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1Policy.cpp | 38 openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.cpp | 4 openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1RemSet.cpp | 6 openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp | 4 openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1YoungGCPreEvacuateTasks.cpp | 6 openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/bufferNode.cpp | 8 openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/bufferNode.hpp | 8 openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/gcArguments.cpp | 8 openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/locationPrinter.inline.hpp | 2 openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/ptrQueue.cpp | 9 openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/ptrQueue.hpp | 8 openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/satbMarkQueue.cpp | 14 openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/satbMarkQueue.hpp | 2 openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/weakProcessorTimes.cpp | 2 openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/workerDataArray.cpp | 9 openjdk-21-21.0.9+10/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp | 98 openjdk-21-21.0.9+10/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp | 11 openjdk-21-21.0.9+10/src/hotspot/share/include/jvm.h | 3 openjdk-21-21.0.9+10/src/hotspot/share/interpreter/bytecodeStream.hpp | 19 openjdk-21-21.0.9+10/src/hotspot/share/jfr/support/jfrSymbolTable.cpp | 69 openjdk-21-21.0.9+10/src/hotspot/share/jfr/support/jfrSymbolTable.hpp | 7 openjdk-21-21.0.9+10/src/hotspot/share/oops/cpCache.hpp | 9 openjdk-21-21.0.9+10/src/hotspot/share/opto/convertnode.cpp | 5 openjdk-21-21.0.9+10/src/hotspot/share/opto/loopnode.cpp | 14 openjdk-21-21.0.9+10/src/hotspot/share/opto/loopopts.cpp | 9 openjdk-21-21.0.9+10/src/hotspot/share/opto/mulnode.cpp | 4 openjdk-21-21.0.9+10/src/hotspot/share/opto/reg_split.cpp | 34 openjdk-21-21.0.9+10/src/hotspot/share/opto/subnode.cpp | 4 openjdk-21-21.0.9+10/src/hotspot/share/opto/type.cpp | 20 openjdk-21-21.0.9+10/src/hotspot/share/prims/jvm.cpp | 15 openjdk-21-21.0.9+10/src/hotspot/share/prims/methodHandles.cpp | 33 openjdk-21-21.0.9+10/src/hotspot/share/prims/whitebox.cpp | 34 openjdk-21-21.0.9+10/src/hotspot/share/prims/whitebox.hpp | 5 openjdk-21-21.0.9+10/src/hotspot/share/runtime/globals.hpp | 4 openjdk-21-21.0.9+10/src/hotspot/share/runtime/mutexLocker.cpp | 3 openjdk-21-21.0.9+10/src/hotspot/share/runtime/mutexLocker.hpp | 2 openjdk-21-21.0.9+10/src/hotspot/share/runtime/os.cpp | 50 openjdk-21-21.0.9+10/src/hotspot/share/runtime/os.hpp | 5 openjdk-21-21.0.9+10/src/hotspot/share/runtime/threads.cpp | 23 openjdk-21-21.0.9+10/src/hotspot/share/sanitizers/ub.hpp | 9 openjdk-21-21.0.9+10/src/hotspot/share/services/memReporter.cpp | 5 openjdk-21-21.0.9+10/src/hotspot/share/utilities/globalDefinitions.hpp | 8 openjdk-21-21.0.9+10/src/hotspot/share/utilities/spinYield.cpp | 2 openjdk-21-21.0.9+10/src/hotspot/share/utilities/vmError.cpp | 8 openjdk-21-21.0.9+10/src/java.base/linux/classes/jdk/internal/platform/CgroupMetrics.java | 6 openjdk-21-21.0.9+10/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystem.java | 5 openjdk-21-21.0.9+10/src/java.base/linux/native/libjava/CgroupMetrics.c | 6 openjdk-21-21.0.9+10/src/java.base/share/classes/java/lang/AbstractStringBuilder.java | 9 openjdk-21-21.0.9+10/src/java.base/share/classes/java/lang/Class.java | 36 openjdk-21-21.0.9+10/src/java.base/share/classes/java/lang/invoke/CallSite.java | 6 openjdk-21-21.0.9+10/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java | 25 openjdk-21-21.0.9+10/src/java.base/share/classes/java/math/BigInteger.java | 226 + openjdk-21-21.0.9+10/src/java.base/share/classes/java/text/MessageFormat.java | 2 openjdk-21-21.0.9+10/src/java.base/share/classes/java/util/Currency.java | 22 openjdk-21-21.0.9+10/src/java.base/share/classes/java/util/Formatter.java | 6 openjdk-21-21.0.9+10/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java | 2 openjdk-21-21.0.9+10/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java | 44 openjdk-21-21.0.9+10/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java | 44 openjdk-21-21.0.9+10/src/java.base/share/classes/java/util/zip/GZIPInputStream.java | 24 openjdk-21-21.0.9+10/src/java.base/share/classes/jdk/internal/platform/Metrics.java | 17 openjdk-21-21.0.9+10/src/java.base/share/classes/sun/launcher/LauncherHelper.java | 7 openjdk-21-21.0.9+10/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java | 14 openjdk-21-21.0.9+10/src/java.base/share/classes/sun/nio/cs/Unicode.java | 8 openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/Alert.java | 10 openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/CertSignAlgsExtension.java | 40 openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java | 124 - openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java | 49 openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/ClientHello.java | 6 openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java | 5 openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/PostHandshakeContext.java | 4 openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java | 21 openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java | 34 openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/SSLLogger.java | 8 openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/SSLScope.java | 55 openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java | 104 openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/ServerHello.java | 24 openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/SessionTicketExtension.java | 9 openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java | 119 - openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java | 129 - openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/util/DerValue.java | 16 openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java | 117 openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/validator/EntrustTLSPolicy.java | 16 openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/x509/AVA.java | 48 openjdk-21-21.0.9+10/src/java.base/share/conf/security/java.security | 25 openjdk-21-21.0.9+10/src/java.base/share/data/cacerts/affirmtrustcommercialca | 27 openjdk-21-21.0.9+10/src/java.base/share/data/cacerts/affirmtrustnetworkingca | 27 openjdk-21-21.0.9+10/src/java.base/share/data/cacerts/affirmtrustpremiumca | 38 openjdk-21-21.0.9+10/src/java.base/share/data/cacerts/affirmtrustpremiumeccca | 20 openjdk-21-21.0.9+10/src/java.base/share/data/currency/CurrencyData.properties | 8 openjdk-21-21.0.9+10/src/java.base/share/data/lsrdata/language-subtag-registry.txt | 122 + openjdk-21-21.0.9+10/src/java.base/share/native/launcher/main.c | 22 openjdk-21-21.0.9+10/src/java.base/share/native/libjava/ub.h | 9 openjdk-21-21.0.9+10/src/java.base/share/native/libjli/java.c | 7 openjdk-21-21.0.9+10/src/java.base/share/native/libverify/check_code.c | 39 openjdk-21-21.0.9+10/src/java.base/unix/native/libjava/java_props_md.c | 2 openjdk-21-21.0.9+10/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java | 32 openjdk-21-21.0.9+10/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java | 8 openjdk-21-21.0.9+10/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/MenuAccessibility.m | 33 openjdk-21-21.0.9+10/src/java.desktop/share/classes/com/sun/beans/introspect/MethodInfo.java | 14 openjdk-21-21.0.9+10/src/java.desktop/share/classes/com/sun/beans/introspect/PropertyInfo.java | 20 openjdk-21-21.0.9+10/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java | 123 + openjdk-21-21.0.9+10/src/java.desktop/share/classes/com/sun/media/sound/StandardMidiFileReader.java | 13 openjdk-21-21.0.9+10/src/java.desktop/share/classes/java/awt/AWTEventMulticaster.java | 62 openjdk-21-21.0.9+10/src/java.desktop/share/classes/java/beans/Introspector.java | 10 openjdk-21-21.0.9+10/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java | 143 - openjdk-21-21.0.9+10/src/java.desktop/share/classes/sun/awt/datatransfer/SunClipboard.java | 22 openjdk-21-21.0.9+10/src/java.desktop/share/classes/sun/font/FileFontStrike.java | 1 openjdk-21-21.0.9+10/src/java.desktop/share/legal/harfbuzz.md | 2 openjdk-21-21.0.9+10/src/java.desktop/share/native/libfontmanager/freetypeScaler.c | 1 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Color/CBDT/CBDT.hh | 12 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh | 158 + openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh | 11 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh | 15 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat1.hh | 2 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat2.hh | 2 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/GDEF/GDEF.hh | 24 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/GPOS.hh | 5 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh | 2 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/VARC.hh | 158 - openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh | 21 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh | 144 + openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh | 62 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh | 84 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh | 47 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc | 59 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.hh | 8 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-aat-map.cc | 5 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh | 80 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh | 4 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-bit-vector.hh | 195 + openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh | 602 ++--- openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-glyphs.hh | 843 +++---- openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-unicode.hh | 192 - openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-serialize.cc | 22 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc | 35 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc | 16 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer.h | 61 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh | 5 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-cache.hh | 37 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh | 66 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-common.cc | 63 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-common.h | 443 --- openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-config.hh | 2 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-debug.hh | 6 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h | 82 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-draw.cc | 93 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-draw.h | 2 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-draw.hh | 60 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-face.cc | 228 + openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-face.h | 16 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-face.hh | 6 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-font.cc | 611 ++++- openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-font.h | 97 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-font.hh | 359 ++- openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ft.cc | 348 +- openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ft.h | 4 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-geometry.hh | 30 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-machinery.hh | 2 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-mutex.hh | 6 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-object.hh | 6 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh | 14 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh | 10 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc | 10 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh | 18 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh | 83 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-color.cc | 8 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh | 2 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-face.cc | 1 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc | 397 +-- openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh | 8 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-kern-table.hh | 2 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh | 2 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh | 55 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-gsubgpos.hh | 22 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc | 17 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.hh | 17 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-math-table.hh | 18 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-math.cc | 14 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table.hh | 2 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-fallback.cc | 9 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.cc | 44 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.hh | 4 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic.cc | 2 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-hangul.cc | 6 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic.cc | 2 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-thai.cc | 2 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-tag.cc | 2 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-var-gvar-table.hh | 10 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-var.cc | 2 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-outline.cc | 6 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-outline.hh | 1 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.cc | 207 + openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.hh | 117 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.cc | 95 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.hh | 11 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-paint.cc | 46 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-paint.h | 16 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-paint.hh | 16 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-script-list.h | 484 ++++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-set-digest.hh | 9 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-set.hh | 1 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-shape.cc | 6 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-static.cc | 1 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-subset-cff-common.hh | 2 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-subset-input.cc | 2 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.cc | 772 ------ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.hh | 70 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-subset.cc | 104 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-subset.h | 24 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-vector.hh | 9 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-version.h | 6 openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb.hh | 55 openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/PlatformGraphicsInfo.java | 5 openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java | 7 openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java | 64 openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java | 27 openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java | 9 openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java | 85 openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java | 18 openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/screencast/XdgDesktopPortal.java | 96 openjdk-21-21.0.9+10/src/java.desktop/unix/native/common/awt/awt_GraphicsEnv.h | 7 openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c | 346 ++ openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c | 20 openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c | 7 openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h | 5 openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h | 5 openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c | 217 + openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.h | 4 openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.c | 515 +++- openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.h | 31 openjdk-21-21.0.9+10/src/java.desktop/unix/native/libpipewire/include/spa/utils/endian.h | 4 openjdk-21-21.0.9+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java | 23 openjdk-21-21.0.9+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java | 16 openjdk-21-21.0.9+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java | 115 openjdk-21-21.0.9+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java | 22 openjdk-21-21.0.9+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java | 22 openjdk-21-21.0.9+10/src/java.desktop/windows/classes/sun/awt/windows/WClipboard.java | 52 openjdk-21-21.0.9+10/src/java.desktop/windows/native/libawt/windows/awt_Clipboard.cpp | 45 openjdk-21-21.0.9+10/src/java.management/share/classes/javax/management/remote/package.html | 30 openjdk-21-21.0.9+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/JCEMapper.java | 16 openjdk-21-21.0.9+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/MessageDigestAlgorithm.java | 2 openjdk-21-21.0.9+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java | 12 openjdk-21-21.0.9+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/ECDSAUtils.java | 40 openjdk-21-21.0.9+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureBaseRSA.java | 3 openjdk-21-21.0.9+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureECDSA.java | 104 openjdk-21-21.0.9+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/KeyInfo.java | 40 openjdk-21-21.0.9+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/DEREncodedKeyValue.java | 6 openjdk-21-21.0.9+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/KeyValue.java | 15 openjdk-21-21.0.9+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/keyvalues/ECKeyValue.java | 53 openjdk-21-21.0.9+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/xmlsecurity_de.properties | 2 openjdk-21-21.0.9+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignature.java | 17 openjdk-21-21.0.9+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Constants.java | 6 openjdk-21-21.0.9+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/ElementProxy.java | 3 openjdk-21-21.0.9+10/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/SignatureMethod.java | 2 openjdk-21-21.0.9+10/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyInfoFactory.java | 2 openjdk-21-21.0.9+10/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyValue.java | 77 openjdk-21-21.0.9+10/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java | 104 openjdk-21-21.0.9+10/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java | 8 openjdk-21-21.0.9+10/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java | 2 openjdk-21-21.0.9+10/src/java.xml.crypto/share/legal/santuario.md | 6 openjdk-21-21.0.9+10/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties | 1 openjdk-21-21.0.9+10/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderFactoryImpl.java | 26 openjdk-21-21.0.9+10/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java | 12 openjdk-21-21.0.9+10/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java | 9 openjdk-21-21.0.9+10/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java | 12 openjdk-21-21.0.9+10/src/java.xml/share/classes/jdk/xml/internal/JdkXmlUtils.java | 18 openjdk-21-21.0.9+10/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java | 16 openjdk-21-21.0.9+10/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java | 40 openjdk-21-21.0.9+10/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java | 19 openjdk-21-21.0.9+10/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c | 51 openjdk-21-21.0.9+10/src/jdk.charsets/share/classes/sun/nio/cs/ext/EUC_JP_Open.java.template | 5 openjdk-21-21.0.9+10/src/jdk.charsets/share/classes/sun/nio/cs/ext/JISAutoDetect.java | 3 openjdk-21-21.0.9+10/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java | 7 openjdk-21-21.0.9+10/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java | 5 openjdk-21-21.0.9+10/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java | 19 openjdk-21-21.0.9+10/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java | 4 openjdk-21-21.0.9+10/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java | 45 openjdk-21-21.0.9+10/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java | 4 openjdk-21-21.0.9+10/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp | 12 openjdk-21-21.0.9+10/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/JWebServer.java | 6 openjdk-21-21.0.9+10/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/Main.java | 5 openjdk-21-21.0.9+10/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/SimpleFileServerImpl.java | 10 openjdk-21-21.0.9+10/src/jdk.jartool/share/classes/sun/tools/jar/Main.java | 13 openjdk-21-21.0.9+10/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-ui.css | 9 openjdk-21-21.0.9+10/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-ui.js | 168 - openjdk-21-21.0.9+10/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-ui.min.css | 8 openjdk-21-21.0.9+10/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-ui.min.js | 8 openjdk-21-21.0.9+10/src/jdk.javadoc/share/legal/jqueryUI.md | 4 openjdk-21-21.0.9+10/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkParser.java | 3 openjdk-21-21.0.9+10/src/jdk.jfr/share/classes/jdk/jfr/internal/query/FieldBuilder.java | 7 openjdk-21-21.0.9+10/test/failure_handler/src/share/conf/windows.properties | 16 openjdk-21-21.0.9+10/test/hotspot/gtest/gc/shared/test_bufferNodeAllocator.cpp | 32 openjdk-21-21.0.9+10/test/hotspot/gtest/gc/shared/test_workerDataArray.cpp | 10 openjdk-21-21.0.9+10/test/hotspot/gtest/os/linux/test_cgroupSubsystem_linux.cpp | 204 - openjdk-21-21.0.9+10/test/hotspot/gtest/runtime/test_cgroupSubsystem_linux.cpp | 557 ++++ openjdk-21-21.0.9+10/test/hotspot/gtest/runtime/test_os_linux_cgroups.cpp | 86 openjdk-21-21.0.9+10/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp | 4 openjdk-21-21.0.9+10/test/hotspot/jtreg/ProblemList-Virtual.txt | 2 openjdk-21-21.0.9+10/test/hotspot/jtreg/ProblemList-Xcomp.txt | 2 openjdk-21-21.0.9+10/test/hotspot/jtreg/ProblemList.txt | 7 openjdk-21-21.0.9+10/test/hotspot/jtreg/TEST.ROOT | 3 openjdk-21-21.0.9+10/test/hotspot/jtreg/TEST.groups | 1 openjdk-21-21.0.9+10/test/hotspot/jtreg/applications/jcstress/README | 2 openjdk-21-21.0.9+10/test/hotspot/jtreg/applications/jcstress/TestGenerator.java | 2 openjdk-21-21.0.9+10/test/hotspot/jtreg/applications/scimark/Scimark.java | 58 openjdk-21-21.0.9+10/test/hotspot/jtreg/compiler/c2/irTests/gc/ReferenceRefersToTests.java | 156 + openjdk-21-21.0.9+10/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseMD5IntrinsicsOptionOnUnsupportedCPU.java | 13 openjdk-21-21.0.9+10/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnUnsupportedCPU.java | 15 openjdk-21-21.0.9+10/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnUnsupportedCPU.java | 15 openjdk-21-21.0.9+10/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA3IntrinsicsOptionOnUnsupportedCPU.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnUnsupportedCPU.java | 15 openjdk-21-21.0.9+10/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHAOptionOnUnsupportedCPU.java | 15 openjdk-21-21.0.9+10/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java | 106 openjdk-21-21.0.9+10/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedAArch64CPU.java | 114 openjdk-21-21.0.9+10/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedCPU.java | 114 openjdk-21-21.0.9+10/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedRISCV64CPU.java | 115 openjdk-21-21.0.9+10/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedX86CPU.java | 110 openjdk-21-21.0.9+10/test/hotspot/jtreg/compiler/jsr292/CallSiteDepContextTest.java | 4 openjdk-21-21.0.9+10/test/hotspot/jtreg/compiler/jsr292/patches/java.base/java/lang/invoke/MethodHandleHelper.java | 4 openjdk-21-21.0.9+10/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/VMInfo.java | 2 openjdk-21-21.0.9+10/test/hotspot/jtreg/compiler/longcountedloops/TestSafePointWithEAState.java | 63 openjdk-21-21.0.9+10/test/hotspot/jtreg/compiler/membars/DekkerTest.java | 2 openjdk-21-21.0.9+10/test/hotspot/jtreg/compiler/rangechecks/TestSunkRangeFromPreLoopRCE.java | 81 openjdk-21-21.0.9+10/test/hotspot/jtreg/compiler/vectorization/TestVectorZeroCount.java | 1 openjdk-21-21.0.9+10/test/hotspot/jtreg/containers/cgroup/PlainRead.java | 78 openjdk-21-21.0.9+10/test/hotspot/jtreg/containers/cgroup/TestContainerized.java | 48 openjdk-21-21.0.9+10/test/hotspot/jtreg/containers/docker/DockerBasicTest.java | 1 openjdk-21-21.0.9+10/test/hotspot/jtreg/containers/docker/ShareTmpDir.java | 1 openjdk-21-21.0.9+10/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java | 1 openjdk-21-21.0.9+10/test/hotspot/jtreg/containers/docker/TestCPUSets.java | 1 openjdk-21-21.0.9+10/test/hotspot/jtreg/containers/docker/TestContainerInfo.java | 1 openjdk-21-21.0.9+10/test/hotspot/jtreg/containers/docker/TestJFREvents.java | 1 openjdk-21-21.0.9+10/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java | 1 openjdk-21-21.0.9+10/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java | 1 openjdk-21-21.0.9+10/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java | 1 openjdk-21-21.0.9+10/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java | 1 openjdk-21-21.0.9+10/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java | 4 openjdk-21-21.0.9+10/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java | 1 openjdk-21-21.0.9+10/test/hotspot/jtreg/containers/docker/TestMisc.java | 5 openjdk-21-21.0.9+10/test/hotspot/jtreg/containers/docker/TestPids.java | 1 openjdk-21-21.0.9+10/test/hotspot/jtreg/containers/systemd/HelloSystemd.java | 28 openjdk-21-21.0.9+10/test/hotspot/jtreg/containers/systemd/SystemdMemoryAwarenessTest.java | 85 openjdk-21-21.0.9+10/test/hotspot/jtreg/containers/systemd/TEST.properties | 24 openjdk-21-21.0.9+10/test/hotspot/jtreg/gc/TestObjectAlignmentCardSize.java | 63 openjdk-21-21.0.9+10/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsFlagsWithUlimit.java | 2 openjdk-21-21.0.9+10/test/hotspot/jtreg/gc/shenandoah/compiler/TestLostAntiDependencyAtExpansion.java | 67 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/ClassInitErrors/InitExceptionUnloadTest.java | 9 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/ClassUnload/DictionaryDependsTest.java | 12 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/ClassUnload/KeepAliveClass.java | 14 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/ClassUnload/KeepAliveClassLoader.java | 13 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/ClassUnload/KeepAliveObject.java | 13 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/ClassUnload/KeepAliveSoftReference.java | 6 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/ClassUnload/SuperDependsTest.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/ClassUnload/UnloadInterfaceTest.java | 11 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/ClassUnload/UnloadTest.java | 8 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/ErrorHandling/TestDwarf.java | 7 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/LoadClass/LoadClassNegative.java | 13 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/Thread/TestAlwaysPreTouchStacks.java | 2 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/Thread/TestBreakSignalThreadDump.java | 2 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/XCheckJniJsig/XCheckJSig.java | 2 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/cds/appcds/TestParallelGCWithCDS.java | 5 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/cds/appcds/complexURI/ComplexURITest.java | 167 + openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/cds/appcds/complexURI/mypackage/Another.java | 27 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/cds/appcds/complexURI/mypackage/Main.java | 37 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/HelloUnload.java | 8 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/UnloadUnregisteredLoader.java | 8 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java | 4 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/classFileParserBug/TestEmptyBootstrapMethodsAttr.java | 16 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/logging/ClassLoadUnloadTest.java | 4 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/logging/LoaderConstraintsTest.java | 17 openjdk-21-21.0.9+10/test/hotspot/jtreg/runtime/os/HugePageConfiguration.java | 3 openjdk-21-21.0.9+10/test/hotspot/jtreg/serviceability/dcmd/vm/SystemDumpMapTest.java | 2 openjdk-21-21.0.9+10/test/hotspot/jtreg/serviceability/dcmd/vm/SystemMapTest.java | 2 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/gc/gctests/PhantomReference/phantom001/phantom001.java | 7 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/metaspace/share/TriggerUnloadingWithFullGC.java | 36 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/metaspace/share/TriggerUnloadingWithWhiteBox.java | 38 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/metaspace/shrink_grow/ShrinkGrowTest/ShrinkGrowTest.java | 2 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/metaspace/staticReferences/StaticReferences.java | 6 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/metaspace/stressHierarchy/common/StressHierarchyBaseClass.java | 6 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/caught_exception/caught_exception002/caught_exception002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/classes/classes001/classes001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/classpath/classpath001/classpath001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/clear/clear002/clear002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/clear/clear003/clear003.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/clear/clear004/clear004.java | 8 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/down/down002/down002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/dump/dump002/dump002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/eval/eval001/eval001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/exclude/exclude001/exclude001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/fields/fields001/fields001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/hidden_class/hc001/hc001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/ignore/ignore001/ignore001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/interrupt/interrupt001/interrupt001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/kill/kill001/kill001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/kill/kill002/kill002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/klass/class001/class001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/list/list002/list002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/list/list003/list003.java | 11 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/locals/locals002/locals002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/methods/methods002/methods002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/monitor/monitor001/monitor001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/monitor/monitor002/monitor002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/next/next001/next001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect001/connect001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect002/connect002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect003/connect003.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect004/connect004.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect005/connect005.java | 13 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/listconnectors/listconnectors001/listconnectors001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/pop/pop001/pop001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/pop_exception/pop_exception001/pop_exception001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/print/print002/print002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/read/read001/read001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/redefine/redefine001/redefine001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/reenter/reenter001/reenter001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/regression/b4689395/b4689395.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/repeat/repeat001/repeat001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/resume/resume002/resume002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/run/run002/run002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/set/set001/set001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/set/set002/set002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/step/step002/step002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/step_up/step_up001/step_up001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_at/stop_at002/stop_at002.java | 8 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_at/stop_at003/stop_at003.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_in/stop_in002/stop_in002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/suspend/suspend001/suspend001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/thread/thread002/thread002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/threadgroup/threadgroup002/threadgroup002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/threadgroups/threadgroups002/threadgroups002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/threads/threads002/threads002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/threads/threads003/threads003.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/trace/trace001/trace001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/uncaught_exception/uncaught_exception002/uncaught_exception002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/unmonitor/unmonitor001/unmonitor001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/untrace/untrace001/untrace001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/unwatch/unwatch001/unwatch001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/unwatch/unwatch002/unwatch002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/up/up002/up002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/use/use001/use001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/watch/watch001/watch001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/watch/watch002/watch002.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/where/where004/where004.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/where/where005/where005.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/where/where006/where006.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/wherei/wherei001/wherei001.java | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetErrorName/geterrname002/TestDescription.java | 5 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadCpuTime/thrcputime002/thrcputime002.cpp | 12 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003/TestDescription.java | 7 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetVerboseFlag/setvrbflag002/TestDescription.java | 5 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI02/bi02t001/bi02t001.cpp | 17 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI03/bi03t001/bi03t001.cpp | 16 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/monitoring/MemoryNotificationInfo/from/from001.java | 89 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/monitoring/MemoryNotificationInfo/from/from001/TestDescription.java | 11 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/GarbageUtils.java | 11 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/JdbTest.java | 11 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java | 6 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/Debugee.java | 7 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress001.cpp | 6 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress003.cpp | 18 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress004.cpp | 10 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress006.cpp | 4 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress007.cpp | 2 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_InternedStrings/TestDescription.java | 4 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_InternedStrings_NonbranchyTree/TestDescription.java | 4 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_Strings_ArrayOf/TestDescription.java | 4 openjdk-21-21.0.9+10/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Humongous_InternedStrings/TestDescription.java | 4 openjdk-21-21.0.9+10/test/jdk/ProblemList.txt | 11 openjdk-21-21.0.9+10/test/jdk/TEST.ROOT | 3 openjdk-21-21.0.9+10/test/jdk/TEST.groups | 28 openjdk-21-21.0.9+10/test/jdk/build/AbsPathsInImage.java | 4 openjdk-21-21.0.9+10/test/jdk/com/sun/java/swing/plaf/motif/MenuItem/AcceleratorDelimiter/MotifLAFMenuAcceleratorDelimiter.java | 95 openjdk-21-21.0.9+10/test/jdk/com/sun/java/swing/plaf/motif/SplitPane/4141400/bug4141400.java | 71 openjdk-21-21.0.9+10/test/jdk/com/sun/java/swing/plaf/windows/MenuItem/4685843/bug4685843.java | 87 openjdk-21-21.0.9+10/test/jdk/com/sun/jdi/ThreadMemoryLeakTest.java | 7 openjdk-21-21.0.9+10/test/jdk/com/sun/net/httpserver/SelCacheTest.java | 83 openjdk-21-21.0.9+10/test/jdk/com/sun/net/httpserver/Test1.java | 81 openjdk-21-21.0.9+10/test/jdk/com/sun/net/httpserver/Test12.java | 86 openjdk-21-21.0.9+10/test/jdk/com/sun/net/httpserver/Test13.java | 70 openjdk-21-21.0.9+10/test/jdk/com/sun/net/httpserver/Test9.java | 111 openjdk-21-21.0.9+10/test/jdk/com/sun/net/httpserver/Test9a.java | 107 openjdk-21-21.0.9+10/test/jdk/com/sun/net/httpserver/TestLogging.java | 24 openjdk-21-21.0.9+10/test/jdk/com/sun/net/httpserver/docs/test1/largefile.txt | 2 openjdk-21-21.0.9+10/test/jdk/com/sun/net/httpserver/docs/test1/smallfile.txt | 1 openjdk-21-21.0.9+10/test/jdk/com/sun/net/httpserver/simpleserver/CommandLineNegativeTest.java | 21 openjdk-21-21.0.9+10/test/jdk/com/sun/net/httpserver/simpleserver/CommandLinePortNotSpecifiedTest.java | 5 openjdk-21-21.0.9+10/test/jdk/com/sun/net/httpserver/simpleserver/CommandLinePositiveTest.java | 23 openjdk-21-21.0.9+10/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLineNegativeTest.java | 21 openjdk-21-21.0.9+10/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLinePortNotSpecifiedTest.java | 5 openjdk-21-21.0.9+10/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLinePositiveTest.java | 23 openjdk-21-21.0.9+10/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/IPv6BoundHost.java | 100 openjdk-21-21.0.9+10/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/MaxRequestTimeTest.java | 5 openjdk-21-21.0.9+10/test/jdk/com/sun/nio/sctp/SctpChannel/CloseDescriptors.java | 12 openjdk-21-21.0.9+10/test/jdk/java/awt/Clipboard/ConcurrentClipboardAccessTest.java | 77 openjdk-21-21.0.9+10/test/jdk/java/awt/Component/UpdatingBootTime.java | 98 openjdk-21-21.0.9+10/test/jdk/java/awt/Component/UpdatingBootTime/UpdatingBootTime.html | 43 openjdk-21-21.0.9+10/test/jdk/java/awt/Component/UpdatingBootTime/UpdatingBootTime.java | 222 - openjdk-21-21.0.9+10/test/jdk/java/awt/Cursor/CursorOverlappedPanelsTest.java | 90 openjdk-21-21.0.9+10/test/jdk/java/awt/Cursor/CursorOverlappedPanelsTest/CursorOverlappedPanelsTest.html | 32 openjdk-21-21.0.9+10/test/jdk/java/awt/Cursor/CursorOverlappedPanelsTest/CursorOverlappedPanelsTest.java | 226 - openjdk-21-21.0.9+10/test/jdk/java/awt/Desktop/BrowseTest.java | 19 openjdk-21-21.0.9+10/test/jdk/java/awt/Desktop/EditAndPrintTest/EditAndPrintTest.java | 35 openjdk-21-21.0.9+10/test/jdk/java/awt/Desktop/OpenTest.java | 21 openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogForDirectories.java | 90 openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogForDirectories/FileDialogForDirectories.html | 47 openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogForDirectories/FileDialogForDirectories.java | 82 openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogForPackages.java | 79 openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogForPackages/FileDialogForPackages.html | 47 openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogForPackages/FileDialogForPackages.java | 84 openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogOpenDirTest.java | 79 openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogOpenDirTest/FileDialogOpenDirTest.html | 43 openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogOpenDirTest/FileDialogOpenDirTest.java | 239 -- openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogReturnTest.java | 142 + openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogReturnTest/FileDialogReturnTest.html | 43 openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogReturnTest/FileDialogReturnTest.java | 246 -- openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileNameOverrideTest.java | 105 openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileNameOverrideTest/FileNameOverrideTest.html | 45 openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileNameOverrideTest/FileNameOverrideTest.java | 96 openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/MultipleMode.java | 106 openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/MultipleMode/MultipleMode.html | 43 openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/MultipleMode/MultipleMode.java | 289 -- openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/RegexpFilterTest.java | 74 openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/RegexpFilterTest/RegexpFilterTest.html | 43 openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/RegexpFilterTest/RegexpFilterTest.java | 226 - openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/SaveFileNameOverrideTest.java | 91 openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/SaveFileNameOverrideTest/SaveFileNameOverrideTest.html | 45 openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/SaveFileNameOverrideTest/SaveFileNameOverrideTest.java | 89 openjdk-21-21.0.9+10/test/jdk/java/awt/FontMetrics/ExtremeFontSizeTest.java | 112 openjdk-21-21.0.9+10/test/jdk/java/awt/Frame/DisposeParentGC/DisposeParentGC.java | 43 openjdk-21-21.0.9+10/test/jdk/java/awt/Frame/InitialMaximizedTest/InitialMaximizedTest.html | 43 openjdk-21-21.0.9+10/test/jdk/java/awt/Frame/InitialMaximizedTest/InitialMaximizedTest.java | 251 -- openjdk-21-21.0.9+10/test/jdk/java/awt/Frame/MiscUndecorated/ActiveAWTWindowTest.java | 23 openjdk-21-21.0.9+10/test/jdk/java/awt/Frame/ShapeNotSetSometimes/ShapeNotSetSometimes.java | 23 openjdk-21-21.0.9+10/test/jdk/java/awt/InputMethods/InputMethodsTest/InputMethodsTest.html | 40 openjdk-21-21.0.9+10/test/jdk/java/awt/InputMethods/InputMethodsTest/InputMethodsTest.java | 103 openjdk-21-21.0.9+10/test/jdk/java/awt/Label/ContainerValidateTest.java | 169 + openjdk-21-21.0.9+10/test/jdk/java/awt/List/KeyEventsTest/KeyEventsTest.java | 102 openjdk-21-21.0.9+10/test/jdk/java/awt/Paint/ButtonRepaint.java | 30 openjdk-21-21.0.9+10/test/jdk/java/awt/Paint/CheckboxRepaint.java | 29 openjdk-21-21.0.9+10/test/jdk/java/awt/Paint/LabelRepaint.java | 24 openjdk-21-21.0.9+10/test/jdk/java/awt/Paint/ListRepaint.java | 45 openjdk-21-21.0.9+10/test/jdk/java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.html | 43 openjdk-21-21.0.9+10/test/jdk/java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.java | 285 -- openjdk-21-21.0.9+10/test/jdk/java/awt/TextField/SetEchoCharTest.java | 178 + openjdk-21-21.0.9+10/test/jdk/java/awt/TextField/SetEchoCharWordOpsTest.java | 90 openjdk-21-21.0.9+10/test/jdk/java/awt/TrayIcon/DblClickActionEventTest/DblClickActionEventTest.html | 48 openjdk-21-21.0.9+10/test/jdk/java/awt/TrayIcon/DblClickActionEventTest/DblClickActionEventTest.java | 116 openjdk-21-21.0.9+10/test/jdk/java/awt/dnd/ImageDecoratedDnD/ImageDecoratedDnD.html | 43 openjdk-21-21.0.9+10/test/jdk/java/awt/dnd/ImageDecoratedDnD/ImageDecoratedDnD.java | 228 - openjdk-21-21.0.9+10/test/jdk/java/awt/event/ClickEventsTest.java | 133 + openjdk-21-21.0.9+10/test/jdk/java/awt/event/KeyEvent/FrenchKeyboard.java | 71 openjdk-21-21.0.9+10/test/jdk/java/awt/event/KeyEvent/HomeEndKeyTest.java | 126 + openjdk-21-21.0.9+10/test/jdk/java/awt/event/KeyEvent/KeyCharTest/KeyCharTest.java | 52 openjdk-21-21.0.9+10/test/jdk/java/awt/event/KeyEvent/NumpadTest.java | 119 + openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/AWTPanelSmoothWheel.java | 131 + openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/AWTPanelSmoothWheel/AWTPanelSmoothWheel.html | 43 openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/AWTPanelSmoothWheel/AWTPanelSmoothWheel.java | 251 -- openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/DragMouseEventTest.java | 438 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/DragToLightweightTest.java | 146 + openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/MouseEnterTest.java | 175 + openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/MouseEventsDuringDrag.java | 307 ++ openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/MouseModifierTest.java | 181 + openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/MouseRButTest.java | 97 openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/TitleBarGetsMousePressed.java | 78 openjdk-21-21.0.9+10/test/jdk/java/awt/event/StressTest/LargeAWTEventMulticasterTest.java | 96 openjdk-21-21.0.9+10/test/jdk/java/awt/event/WindowActivatedEventTest.java | 169 + openjdk-21-21.0.9+10/test/jdk/java/awt/font/TextLayout/MyanmarTextTest.java | 45 openjdk-21-21.0.9+10/test/jdk/java/awt/im/4490692/bug4490692.html | 61 openjdk-21-21.0.9+10/test/jdk/java/awt/im/4490692/bug4490692.java | 70 openjdk-21-21.0.9+10/test/jdk/java/awt/im/8132503/bug8132503.html | 38 openjdk-21-21.0.9+10/test/jdk/java/awt/im/8132503/bug8132503.java | 47 openjdk-21-21.0.9+10/test/jdk/java/awt/im/8148984/bug8148984.html | 38 openjdk-21-21.0.9+10/test/jdk/java/awt/im/8148984/bug8148984.java | 47 openjdk-21-21.0.9+10/test/jdk/java/awt/im/8154816/bug8154816.html | 39 openjdk-21-21.0.9+10/test/jdk/java/awt/im/8154816/bug8154816.java | 47 openjdk-21-21.0.9+10/test/jdk/java/awt/im/PinyinIMCapsTest.java | 82 openjdk-21-21.0.9+10/test/jdk/java/awt/im/PinyinIMCommaTest.java | 78 openjdk-21-21.0.9+10/test/jdk/java/awt/im/PinyinIMFullstopTest.java | 79 openjdk-21-21.0.9+10/test/jdk/java/awt/im/bug4490692.java | 107 openjdk-21-21.0.9+10/test/jdk/java/awt/print/PrinterJob/PrintNullString.java | 215 - openjdk-21-21.0.9+10/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java | 61 openjdk-21-21.0.9+10/test/jdk/java/beans/Introspector/DefaultMethodBeanPropertyTest.java | 462 +++ openjdk-21-21.0.9+10/test/jdk/java/lang/Class/ProtectionDomainRace.java | 80 openjdk-21-21.0.9+10/test/jdk/java/lang/ProcessBuilder/Basic.java | 12 openjdk-21-21.0.9+10/test/jdk/java/lang/management/ThreadMXBean/Locks.java | 5 openjdk-21-21.0.9+10/test/jdk/java/lang/management/ThreadMXBean/VirtualThreadDeadlocks.java | 15 openjdk-21-21.0.9+10/test/jdk/java/math/BigInteger/ByteArrayConstructorTest.java | 148 + openjdk-21-21.0.9+10/test/jdk/java/math/BigInteger/java.base/java/math/Accessor.java | 32 openjdk-21-21.0.9+10/test/jdk/java/net/CookieHandler/B6644726.java | 9 openjdk-21-21.0.9+10/test/jdk/java/net/HttpURLConnection/HttpURLConnectionExpect100Test.java | 254 ++ openjdk-21-21.0.9+10/test/jdk/java/net/HttpURLConnection/HttpURLConnectionExpectContinueTest.java | 2 openjdk-21-21.0.9+10/test/jdk/java/net/Inet4Address/PingThis.java | 13 openjdk-21-21.0.9+10/test/jdk/java/net/MulticastSocket/NoLoopbackPackets.java | 17 openjdk-21-21.0.9+10/test/jdk/java/net/MulticastSocket/PromiscuousIPv6.java | 18 openjdk-21-21.0.9+10/test/jdk/java/net/MulticastSocket/SetOutgoingIf.java | 17 openjdk-21-21.0.9+10/test/jdk/java/net/ServerSocket/AnotherSelectFdsLimit.java | 7 openjdk-21-21.0.9+10/test/jdk/java/net/ServerSocket/SelectFdsLimit.java | 10 openjdk-21-21.0.9+10/test/jdk/java/net/URLConnection/UNCTest.java | 37 openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/AbstractConnectTimeoutHandshake.java | 19 openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/AsyncShutdownNow.java | 6 openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/ConnectTimeoutHandshakeAsync.java | 4 openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/ConnectTimeoutHandshakeSync.java | 4 openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/HttpClientShutdown.java | 8 openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/ShutdownNow.java | 6 openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/http2/BasicTest.java | 45 openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/http2/FixedThreadPoolTest.java | 45 openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/http2/ServerPush.java | 20 openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/HttpServerAdapters.java | 14 openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/TestUtil.java | 85 openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestServer.java | 23 openjdk-21-21.0.9+10/test/jdk/java/net/ipv6tests/TcpTest.java | 9 openjdk-21-21.0.9+10/test/jdk/java/nio/charset/Charset/Contains.java | 27 openjdk-21-21.0.9+10/test/jdk/java/security/cert/CertificateFactory/SlowStream.java | 85 openjdk-21-21.0.9+10/test/jdk/java/security/cert/CertificateFactory/slowstream.sh | 54 openjdk-21-21.0.9+10/test/jdk/java/text/Format/MessageFormat/SerializationTest.java | 10 openjdk-21-21.0.9+10/test/jdk/java/util/Currency/CurrencyTest.java | 56 openjdk-21-21.0.9+10/test/jdk/java/util/Currency/ISO4217-list-one.txt | 12 openjdk-21-21.0.9+10/test/jdk/java/util/Currency/ValidateISO4217.java | 4 openjdk-21-21.0.9+10/test/jdk/java/util/Locale/LanguageSubtagRegistryTest.java | 28 openjdk-21-21.0.9+10/test/jdk/java/util/TimeZone/CLDRDisplayNamesTest.java | 2 openjdk-21-21.0.9+10/test/jdk/java/util/concurrent/tck/ScheduledExecutorTest.java | 8 openjdk-21-21.0.9+10/test/jdk/java/util/zip/EntryCount64k.java | 11 openjdk-21-21.0.9+10/test/jdk/java/util/zip/GZIP/GZIPInputStreamAvailable.java | 93 openjdk-21-21.0.9+10/test/jdk/javax/accessibility/TestPopupMenuChildCount.java | 109 openjdk-21-21.0.9+10/test/jdk/javax/crypto/CryptoPermissions/InconsistentEntries.java | 63 openjdk-21-21.0.9+10/test/jdk/javax/management/remote/mandatory/notif/ListenerScaleTest.java | 6 openjdk-21-21.0.9+10/test/jdk/javax/net/ssl/HttpsURLConnection/CriticalSubjectAltName.java | 3 openjdk-21-21.0.9+10/test/jdk/javax/net/ssl/SSLSession/CertMsgCheck.java | 64 openjdk-21-21.0.9+10/test/jdk/javax/net/ssl/SSLSession/CheckSessionContext.java | 18 openjdk-21-21.0.9+10/test/jdk/javax/net/ssl/templates/SSLEngineTemplate.java | 75 openjdk-21-21.0.9+10/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java | 6 openjdk-21-21.0.9+10/test/jdk/javax/net/ssl/templates/TLSBase.java | 230 + openjdk-21-21.0.9+10/test/jdk/javax/sound/midi/File/SMFInterruptedRunningStatus.java | 144 + openjdk-21-21.0.9+10/test/jdk/javax/swing/JColorChooser/Test6977726.java | 9 openjdk-21-21.0.9+10/test/jdk/javax/swing/JComboBox/6559152/bug6559152.java | 8 openjdk-21-21.0.9+10/test/jdk/javax/swing/JFileChooser/6798062/bug6798062.html | 36 openjdk-21-21.0.9+10/test/jdk/javax/swing/JFileChooser/6798062/bug6798062.java | 98 openjdk-21-21.0.9+10/test/jdk/javax/swing/JFileChooser/FileFilterDescription/FileFilterDescription.html | 40 openjdk-21-21.0.9+10/test/jdk/javax/swing/JFileChooser/FileFilterDescription/FileFilterDescription.java | 51 openjdk-21-21.0.9+10/test/jdk/javax/swing/JInternalFrame/6726866/bug6726866.html | 30 openjdk-21-21.0.9+10/test/jdk/javax/swing/JInternalFrame/6726866/bug6726866.java | 37 openjdk-21-21.0.9+10/test/jdk/javax/swing/JMenu/bug4187996.java | 74 openjdk-21-21.0.9+10/test/jdk/javax/swing/JMenu/bug6471949.java | 134 + openjdk-21-21.0.9+10/test/jdk/javax/swing/JMenu/bug6513492.java | 148 + openjdk-21-21.0.9+10/test/jdk/javax/swing/JMenuItem/TestRadioAndCheckMenuItemWithIcon.java | 155 + openjdk-21-21.0.9+10/test/jdk/javax/swing/JOptionPane/4174551/bug4174551.html | 36 openjdk-21-21.0.9+10/test/jdk/javax/swing/JOptionPane/4174551/bug4174551.java | 52 openjdk-21-21.0.9+10/test/jdk/javax/swing/JOptionPane/8024926/bug8024926.html | 32 openjdk-21-21.0.9+10/test/jdk/javax/swing/JOptionPane/8024926/bug8024926.java | 212 - openjdk-21-21.0.9+10/test/jdk/javax/swing/JOptionPane/bug4174551.java | 78 openjdk-21-21.0.9+10/test/jdk/javax/swing/JOptionPane/bug8024926.java | 71 openjdk-21-21.0.9+10/test/jdk/javax/swing/JPopupMenu/7160604/bug7160604.html | 30 openjdk-21-21.0.9+10/test/jdk/javax/swing/JPopupMenu/7160604/bug7160604.java | 95 openjdk-21-21.0.9+10/test/jdk/javax/swing/JPopupMenu/bug7160604.java | 112 openjdk-21-21.0.9+10/test/jdk/javax/swing/JRadioButton/8033699/bug8033699.java | 258 +- openjdk-21-21.0.9+10/test/jdk/javax/swing/JScrollBar/8039464/Test8039464.html | 32 openjdk-21-21.0.9+10/test/jdk/javax/swing/JScrollBar/8039464/Test8039464.java | 92 openjdk-21-21.0.9+10/test/jdk/javax/swing/JScrollBar/Test8039464.java | 95 openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/4987336/bug4987336.html | 32 openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/4987336/bug4987336.java | 63 openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/6587742/bug6587742.html | 36 openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/6587742/bug6587742.java | 130 - openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/6742358/bug6742358.html | 29 openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/6742358/bug6742358.java | 92 openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/bug6587742.java | 166 + openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/bug6742358.java | 106 openjdk-21-21.0.9+10/test/jdk/javax/swing/JSplitPane/4164779/JSplitPaneKeyboardNavigationTest.java | 33 openjdk-21-21.0.9+10/test/jdk/javax/swing/JSplitPane/8132123/bug8132123.html | 38 openjdk-21-21.0.9+10/test/jdk/javax/swing/JSplitPane/8132123/bug8132123.java | 51 openjdk-21-21.0.9+10/test/jdk/javax/swing/JSplitPane/bug8132123.java | 77 openjdk-21-21.0.9+10/test/jdk/javax/swing/JTabbedPane/4666224/bug4666224.html | 42 openjdk-21-21.0.9+10/test/jdk/javax/swing/JTabbedPane/4666224/bug4666224.java | 572 ---- openjdk-21-21.0.9+10/test/jdk/javax/swing/JTabbedPane/bug4499556.java | 280 ++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JTabbedPane/bug4666224.java | 168 + openjdk-21-21.0.9+10/test/jdk/javax/swing/JTabbedPane/bug6259533.java | 82 openjdk-21-21.0.9+10/test/jdk/javax/swing/JTable/4222153/bug4222153.html | 31 openjdk-21-21.0.9+10/test/jdk/javax/swing/JTable/4222153/bug4222153.java | 48 openjdk-21-21.0.9+10/test/jdk/javax/swing/JTable/TAB/TAB.html | 43 openjdk-21-21.0.9+10/test/jdk/javax/swing/JTable/TAB/TAB.java | 169 - openjdk-21-21.0.9+10/test/jdk/javax/swing/JTable/Tab.java | 225 + openjdk-21-21.0.9+10/test/jdk/javax/swing/JTable/bug4222153.java | 117 openjdk-21-21.0.9+10/test/jdk/javax/swing/JTextArea/bug4265784.java | 4 openjdk-21-21.0.9+10/test/jdk/javax/swing/JToolTip/4644444/bug4644444.html | 44 openjdk-21-21.0.9+10/test/jdk/javax/swing/JToolTip/4644444/bug4644444.java | 354 -- openjdk-21-21.0.9+10/test/jdk/javax/swing/JToolTip/bug4644444.java | 63 openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/4314199/bug4314199.html | 31 openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/4314199/bug4314199.java | 92 openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/NodeChangedTest.java | 72 openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/bug4118860.java | 97 openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/bug4169215.java | 65 openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/bug4196987.java | 70 openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/bug4270654.java | 76 openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/bug4314199.java | 99 openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/bug4618767.java | 121 + openjdk-21-21.0.9+10/test/jdk/javax/swing/JViewport/bug4137282.java | 90 openjdk-21-21.0.9+10/test/jdk/javax/swing/JViewport/bug4217252.java | 103 openjdk-21-21.0.9+10/test/jdk/javax/swing/JViewport/bug4237176.java | 70 openjdk-21-21.0.9+10/test/jdk/javax/swing/JViewport/bug4243479.java | 96 openjdk-21-21.0.9+10/test/jdk/javax/swing/JViewport/bug4750421.java | 69 openjdk-21-21.0.9+10/test/jdk/javax/swing/ProgressMonitor/bug4401480.java | 105 openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4243289.html | 32 openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4243289.java | 49 openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4247606.html | 33 openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4247606.java | 49 openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4252164.html | 33 openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4252164.java | 75 openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4760089.html | 33 openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4760089.java | 49 openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test6910490.html | 32 openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test6910490.java | 36 openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicGraphicsUtils/DrawEtchedRectTest.java | 77 openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicHTML/4228104/bug4228104.java | 75 openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicInternalFrameTitlePane/bug4331515.java | 68 openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicSliderUI/bug4220108.java | 75 openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicSplitPaneDivider/AddMouseListenerTest.java | 68 openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicSplitPaneUI/NegativeSizeTest.java | 87 openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicSplitPaneUI/PreferredSizeLayoutTest.java | 71 openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicToolBarUI/bug4305622.java | 87 openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicToolBarUI/bug4331392.java | 73 openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/metal/MenuItemUI/JavaLAFMenuAcceleratorDelimiter.java | 83 openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/metal/MetalIconFactory/bug4952462.java | 98 openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/bug4186347.java | 74 openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/bug4969419.java | 229 + openjdk-21-21.0.9+10/test/jdk/javax/swing/text/BoxView/bug6494356.java | 135 + openjdk-21-21.0.9+10/test/jdk/javax/swing/text/GlyphView/4984669/bug4984669.html | 30 openjdk-21-21.0.9+10/test/jdk/javax/swing/text/GlyphView/4984669/bug4984669.java | 55 openjdk-21-21.0.9+10/test/jdk/javax/swing/text/GlyphView/htmlUnderliningTest.java | 80 openjdk-21-21.0.9+10/test/jdk/javax/swing/text/html/TableView/7030332/bug7030332.html | 35 openjdk-21-21.0.9+10/test/jdk/javax/swing/text/html/TableView/7030332/bug7030332.java | 87 openjdk-21-21.0.9+10/test/jdk/javax/xml/crypto/dsig/GenerationTests.java | 41 openjdk-21-21.0.9+10/test/jdk/javax/xml/crypto/dsig/PSS.java | 61 openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/cgroup/TestSystemSettings.java | 45 openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java | 1 openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java | 1 openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java | 1 openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java | 1 openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java | 1 openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java | 1 openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java | 1 openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java | 1 openjdk-21-21.0.9+10/test/jdk/jdk/jfr/api/metadata/annotations/TestPeriod.java | 4 openjdk-21-21.0.9+10/test/jdk/jdk/jfr/api/metadata/settingdescriptor/TestGetContentType.java | 6 openjdk-21-21.0.9+10/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java | 58 openjdk-21-21.0.9+10/test/jdk/sun/java2d/Disposer/TestDisposerRace.java | 61 openjdk-21-21.0.9+10/test/jdk/sun/java2d/loops/CopyAreaSpeed.html | 39 openjdk-21-21.0.9+10/test/jdk/sun/java2d/loops/CopyAreaSpeed.java | 243 -- openjdk-21-21.0.9+10/test/jdk/sun/net/www/protocol/file/NonLocalFtpFallback.java | 145 + openjdk-21-21.0.9+10/test/jdk/sun/net/www/protocol/http/UserCookie.java | 6 openjdk-21-21.0.9+10/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/DNSIdentities.java | 4 openjdk-21-21.0.9+10/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPAddressIPIdentities.java | 4 openjdk-21-21.0.9+10/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java | 4 openjdk-21-21.0.9+10/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/Identities.java | 4 openjdk-21-21.0.9+10/test/jdk/sun/security/krb5/auto/TEST.properties | 24 openjdk-21-21.0.9+10/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java | 14 openjdk-21-21.0.9+10/test/jdk/sun/security/mscapi/AllTypes.java | 27 openjdk-21-21.0.9+10/test/jdk/sun/security/pkcs11/PKCS11Test.java | 38 openjdk-21-21.0.9+10/test/jdk/sun/security/pkcs11/SecmodTest.java | 4 openjdk-21-21.0.9+10/test/jdk/sun/security/pkcs11/tls/TestKeyMaterialMisuse.java | 87 openjdk-21-21.0.9+10/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java | 17 openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/CipherSuite/AbstractDisableCipherSuites.java | 295 ++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/CipherSuite/NoDesRC4DesEdeCiphSuite.java | 275 -- openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/CipherSuite/TLSCipherSuiteWildCardMatchingDisablePartsOfCipherSuite.java | 86 openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/CipherSuite/TLSCipherSuiteWildCardMatchingIllegalArgument.java | 71 openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/DHKeyExchange/LegacyDHEKeyExchange.java | 6 openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SSLLogger/DebugPropertyValuesTest.java | 185 + openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SSLSessionImpl/NoInvalidateSocketException.java | 8 openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeClientTLS12withSNI.java | 361 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SSLSocketImpl/NonAutoClose.java | 370 --- openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SSLSocketImpl/SetClientMode.java | 171 - openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/AbstractCheckSignatureSchemes.java | 246 ++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/DisableSignatureSchemePerScopeDTLS12.java | 58 openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/DisableSignatureSchemePerScopeTLS12.java | 149 + openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/DisableSignatureSchemePerScopeTLS13.java | 103 openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/MD5NotAllowedInTLS13CertificateSignature.java | 231 + openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/MixingTLSUsageConstraintsWithNonTLS.java | 56 openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java | 5 openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java | 3 openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/SigSchemePropOrdering.java | 236 - openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Entrust.java | 15 openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustcommercialca-chain.pem | 77 openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustnetworkingca-chain.pem | 76 openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustpremiumca-chain.pem | 88 openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustpremiumeccca-chain.pem | 63 openjdk-21-21.0.9+10/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java | 13 openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcCapacityOutput1.sh | 7 openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcCauseOutput1.sh | 7 openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcMetaCapacityOutput1.sh | 7 openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcNewCapacityOutput1.sh | 7 openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcNewOutput1.sh | 7 openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcOldCapacityOutput1.sh | 7 openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcOldOutput1.sh | 7 openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcOutput1.sh | 7 openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatLineCounts1.sh | 7 openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatLineCounts2.sh | 7 openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatLineCounts3.sh | 7 openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatLineCounts4.sh | 7 openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/lineCounts1.awk | 2 openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/lineCounts2.awk | 2 openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/lineCounts3.awk | 2 openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/lineCounts4.awk | 2 openjdk-21-21.0.9+10/test/jdk/tools/jar/JarCreateFileNameTest.java | 70 openjdk-21-21.0.9+10/test/jdk/tools/jimage/JImageToolTest.java | 3 openjdk-21-21.0.9+10/test/jdk/tools/jpackage/windows/Win8301247Test.java | 29 openjdk-21-21.0.9+10/test/jdk/tools/launcher/DisableBestFitMappingTest.java | 83 openjdk-21-21.0.9+10/test/jdk/tools/launcher/Settings.java | 7 openjdk-21-21.0.9+10/test/jtreg-ext/requires/VMProps.java | 47 openjdk-21-21.0.9+10/test/langtools/jdk/javadoc/doclet/testLinkOption/TestRedirectLinks.java | 1 openjdk-21-21.0.9+10/test/langtools/tools/javac/annotations/typeAnnotations/TypeAnnotationsInConstantInit.java | 81 openjdk-21-21.0.9+10/test/langtools/tools/javac/lambda/LambdaExpr02.java | 2 openjdk-21-21.0.9+10/test/langtools/tools/javac/patterns/SOEDeeplyNestedBlocksTest.java | 1187 ++++++++++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/Asserts.java | 30 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/SecurityTools.java | 29 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/Utils.java | 60 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/apps/LingeredApp.java | 5 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/artifacts/ArtifactResolver.java | 38 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/artifacts/ArtifactResolverException.java | 6 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/artifacts/JibArtifactManager.java | 4 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/classloader/ClassUnloadCommon.java | 44 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/classloader/GeneratingClassLoader.java | 10 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/classloader/GeneratingCompilingClassLoader.java | 4 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java | 10 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/containers/systemd/SystemdRunOptions.java | 152 + openjdk-21-21.0.9+10/test/lib/jdk/test/lib/containers/systemd/SystemdTestUtils.java | 376 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/format/ArrayDiff.java | 4 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/model/JavaHeapObject.java | 8 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/model/JavaStatic.java | 7 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/model/JavaThing.java | 8 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/model/Root.java | 8 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/model/Snapshot.java | 10 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/model/StackFrame.java | 8 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/model/StackTrace.java | 8 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/parser/FileReadBuffer.java | 4 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/parser/MappedReadBuffer.java | 4 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/parser/ReadBuffer.java | 3 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/parser/Reader.java | 4 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/jfr/Events.java | 4 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/jvmti/DebugeeClass.java | 8 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/jvmti/jvmti_common.hpp | 22 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/management/ThreadMXBeanTool.java | 6 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/net/IPSupport.java | 3 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/process/ProcessTools.java | 4 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/security/CertificateBuilder.java | 23 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/security/OpensslArtifactFetcher.java | 36 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/security/XMLUtils.java | 46 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/thread/VThreadPinner.java | 6 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/thread/VThreadRunner.java | 6 openjdk-21-21.0.9+10/test/lib/jdk/test/lib/util/FileUtils.java | 38 openjdk-21-21.0.9+10/test/lib/jdk/test/whitebox/WhiteBox.java | 5 openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/net/UnixSocketChannelReadWrite.java | 19 openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/util/stream/tasks/DataProviders.java | 43 openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Bulk.java | 150 - openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/DictionaryProblem.java | 101 openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Lambda.java | 89 openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Xtras.java | 32 openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/util/stream/tasks/PhoneCode/Bulk.java | 229 - openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/util/stream/tasks/PhoneCode/PhoneCodeProblem.java | 105 959 files changed, 30851 insertions(+), 18396 deletions(-) gpgv: Signature made Thu Oct 23 10:22:58 2025 UTC gpgv: using RSA key B6E62F3D12AC38495C0DA90510C293B6C37C4E36 gpgv: Note: signatures using the SHA1 algorithm are rejected gpgv: Can't check signature: Bad public key dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpnz40qh5a/openjdk-21_21.0.9+10-1~deb13u1.dsc: no acceptable signature found diff -Nru openjdk-21-21.0.8+9/.jcheck/conf openjdk-21-21.0.9+10/.jcheck/conf --- openjdk-21-21.0.8+9/.jcheck/conf 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/.jcheck/conf 2025-10-13 07:49:24.000000000 +0000 @@ -1,7 +1,7 @@ [general] project=jdk-updates jbs=JDK -version=21.0.8 +version=21.0.9 [checks] error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists diff -Nru openjdk-21-21.0.8+9/debian/changelog openjdk-21-21.0.9+10/debian/changelog --- openjdk-21-21.0.8+9/debian/changelog 2025-07-17 12:34:13.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/changelog 2025-10-23 10:14:51.000000000 +0000 @@ -1,3 +1,53 @@ +openjdk-21 (21.0.9+10-1~deb13u1) trixie-security; urgency=medium + + * Rebuild for trixie + + -- Moritz Mühlenhoff Thu, 23 Oct 2025 12:14:51 +0200 + +openjdk-21 (21.0.9+10-1) unstable; urgency=medium + + * OpenJDK 21.0.9 release, build 10. + - CVEs: + + CVE-2025-53057, 8360937: Enhance certificate handling. + + CVE-2025-53066, 8356294: Enhance Path Factories. + + CVE-2025-61748, 8359454: Enhance String handling. + + [ Vladimir Petko ] + * d/t/dependencies.sh: Relax test assertion for PC/SC library. + * d/p/jdk-8369450.patch: Fix ftbfs due to rust-coreutils date. LP: #2127120. + * d/rules: Run jtreg autopkgtests only on jtreg architectures. + * d/t/{hotspot-autopkgtest.in, jdk-autopkgtest.in}: Skip tests + that require a large amount of memory. + * d/t/{control,hotspot-autopkgtest.sh, jdk-autopkgtest.sh}: + Regenerate. + + -- Matthias Klose Wed, 22 Oct 2025 08:07:14 +0200 + +openjdk-21 (21.0.9~8ea-1) unstable; urgency=medium + + * OpenJDK 21.0.9 early access, build 8. + + [ Matthias Klose ] + * d/rules: Let the install target depend on the build target. Closes: #1105471. + + [ Vladimir Petko ] + * d/t/problems.csv: Synchronize problem list. + + -- Matthias Klose Sat, 27 Sep 2025 13:52:21 +0200 + +openjdk-21 (21.0.9~5ea-1) unstable; urgency=medium + + * OpenJDK 21.0.9 early access, build 5. + + [ Vladimir Petko ] + * d/copyright-generator/copyright-gen.py: bump copyright year. + * d/copyright: regenerate. + + [ Matthias Klose ] + * Build using GCC 15 on development releases. + + -- Matthias Klose Fri, 29 Aug 2025 12:59:33 +0200 + openjdk-21 (21.0.8+9-1) unstable; urgency=high * OpenJDK 21.0.8 release, build 9. diff -Nru openjdk-21-21.0.8+9/debian/copyright openjdk-21-21.0.9+10/debian/copyright --- openjdk-21-21.0.8+9/debian/copyright 2025-07-17 14:12:13.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/copyright 2025-08-05 11:21:14.000000000 +0000 @@ -40,7 +40,7 @@ Files: * Copyright: - Copyright (c) 1996-2023 Oracle and/or its affiliates. + Copyright (c) 1996-2025 Oracle and/or its affiliates. Copyright (c) 1996-2003 Sun Microsystems, Inc. Copyright (c) 2009-2012 Red Hat, Inc. Copyright (c) 2012-2022 SAP SE. diff -Nru openjdk-21-21.0.8+9/debian/copyright-generator/copyright-gen.py openjdk-21-21.0.9+10/debian/copyright-generator/copyright-gen.py --- openjdk-21-21.0.8+9/debian/copyright-generator/copyright-gen.py 2024-03-20 23:08:28.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/copyright-generator/copyright-gen.py 2025-08-05 11:21:14.000000000 +0000 @@ -52,7 +52,7 @@ ## TODO: Can the script deduce this list? openjdk_copyrights = [ - "Copyright (c) 1996-2023 Oracle and/or its affiliates.", + "Copyright (c) 1996-2025 Oracle and/or its affiliates.", "Copyright (c) 1996-2003 Sun Microsystems, Inc.", "Copyright (c) 2009-2012 Red Hat, Inc.", "Copyright (c) 2012-2022 SAP SE.", diff -Nru openjdk-21-21.0.8+9/debian/patches/default-jvm-cfg.diff openjdk-21-21.0.9+10/debian/patches/default-jvm-cfg.diff --- openjdk-21-21.0.8+9/debian/patches/default-jvm-cfg.diff 2024-03-20 23:08:28.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/patches/default-jvm-cfg.diff 2025-08-29 11:06:27.000000000 +0000 @@ -1,6 +1,6 @@ --- a/src/java.base/share/native/libjli/java.c +++ b/src/java.base/share/native/libjli/java.c -@@ -2047,7 +2047,7 @@ +@@ -2054,7 +2054,7 @@ jint ReadKnownVMs(const char *jvmCfgName, jboolean speculative) { FILE *jvmCfg; @@ -9,7 +9,7 @@ int cnt = 0; int lineno = 0; jlong start = 0, end = 0; -@@ -2061,6 +2061,11 @@ +@@ -2068,6 +2068,11 @@ ReadKnownVMs(const char *jvmCfgName, jbo jvmCfg = fopen(jvmCfgName, "r"); if (jvmCfg == NULL) { diff -Nru openjdk-21-21.0.8+9/debian/patches/icedtea-override-redirect-compiz.diff openjdk-21-21.0.9+10/debian/patches/icedtea-override-redirect-compiz.diff --- openjdk-21-21.0.8+9/debian/patches/icedtea-override-redirect-compiz.diff 2024-03-20 23:08:28.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/patches/icedtea-override-redirect-compiz.diff 2025-08-29 11:06:24.000000000 +0000 @@ -1,6 +1,6 @@ --- a/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java -@@ -1259,6 +1259,7 @@ +@@ -1260,6 +1260,7 @@ class XWindowPeer extends XPanelPeer imp boolean isOverrideRedirect() { return XWM.getWMID() == XWM.OPENLOOK_WM || diff -Nru openjdk-21-21.0.8+9/debian/patches/jdk-8307977-proposed.patch openjdk-21-21.0.9+10/debian/patches/jdk-8307977-proposed.patch --- openjdk-21-21.0.8+9/debian/patches/jdk-8307977-proposed.patch 2025-07-17 14:12:13.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/patches/jdk-8307977-proposed.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,81 +0,0 @@ -Description: attach in linux hangs due to permission denied accessing /proc/pid/root - The attach API uses /proc/pid/root in order to support containers. - Dereferencing this symlink is governed by ptrace access mode PTRACE_MODE_READ_FSCREDS - which may not succeed when running as the user running the JRE. - This breaks running jcmd and jmap as the same user the JVM is running as. - Use tmpdir when pid matches ns_pid. -Author: Sebastian Lövdahl -Bug: https://bugs.openjdk.org/browse/JDK-8307977 -Bug: https://bugs.openjdk.org/browse/JDK-8226919 -Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1034601 -Last-Update: 2023-04-18 - -From 36b554e2de46d77898be4d0feae0ee2171b445bc Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Sebastian=20L=C3=B6vdahl?= -Date: Tue, 18 Apr 2023 12:50:32 +0300 -Subject: [PATCH] 8226919: Fix dynamic attach in Linux for non-container - environments - ---- - .../sun/tools/attach/VirtualMachineImpl.java | 37 ++++++++++++------- - 1 file changed, 23 insertions(+), 14 deletions(-) - ---- a/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java -+++ b/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java -@@ -210,11 +210,8 @@ public class VirtualMachineImpl extends - } - - // Return the socket file for the given process. -- private File findSocketFile(int pid, int ns_pid) { -- // A process may not exist in the same mount namespace as the caller. -- // Instead, attach relative to the target root filesystem as exposed by -- // procfs regardless of namespaces. -- String root = "/proc/" + pid + "/root/" + tmpdir; -+ private File findSocketFile(int pid, int ns_pid) throws IOException { -+ String root = findTargetProcessTmpDirectory(pid, ns_pid); - return new File(root, ".java_pid" + ns_pid); - } - -@@ -230,21 +227,33 @@ public class VirtualMachineImpl extends - // Do not canonicalize the file path, or we will fail to attach to a VM in a container. - f.createNewFile(); - } catch (IOException x) { -- String root; -- if (pid != ns_pid) { -- // A process may not exist in the same mount namespace as the caller. -- // Instead, attach relative to the target root filesystem as exposed by -- // procfs regardless of namespaces. -- root = "/proc/" + pid + "/root/" + tmpdir; -- } else { -- root = tmpdir; -- } -+ String root = findTargetProcessTmpDirectory(pid, ns_pid); - f = new File(root, fn); - f.createNewFile(); - } - return f; - } - -+ private String findTargetProcessTmpDirectory(int pid, int ns_pid) throws IOException { -+ String root; -+ if (pid != ns_pid) { -+ // A process may not exist in the same mount namespace as the caller. -+ // Instead, attach relative to the target root filesystem as exposed by -+ // procfs regardless of namespaces. -+ String procRootDirectory = "/proc/" + pid + "/root"; -+ if (!Files.isReadable(Path.of(procRootDirectory))) { -+ throw new IOException( -+ String.format("Unable to access root directory %s " + -+ "of target process %d", procRootDirectory, pid)); -+ } -+ -+ root = procRootDirectory + "/" + tmpdir; -+ } else { -+ root = tmpdir; -+ } -+ return root; -+ } -+ - /* - * Write/sends the given to the target VM. String is transmitted in - * UTF-8 encoding. diff -Nru openjdk-21-21.0.8+9/debian/patches/jdk-8334502-proposed.patch openjdk-21-21.0.9+10/debian/patches/jdk-8334502-proposed.patch --- openjdk-21-21.0.8+9/debian/patches/jdk-8334502-proposed.patch 2025-07-17 14:12:13.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/patches/jdk-8334502-proposed.patch 2025-08-29 11:07:01.000000000 +0000 @@ -6,7 +6,7 @@ --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp -@@ -197,8 +197,8 @@ char* os::iso8601_time(jlong millisecond +@@ -198,8 +198,8 @@ char* os::iso8601_time(jlong millisecond abs_local_to_UTC = -(abs_local_to_UTC); } // Convert time zone offset seconds to hours and minutes. diff -Nru openjdk-21-21.0.8+9/debian/patches/jdk-8359735.patch openjdk-21-21.0.9+10/debian/patches/jdk-8359735.patch --- openjdk-21-21.0.8+9/debian/patches/jdk-8359735.patch 2025-07-17 12:32:27.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/patches/jdk-8359735.patch 2025-08-29 11:07:10.000000000 +0000 @@ -17,7 +17,7 @@ --- a/test/jdk/java/lang/ProcessBuilder/Basic.java +++ b/test/jdk/java/lang/ProcessBuilder/Basic.java -@@ -696,7 +696,7 @@ +@@ -691,7 +691,7 @@ public class Basic { public static String path() { return path; } private static final String path = path0(); private static String path0(){ @@ -26,7 +26,7 @@ return "/bin/true"; } else { File trueExe = new File("true"); -@@ -711,7 +711,7 @@ +@@ -706,7 +706,7 @@ public class Basic { public static String path() { return path; } private static final String path = path0(); private static String path0(){ @@ -44,7 +44,7 @@ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it -@@ -295,10 +295,12 @@ +@@ -294,10 +294,12 @@ public class InfoTest { String expected = "sleep"; if (Platform.isWindows()) { expected = "sleep.exe"; diff -Nru openjdk-21-21.0.8+9/debian/patches/jdk-8369450-proposed.patch openjdk-21-21.0.9+10/debian/patches/jdk-8369450-proposed.patch --- openjdk-21-21.0.8+9/debian/patches/jdk-8369450-proposed.patch 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/patches/jdk-8369450-proposed.patch 2025-10-09 08:03:04.000000000 +0000 @@ -0,0 +1,18 @@ +Description: [Ubuntu 25.10] openjdk fails to build due to rust-coreutils date + Add uutils as a GNU-compatible date provider. +Author: Vladimir Petko +Origin: upstream, https://github.com/openjdk/jdk/pull/27705 +Bug: https://bugs.openjdk.org/browse/JDK-8369450 +Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/openjdk-25/+bug/2127120 +Last-Update: 2025-10-09 +--- a/make/autoconf/basic_tools.m4 ++++ b/make/autoconf/basic_tools.m4 +@@ -378,7 +378,7 @@ + + # Check if it's a GNU date compatible version + AC_MSG_CHECKING([if date is a GNU compatible version]) +- check_date=`$DATE --version 2>&1 | $GREP "GNU\|BusyBox"` ++ check_date=`$DATE --version 2>&1 | $GREP "GNU\|BusyBox\|uutils"` + if test "x$check_date" != x; then + AC_MSG_RESULT([yes]) + IS_GNU_DATE=yes diff -Nru openjdk-21-21.0.8+9/debian/patches/jdk-getAccessibleValue.diff openjdk-21-21.0.9+10/debian/patches/jdk-getAccessibleValue.diff --- openjdk-21-21.0.8+9/debian/patches/jdk-getAccessibleValue.diff 2024-03-20 23:08:28.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/patches/jdk-getAccessibleValue.diff 2025-08-29 11:06:34.000000000 +0000 @@ -1,6 +1,6 @@ --- a/src/java.desktop/share/classes/javax/swing/JTree.java +++ b/src/java.desktop/share/classes/javax/swing/JTree.java -@@ -5153,7 +5153,7 @@ +@@ -5153,7 +5153,7 @@ public class JTree extends JComponent im public AccessibleSelection getAccessibleSelection() { AccessibleContext ac = getCurrentAccessibleContext(); if (ac != null && isLeaf) { @@ -9,7 +9,7 @@ } else { return this; } -@@ -5168,7 +5168,7 @@ +@@ -5168,7 +5168,7 @@ public class JTree extends JComponent im public AccessibleText getAccessibleText() { AccessibleContext ac = getCurrentAccessibleContext(); if (ac != null) { @@ -18,7 +18,7 @@ } else { return null; } -@@ -5183,7 +5183,7 @@ +@@ -5183,7 +5183,7 @@ public class JTree extends JComponent im public AccessibleValue getAccessibleValue() { AccessibleContext ac = getCurrentAccessibleContext(); if (ac != null) { @@ -29,7 +29,7 @@ } --- a/src/java.desktop/share/classes/javax/swing/table/JTableHeader.java +++ b/src/java.desktop/share/classes/javax/swing/table/JTableHeader.java -@@ -1143,7 +1143,12 @@ +@@ -1143,7 +1143,12 @@ public class JTableHeader extends JCompo } public AccessibleAction getAccessibleAction() { @@ -43,7 +43,7 @@ } /** -@@ -1159,15 +1164,30 @@ +@@ -1159,15 +1164,30 @@ public class JTableHeader extends JCompo } public AccessibleSelection getAccessibleSelection() { @@ -79,7 +79,7 @@ --- a/src/java.desktop/share/classes/javax/swing/JTable.java +++ b/src/java.desktop/share/classes/javax/swing/JTable.java -@@ -8443,7 +8443,12 @@ +@@ -8443,7 +8443,12 @@ public class JTable extends JComponent i * null */ public AccessibleSelection getAccessibleSelection() { @@ -93,7 +93,7 @@ } /** -@@ -8453,7 +8458,12 @@ +@@ -8453,7 +8458,12 @@ public class JTable extends JComponent i * @return the AccessibleText, or null */ public AccessibleText getAccessibleText() { @@ -107,7 +107,7 @@ } /** -@@ -8463,7 +8473,12 @@ +@@ -8463,7 +8473,12 @@ public class JTable extends JComponent i * @return the AccessibleValue, or null */ public AccessibleValue getAccessibleValue() { @@ -121,7 +121,7 @@ } -@@ -9223,7 +9238,12 @@ +@@ -9223,7 +9238,12 @@ public class JTable extends JComponent i * @return the AccessibleAction, or null */ public AccessibleAction getAccessibleAction() { @@ -135,7 +135,7 @@ } /** -@@ -9245,7 +9265,12 @@ +@@ -9245,7 +9265,12 @@ public class JTable extends JComponent i * null */ public AccessibleSelection getAccessibleSelection() { @@ -149,7 +149,7 @@ } /** -@@ -9255,7 +9280,12 @@ +@@ -9255,7 +9280,12 @@ public class JTable extends JComponent i * @return the AccessibleText, or null */ public AccessibleText getAccessibleText() { @@ -163,7 +163,7 @@ } /** -@@ -9265,7 +9295,12 @@ +@@ -9265,7 +9295,12 @@ public class JTable extends JComponent i * @return the AccessibleValue, or null */ public AccessibleValue getAccessibleValue() { @@ -179,7 +179,7 @@ --- a/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java +++ b/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java -@@ -6636,7 +6636,7 @@ +@@ -6633,7 +6633,7 @@ public final class AccessBridge { public AccessibleSelection getAccessibleSelection() { AccessibleContext ac = getCurrentAccessibleContext(); if (ac != null && isLeaf) { @@ -188,7 +188,7 @@ } else { return this; } -@@ -6651,7 +6651,7 @@ +@@ -6648,7 +6648,7 @@ public final class AccessBridge { public AccessibleText getAccessibleText() { AccessibleContext ac = getCurrentAccessibleContext(); if (ac != null) { @@ -197,7 +197,7 @@ } else { return null; } -@@ -6666,7 +6666,7 @@ +@@ -6663,7 +6663,7 @@ public final class AccessBridge { public AccessibleValue getAccessibleValue() { AccessibleContext ac = getCurrentAccessibleContext(); if (ac != null) { diff -Nru openjdk-21-21.0.8+9/debian/patches/make-debug-print.diff openjdk-21-21.0.9+10/debian/patches/make-debug-print.diff --- openjdk-21-21.0.8+9/debian/patches/make-debug-print.diff 2024-03-20 23:08:28.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/patches/make-debug-print.diff 2025-08-29 11:06:43.000000000 +0000 @@ -1,6 +1,6 @@ --- a/make/Main.gmk +++ b/make/Main.gmk -@@ -1285,6 +1285,7 @@ +@@ -1277,6 +1277,7 @@ ALL_TARGETS += default jdk images docs b # Aliases used for running tests. diff -Nru openjdk-21-21.0.8+9/debian/patches/multiple-pkcs11-library-init.diff openjdk-21-21.0.9+10/debian/patches/multiple-pkcs11-library-init.diff --- openjdk-21-21.0.8+9/debian/patches/multiple-pkcs11-library-init.diff 2024-03-20 23:08:28.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/patches/multiple-pkcs11-library-init.diff 2025-08-29 11:06:30.000000000 +0000 @@ -7,7 +7,7 @@ --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java -@@ -52,6 +52,7 @@ +@@ -52,6 +52,7 @@ final class Config { static final int ERR_HALT = 1; static final int ERR_IGNORE_ALL = 2; static final int ERR_IGNORE_LIB = 3; @@ -15,7 +15,7 @@ // same as allowSingleThreadedModules but controlled via a system property // and applied to all providers. if set to false, no SunPKCS11 instances -@@ -1038,6 +1039,7 @@ +@@ -1047,6 +1048,7 @@ final class Config { case "ignoreAll" -> ERR_IGNORE_ALL; case "ignoreMissingLibrary" -> ERR_IGNORE_LIB; case "halt" -> ERR_HALT; @@ -25,7 +25,7 @@ if (DEBUG) { --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java -@@ -184,26 +184,37 @@ +@@ -184,26 +184,37 @@ public final class SunPKCS11 extends Aut String nssLibraryDirectory = config.getNssLibraryDirectory(); String nssSecmodDirectory = config.getNssSecmodDirectory(); boolean nssOptimizeSpace = config.getNssOptimizeSpace(); diff -Nru openjdk-21-21.0.8+9/debian/patches/series openjdk-21-21.0.9+10/debian/patches/series --- openjdk-21-21.0.8+9/debian/patches/series 2025-07-17 12:32:18.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/patches/series 2025-10-09 08:04:05.000000000 +0000 @@ -35,7 +35,6 @@ test-use-ip-address.patch arch-add-ports.diff compile-preview.diff -jdk-8307977-proposed.patch warn-fontmanager.patch jdk-8318418.patch jdk-8295795.patch @@ -49,3 +48,4 @@ zero-alpha-workaround.diff #jdk-8347014-proposed.patch jdk-8359735.patch +jdk-8369450-proposed.patch diff -Nru openjdk-21-21.0.8+9/debian/patches/zero-alpha-workaround.diff openjdk-21-21.0.9+10/debian/patches/zero-alpha-workaround.diff --- openjdk-21-21.0.8+9/debian/patches/zero-alpha-workaround.diff 2025-07-17 14:12:13.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/patches/zero-alpha-workaround.diff 2025-08-29 11:07:07.000000000 +0000 @@ -1,6 +1,6 @@ --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp -@@ -2985,6 +2985,10 @@ +@@ -2878,6 +2878,10 @@ void os::pd_commit_memory_or_exit(char* // Note that the value for MAP_FIXED_NOREPLACE differs between architectures, but all architectures // supported by OpenJDK share the same flag value. #define MAP_FIXED_NOREPLACE_value 0x100000 diff -Nru openjdk-21-21.0.8+9/debian/rules openjdk-21-21.0.9+10/debian/rules --- openjdk-21-21.0.8+9/debian/rules 2025-07-17 14:12:28.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/rules 2025-10-21 21:41:36.000000000 +0000 @@ -277,10 +277,14 @@ export CC = $(DEB_HOST_GNU_TYPE)-gcc-13 export CXX = $(DEB_HOST_GNU_TYPE)-g++-13 bd_gcc = g++-13 , -else +else ifneq (,$(filter $(distrel),trixie oracular plucky)) export CC = $(DEB_HOST_GNU_TYPE)-gcc-14 export CXX = $(DEB_HOST_GNU_TYPE)-g++-14 bd_gcc = g++-14 , +else + export CC = $(DEB_HOST_GNU_TYPE)-gcc-15 + export CXX = $(DEB_HOST_GNU_TYPE)-g++-15 + bd_gcc = g++-15 , endif # GCC 11 only @@ -1004,6 +1008,7 @@ -e 's/@jtreg_dep@/$(jtreg_dep)/g' \ -e 's/@testng_dep@/$(testng_dep)/g' \ -e 's/@basename@/$(basename)/g' \ + -e 's/@jtreg_archs@/$(jtreg_archs)/g' \ $< > $@; debian/tests/%.sh: debian/tests/%.in debian/rules @@ -1356,7 +1361,7 @@ lib_ext_dirs := $(filter-out arm hppa, $(lib_ext_dirs)) endif -install: packaging-files +install: packaging-files build dh_testdir dh_testroot dh_prep || dh_clean -k @@ -2035,7 +2040,7 @@ dh_builddeb -a $(nodemo) $(nojrez) #$(bd_options) git_project = jdk21u -git_tag = jdk-21.0.8+9 +git_tag = jdk-21.0.9+10 package_version = $(shell echo $(PKGVERSION) | sed 's/-[^-][^-]*$$//') ifneq ($(is_upstream_release),yes) package_version := $(subst +,~,$(package_version)) diff -Nru openjdk-21-21.0.8+9/debian/tests/control openjdk-21-21.0.9+10/debian/tests/control --- openjdk-21-21.0.8+9/debian/tests/control 2025-07-17 14:12:13.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/tests/control 2025-10-21 22:12:00.000000000 +0000 @@ -9,10 +9,12 @@ Tests: hotspot-autopkgtest.sh Depends: @, jtreg7 (>= 7.3.1+1~), libtestng7-java, build-essential, bash, lsb-release, xfwm4, xvfb, xauth, dbus-x11, libatk-wrapper-java, libatk-wrapper-java-jni Restrictions: allow-stderr, skippable, flaky, rw-build-tree +Architecture: amd64 i386 arm64 armhf ppc64 ppc64el riscv64 s390x alpha ia64 powerpc ppc64 sh4 x32 armel loong64 mipsel mips64el riscv64 Tests: jdk-autopkgtest.sh Depends: @, jtreg7 (>= 7.3.1+1~), libtestng7-java, build-essential, bash, lsb-release, xfwm4, xvfb, xauth, dbus-x11, libatk-wrapper-java, libatk-wrapper-java-jni Restrictions: allow-stderr, skippable, flaky, rw-build-tree +Architecture: amd64 i386 arm64 armhf ppc64 ppc64el riscv64 s390x alpha ia64 powerpc ppc64 sh4 x32 armel loong64 mipsel mips64el riscv64 Tests: dependencies.sh Depends: @, build-essential, bash diff -Nru openjdk-21-21.0.8+9/debian/tests/control.in openjdk-21-21.0.9+10/debian/tests/control.in --- openjdk-21-21.0.8+9/debian/tests/control.in 2025-07-17 14:12:13.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/tests/control.in 2025-10-17 07:19:14.000000000 +0000 @@ -9,10 +9,12 @@ Tests: hotspot-autopkgtest.sh Depends: @, @jtreg_dep@, @testng_dep@, build-essential, bash, lsb-release, xfwm4, xvfb, xauth, dbus-x11, libatk-wrapper-java, libatk-wrapper-java-jni Restrictions: allow-stderr, skippable, flaky, rw-build-tree +Architecture: @jtreg_archs@ Tests: jdk-autopkgtest.sh Depends: @, @jtreg_dep@, @testng_dep@, build-essential, bash, lsb-release, xfwm4, xvfb, xauth, dbus-x11, libatk-wrapper-java, libatk-wrapper-java-jni Restrictions: allow-stderr, skippable, flaky, rw-build-tree +Architecture: @jtreg_archs@ Tests: dependencies.sh Depends: @, build-essential, bash diff -Nru openjdk-21-21.0.8+9/debian/tests/dependencies.sh openjdk-21-21.0.9+10/debian/tests/dependencies.sh --- openjdk-21-21.0.8+9/debian/tests/dependencies.sh 2025-07-17 14:12:13.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/tests/dependencies.sh 2025-10-07 08:00:01.000000000 +0000 @@ -27,7 +27,7 @@ ${jdk_path}/bin/java -Djava.security.debug=all \ -cp . ${AUTOPKGTEST_TMP}/Test.java > ${AUTOPKGTEST_TMP}/dependencies-pcsc.log 2>&1 -if grep "pcsc: Using PC/SC library" ${AUTOPKGTEST_TMP}/dependencies-pcsc.log; then +if grep "Using PC/SC library" ${AUTOPKGTEST_TMP}/dependencies-pcsc.log; then echo "Test passed." else cat ${AUTOPKGTEST_TMP}/dependencies-pcsc.log diff -Nru openjdk-21-21.0.8+9/debian/tests/hotspot-autopkgtest.in openjdk-21-21.0.9+10/debian/tests/hotspot-autopkgtest.in --- openjdk-21-21.0.8+9/debian/tests/hotspot-autopkgtest.in 2025-07-17 14:12:13.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/tests/hotspot-autopkgtest.in 2025-10-17 07:19:14.000000000 +0000 @@ -22,6 +22,7 @@ problem_list=${AUTOPKGTEST_TMP}/problems.txt debian/tests/write-problems.sh ${problem_list} ${HOTSPOT_JTREG_PATH}/ProblemList.txt hotspot +cat debian/tests/skip-large-autopkgtest.txt >> ${problem_list} ARGS="$*" JT_DEFAULT_ARGS="-exclude:${problem_list} -k:!stress :tier1" diff -Nru openjdk-21-21.0.8+9/debian/tests/hotspot-autopkgtest.sh openjdk-21-21.0.9+10/debian/tests/hotspot-autopkgtest.sh --- openjdk-21-21.0.8+9/debian/tests/hotspot-autopkgtest.sh 2025-07-17 14:12:13.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/tests/hotspot-autopkgtest.sh 2025-10-17 07:19:14.000000000 +0000 @@ -22,6 +22,7 @@ problem_list=${AUTOPKGTEST_TMP}/problems.txt debian/tests/write-problems.sh ${problem_list} ${HOTSPOT_JTREG_PATH}/ProblemList.txt hotspot +cat debian/tests/skip-large-autopkgtest.txt >> ${problem_list} ARGS="$*" JT_DEFAULT_ARGS="-exclude:${problem_list} -k:!stress :tier1" diff -Nru openjdk-21-21.0.8+9/debian/tests/jdk-autopkgtest.in openjdk-21-21.0.9+10/debian/tests/jdk-autopkgtest.in --- openjdk-21-21.0.8+9/debian/tests/jdk-autopkgtest.in 2025-07-17 14:12:13.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/tests/jdk-autopkgtest.in 2025-10-17 07:19:14.000000000 +0000 @@ -43,6 +43,7 @@ problem_list=${AUTOPKGTEST_TMP}/problems.txt debian/tests/write-problems.sh ${problem_list} ${JDK_JTREG_PATH}/ProblemList.txt jdk +cat debian/tests/skip-large-autopkgtest.txt >> ${problem_list} ARGS="$*" JT_DEFAULT_ARGS="-exclude:${problem_list} -k:!stress :tier1" diff -Nru openjdk-21-21.0.8+9/debian/tests/jdk-autopkgtest.sh openjdk-21-21.0.9+10/debian/tests/jdk-autopkgtest.sh --- openjdk-21-21.0.8+9/debian/tests/jdk-autopkgtest.sh 2025-07-17 14:12:13.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/tests/jdk-autopkgtest.sh 2025-10-17 07:19:14.000000000 +0000 @@ -43,6 +43,7 @@ problem_list=${AUTOPKGTEST_TMP}/problems.txt debian/tests/write-problems.sh ${problem_list} ${JDK_JTREG_PATH}/ProblemList.txt jdk +cat debian/tests/skip-large-autopkgtest.txt >> ${problem_list} ARGS="$*" JT_DEFAULT_ARGS="-exclude:${problem_list} -k:!stress :tier1" diff -Nru openjdk-21-21.0.8+9/debian/tests/problems.csv openjdk-21-21.0.9+10/debian/tests/problems.csv --- openjdk-21-21.0.8+9/debian/tests/problems.csv 2025-07-17 14:12:13.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/tests/problems.csv 2025-09-27 11:56:27.000000000 +0000 @@ -1,7 +1,7 @@ Test,Bug,Comment,Packages,Arch,Release -Error: runtime/Unsafe/InternalErrorTest.java,JDK-8335238,"To investigate, not critical for security release – JDK-22 will expire before OO release",:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,i386,:release-all +Error: runtime/Unsafe/InternalErrorTest.java,JDK-8335238,"To investigate, not critical for security release – JDK-22 will expire before OO release",:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,i386,:release-all Error: serviceability/jvmti/vthread/SuspendResume1/SuspendResume1.java#default,,"Deadlock, new failure, not critical – JDK-22 will expire before OO release",:openjdk-22,ppc64el,:release-all -FAILED: compiler/arguments/CheckCICompilerCount.java,,"Existing failure (exit code 0, expected 1)",:openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,i386,:release-all +FAILED: compiler/arguments/CheckCICompilerCount.java,,"Existing failure (exit code 0, expected 1)",:openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,i386,:release-all FAILED: compiler/codecache/MHIntrinsicAllocFailureTest.java,JDK-8298947,The issue only happens on armhf platform. ,:openjdk-17:openjdk-21,armhf,:release-all FAILED: gtest/GTestWrapper.java,,"17:UninitializedDoubleElementWorkerDataArrayTest.print_summary_on_test_vm, ",:openjdk-17:openjdk-21,i386,:release-all FAILED: java/foreign/critical/TestCritical.java,,"SEGSEGV in test, submit bug, not critical for security release",:openjdk-22,s390x,:release-all @@ -12,38 +12,38 @@ FAILED: java/foreign/TestSegments.java,,Ignore test failure in the preview api,:openjdk-21,:i386,:release-all FAILED: java/foreign/TestUpcallHighArity.java,,Ignore test failure in the preview api,:openjdk-21,:i386,:release-all FAILED: java/foreign/TestUpcallStructScope.java,,Ignore test failure in the preview api,:openjdk-21,:i386,:release-all -FAILED: java/io/File/createTempFile/TargetDirectory.java,JDK-8166162,Container issue,:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all +FAILED: java/io/File/createTempFile/TargetDirectory.java,JDK-8166162,Container issue,:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all FAILED: java/io/File/GetXSpace.java,,"Container issue, disk space size exceeds 32 bit integer",:openjdk-17:openjdk-21:openjdk-22,:i386:armhf,:release-all -FAILED: java/nio/channels/FileChannel/directio/DirectIOTest.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/channels/FileChannel/directio/PreadDirect.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/channels/FileChannel/directio/PwriteDirect.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/channels/FileChannel/directio/ReadDirect.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/channels/FileChannel/directio/WriteDirect.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/attribute/AclFileAttributeView/Basic.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all +FAILED: java/nio/channels/FileChannel/directio/DirectIOTest.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/channels/FileChannel/directio/PreadDirect.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/channels/FileChannel/directio/PwriteDirect.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/channels/FileChannel/directio/ReadDirect.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/channels/FileChannel/directio/WriteDirect.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/attribute/AclFileAttributeView/Basic.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all FAILED: java/nio/file/attribute/BasicFileAttributeView/CreationTime.java,JDK-8166162,Container issue,:openjdk-22,i386,:release-all -FAILED: java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/attribute/DosFileAttributeView/Basic.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/attribute/PosixFileAttributeView/Basic.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/Files/CheckPermissions.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/Files/CopyAndMove.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/Files/CopyMoveVariations.java,JDK-8166162,Container issue,:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/Files/FileAttributes.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/Files/InterruptCopy.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/Files/Misc.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/Files/TemporaryFiles.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/FileStore/Basic.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: com/sun/net/httpserver/simpleserver/RootDirPermissionsTest.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all +FAILED: java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/attribute/DosFileAttributeView/Basic.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/attribute/PosixFileAttributeView/Basic.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/Files/CheckPermissions.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/Files/CopyAndMove.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/Files/CopyMoveVariations.java,JDK-8166162,Container issue,:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/Files/FileAttributes.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/Files/InterruptCopy.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/Files/Misc.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/Files/TemporaryFiles.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/FileStore/Basic.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: com/sun/net/httpserver/simpleserver/DocRootDirPermissionsTest.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all FAILED: runtime/cds/appcds/jcmd/JCmdTestDynamicDump.java,,flaky test (?) existing comment,:openjdk-17,:arch-all,:release-all FAILED: runtime/cds/appcds/jcmd/JCmdTestFileSafety.java,,flaky test (?) existing comment,:openjdk-17,i386:arm64:amd64:ppc64el,:release-all FAILED: runtime/cds/appcds/jcmd/JCmdTestStaticDump.java,,flaky test (?) existing comment,:openjdk-17,:arch-all,:release-all FAILED: runtime/ErrorHandling/MachCodeFramesInErrorFile.java,,java.lang.InternalError: a fault occurred in a recent unsafe memory access operation in compiled Java code at java.base/java.lang.Long.toHexString(Long.java:309) at,:openjdk-17:openjdk-21,armhf,:release-all FAILED: runtime/jni/nativeStack/TestNativeStack.java,JDK-8312016,"Backport fix (do not add patch, the fix just disables the test)",:openjdk-lts:openjdk-11:openjdk-17,armhf,:release-all -FAILED: runtime/LoadClass/LongBCP.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11:openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all +FAILED: runtime/LoadClass/LongBCP.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11:openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all FAILED: runtime/Monitor/ConcurrentDeflation.java,,LockingMode == 0 (LM_MONITOR) is not fully implemented on this architectureError: Could not create the Java Virtual Machine.,:openjdk-21,armhf,:release-all -FAILED: runtime/NMT/VirtualAllocCommitMerge.java,JDK-8309698,P4 bug (existing issue),:openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,s390x,:release-all +FAILED: runtime/NMT/VirtualAllocCommitMerge.java,JDK-8309698,P4 bug (existing issue),:openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,s390x,:release-all FAILED: serviceability/AsyncGetCallTrace/MyPackage/ASGCTBaseTest.java,JDK-8303168,Existing bug,:openjdk-21,armhf,:release-all -FAILED: tools/jlink/JLinkTest.java,JDK-8240349,Bugfix failed for i386 (P4 bug),:openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,i386,:release-all +FAILED: tools/jlink/JLinkTest.java,JDK-8240349,Bugfix failed for i386 (P4 bug),:openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,i386,:release-all FAILED: jdk/javadoc/doclet/dupThrowsTags/TestDupThrowsTags.java,,tests failing due to disable-doclint-by-default.diff (reproducible build maintainer patch),:openjdk-lts:openjdk-11,:arch-all,:release-all FAILED: jdk/javadoc/doclet/T6735320/T6735320.java,,tests failing due to disable-doclint-by-default.diff (reproducible build maintainer patch),:openjdk-lts:openjdk-11,:arch-all,:release-all FAILED: jdk/javadoc/doclet/testBadHtml/TestBadHtml.java,,tests failing due to disable-doclint-by-default.diff (reproducible build maintainer patch),:openjdk-lts:openjdk-11,:arch-all,:release-all @@ -84,6 +84,6 @@ FAILED: java/foreign/TestUpcallStack.java,, asserts due to the invalid structure size. Ignore as this is a preview API and the issue does not occur in openjdk-22. I will add it to the problemlist.,:openjdk-21,:armhf,:release-all FAILED: java/foreign/TestVarArgs.java,, asserts due to the invalid structure size. Ignore as this is a preview API and the issue does not occur in openjdk-22. I will add it to the problemlist.,:openjdk-21,:armhf,:release-all FAILED: runtime/os/TestTrimNative.java#trimNative,, java.lang.RuntimeException: We found fewer (periodic) trim lines in UL log than expected (expected at least 13 found 11). This looks like a flaky test - it asserts number of lines from the periodic trimmer e.g. src/hotspot/share/runtime/trimNativeHeap.hpp:56 which causes the test to fail due to the slow VM. Test passes locally.,:openjdk-21,:armhf,:release-all -FAILED: sun/security/util/Debug/DebugOptions.java,JDK-8339713,Stack overflow error on 32-bit platforms,:openjdk-17:openjdk-21:openjdk-23:openjdk-24:openjdk-25:,:armhf:i386:s390x,:release-all -Error: jdk/jshell/TerminalNoExecTest.java,,BackingStoreException: Couldn't get file lock - possibly because the LP (non-root) container has no home directory,:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: applications/ctw/modules/jdk_jfr.java,JDK-8352567, Unimplemented SharedRuntime::generate_jfr_write_checkpoint for S390x, :openjdk-25:,:s390x,:release-all +FAILED: sun/security/util/Debug/DebugOptions.java,JDK-8339713,Stack overflow error on 32-bit platforms,:openjdk-17:openjdk-21:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:armhf:i386:s390x,:release-all +Error: jdk/jshell/TerminalNoExecTest.java,,BackingStoreException: Couldn't get file lock - possibly because the LP (non-root) container has no home directory,:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: applications/ctw/modules/jdk_jfr.java,JDK-8352567, Unimplemented SharedRuntime::generate_jfr_write_checkpoint for S390x, :openjdk-25:openjdk-26:,:s390x,:release-all diff -Nru openjdk-21-21.0.8+9/debian/tests/skip-large-autopkgtest.txt openjdk-21-21.0.9+10/debian/tests/skip-large-autopkgtest.txt --- openjdk-21-21.0.8+9/debian/tests/skip-large-autopkgtest.txt 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/debian/tests/skip-large-autopkgtest.txt 2025-10-17 07:19:14.000000000 +0000 @@ -0,0 +1,7 @@ +# The list of tier1 tests that require large amount of memory >=2G + +runtime/cds/NonJVMVariantLocation.java 0000000 generic-all +runtime/jni/checked/TestLargeUTF8Length.java 0000000 generic-all +java/foreign/TestLargeSegmentCopy.java 0000000 generic-all +java/foreign/TestStringEncodingJumbo.java 0000000 generic-all +java/util/HashMap/WhiteBoxResizeTest.java 0000000 generic-all diff -Nru openjdk-21-21.0.8+9/doc/building.html openjdk-21-21.0.9+10/doc/building.html --- openjdk-21-21.0.8+9/doc/building.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/doc/building.html 2025-10-13 07:49:24.000000000 +0000 @@ -1112,13 +1112,13 @@ Test framework. The top directory, which contains both googletest and googlemock directories, should be specified via --with-gtest. The minimum supported -version of Google Test is 1.13.0, whose source code can be obtained:

+version of Google Test is 1.14.0, whose source code can be obtained:

  • by downloading and unpacking the source bundle from here
  • -
  • or by checking out v1.13.0 tag of +href="https://github.com/google/googletest/releases/tag/v1.14.0">here
  • +
  • or by checking out v1.14.0 tag of googletest project: -git clone -b v1.13.0 https://github.com/google/googletest
  • +git clone -b v1.14.0 https://github.com/google/googletest

To execute the most basic tests (tier 1), use:

make run-test-tier1
diff -Nru openjdk-21-21.0.8+9/doc/building.md openjdk-21-21.0.9+10/doc/building.md --- openjdk-21-21.0.8+9/doc/building.md 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/doc/building.md 2025-10-13 07:49:24.000000000 +0000 @@ -881,11 +881,11 @@ Building of Hotspot Gtest suite requires the source code of Google Test framework. The top directory, which contains both `googletest` and `googlemock` directories, should be specified via `--with-gtest`. -The minimum supported version of Google Test is 1.13.0, whose source +The minimum supported version of Google Test is 1.14.0, whose source code can be obtained: - * by downloading and unpacking the source bundle from [here](https://github.com/google/googletest/releases/tag/v1.13.0) - * or by checking out `v1.13.0` tag of `googletest` project: `git clone -b v1.13.0 https://github.com/google/googletest` + * by downloading and unpacking the source bundle from [here](https://github.com/google/googletest/releases/tag/v1.14.0) + * or by checking out `v1.14.0` tag of `googletest` project: `git clone -b v1.14.0 https://github.com/google/googletest` To execute the most basic tests (tier 1), use: ``` diff -Nru openjdk-21-21.0.8+9/make/Global.gmk openjdk-21-21.0.9+10/make/Global.gmk --- openjdk-21-21.0.8+9/make/Global.gmk 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/make/Global.gmk 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,6 @@ $(info $(_) make docs # Create all docs) $(info $(_) make docs-jdk-api # Create just JDK javadocs) $(info $(_) make bootcycle-images # Build images twice, second time with newly built JDK) - $(info $(_) make install # Install the generated images locally) $(info $(_) make check # Run basic testing (currently tier1)) $(info $(_) make test- # Run test, e.g. test-tier1) $(info $(_) make test TEST= # Run test(s) given by TEST specification) diff -Nru openjdk-21-21.0.8+9/make/Install.gmk openjdk-21-21.0.9+10/make/Install.gmk --- openjdk-21-21.0.8+9/make/Install.gmk 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/make/Install.gmk 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -# -# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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. -# - -default: install - -include $(SPEC) - -BINARIES := $(notdir $(wildcard $(JDK_IMAGE_DIR)/bin/*)) -INSTALLDIR := openjdk-$(VERSION_SHORT) - -# Install the jdk image, in a very crude way. Not taking into -# account, how to install properly on macosx or windows etc. -install: - echo Installing jdk image into $(INSTALL_PREFIX)/jvm/$(INSTALLDIR) - echo and creating $(words $(BINARIES)) links from $(INSTALL_PREFIX)/bin into the jdk. - $(MKDIR) -p $(INSTALL_PREFIX)/jvm/$(INSTALLDIR) - $(RM) -r $(INSTALL_PREFIX)/jvm/$(INSTALLDIR)/* - $(CP) -rp $(JDK_IMAGE_DIR)/* $(INSTALL_PREFIX)/jvm/$(INSTALLDIR) - $(MKDIR) -p $(INSTALL_PREFIX)/bin - $(RM) $(addprefix $(INSTALL_PREFIX)/bin/, $(BINARIES)) - $(foreach b, $(BINARIES), $(LN) -s $(INSTALL_PREFIX)/jvm/$(INSTALLDIR)/bin/$b $(INSTALL_PREFIX)/bin/$b &&) true diff -Nru openjdk-21-21.0.8+9/make/Main.gmk openjdk-21-21.0.9+10/make/Main.gmk --- openjdk-21-21.0.8+9/make/Main.gmk 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/make/Main.gmk 2025-10-13 07:49:24.000000000 +0000 @@ -845,14 +845,6 @@ endif ################################################################################ -# Install targets - -$(eval $(call SetupTarget, install, \ - MAKEFILE := Install, \ - DEPS := product-images, \ -)) - -################################################################################ # # Dependency declarations between targets. # diff -Nru openjdk-21-21.0.8+9/make/RunTestsPrebuilt.gmk openjdk-21-21.0.9+10/make/RunTestsPrebuilt.gmk --- openjdk-21-21.0.8+9/make/RunTestsPrebuilt.gmk 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/make/RunTestsPrebuilt.gmk 2025-10-13 07:49:24.000000000 +0000 @@ -216,9 +216,9 @@ else ifeq ($(OPENJDK_TARGET_OS), windows) NUM_CORES := $(NUMBER_OF_PROCESSORS) MEMORY_SIZE := $(shell \ - $(EXPR) `wmic computersystem get totalphysicalmemory -value \ - | $(GREP) = | $(SED) 's/\\r//g' \ - | $(CUT) -d "=" -f 2-` / 1024 / 1024 \ + $(EXPR) `powershell -Command \ + "(Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory" \ + | $(SED) 's/\\r//g' ` / 1024 / 1024 \ ) endif ifeq ($(NUM_CORES), ) diff -Nru openjdk-21-21.0.8+9/make/autoconf/build-performance.m4 openjdk-21-21.0.9+10/make/autoconf/build-performance.m4 --- openjdk-21-21.0.8+9/make/autoconf/build-performance.m4 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/make/autoconf/build-performance.m4 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -75,7 +75,8 @@ FOUND_MEM=yes elif test "x$OPENJDK_BUILD_OS" = xwindows; then # Windows, but without cygwin - MEMORY_SIZE=`wmic computersystem get totalphysicalmemory -value | grep = | cut -d "=" -f 2-` + MEMORY_SIZE=`powershell -Command \ + "(Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory" | $SED 's/\\r//g' ` MEMORY_SIZE=`expr $MEMORY_SIZE / 1024 / 1024` FOUND_MEM=yes fi diff -Nru openjdk-21-21.0.8+9/make/autoconf/flags-cflags.m4 openjdk-21-21.0.9+10/make/autoconf/flags-cflags.m4 --- openjdk-21-21.0.8+9/make/autoconf/flags-cflags.m4 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/make/autoconf/flags-cflags.m4 2025-10-13 07:49:24.000000000 +0000 @@ -387,7 +387,7 @@ C_O_FLAG_DEBUG="-Od" C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="-Od" - C_O_FLAG_SIZE="-Os" + C_O_FLAG_SIZE="-O1" fi # Now copy to C++ flags diff -Nru openjdk-21-21.0.8+9/make/autoconf/lib-tests.m4 openjdk-21-21.0.9+10/make/autoconf/lib-tests.m4 --- openjdk-21-21.0.8+9/make/autoconf/lib-tests.m4 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/make/autoconf/lib-tests.m4 2025-10-13 07:49:24.000000000 +0000 @@ -29,7 +29,7 @@ # Minimum supported versions JTREG_MINIMUM_VERSION=7.3.1 -GTEST_MINIMUM_VERSION=1.13.0 +GTEST_MINIMUM_VERSION=1.14.0 ############################################################################### # diff -Nru openjdk-21-21.0.8+9/make/autoconf/spec.gmk.in openjdk-21-21.0.9+10/make/autoconf/spec.gmk.in --- openjdk-21-21.0.8+9/make/autoconf/spec.gmk.in 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/make/autoconf/spec.gmk.in 2025-10-13 07:49:24.000000000 +0000 @@ -819,57 +819,6 @@ #################################################### # -# INSTALLATION -# - -# Common prefix for all installed files. Defaults to /usr/local, -# but /opt/myjdk is another common version. -INSTALL_PREFIX=@prefix@ - -# Directories containing architecture-dependent files should be relative to exec_prefix -INSTALL_EXECPREFIX=@exec_prefix@ - -# java,javac,javap etc are installed here. -INSTALL_BINDIR=@bindir@ - -# Read only architecture-independent data -INSTALL_DATADIR=@datadir@ - -# Root of above. -INSTALL_DATAROOTDIR=@datarootdir@ - -# Doc files, other than info and man. -INSTALL_DOCDIR=@docdir@ - -# Html documentation -INSTALL_HTMLDIR=@htmldir@ - -# Installing C header files, JNI headers for example. -INSTALL_INCLUDEDIR=@includedir@ - -# Installing library files.... -INSTALL_INCLUDEDIR=@libdir@ - -# Executables that other programs run. -INSTALL_LIBEXECDIR=@libexecdir@ - -# Locale-dependent but architecture-independent data, such as message catalogs. -INSTALL_LOCALEDIR=@localedir@ - -# Modifiable single-machine data -INSTALL_LOCALSTATEDIR=@localstatedir@ - -# Man pages -INSTALL_MANDIR=@mandir@ - -# Modifiable architecture-independent data. -INSTALL_SHAREDSTATEDIR=@sharedstatedir@ - -# Read-only single-machine data -INSTALL_SYSCONFDIR=@sysconfdir@ - -#################################################### -# # Libraries # diff -Nru openjdk-21-21.0.8+9/make/conf/github-actions.conf openjdk-21-21.0.9+10/make/conf/github-actions.conf --- openjdk-21-21.0.8+9/make/conf/github-actions.conf 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/make/conf/github-actions.conf 2025-10-13 07:49:24.000000000 +0000 @@ -25,7 +25,7 @@ # Versions and download locations for dependencies used by GitHub Actions (GHA) -GTEST_VERSION=1.13.0 +GTEST_VERSION=1.14.0 JTREG_VERSION=7.3.1+1 LINUX_X64_BOOT_JDK_EXT=tar.gz diff -Nru openjdk-21-21.0.8+9/make/conf/jib-profiles.js openjdk-21-21.0.9+10/make/conf/jib-profiles.js --- openjdk-21-21.0.8+9/make/conf/jib-profiles.js 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/make/conf/jib-profiles.js 2025-10-13 07:49:24.000000000 +0000 @@ -1267,7 +1267,7 @@ gtest: { organization: common.organization, ext: "tar.gz", - revision: "1.13.0+1.0" + revision: "1.14.0+1.0" }, libffi: { diff -Nru openjdk-21-21.0.8+9/make/conf/version-numbers.conf openjdk-21-21.0.9+10/make/conf/version-numbers.conf --- openjdk-21-21.0.8+9/make/conf/version-numbers.conf 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/make/conf/version-numbers.conf 2025-10-13 07:49:24.000000000 +0000 @@ -28,12 +28,12 @@ DEFAULT_VERSION_FEATURE=21 DEFAULT_VERSION_INTERIM=0 -DEFAULT_VERSION_UPDATE=8 +DEFAULT_VERSION_UPDATE=9 DEFAULT_VERSION_PATCH=0 DEFAULT_VERSION_EXTRA1=0 DEFAULT_VERSION_EXTRA2=0 DEFAULT_VERSION_EXTRA3=0 -DEFAULT_VERSION_DATE=2025-07-15 +DEFAULT_VERSION_DATE=2025-10-21 DEFAULT_VERSION_CLASSFILE_MAJOR=65 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" DEFAULT_VERSION_CLASSFILE_MINOR=0 DEFAULT_VERSION_DOCS_API_SINCE=11 diff -Nru openjdk-21-21.0.8+9/make/data/hotspot-symbols/symbols-linux openjdk-21-21.0.9+10/make/data/hotspot-symbols/symbols-linux --- openjdk-21-21.0.8+9/make/data/hotspot-symbols/symbols-linux 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/make/data/hotspot-symbols/symbols-linux 2025-10-13 07:49:24.000000000 +0000 @@ -22,6 +22,7 @@ # JVM_handle_linux_signal +JVM_IsContainerized JVM_IsUseContainerSupport numa_error numa_warn diff -Nru openjdk-21-21.0.8+9/make/modules/java.desktop/lib/Awt2dLibraries.gmk openjdk-21-21.0.9+10/make/modules/java.desktop/lib/Awt2dLibraries.gmk --- openjdk-21-21.0.8+9/make/modules/java.desktop/lib/Awt2dLibraries.gmk 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/make/modules/java.desktop/lib/Awt2dLibraries.gmk 2025-10-13 07:49:24.000000000 +0000 @@ -202,8 +202,12 @@ common/awt/systemscale \ common/font \ common/java2d/opengl \ - common/java2d/x11 \ - $(LIBPIPEWIRE_HEADER_DIRS) + common/java2d/x11 + + # exclude pipewire from the AIX build, no Wayland support + ifeq ($(call isTargetOs, aix), false) + LIBAWT_XAWT_EXTRA_HEADER_DIRS += $(LIBPIPEWIRE_HEADER_DIRS) + endif LIBAWT_XAWT_CFLAGS += -DXAWT -DXAWT_HACK \ $(FONTCONFIG_CFLAGS) \ @@ -785,7 +789,7 @@ EXCLUDE_SRC_PATTERNS := $(LIBSPLASHSCREEN_EXCLUDE_SRC_PATTERNS), \ EXCLUDE_FILES := imageioJPEG.c jpegdecoder.c pngtest.c, \ EXCLUDES := $(LIBSPLASHSCREEN_EXCLUDES), \ - OPTIMIZATION := LOW, \ + OPTIMIZATION := SIZE, \ CFLAGS := $(CFLAGS_JDKLIB) $(LIBSPLASHSCREEN_CFLAGS) \ $(GIFLIB_CFLAGS) $(LIBJPEG_CFLAGS) $(PNG_CFLAGS) $(LIBZ_CFLAGS), \ EXTRA_HEADER_DIRS := $(LIBSPLASHSCREEN_HEADER_DIRS), \ diff -Nru openjdk-21-21.0.8+9/make/modules/jdk.internal.le/Lib.gmk openjdk-21-21.0.9+10/make/modules/jdk.internal.le/Lib.gmk --- openjdk-21-21.0.8+9/make/modules/jdk.internal.le/Lib.gmk 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/make/modules/jdk.internal.le/Lib.gmk 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,8 @@ TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ OPTIMIZATION := LOW, \ CFLAGS := $(CXXFLAGS_JDKLIB), \ - LDFLAGS := $(LDFLAGS_JDKLIB), \ + LDFLAGS := $(LDFLAGS_JDKLIB) \ + $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS_unix := $(JDKLIB_LIBS) $(LIBCXX), \ LIBS_windows := $(JDKLIB_LIBS) user32.lib, \ )) diff -Nru openjdk-21-21.0.8+9/make/test/BuildTestLib.gmk openjdk-21-21.0.9+10/make/test/BuildTestLib.gmk --- openjdk-21-21.0.8+9/make/test/BuildTestLib.gmk 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/make/test/BuildTestLib.gmk 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,6 @@ SRC := $(TEST_LIB_SOURCE_DIR)/jdk/test/whitebox/, \ BIN := $(TEST_LIB_SUPPORT)/wb_classes, \ JAR := $(TEST_LIB_SUPPORT)/wb.jar, \ - DISABLED_WARNINGS := deprecation removal preview, \ JAVAC_FLAGS := --enable-preview, \ )) diff -Nru openjdk-21-21.0.8+9/src/hotspot/cpu/aarch64/assembler_aarch64.cpp openjdk-21-21.0.9+10/src/hotspot/cpu/aarch64/assembler_aarch64.cpp --- openjdk-21-21.0.8+9/src/hotspot/cpu/aarch64/assembler_aarch64.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/cpu/aarch64/assembler_aarch64.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -461,7 +461,7 @@ bool asm_util::operand_valid_for_immediate_bits(int64_t imm, unsigned nbits) { guarantee(nbits == 8 || nbits == 12, "invalid nbits value"); - uint64_t uimm = (uint64_t)uabs((jlong)imm); + uint64_t uimm = (uint64_t)g_uabs((jlong)imm); if (uimm < (UCONST64(1) << nbits)) return true; if (uimm < (UCONST64(1) << (2 * nbits)) diff -Nru openjdk-21-21.0.8+9/src/hotspot/cpu/aarch64/assembler_aarch64.hpp openjdk-21-21.0.9+10/src/hotspot/cpu/aarch64/assembler_aarch64.hpp --- openjdk-21-21.0.8+9/src/hotspot/cpu/aarch64/assembler_aarch64.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/cpu/aarch64/assembler_aarch64.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -930,7 +930,7 @@ static const uint64_t branch_range = NOT_DEBUG(128 * M) DEBUG_ONLY(2 * M); static bool reachable_from_branch_at(address branch, address target) { - return uabs(target - branch) < branch_range; + return g_uabs(target - branch) < branch_range; } // Unconditional branch (immediate) diff -Nru openjdk-21-21.0.8+9/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp openjdk-21-21.0.9+10/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp --- openjdk-21-21.0.8+9/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -2894,7 +2894,7 @@ if (fits) { (this->*insn1)(Rd, Rn, imm); } else { - if (uabs(imm) < (1 << 24)) { + if (g_uabs(imm) < (1 << 24)) { (this->*insn1)(Rd, Rn, imm & -(1 << 12)); (this->*insn1)(Rd, Rd, imm & ((1 << 12)-1)); } else { diff -Nru openjdk-21-21.0.8+9/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp openjdk-21-21.0.9+10/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp --- openjdk-21-21.0.8+9/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -1130,7 +1130,7 @@ void copy_memory_small(DecoratorSet decorators, BasicType type, Register s, Register d, Register count, int step) { bool is_backwards = step < 0; - size_t granularity = uabs(step); + size_t granularity = g_uabs(step); int direction = is_backwards ? -1 : 1; Label Lword, Lint, Lshort, Lbyte; @@ -1189,7 +1189,7 @@ Register s, Register d, Register count, int step) { copy_direction direction = step < 0 ? copy_backwards : copy_forwards; bool is_backwards = step < 0; - unsigned int granularity = uabs(step); + unsigned int granularity = g_uabs(step); const Register t0 = r3, t1 = r4; // <= 80 (or 96 for SIMD) bytes do inline. Direction doesn't matter because we always diff -Nru openjdk-21-21.0.8+9/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp openjdk-21-21.0.9+10/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp --- openjdk-21-21.0.8+9/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -1135,6 +1135,7 @@ // Get the value we will store __ ldr(r0, at_tos()); // Now store using the appropriate barrier + // Clobbers: r10, r11, r3 do_oop_store(_masm, element_address, r0, IS_ARRAY); __ b(done); @@ -1143,6 +1144,7 @@ __ profile_null_seen(r2); // Store a null + // Clobbers: r10, r11, r3 do_oop_store(_masm, element_address, noreg, IS_ARRAY); // Pop stack arguments @@ -2774,6 +2776,7 @@ __ pop(atos); if (!is_static) pop_and_check_object(obj); // Store into the field + // Clobbers: r10, r11, r3 do_oop_store(_masm, field, r0, IN_HEAP); if (rc == may_rewrite) { patch_bytecode(Bytecodes::_fast_aputfield, bc, r1, true, byte_no); @@ -2973,8 +2976,8 @@ // Must prevent reordering of the following cp cache loads with bytecode load __ membar(MacroAssembler::LoadLoad); - // test for volatile with r3 - __ ldrw(r3, Address(r2, in_bytes(base + + // test for volatile with r5 + __ ldrw(r5, Address(r2, in_bytes(base + ConstantPoolCacheEntry::flags_offset()))); // replace index with field offset from cache entry @@ -2982,7 +2985,7 @@ { Label notVolatile; - __ tbz(r3, ConstantPoolCacheEntry::is_volatile_shift, notVolatile); + __ tbz(r5, ConstantPoolCacheEntry::is_volatile_shift, notVolatile); __ membar(MacroAssembler::StoreStore | MacroAssembler::LoadStore); __ bind(notVolatile); } @@ -2998,6 +3001,7 @@ // access field switch (bytecode()) { case Bytecodes::_fast_aputfield: + // Clobbers: r10, r11, r3 do_oop_store(_masm, field, r0, IN_HEAP); break; case Bytecodes::_fast_lputfield: @@ -3030,7 +3034,7 @@ { Label notVolatile; - __ tbz(r3, ConstantPoolCacheEntry::is_volatile_shift, notVolatile); + __ tbz(r5, ConstantPoolCacheEntry::is_volatile_shift, notVolatile); __ membar(MacroAssembler::StoreLoad | MacroAssembler::StoreStore); __ bind(notVolatile); } diff -Nru openjdk-21-21.0.8+9/src/hotspot/cpu/ppc/frame_ppc.cpp openjdk-21-21.0.9+10/src/hotspot/cpu/ppc/frame_ppc.cpp --- openjdk-21-21.0.8+9/src/hotspot/cpu/ppc/frame_ppc.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/cpu/ppc/frame_ppc.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2023 SAP SE. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -191,6 +191,15 @@ return false; } + if (sender_pc() == nullptr) { + // Likely the return pc was not yet stored to stack. We rather discard this + // sample also because we would hit an assertion in frame::setup(). We can + // find any other random value if the return pc was not yet stored to + // stack. We rely on consistency checks to handle this (see + // e.g. find_initial_Java_frame()) + return false; + } + return true; } diff -Nru openjdk-21-21.0.8+9/src/hotspot/cpu/ppc/gc/x/xGlobals_ppc.cpp openjdk-21-21.0.9+10/src/hotspot/cpu/ppc/gc/x/xGlobals_ppc.cpp --- openjdk-21-21.0.8+9/src/hotspot/cpu/ppc/gc/x/xGlobals_ppc.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/cpu/ppc/gc/x/xGlobals_ppc.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -82,12 +82,12 @@ // Maximum value as per spec (Power ISA v2.07): 2 ^ 60 bytes, i.e. 1 EiB (exbibyte) static const unsigned int MAXIMUM_MAX_ADDRESS_BIT = 60; -// Most modern power processors provide an address space with not more than 45 bit addressable bit, -// that is an address space of 32 TiB in size. -static const unsigned int DEFAULT_MAX_ADDRESS_BIT = 45; - -// Minimum value returned, if probing fails: 64 GiB -static const unsigned int MINIMUM_MAX_ADDRESS_BIT = 36; +// Default value if probing is not implemented for a certain platform +// Max address bit is restricted by implicit assumptions in the code, for instance +// the bit layout of XForwardingEntry or Partial array entry (see XMarkStackEntry) in mark stack +static const size_t DEFAULT_MAX_ADDRESS_BIT = 46; +// Minimum value returned, if probing fails +static const size_t MINIMUM_MAX_ADDRESS_BIT = 36; // Determines the highest addressable bit of the virtual address space (depends on platform) // by trying to interact with memory in that address range, diff -Nru openjdk-21-21.0.8+9/src/hotspot/cpu/ppc/gc/z/zAddress_ppc.cpp openjdk-21-21.0.9+10/src/hotspot/cpu/ppc/gc/z/zAddress_ppc.cpp --- openjdk-21-21.0.8+9/src/hotspot/cpu/ppc/gc/z/zAddress_ppc.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/cpu/ppc/gc/z/zAddress_ppc.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -35,9 +35,11 @@ #include #endif // LINUX -// Default value if probing is not implemented for a certain platform: 128TB -static const size_t DEFAULT_MAX_ADDRESS_BIT = 47; -// Minimum value returned, if probing fails: 64GB +// Default value if probing is not implemented for a certain platform +// Max address bit is restricted by implicit assumptions in the code, for instance +// the bit layout of ZForwardingEntry or Partial array entry (see ZMarkStackEntry) in mark stack +static const size_t DEFAULT_MAX_ADDRESS_BIT = 46; +// Minimum value returned, if probing fail static const size_t MINIMUM_MAX_ADDRESS_BIT = 36; static size_t probe_valid_max_address_bit() { @@ -92,10 +94,15 @@ size_t ZPlatformAddressOffsetBits() { const static size_t valid_max_address_offset_bits = probe_valid_max_address_bit() + 1; const size_t max_address_offset_bits = valid_max_address_offset_bits - 3; +#ifdef ADDRESS_SANITIZER + // The max supported value is 44 because of other internal data structures. + return MIN2(valid_max_address_offset_bits, (size_t)44); +#else const size_t min_address_offset_bits = max_address_offset_bits - 2; const size_t address_offset = round_up_power_of_2(MaxHeapSize * ZVirtualToPhysicalRatio); const size_t address_offset_bits = log2i_exact(address_offset); return clamp(address_offset_bits, min_address_offset_bits, max_address_offset_bits); +#endif } size_t ZPlatformAddressHeapBaseShift() { diff -Nru openjdk-21-21.0.8+9/src/hotspot/cpu/ppc/methodHandles_ppc.cpp openjdk-21-21.0.9+10/src/hotspot/cpu/ppc/methodHandles_ppc.cpp --- openjdk-21-21.0.8+9/src/hotspot/cpu/ppc/methodHandles_ppc.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/cpu/ppc/methodHandles_ppc.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -360,7 +360,9 @@ ? -1 // enforce receiver null check : oopDesc::klass_offset_in_bytes(); // regular null-checking behavior - __ null_check_throw(receiver_reg, klass_offset, temp1, Interpreter::throw_NullPointerException_entry()); + address NullPointerException_entry = for_compiler_entry ? StubRoutines::throw_NullPointerException_at_call_entry() + : Interpreter::throw_NullPointerException_entry(); + __ null_check_throw(receiver_reg, klass_offset, temp1, NullPointerException_entry); if (iid != vmIntrinsics::_linkToSpecial || VerifyMethodHandles) { __ load_klass(temp1_recv_klass, receiver_reg); diff -Nru openjdk-21-21.0.8+9/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp openjdk-21-21.0.9+10/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp --- openjdk-21-21.0.8+9/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -1041,7 +1041,7 @@ // Need to check whether array is boolean or byte // since both types share the bastore bytecode. - __ load_klass(Rscratch, Rarray); + __ load_klass_check_null_throw(Rscratch, Rarray, Rscratch); __ lwz(Rscratch, in_bytes(Klass::layout_helper_offset()), Rscratch); int diffbit = exact_log2(Klass::layout_helper_boolean_diffbit()); __ testbitdi(CCR0, R0, Rscratch, diffbit); diff -Nru openjdk-21-21.0.8+9/src/hotspot/cpu/riscv/assembler_riscv.hpp openjdk-21-21.0.9+10/src/hotspot/cpu/riscv/assembler_riscv.hpp --- openjdk-21-21.0.8+9/src/hotspot/cpu/riscv/assembler_riscv.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/cpu/riscv/assembler_riscv.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -2913,7 +2913,7 @@ static const unsigned long branch_range = 1 * M; static bool reachable_from_branch_at(address branch, address target) { - return uabs(target - branch) < branch_range; + return g_uabs(target - branch) < branch_range; } // Decode the given instruction, checking if it's a 16-bit compressed diff -Nru openjdk-21-21.0.8+9/src/hotspot/cpu/riscv/gc/x/xGlobals_riscv.cpp openjdk-21-21.0.9+10/src/hotspot/cpu/riscv/gc/x/xGlobals_riscv.cpp --- openjdk-21-21.0.8+9/src/hotspot/cpu/riscv/gc/x/xGlobals_riscv.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/cpu/riscv/gc/x/xGlobals_riscv.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -144,9 +144,11 @@ // * 63-48 Fixed (16-bits, always zero) // -// Default value if probing is not implemented for a certain platform: 128TB -static const size_t DEFAULT_MAX_ADDRESS_BIT = 47; -// Minimum value returned, if probing fails: 64GB +// Default value if probing is not implemented for a certain platform +// Max address bit is restricted by implicit assumptions in the code, for instance +// the bit layout of XForwardingEntry or Partial array entry (see XMarkStackEntry) in mark stack +static const size_t DEFAULT_MAX_ADDRESS_BIT = 46; +// Minimum value returned, if probing fails static const size_t MINIMUM_MAX_ADDRESS_BIT = 36; static size_t probe_valid_max_address_bit() { diff -Nru openjdk-21-21.0.8+9/src/hotspot/cpu/riscv/gc/z/zAddress_riscv.cpp openjdk-21-21.0.9+10/src/hotspot/cpu/riscv/gc/z/zAddress_riscv.cpp --- openjdk-21-21.0.8+9/src/hotspot/cpu/riscv/gc/z/zAddress_riscv.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/cpu/riscv/gc/z/zAddress_riscv.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -37,9 +37,11 @@ #include #endif // LINUX -// Default value if probe is not implemented for a certain platform: 128TB -static const size_t DEFAULT_MAX_ADDRESS_BIT = 47; -// Minimum value returned, if probing fails: 64GB +// Default value if probing is not implemented for a certain platform +// Max address bit is restricted by implicit assumptions in the code, for instance +// the bit layout of ZForwardingEntry or Partial array entry (see ZMarkStackEntry) in mark stack +static const size_t DEFAULT_MAX_ADDRESS_BIT = 46; +// Minimum value returned, if probing fail static const size_t MINIMUM_MAX_ADDRESS_BIT = 36; static size_t probe_valid_max_address_bit() { diff -Nru openjdk-21-21.0.8+9/src/hotspot/cpu/riscv/riscv.ad openjdk-21-21.0.9+10/src/hotspot/cpu/riscv/riscv.ad --- openjdk-21-21.0.8+9/src/hotspot/cpu/riscv/riscv.ad 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/cpu/riscv/riscv.ad 2025-10-13 07:49:24.000000000 +0000 @@ -2222,11 +2222,6 @@ __ mv(dst_reg, 1); %} - enc_class riscv_enc_mov_byte_map_base(iRegP dst) %{ - C2_MacroAssembler _masm(&cbuf); - __ load_byte_map_base($dst$$Register); - %} - enc_class riscv_enc_mov_n(iRegN dst, immN src) %{ C2_MacroAssembler _masm(&cbuf); Register dst_reg = as_Register($dst$$reg); @@ -2870,20 +2865,6 @@ interface(CONST_INTER); %} -// Card Table Byte Map Base -operand immByteMapBase() -%{ - // Get base of card map - predicate(BarrierSet::barrier_set()->is_a(BarrierSet::CardTableBarrierSet) && - (CardTable::CardValue*)n->get_ptr() == - ((CardTableBarrierSet*)(BarrierSet::barrier_set()))->card_table()->byte_map_base()); - match(ConP); - - op_cost(0); - format %{ %} - interface(CONST_INTER); -%} - // Int Immediate: low 16-bit mask operand immI_16bits() %{ @@ -4837,18 +4818,6 @@ ins_pipe(ialu_imm); %} - -// Load Byte Map Base Constant -instruct loadByteMapBase(iRegPNoSp dst, immByteMapBase con) -%{ - match(Set dst con); - ins_cost(ALU_COST); - format %{ "mv $dst, $con\t# Byte Map Base, #@loadByteMapBase" %} - - ins_encode(riscv_enc_mov_byte_map_base(dst)); - - ins_pipe(ialu_imm); -%} // Load Narrow Pointer Constant instruct loadConN(iRegNNoSp dst, immN con) diff -Nru openjdk-21-21.0.8+9/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp openjdk-21-21.0.9+10/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp --- openjdk-21-21.0.8+9/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -917,7 +917,7 @@ void copy_memory_v(Register s, Register d, Register count, int step) { bool is_backward = step < 0; - int granularity = uabs(step); + int granularity = g_uabs(step); const Register src = x30, dst = x31, vl = x14, cnt = x15, tmp1 = x16, tmp2 = x17; assert_different_registers(s, d, cnt, vl, tmp1, tmp2); @@ -973,7 +973,7 @@ } bool is_backwards = step < 0; - int granularity = uabs(step); + int granularity = g_uabs(step); const Register src = x30, dst = x31, cnt = x15, tmp3 = x16, tmp4 = x17, tmp5 = x14, tmp6 = x13; const Register gct1 = x28, gct2 = x29, gct3 = t2; diff -Nru openjdk-21-21.0.8+9/src/hotspot/cpu/riscv/templateTable_riscv.cpp openjdk-21-21.0.9+10/src/hotspot/cpu/riscv/templateTable_riscv.cpp --- openjdk-21-21.0.8+9/src/hotspot/cpu/riscv/templateTable_riscv.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/cpu/riscv/templateTable_riscv.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -123,24 +123,6 @@ return Address(esp, Interpreter::expr_offset_in_bytes(5)); } -// Miscellaneous helper routines -// Store an oop (or null) at the Address described by obj. -// If val == noreg this means store a null -static void do_oop_store(InterpreterMacroAssembler* _masm, - Address dst, - Register val, - DecoratorSet decorators) { - assert(val == noreg || val == x10, "parameter is just for looks"); - __ store_heap_oop(dst, val, x28, x29, x13, decorators); -} - -static void do_oop_load(InterpreterMacroAssembler* _masm, - Address src, - Register dst, - DecoratorSet decorators) { - __ load_heap_oop(dst, src, x28, x29, decorators); -} - Address TemplateTable::at_bcp(int offset) { assert(_desc->uses_bcp(), "inconsistent uses_bcp information"); return Address(xbcp, offset); @@ -770,7 +752,7 @@ index_check(x10, x11); // leaves index in x11 __ add(x11, x11, arrayOopDesc::base_offset_in_bytes(T_OBJECT) >> LogBytesPerHeapOop); __ shadd(x10, x11, x10, t0, LogBytesPerHeapOop); - do_oop_load(_masm, Address(x10), x10, IS_ARRAY); + __ load_heap_oop(x10, Address(x10), x28, x29, IS_ARRAY); } void TemplateTable::baload() { @@ -1082,7 +1064,7 @@ // Get the value we will store __ ld(x10, at_tos()); // Now store using the appropriate barrier - do_oop_store(_masm, element_address, x10, IS_ARRAY); + __ store_heap_oop(element_address, x10, x28, x29, x13, IS_ARRAY); __ j(done); // Have a null in x10, x13=array, x12=index. Store null at ary[idx] @@ -1090,7 +1072,7 @@ __ profile_null_seen(x12); // Store a null - do_oop_store(_masm, element_address, noreg, IS_ARRAY); + __ store_heap_oop(element_address, noreg, x28, x29, x13, IS_ARRAY); // Pop stack arguments __ bind(done); @@ -2429,7 +2411,7 @@ __ sub(t0, flags, (u1)atos); __ bnez(t0, notObj); // atos - do_oop_load(_masm, field, x10, IN_HEAP); + __ load_heap_oop(x10, field, x28, x29, IN_HEAP); __ push(atos); if (rc == may_rewrite) { patch_bytecode(Bytecodes::_fast_agetfield, bc, x11); @@ -2689,7 +2671,7 @@ __ add(off, obj, off); // if static, obj from cache, else obj from stack. const Address field(off, 0); // Store into the field - do_oop_store(_masm, field, x10, IN_HEAP); + __ store_heap_oop(field, x10, x28, x29, x13, IN_HEAP); if (rc == may_rewrite) { patch_bytecode(Bytecodes::_fast_aputfield, bc, x11, true, byte_no); } @@ -2942,10 +2924,10 @@ __ add(x11, x12, x11); const Address field(x11, 0); - // access field + // access field, must not clobber x13 - flags switch (bytecode()) { case Bytecodes::_fast_aputfield: - do_oop_store(_masm, field, x10, IN_HEAP); + __ store_heap_oop(field, x10, x28, x29, x15, IN_HEAP); break; case Bytecodes::_fast_lputfield: __ access_store_at(T_LONG, IN_HEAP, field, x10, noreg, noreg, noreg); @@ -3033,7 +3015,7 @@ // access field switch (bytecode()) { case Bytecodes::_fast_agetfield: - do_oop_load(_masm, field, x10, IN_HEAP); + __ load_heap_oop(x10, field, x28, x29, IN_HEAP); __ verify_oop(x10); break; case Bytecodes::_fast_lgetfield: @@ -3092,7 +3074,7 @@ break; case atos: __ add(x10, x10, x11); - do_oop_load(_masm, Address(x10, 0), x10, IN_HEAP); + __ load_heap_oop(x10, Address(x10, 0), x28, x29, IN_HEAP); __ verify_oop(x10); break; case ftos: diff -Nru openjdk-21-21.0.8+9/src/hotspot/cpu/x86/gc/z/zAddress_x86.cpp openjdk-21-21.0.9+10/src/hotspot/cpu/x86/gc/z/zAddress_x86.cpp --- openjdk-21-21.0.8+9/src/hotspot/cpu/x86/gc/z/zAddress_x86.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/cpu/x86/gc/z/zAddress_x86.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -31,11 +31,15 @@ size_t ZPointerLoadShift; size_t ZPlatformAddressOffsetBits() { +#ifdef ADDRESS_SANITIZER + return 44; +#else const size_t min_address_offset_bits = 42; // 4TB const size_t max_address_offset_bits = 44; // 16TB const size_t address_offset = round_up_power_of_2(MaxHeapSize * ZVirtualToPhysicalRatio); const size_t address_offset_bits = log2i_exact(address_offset); return clamp(address_offset_bits, min_address_offset_bits, max_address_offset_bits); +#endif } size_t ZPlatformAddressHeapBaseShift() { diff -Nru openjdk-21-21.0.8+9/src/hotspot/cpu/x86/macroAssembler_x86.cpp openjdk-21-21.0.9+10/src/hotspot/cpu/x86/macroAssembler_x86.cpp --- openjdk-21-21.0.8+9/src/hotspot/cpu/x86/macroAssembler_x86.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/cpu/x86/macroAssembler_x86.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -3998,7 +3998,7 @@ RegSet regs; #ifdef _LP64 regs += RegSet::of(rax, rcx, rdx); -#ifndef WINDOWS +#ifndef _WINDOWS regs += RegSet::of(rsi, rdi); #endif regs += RegSet::range(r8, r11); @@ -4010,7 +4010,7 @@ XMMRegSet MacroAssembler::call_clobbered_xmm_registers() { int num_xmm_registers = XMMRegister::available_xmm_registers(); -#if defined(WINDOWS) && defined(_LP64) +#if defined(_WINDOWS) && defined(_LP64) XMMRegSet result = XMMRegSet::range(xmm0, xmm5); if (num_xmm_registers > 16) { result += XMMRegSet::range(xmm16, as_XMMRegister(num_xmm_registers - 1)); diff -Nru openjdk-21-21.0.8+9/src/hotspot/os/aix/os_aix.cpp openjdk-21-21.0.9+10/src/hotspot/os/aix/os_aix.cpp --- openjdk-21-21.0.8+9/src/hotspot/os/aix/os_aix.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/os/aix/os_aix.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -2702,7 +2702,7 @@ dummy, &dummy_size) == 0) { tid = pinfo.__pi_tid; } else { - tty->print_cr("pthread_getthrds_np failed."); + tty->print_cr("pthread_getthrds_np failed, errno: %d.", errno); error = true; } @@ -2713,7 +2713,7 @@ sys_time = thrdentry.ti_ru.ru_stime.tv_sec * 1000000000LL + thrdentry.ti_ru.ru_stime.tv_usec * 1000LL; user_time = thrdentry.ti_ru.ru_utime.tv_sec * 1000000000LL + thrdentry.ti_ru.ru_utime.tv_usec * 1000LL; } else { - tty->print_cr("pthread_getthrds_np failed."); + tty->print_cr("getthrds64 failed, errno: %d.", errno); error = true; } } diff -Nru openjdk-21-21.0.8+9/src/hotspot/os/linux/cgroupSubsystem_linux.cpp openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupSubsystem_linux.cpp --- openjdk-21-21.0.8+9/src/hotspot/os/linux/cgroupSubsystem_linux.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupSubsystem_linux.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -28,6 +28,7 @@ #include "cgroupSubsystem_linux.hpp" #include "cgroupV1Subsystem_linux.hpp" #include "cgroupV2Subsystem_linux.hpp" +#include "cgroupUtil_linux.hpp" #include "logging/log.hpp" #include "memory/allocation.hpp" #include "os_linux.hpp" @@ -41,7 +42,7 @@ CgroupSubsystem* CgroupSubsystemFactory::create() { CgroupV1MemoryController* memory = nullptr; CgroupV1Controller* cpuset = nullptr; - CgroupV1Controller* cpu = nullptr; + CgroupV1CpuController* cpu = nullptr; CgroupV1Controller* cpuacct = nullptr; CgroupV1Controller* pids = nullptr; CgroupInfo cg_infos[CG_INFO_LENGTH]; @@ -61,12 +62,18 @@ if (is_cgroup_v2(&cg_type_flags)) { // Cgroups v2 case, we have all the info we need. // Construct the subsystem, free resources and return - // Note: any index in cg_infos will do as the path is the same for - // all controllers. - CgroupController* unified = new CgroupV2Controller(cg_infos[MEMORY_IDX]._mount_path, cg_infos[MEMORY_IDX]._cgroup_path); + // Note: We use the memory for non-cpu non-memory controller look-ups. + // Perhaps we ought to have separate controllers for all. + CgroupV2Controller mem_other = CgroupV2Controller(cg_infos[MEMORY_IDX]._mount_path, + cg_infos[MEMORY_IDX]._cgroup_path, + cg_infos[MEMORY_IDX]._read_only); + CgroupV2MemoryController* memory = new CgroupV2MemoryController(mem_other); + CgroupV2CpuController* cpu = new CgroupV2CpuController(CgroupV2Controller(cg_infos[CPU_IDX]._mount_path, + cg_infos[CPU_IDX]._cgroup_path, + cg_infos[CPU_IDX]._read_only)); log_debug(os, container)("Detected cgroups v2 unified hierarchy"); cleanup(cg_infos); - return new CgroupV2Subsystem(unified); + return new CgroupV2Subsystem(memory, cpu, mem_other); } /* @@ -100,19 +107,19 @@ CgroupInfo info = cg_infos[i]; if (info._data_complete) { // pids controller might have incomplete data if (strcmp(info._name, "memory") == 0) { - memory = new CgroupV1MemoryController(info._root_mount_path, info._mount_path); + memory = new CgroupV1MemoryController(CgroupV1Controller(info._root_mount_path, info._mount_path, info._read_only)); memory->set_subsystem_path(info._cgroup_path); } else if (strcmp(info._name, "cpuset") == 0) { - cpuset = new CgroupV1Controller(info._root_mount_path, info._mount_path); + cpuset = new CgroupV1Controller(info._root_mount_path, info._mount_path, info._read_only); cpuset->set_subsystem_path(info._cgroup_path); } else if (strcmp(info._name, "cpu") == 0) { - cpu = new CgroupV1Controller(info._root_mount_path, info._mount_path); + cpu = new CgroupV1CpuController(CgroupV1Controller(info._root_mount_path, info._mount_path, info._read_only)); cpu->set_subsystem_path(info._cgroup_path); } else if (strcmp(info._name, "cpuacct") == 0) { - cpuacct = new CgroupV1Controller(info._root_mount_path, info._mount_path); + cpuacct = new CgroupV1Controller(info._root_mount_path, info._mount_path, info._read_only); cpuacct->set_subsystem_path(info._cgroup_path); } else if (strcmp(info._name, "pids") == 0) { - pids = new CgroupV1Controller(info._root_mount_path, info._mount_path); + pids = new CgroupV1Controller(info._root_mount_path, info._mount_path, info._read_only); pids->set_subsystem_path(info._cgroup_path); } } else { @@ -127,7 +134,8 @@ int controller, const char* name, char* mount_path, - char* root_path) { + char* root_path, + bool read_only) { if (cg_infos[controller]._mount_path != nullptr) { // On some systems duplicate controllers get mounted in addition to // the main cgroup controllers most likely under /sys/fs/cgroup. In that @@ -139,6 +147,7 @@ os::free(cg_infos[controller]._root_mount_path); cg_infos[controller]._mount_path = os::strdup(mount_path); cg_infos[controller]._root_mount_path = os::strdup(root_path); + cg_infos[controller]._read_only = read_only; } else { log_debug(os, container)("Duplicate %s controllers detected. Picking %s, skipping %s.", name, cg_infos[controller]._mount_path, mount_path); @@ -146,9 +155,66 @@ } else { cg_infos[controller]._mount_path = os::strdup(mount_path); cg_infos[controller]._root_mount_path = os::strdup(root_path); + cg_infos[controller]._read_only = read_only; } } +/* + * Determine whether or not the mount options, which are comma separated, + * contain the 'ro' string. + */ +static bool find_ro_opt(char* mount_opts) { + char* token; + char* mo_ptr = mount_opts; + // mount options are comma-separated (man proc). + while ((token = strsep(&mo_ptr, ",")) != NULL) { + if (strcmp(token, "ro") == 0) { + return true; + } + } + return false; +} + +/* + * Read values of a /proc/self/mountinfo line into variables. For cgroups v1 + * super options are needed. On cgroups v2 super options are not used. + * + * The scanning of a single mountinfo line entry is as follows: + * + * 36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue + * (1) (2) (3):(4) (5) (6) (7) (8) (9) (10) (11) (12) + * + * The numbers in parentheses are labels for the descriptions below: + * + * (1) mount ID: matched with '%*d' and discarded + * (2) parent ID: matched with '%*d' and discarded + * (3) major: ---,---> major, minor separated by ':'. matched with '%*d:%*d' and discarded + * (4) minor: ---' + * (5) root: matched with '%s' and captured in 'tmproot'. Must be non-empty. + * (6) mount point: matched with '%s' and captured in 'tmpmount'. Must be non-empty. + * (7) mount options: matched with '%s' and captured in 'mount_opts'. Must be non-empty. + * (8) optional fields: ---,---> matched with '%*[^-]-'. Anything not a hyphen, followed by a hyphen + * (9) separator: ---' and discarded. Note: The discarded match is space characters if there + * are no optionals. Otherwise it includes the optional fields as well. + * (10) filesystem type: matched with '%s' and captured in 'tmp_fs_type' + * (11) mount source: matched with '%*s' and discarded + * (12) super options: matched with '%s' and captured in 'tmpcgroups' + */ +static inline bool match_mount_info_line(char* line, + char* tmproot, + char* tmpmount, + char* mount_opts, + char* tmp_fs_type, + char* tmpcgroups) { + return sscanf(line, + "%*d %*d %*d:%*d %s %s %s%*[^-]- %s %*s %s", + tmproot, + tmpmount, + mount_opts, + tmp_fs_type, + tmpcgroups) == 5; +} + bool CgroupSubsystemFactory::determine_type(CgroupInfo* cg_infos, const char* proc_cgroups, const char* proc_self_cgroup, @@ -320,26 +386,40 @@ char tmproot[MAXPATHLEN+1]; char tmpmount[MAXPATHLEN+1]; char tmpcgroups[MAXPATHLEN+1]; + char mount_opts[MAXPATHLEN+1]; char *cptr = tmpcgroups; char *token; - // Cgroup v2 relevant info. We only look for the _mount_path iff is_cgroupsV2 so - // as to avoid memory stomping of the _mount_path pointer later on in the cgroup v1 - // block in the hybrid case. - if (is_cgroupsV2 && sscanf(p, "%*d %*d %*d:%*d %s %s %*[^-]- %s %*s %*s", tmproot, tmpmount, tmp_fs_type) == 3) { + /* Cgroup v2 relevant info. We only look for the _mount_path iff is_cgroupsV2 so + * as to avoid memory stomping of the _mount_path pointer later on in the cgroup v1 + * block in the hybrid case. + * + * We collect the read only mount option in the cgroup infos so as to have that + * info ready when determining is_containerized(). + */ + if (is_cgroupsV2 && match_mount_info_line(p, + tmproot, + tmpmount, + mount_opts, + tmp_fs_type, + tmpcgroups /* unused */)) { // we likely have an early match return (e.g. cgroup fs match), be sure we have cgroup2 as fstype if (strcmp("cgroup2", tmp_fs_type) == 0) { cgroupv2_mount_point_found = true; any_cgroup_mounts_found = true; + // For unified we only have a single line with cgroup2 fs type. + // Therefore use that option for all CG info structs. + bool ro_option = find_ro_opt(mount_opts); for (int i = 0; i < CG_INFO_LENGTH; i++) { - set_controller_paths(cg_infos, i, "(cg2, unified)", tmpmount, tmproot); + set_controller_paths(cg_infos, i, "(cg2, unified)", tmpmount, tmproot, ro_option); } } } /* Cgroup v1 relevant info * - * Find the cgroup mount point for memory, cpuset, cpu, cpuacct, pids + * Find the cgroup mount point for memory, cpuset, cpu, cpuacct, pids. For each controller + * determine whether or not they show up as mounted read only or not. * * Example for docker: * 219 214 0:29 /docker/7208cebd00fa5f2e342b1094f7bed87fa25661471a4637118e65f1c995be8a34 /sys/fs/cgroup/memory ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,memory @@ -348,8 +428,9 @@ * 34 28 0:29 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,memory * * 44 31 0:39 / /sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:23 - cgroup cgroup rw,pids + * */ - if (sscanf(p, "%*d %*d %*d:%*d %s %s %*[^-]- %s %*s %s", tmproot, tmpmount, tmp_fs_type, tmpcgroups) == 4) { + if (match_mount_info_line(p, tmproot, tmpmount, mount_opts, tmp_fs_type, tmpcgroups)) { if (strcmp("cgroup", tmp_fs_type) != 0) { // Skip cgroup2 fs lines on hybrid or unified hierarchy. continue; @@ -357,23 +438,28 @@ while ((token = strsep(&cptr, ",")) != nullptr) { if (strcmp(token, "memory") == 0) { any_cgroup_mounts_found = true; - set_controller_paths(cg_infos, MEMORY_IDX, token, tmpmount, tmproot); + bool ro_option = find_ro_opt(mount_opts); + set_controller_paths(cg_infos, MEMORY_IDX, token, tmpmount, tmproot, ro_option); cg_infos[MEMORY_IDX]._data_complete = true; } else if (strcmp(token, "cpuset") == 0) { any_cgroup_mounts_found = true; - set_controller_paths(cg_infos, CPUSET_IDX, token, tmpmount, tmproot); + bool ro_option = find_ro_opt(mount_opts); + set_controller_paths(cg_infos, CPUSET_IDX, token, tmpmount, tmproot, ro_option); cg_infos[CPUSET_IDX]._data_complete = true; } else if (strcmp(token, "cpu") == 0) { any_cgroup_mounts_found = true; - set_controller_paths(cg_infos, CPU_IDX, token, tmpmount, tmproot); + bool ro_option = find_ro_opt(mount_opts); + set_controller_paths(cg_infos, CPU_IDX, token, tmpmount, tmproot, ro_option); cg_infos[CPU_IDX]._data_complete = true; } else if (strcmp(token, "cpuacct") == 0) { any_cgroup_mounts_found = true; - set_controller_paths(cg_infos, CPUACCT_IDX, token, tmpmount, tmproot); + bool ro_option = find_ro_opt(mount_opts); + set_controller_paths(cg_infos, CPUACCT_IDX, token, tmpmount, tmproot, ro_option); cg_infos[CPUACCT_IDX]._data_complete = true; } else if (strcmp(token, "pids") == 0) { any_cgroup_mounts_found = true; - set_controller_paths(cg_infos, PIDS_IDX, token, tmpmount, tmproot); + bool ro_option = find_ro_opt(mount_opts); + set_controller_paths(cg_infos, PIDS_IDX, token, tmpmount, tmproot, ro_option); cg_infos[PIDS_IDX]._data_complete = true; } } @@ -477,13 +563,13 @@ */ int CgroupSubsystem::active_processor_count() { int quota_count = 0; - int cpu_count, limit_count; + int cpu_count; int result; // We use a cache with a timeout to avoid performing expensive // computations in the event this function is called frequently. // [See 8227006]. - CachingCgroupController* contrl = cpu_controller(); + CachingCgroupController* contrl = cpu_controller(); CachedMetric* cpu_limit = contrl->metrics_cache(); if (!cpu_limit->should_check_metric()) { int val = (int)cpu_limit->value(); @@ -491,23 +577,8 @@ return val; } - cpu_count = limit_count = os::Linux::active_processor_count(); - int quota = cpu_quota(); - int period = cpu_period(); - - if (quota > -1 && period > 0) { - quota_count = ceilf((float)quota / (float)period); - log_trace(os, container)("CPU Quota count based on quota/period: %d", quota_count); - } - - // Use quotas - if (quota_count != 0) { - limit_count = quota_count; - } - - result = MIN2(cpu_count, limit_count); - log_trace(os, container)("OSContainer::active_processor_count: %d", result); - + cpu_count = os::Linux::active_processor_count(); + result = CgroupUtil::processor_count(contrl->controller(), cpu_count); // Update cached metric to avoid re-reading container settings too often cpu_limit->set_value(result, OSCONTAINER_CACHE_TIMEOUT); @@ -524,55 +595,221 @@ * OSCONTAINER_ERROR for not supported */ jlong CgroupSubsystem::memory_limit_in_bytes() { - CachingCgroupController* contrl = memory_controller(); + CachingCgroupController* contrl = memory_controller(); CachedMetric* memory_limit = contrl->metrics_cache(); if (!memory_limit->should_check_metric()) { return memory_limit->value(); } jlong phys_mem = os::Linux::physical_memory(); log_trace(os, container)("total physical memory: " JLONG_FORMAT, phys_mem); - jlong mem_limit = read_memory_limit_in_bytes(); + jlong mem_limit = contrl->controller()->read_memory_limit_in_bytes(phys_mem); + // Update cached metric to avoid re-reading container settings too often + memory_limit->set_value(mem_limit, OSCONTAINER_CACHE_TIMEOUT); + return mem_limit; +} - if (mem_limit <= 0 || mem_limit >= phys_mem) { - jlong read_mem_limit = mem_limit; - const char *reason; - if (mem_limit >= phys_mem) { - // Exceeding physical memory is treated as unlimited. Cg v1's implementation - // of read_memory_limit_in_bytes() caps this at phys_mem since Cg v1 has no - // value to represent 'max'. Cg v2 may return a value >= phys_mem if e.g. the - // container engine was started with a memory flag exceeding it. - reason = "ignored"; - mem_limit = -1; - } else if (OSCONTAINER_ERROR == mem_limit) { - reason = "failed"; - } else { - assert(mem_limit == -1, "Expected unlimited"); - reason = "unlimited"; +bool CgroupController::read_string(const char* filename, char* buf, size_t buf_size) { + assert(buf != nullptr, "buffer must not be null"); + assert(filename != nullptr, "filename must be given"); + const char* s_path = subsystem_path(); + if (s_path == nullptr) { + log_debug(os, container)("read_string: subsystem path is null"); + return false; + } + + stringStream file_path; + file_path.print_raw(s_path); + file_path.print_raw(filename); + + if (file_path.size() > MAXPATHLEN) { + log_debug(os, container)("File path too long %s, %s", file_path.base(), filename); + return false; + } + const char* absolute_path = file_path.freeze(); + log_trace(os, container)("Path to %s is %s", filename, absolute_path); + + FILE* fp = os::fopen(absolute_path, "r"); + if (fp == nullptr) { + log_debug(os, container)("Open of file %s failed, %s", absolute_path, os::strerror(errno)); + return false; + } + + // Read a single line into the provided buffer. + // At most buf_size - 1 characters. + char* line = fgets(buf, buf_size, fp); + fclose(fp); + if (line == nullptr) { + log_debug(os, container)("Empty file %s", absolute_path); + return false; + } + size_t len = strlen(line); + assert(len <= buf_size - 1, "At most buf_size - 1 bytes can be read"); + if (line[len - 1] == '\n') { + line[len - 1] = '\0'; // trim trailing new line + } + return true; +} + +bool CgroupController::read_number(const char* filename, julong* result) { + char buf[1024]; + bool is_ok = read_string(filename, buf, 1024); + if (!is_ok) { + return false; + } + int matched = sscanf(buf, JULONG_FORMAT, result); + if (matched == 1) { + return true; + } + return false; +} + +bool CgroupController::read_number_handle_max(const char* filename, jlong* result) { + char buf[1024]; + bool is_ok = read_string(filename, buf, 1024); + if (!is_ok) { + return false; + } + jlong val = limit_from_str(buf); + if (val == OSCONTAINER_ERROR) { + return false; + } + *result = val; + return true; +} + +bool CgroupController::read_numerical_key_value(const char* filename, const char* key, julong* result) { + assert(key != nullptr, "key must be given"); + assert(result != nullptr, "result pointer must not be null"); + assert(filename != nullptr, "file to search in must be given"); + const char* s_path = subsystem_path(); + if (s_path == nullptr) { + log_debug(os, container)("read_numerical_key_value: subsystem path is null"); + return false; + } + + stringStream file_path; + file_path.print_raw(s_path); + file_path.print_raw(filename); + + if (file_path.size() > MAXPATHLEN) { + log_debug(os, container)("File path too long %s, %s", file_path.base(), filename); + return false; + } + const char* absolute_path = file_path.freeze(); + log_trace(os, container)("Path to %s is %s", filename, absolute_path); + FILE* fp = os::fopen(absolute_path, "r"); + if (fp == nullptr) { + log_debug(os, container)("Open of file %s failed, %s", absolute_path, os::strerror(errno)); + return false; + } + + const int buf_len = MAXPATHLEN+1; + char buf[buf_len]; + char* line = fgets(buf, buf_len, fp); + bool found_match = false; + // File consists of multiple lines in a "key value" + // fashion, we have to find the key. + const size_t key_len = strlen(key); + for (; line != nullptr; line = fgets(buf, buf_len, fp)) { + char after_key = line[key_len]; + if (strncmp(line, key, key_len) == 0 + && isspace(after_key) != 0 + && after_key != '\n') { + // Skip key, skip space + const char* value_substr = line + key_len + 1; + int matched = sscanf(value_substr, JULONG_FORMAT, result); + found_match = matched == 1; + if (found_match) { + break; + } } - log_debug(os, container)("container memory limit %s: " JLONG_FORMAT ", using host value " JLONG_FORMAT, - reason, read_mem_limit, phys_mem); } + fclose(fp); + if (found_match) { + return true; + } + log_debug(os, container)("Type %s (key == %s) not found in file %s", JULONG_FORMAT, + key, absolute_path); + return false; +} - // Update cached metric to avoid re-reading container settings too often - memory_limit->set_value(mem_limit, OSCONTAINER_CACHE_TIMEOUT); - return mem_limit; +bool CgroupController::read_numerical_tuple_value(const char* filename, bool use_first, jlong* result) { + char buf[1024]; + bool is_ok = read_string(filename, buf, 1024); + if (!is_ok) { + return false; + } + char token[1024]; + const int matched = sscanf(buf, (use_first ? "%1023s %*s" : "%*s %1023s"), token); + if (matched != 1) { + return false; + } + jlong val = limit_from_str(token); + if (val == OSCONTAINER_ERROR) { + return false; + } + *result = val; + return true; } -jlong CgroupSubsystem::limit_from_str(char* limit_str) { +jlong CgroupController::limit_from_str(char* limit_str) { if (limit_str == nullptr) { return OSCONTAINER_ERROR; } // Unlimited memory in cgroups is the literal string 'max' for // some controllers, for example the pids controller. if (strcmp("max", limit_str) == 0) { - os::free(limit_str); return (jlong)-1; } julong limit; if (sscanf(limit_str, JULONG_FORMAT, &limit) != 1) { - os::free(limit_str); return OSCONTAINER_ERROR; } - os::free(limit_str); return (jlong)limit; } + +// CgroupSubsystem implementations + +jlong CgroupSubsystem::memory_and_swap_limit_in_bytes() { + julong phys_mem = os::Linux::physical_memory(); + julong host_swap = os::Linux::host_swap(); + return memory_controller()->controller()->memory_and_swap_limit_in_bytes(phys_mem, host_swap); +} + +jlong CgroupSubsystem::memory_soft_limit_in_bytes() { + julong phys_mem = os::Linux::physical_memory(); + return memory_controller()->controller()->memory_soft_limit_in_bytes(phys_mem); +} + +jlong CgroupSubsystem::memory_usage_in_bytes() { + return memory_controller()->controller()->memory_usage_in_bytes(); +} + +jlong CgroupSubsystem::memory_max_usage_in_bytes() { + return memory_controller()->controller()->memory_max_usage_in_bytes(); +} + +jlong CgroupSubsystem::rss_usage_in_bytes() { + return memory_controller()->controller()->rss_usage_in_bytes(); +} + +jlong CgroupSubsystem::cache_usage_in_bytes() { + return memory_controller()->controller()->cache_usage_in_bytes(); +} + +int CgroupSubsystem::cpu_quota() { + return cpu_controller()->controller()->cpu_quota(); +} + +int CgroupSubsystem::cpu_period() { + return cpu_controller()->controller()->cpu_period(); +} + +int CgroupSubsystem::cpu_shares() { + return cpu_controller()->controller()->cpu_shares(); +} + +void CgroupSubsystem::print_version_specific_info(outputStream* st) { + julong phys_mem = os::Linux::physical_memory(); + memory_controller()->controller()->print_version_specific_info(st, phys_mem); +} diff -Nru openjdk-21-21.0.8+9/src/hotspot/os/linux/cgroupSubsystem_linux.hpp openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupSubsystem_linux.hpp --- openjdk-21-21.0.8+9/src/hotspot/os/linux/cgroupSubsystem_linux.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupSubsystem_linux.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -69,148 +69,98 @@ #define MEMORY_IDX 3 #define PIDS_IDX 4 -typedef char * cptr; - -class CgroupController: public CHeapObj { - public: - virtual char *subsystem_path() = 0; -}; - -PRAGMA_DIAG_PUSH -PRAGMA_FORMAT_NONLITERAL_IGNORED -// Parses a subsystem's file, looking for a matching line. -// If key is null, then the first line will be matched with scan_fmt. -// If key isn't null, then each line will be matched, looking for something that matches "$key $scan_fmt". -// The matching value will be assigned to returnval. -// scan_fmt uses scanf() syntax. -// Return value: 0 on match, OSCONTAINER_ERROR on error. -template int subsystem_file_line_contents(CgroupController* c, - const char *filename, - const char *key, - const char *scan_fmt, - T returnval) { - if (c == nullptr) { - log_debug(os, container)("subsystem_file_line_contents: CgroupController* is null"); - return OSCONTAINER_ERROR; - } - if (c->subsystem_path() == nullptr) { - log_debug(os, container)("subsystem_file_line_contents: subsystem path is null"); - return OSCONTAINER_ERROR; - } - - stringStream file_path; - file_path.print_raw(c->subsystem_path()); - file_path.print_raw(filename); - - if (file_path.size() > (MAXPATHLEN-1)) { - log_debug(os, container)("File path too long %s, %s", file_path.base(), filename); - return OSCONTAINER_ERROR; - } - const char* absolute_path = file_path.freeze(); - log_trace(os, container)("Path to %s is %s", filename, absolute_path); - - FILE* fp = os::fopen(absolute_path, "r"); - if (fp == nullptr) { - log_debug(os, container)("Open of file %s failed, %s", absolute_path, os::strerror(errno)); - return OSCONTAINER_ERROR; - } - - const int buf_len = MAXPATHLEN+1; - char buf[buf_len]; - char* line = fgets(buf, buf_len, fp); - if (line == nullptr) { - log_debug(os, container)("Empty file %s", absolute_path); - fclose(fp); - return OSCONTAINER_ERROR; - } - - bool found_match = false; - if (key == nullptr) { - // File consists of a single line according to caller, with only a value - int matched = sscanf(line, scan_fmt, returnval); - found_match = matched == 1; - } else { - // File consists of multiple lines in a "key value" - // fashion, we have to find the key. - const int key_len = (int)strlen(key); - for (; line != nullptr; line = fgets(buf, buf_len, fp)) { - char* key_substr = strstr(line, key); - char after_key = line[key_len]; - if (key_substr == line - && isspace(after_key) != 0 - && after_key != '\n') { - // Skip key, skip space - const char* value_substr = line + key_len + 1; - int matched = sscanf(value_substr, scan_fmt, returnval); - found_match = matched == 1; - if (found_match) { - break; - } - } - } - } - fclose(fp); - if (found_match) { - return 0; - } - log_debug(os, container)("Type %s (key == %s) not found in file %s", scan_fmt, - (key == nullptr ? "null" : key), absolute_path); - return OSCONTAINER_ERROR; +#define CONTAINER_READ_NUMBER_CHECKED(controller, filename, log_string, retval) \ +{ \ + bool is_ok; \ + is_ok = controller->read_number(filename, &retval); \ + if (!is_ok) { \ + log_trace(os, container)(log_string " failed: %d", OSCONTAINER_ERROR); \ + return OSCONTAINER_ERROR; \ + } \ + log_trace(os, container)(log_string " is: " JULONG_FORMAT, retval); \ } -PRAGMA_DIAG_POP -// log_fmt can be different than scan_fmt. For example -// cpu_period() for cgv2 uses log_fmt='%d' and scan_fmt='%*s %d' -#define GET_CONTAINER_INFO(return_type, subsystem, filename, \ - logstring, log_fmt, scan_fmt, variable) \ - return_type variable; \ -{ \ - int err; \ - err = subsystem_file_line_contents(subsystem, \ - filename, \ - nullptr, \ - scan_fmt, \ - &variable); \ - if (err != 0) { \ - log_trace(os, container)(logstring "%d", OSCONTAINER_ERROR); \ - return (return_type) OSCONTAINER_ERROR; \ - } \ - \ - log_trace(os, container)(logstring log_fmt, variable); \ +#define CONTAINER_READ_NUMBER_CHECKED_MAX(controller, filename, log_string, retval) \ +{ \ + bool is_ok; \ + is_ok = controller->read_number_handle_max(filename, &retval); \ + if (!is_ok) { \ + log_trace(os, container)(log_string " failed: %d", OSCONTAINER_ERROR); \ + return OSCONTAINER_ERROR; \ + } \ + log_trace(os, container)(log_string " is: " JLONG_FORMAT, retval); \ } -#define GET_CONTAINER_INFO_CPTR(return_type, subsystem, filename, \ - logstring, scan_fmt, variable, bufsize) \ - char variable[bufsize]; \ -{ \ - int err; \ - err = subsystem_file_line_contents(subsystem, \ - filename, \ - nullptr, \ - scan_fmt, \ - variable); \ - if (err != 0) \ - return (return_type) nullptr; \ - \ - log_trace(os, container)(logstring, variable); \ +#define CONTAINER_READ_STRING_CHECKED(controller, filename, log_string, retval, buf_size) \ +{ \ + bool is_ok; \ + is_ok = controller->read_string(filename, retval, buf_size); \ + if (!is_ok) { \ + log_trace(os, container)(log_string " failed: %d", OSCONTAINER_ERROR); \ + return nullptr; \ + } \ + log_trace(os, container)(log_string " is: %s", retval); \ } -#define GET_CONTAINER_INFO_LINE(return_type, controller, filename, \ - matchline, logstring, scan_fmt, variable) \ - return_type variable; \ -{ \ - int err; \ - err = subsystem_file_line_contents(controller, \ - filename, \ - matchline, \ - scan_fmt, \ - &variable); \ - if (err != 0) \ - return (return_type) OSCONTAINER_ERROR; \ - \ - log_trace(os, container)(logstring, variable); \ -} +class CgroupController: public CHeapObj { + protected: + char* _cgroup_path; + char* _mount_point; + public: + virtual const char* subsystem_path() = 0; + virtual bool is_read_only() = 0; + const char* cgroup_path() { return _cgroup_path; } + const char* mount_point() { return _mount_point; } + virtual bool needs_hierarchy_adjustment() { return false; } + + /* Read a numerical value as unsigned long + * + * returns: false if any error occurred. true otherwise and + * the parsed value is set in the provided julong pointer. + */ + bool read_number(const char* filename, julong* result); + + /* Convenience method to deal with numbers as well as the string 'max' + * in interface files. Otherwise same as read_number(). + * + * returns: false if any error occurred. true otherwise and + * the parsed value (which might be negative) is being set in + * the provided jlong pointer. + */ + bool read_number_handle_max(const char* filename, jlong* result); + + /* Read a string of at most buf_size - 1 characters from the interface file. + * The provided buffer must be at least buf_size in size so as to account + * for the null terminating character. Callers must ensure that the buffer + * is appropriately in-scope and of sufficient size. + * + * returns: false if any error occured. true otherwise and the passed + * in buffer will contain the first buf_size - 1 characters of the string + * or up to the first new line character ('\n') whichever comes first. + */ + bool read_string(const char* filename, char* buf, size_t buf_size); + + /* Read a tuple value as a number. Tuple is: ' '. + * Handles 'max' (for unlimited) for any tuple value. This is handy for + * parsing interface files like cpu.max which contain such tuples. + * + * returns: false if any error occurred. true otherwise and the parsed + * value of the appropriate tuple entry set in the provided jlong pointer. + */ + bool read_numerical_tuple_value(const char* filename, bool use_first, jlong* result); + + /* Read a numerical value from a multi-line interface file. The matched line is + * determined by the provided 'key'. The associated numerical value is being set + * via the passed in julong pointer. Example interface file 'memory.stat' + * + * returns: false if any error occurred. true otherwise and the parsed value is + * being set in the provided julong pointer. + */ + bool read_numerical_key_value(const char* filename, const char* key, julong* result); + private: + static jlong limit_from_str(char* limit_str); +}; class CachedMetric : public CHeapObj{ private: @@ -236,45 +186,81 @@ } }; +template class CachingCgroupController : public CHeapObj { private: - CgroupController* _controller; + T* _controller; CachedMetric* _metrics_cache; public: - CachingCgroupController(CgroupController* cont) { + CachingCgroupController(T* cont) { _controller = cont; _metrics_cache = new CachedMetric(); } CachedMetric* metrics_cache() { return _metrics_cache; } - CgroupController* controller() { return _controller; } + T* controller() { return _controller; } +}; + +// Pure virtual class representing version agnostic CPU controllers +class CgroupCpuController: public CHeapObj { + public: + virtual int cpu_quota() = 0; + virtual int cpu_period() = 0; + virtual int cpu_shares() = 0; + virtual bool needs_hierarchy_adjustment() = 0; + virtual bool is_read_only() = 0; + virtual const char* subsystem_path() = 0; + virtual void set_subsystem_path(const char* cgroup_path) = 0; + virtual const char* mount_point() = 0; + virtual const char* cgroup_path() = 0; +}; + +// Pure virtual class representing version agnostic memory controllers +class CgroupMemoryController: public CHeapObj { + public: + virtual jlong read_memory_limit_in_bytes(julong upper_bound) = 0; + virtual jlong memory_usage_in_bytes() = 0; + virtual jlong memory_and_swap_limit_in_bytes(julong host_mem, julong host_swap) = 0; + virtual jlong memory_soft_limit_in_bytes(julong upper_bound) = 0; + virtual jlong memory_max_usage_in_bytes() = 0; + virtual jlong rss_usage_in_bytes() = 0; + virtual jlong cache_usage_in_bytes() = 0; + virtual void print_version_specific_info(outputStream* st, julong host_mem) = 0; + virtual bool needs_hierarchy_adjustment() = 0; + virtual bool is_read_only() = 0; + virtual const char* subsystem_path() = 0; + virtual void set_subsystem_path(const char* cgroup_path) = 0; + virtual const char* mount_point() = 0; + virtual const char* cgroup_path() = 0; }; class CgroupSubsystem: public CHeapObj { public: jlong memory_limit_in_bytes(); int active_processor_count(); - jlong limit_from_str(char* limit_str); - virtual int cpu_quota() = 0; - virtual int cpu_period() = 0; - virtual int cpu_shares() = 0; virtual jlong pids_max() = 0; virtual jlong pids_current() = 0; - virtual jlong memory_usage_in_bytes() = 0; - virtual jlong memory_and_swap_limit_in_bytes() = 0; - virtual jlong memory_soft_limit_in_bytes() = 0; - virtual jlong memory_max_usage_in_bytes() = 0; + virtual bool is_containerized() = 0; virtual char * cpu_cpuset_cpus() = 0; virtual char * cpu_cpuset_memory_nodes() = 0; - virtual jlong read_memory_limit_in_bytes() = 0; virtual const char * container_type() = 0; - virtual CachingCgroupController* memory_controller() = 0; - virtual CachingCgroupController* cpu_controller() = 0; + virtual CachingCgroupController* memory_controller() = 0; + virtual CachingCgroupController* cpu_controller() = 0; - virtual void print_version_specific_info(outputStream* st) = 0; + int cpu_quota(); + int cpu_period(); + int cpu_shares(); + + jlong memory_usage_in_bytes(); + jlong memory_and_swap_limit_in_bytes(); + jlong memory_soft_limit_in_bytes(); + jlong memory_max_usage_in_bytes(); + jlong rss_usage_in_bytes(); + jlong cache_usage_in_bytes(); + void print_version_specific_info(outputStream* st); }; // Utility class for storing info retrieved from /proc/cgroups, @@ -288,6 +274,7 @@ char* _name; int _hierarchy_id; bool _enabled; + bool _read_only; // whether or not the mount path is mounted read-only bool _data_complete; // indicating cgroup v1 data is complete for this controller char* _cgroup_path; // cgroup controller path from /proc/self/cgroup char* _root_mount_path; // root mount path from /proc/self/mountinfo. Unused for cgroup v2 @@ -298,6 +285,7 @@ _name = nullptr; _hierarchy_id = -1; _enabled = false; + _read_only = false; _data_complete = false; _cgroup_path = nullptr; _root_mount_path = nullptr; @@ -329,7 +317,8 @@ int controller, const char* name, char* mount_path, - char* root_path); + char* root_path, + bool read_only); // Determine the cgroup type (version 1 or version 2), given // relevant paths to files. Sets 'flags' accordingly. static bool determine_type(CgroupInfo* cg_infos, diff -Nru openjdk-21-21.0.8+9/src/hotspot/os/linux/cgroupUtil_linux.cpp openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupUtil_linux.cpp --- openjdk-21-21.0.8+9/src/hotspot/os/linux/cgroupUtil_linux.cpp 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupUtil_linux.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2024, Red Hat, Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "os_linux.hpp" +#include "cgroupUtil_linux.hpp" + +int CgroupUtil::processor_count(CgroupCpuController* cpu_ctrl, int host_cpus) { + assert(host_cpus > 0, "physical host cpus must be positive"); + int limit_count = host_cpus; + int quota = cpu_ctrl->cpu_quota(); + int period = cpu_ctrl->cpu_period(); + int quota_count = 0; + int result = 0; + + if (quota > -1 && period > 0) { + quota_count = ceilf((float)quota / (float)period); + log_trace(os, container)("CPU Quota count based on quota/period: %d", quota_count); + } + + // Use quotas + if (quota_count != 0) { + limit_count = quota_count; + } + + result = MIN2(host_cpus, limit_count); + log_trace(os, container)("OSContainer::active_processor_count: %d", result); + return result; +} + +void CgroupUtil::adjust_controller(CgroupMemoryController* mem) { + if (!mem->needs_hierarchy_adjustment()) { + // nothing to do + return; + } + log_trace(os, container)("Adjusting controller path for memory: %s", mem->subsystem_path()); + assert(mem->cgroup_path() != nullptr, "invariant"); + char* orig = os::strdup(mem->cgroup_path()); + char* cg_path = os::strdup(orig); + char* last_slash; + assert(cg_path[0] == '/', "cgroup path must start with '/'"); + julong phys_mem = os::Linux::physical_memory(); + char* limit_cg_path = nullptr; + jlong limit = mem->read_memory_limit_in_bytes(phys_mem); + jlong lowest_limit = phys_mem; + while ((last_slash = strrchr(cg_path, '/')) != cg_path) { + *last_slash = '\0'; // strip path + // update to shortened path and try again + mem->set_subsystem_path(cg_path); + limit = mem->read_memory_limit_in_bytes(phys_mem); + if (limit >= 0 && limit < lowest_limit) { + lowest_limit = limit; + os::free(limit_cg_path); // handles nullptr + limit_cg_path = os::strdup(cg_path); + } + } + // need to check limit at mount point + mem->set_subsystem_path("/"); + limit = mem->read_memory_limit_in_bytes(phys_mem); + if (limit >= 0 && limit < lowest_limit) { + lowest_limit = limit; + os::free(limit_cg_path); // handles nullptr + limit_cg_path = os::strdup("/"); + } + assert(lowest_limit >= 0, "limit must be positive"); + if ((julong)lowest_limit != phys_mem) { + // we've found a lower limit anywhere in the hierarchy, + // set the path to the limit path + assert(limit_cg_path != nullptr, "limit path must be set"); + mem->set_subsystem_path(limit_cg_path); + log_trace(os, container)("Adjusted controller path for memory to: %s. " + "Lowest limit was: " JLONG_FORMAT, + mem->subsystem_path(), + lowest_limit); + } else { + log_trace(os, container)("No lower limit found for memory in hierarchy %s, " + "adjusting to original path %s", + mem->mount_point(), orig); + mem->set_subsystem_path(orig); + } + os::free(cg_path); + os::free(orig); + os::free(limit_cg_path); +} + +void CgroupUtil::adjust_controller(CgroupCpuController* cpu) { + if (!cpu->needs_hierarchy_adjustment()) { + // nothing to do + return; + } + log_trace(os, container)("Adjusting controller path for cpu: %s", cpu->subsystem_path()); + assert(cpu->cgroup_path() != nullptr, "invariant"); + char* orig = os::strdup(cpu->cgroup_path()); + char* cg_path = os::strdup(orig); + char* last_slash; + assert(cg_path[0] == '/', "cgroup path must start with '/'"); + int host_cpus = os::Linux::active_processor_count(); + int cpus = CgroupUtil::processor_count(cpu, host_cpus); + int lowest_limit = host_cpus; + char* limit_cg_path = nullptr; + while ((last_slash = strrchr(cg_path, '/')) != cg_path) { + *last_slash = '\0'; // strip path + // update to shortened path and try again + cpu->set_subsystem_path(cg_path); + cpus = CgroupUtil::processor_count(cpu, host_cpus); + if (cpus != host_cpus && cpus < lowest_limit) { + lowest_limit = cpus; + os::free(limit_cg_path); // handles nullptr + limit_cg_path = os::strdup(cg_path); + } + } + // need to check limit at mount point + cpu->set_subsystem_path("/"); + cpus = CgroupUtil::processor_count(cpu, host_cpus); + if (cpus != host_cpus && cpus < lowest_limit) { + lowest_limit = cpus; + os::free(limit_cg_path); // handles nullptr + limit_cg_path = os::strdup(cg_path); + } + assert(lowest_limit >= 0, "limit must be positive"); + if (lowest_limit != host_cpus) { + // we've found a lower limit anywhere in the hierarchy, + // set the path to the limit path + assert(limit_cg_path != nullptr, "limit path must be set"); + cpu->set_subsystem_path(limit_cg_path); + log_trace(os, container)("Adjusted controller path for cpu to: %s. " + "Lowest limit was: %d", + cpu->subsystem_path(), + lowest_limit); + } else { + log_trace(os, container)("No lower limit found for cpu in hierarchy %s, " + "adjusting to original path %s", + cpu->mount_point(), orig); + cpu->set_subsystem_path(orig); + } + os::free(cg_path); + os::free(orig); + os::free(limit_cg_path); +} diff -Nru openjdk-21-21.0.8+9/src/hotspot/os/linux/cgroupUtil_linux.hpp openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupUtil_linux.hpp --- openjdk-21-21.0.8+9/src/hotspot/os/linux/cgroupUtil_linux.hpp 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupUtil_linux.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024, Red Hat, Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CGROUP_UTIL_LINUX_HPP +#define CGROUP_UTIL_LINUX_HPP + +#include "utilities/globalDefinitions.hpp" +#include "cgroupSubsystem_linux.hpp" + +class CgroupUtil: AllStatic { + + public: + static int processor_count(CgroupCpuController* cpu, int host_cpus); + // Given a memory controller, adjust its path to a point in the hierarchy + // that represents the closest memory limit. + static void adjust_controller(CgroupMemoryController* m); + // Given a cpu controller, adjust its path to a point in the hierarchy + // that represents the closest cpu limit. + static void adjust_controller(CgroupCpuController* c); +}; + +#endif // CGROUP_UTIL_LINUX_HPP diff -Nru openjdk-21-21.0.8+9/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp --- openjdk-21-21.0.8+9/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -26,6 +26,7 @@ #include #include #include "cgroupV1Subsystem_linux.hpp" +#include "cgroupUtil_linux.hpp" #include "logging/log.hpp" #include "memory/allocation.hpp" #include "runtime/globals.hpp" @@ -37,7 +38,15 @@ * Set directory to subsystem specific files based * on the contents of the mountinfo and cgroup files. */ -void CgroupV1Controller::set_subsystem_path(char *cgroup_path) { +void CgroupV1Controller::set_subsystem_path(const char* cgroup_path) { + if (_cgroup_path != nullptr) { + os::free(_cgroup_path); + } + if (_path != nullptr) { + os::free(_path); + _path = nullptr; + } + _cgroup_path = os::strdup(cgroup_path); stringStream ss; if (_root != nullptr && cgroup_path != nullptr) { if (strcmp(_root, "/") == 0) { @@ -51,7 +60,7 @@ ss.print_raw(_mount_point); _path = os::strdup(ss.base()); } else { - char *p = strstr(cgroup_path, _root); + char *p = strstr((char*)cgroup_path, _root); if (p != nullptr && p == _root) { if (strlen(cgroup_path) > strlen(_root)) { ss.print_raw(_mount_point); @@ -65,48 +74,47 @@ } } -/* uses_mem_hierarchy - * - * Return whether or not hierarchical cgroup accounting is being - * done. - * - * return: - * A number > 0 if true, or - * OSCONTAINER_ERROR for not supported +/* + * The common case, containers, we have _root == _cgroup_path, and thus set the + * controller path to the _mount_point. This is where the limits are exposed in + * the cgroup pseudo filesystem (at the leaf) and adjustment of the path won't + * be needed for that reason. */ -jlong CgroupV1MemoryController::uses_mem_hierarchy() { - GET_CONTAINER_INFO(jlong, this, "/memory.use_hierarchy", - "Use Hierarchy is: ", JLONG_FORMAT, JLONG_FORMAT, use_hierarchy); - return use_hierarchy; -} - -void CgroupV1MemoryController::set_subsystem_path(char *cgroup_path) { - CgroupV1Controller::set_subsystem_path(cgroup_path); - jlong hierarchy = uses_mem_hierarchy(); - if (hierarchy > 0) { - set_hierarchical(true); - } +bool CgroupV1Controller::needs_hierarchy_adjustment() { + assert(_cgroup_path != nullptr, "sanity"); + return strcmp(_root, _cgroup_path) != 0; } -jlong CgroupV1Subsystem::read_memory_limit_in_bytes() { - GET_CONTAINER_INFO(julong, _memory->controller(), "/memory.limit_in_bytes", - "Memory Limit is: ", JULONG_FORMAT, JULONG_FORMAT, memlimit); - - if (memlimit >= os::Linux::physical_memory()) { - log_trace(os, container)("Non-Hierarchical Memory Limit is: Unlimited"); - CgroupV1MemoryController* mem_controller = reinterpret_cast(_memory->controller()); - if (mem_controller->is_hierarchical()) { - GET_CONTAINER_INFO_LINE(julong, _memory->controller(), "/memory.stat", "hierarchical_memory_limit", - "Hierarchical Memory Limit is: " JULONG_FORMAT, JULONG_FORMAT, hier_memlimit) - if (hier_memlimit >= os::Linux::physical_memory()) { - log_trace(os, container)("Hierarchical Memory Limit is: Unlimited"); +static inline +void verbose_log(julong read_mem_limit, julong host_mem) { + if (log_is_enabled(Debug, os, container)) { + jlong mem_limit = (jlong)read_mem_limit; // account for negative values + if (mem_limit < 0 || read_mem_limit >= host_mem) { + const char *reason; + if (mem_limit == OSCONTAINER_ERROR) { + reason = "failed"; + } else if (mem_limit == -1) { + reason = "unlimited"; } else { - return (jlong)hier_memlimit; + assert(read_mem_limit >= host_mem, "Expected read value exceeding host_mem"); + // Exceeding physical memory is treated as unlimited. This implementation + // caps it at host_mem since Cg v1 has no value to represent 'max'. + reason = "ignored"; } + log_debug(os, container)("container memory limit %s: " JLONG_FORMAT ", using host value " JLONG_FORMAT, + reason, mem_limit, host_mem); } - return (jlong)-1; } - else { +} + +jlong CgroupV1MemoryController::read_memory_limit_in_bytes(julong phys_mem) { + julong memlimit; + CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.limit_in_bytes", "Memory Limit", memlimit); + if (memlimit >= phys_mem) { + verbose_log(memlimit, phys_mem); + return (jlong)-1; + } else { + verbose_log(memlimit, phys_mem); return (jlong)memlimit; } } @@ -123,32 +131,19 @@ * * -1 if there isn't any limit in place (note: includes values which exceed a physical * upper bound) */ -jlong CgroupV1Subsystem::read_mem_swap() { - julong host_total_memsw; - GET_CONTAINER_INFO(julong, _memory->controller(), "/memory.memsw.limit_in_bytes", - "Memory and Swap Limit is: ", JULONG_FORMAT, JULONG_FORMAT, memswlimit); - host_total_memsw = os::Linux::host_swap() + os::Linux::physical_memory(); +jlong CgroupV1MemoryController::read_mem_swap(julong host_total_memsw) { + julong memswlimit; + CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.memsw.limit_in_bytes", "Memory and Swap Limit", memswlimit); if (memswlimit >= host_total_memsw) { - log_trace(os, container)("Non-Hierarchical Memory and Swap Limit is: Unlimited"); - CgroupV1MemoryController* mem_controller = reinterpret_cast(_memory->controller()); - if (mem_controller->is_hierarchical()) { - const char* matchline = "hierarchical_memsw_limit"; - GET_CONTAINER_INFO_LINE(julong, _memory->controller(), "/memory.stat", matchline, - "Hierarchical Memory and Swap Limit is : " JULONG_FORMAT, JULONG_FORMAT, hier_memswlimit) - if (hier_memswlimit >= host_total_memsw) { - log_trace(os, container)("Hierarchical Memory and Swap Limit is: Unlimited"); - } else { - return (jlong)hier_memswlimit; - } - } + log_trace(os, container)("Memory and Swap Limit is: Unlimited"); return (jlong)-1; } else { return (jlong)memswlimit; } } -jlong CgroupV1Subsystem::memory_and_swap_limit_in_bytes() { - jlong memory_swap = read_mem_swap(); +jlong CgroupV1MemoryController::memory_and_swap_limit_in_bytes(julong host_mem, julong host_swap) { + jlong memory_swap = read_mem_swap(host_mem + host_swap); if (memory_swap == -1) { return memory_swap; } @@ -157,7 +152,7 @@ // supported. jlong swappiness = read_mem_swappiness(); if (swappiness == 0 || memory_swap == OSCONTAINER_ERROR) { - jlong memlimit = read_memory_limit_in_bytes(); + jlong memlimit = read_memory_limit_in_bytes(host_mem); if (memory_swap == OSCONTAINER_ERROR) { log_trace(os, container)("Memory and Swap Limit has been reset to " JLONG_FORMAT " because swap is not supported", memlimit); } else { @@ -168,16 +163,23 @@ return memory_swap; } -jlong CgroupV1Subsystem::read_mem_swappiness() { - GET_CONTAINER_INFO(julong, _memory->controller(), "/memory.swappiness", - "Swappiness is: ", JULONG_FORMAT, JULONG_FORMAT, swappiness); - return swappiness; -} - -jlong CgroupV1Subsystem::memory_soft_limit_in_bytes() { - GET_CONTAINER_INFO(julong, _memory->controller(), "/memory.soft_limit_in_bytes", - "Memory Soft Limit is: ", JULONG_FORMAT, JULONG_FORMAT, memsoftlimit); - if (memsoftlimit >= os::Linux::physical_memory()) { +static inline +jlong memory_swap_usage_impl(CgroupController* ctrl) { + julong memory_swap_usage; + CONTAINER_READ_NUMBER_CHECKED(ctrl, "/memory.memsw.usage_in_bytes", "mem swap usage", memory_swap_usage); + return (jlong)memory_swap_usage; +} + +jlong CgroupV1MemoryController::read_mem_swappiness() { + julong swappiness; + CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.swappiness", "Swappiness", swappiness); + return (jlong)swappiness; +} + +jlong CgroupV1MemoryController::memory_soft_limit_in_bytes(julong phys_mem) { + julong memsoftlimit; + CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.soft_limit_in_bytes", "Memory Soft Limit", memsoftlimit); + if (memsoftlimit >= phys_mem) { log_trace(os, container)("Memory Soft Limit is: Unlimited"); return (jlong)-1; } else { @@ -185,6 +187,32 @@ } } +// Constructor +CgroupV1Subsystem::CgroupV1Subsystem(CgroupV1Controller* cpuset, + CgroupV1CpuController* cpu, + CgroupV1Controller* cpuacct, + CgroupV1Controller* pids, + CgroupV1MemoryController* memory) : + _cpuset(cpuset), + _cpuacct(cpuacct), + _pids(pids) { + CgroupUtil::adjust_controller(memory); + CgroupUtil::adjust_controller(cpu); + _memory = new CachingCgroupController(memory); + _cpu = new CachingCgroupController(cpu); +} + +bool CgroupV1Subsystem::is_containerized() { + // containerized iff all required controllers are mounted + // read-only. See OSContainer::is_containerized() for + // the full logic. + // + return _memory->controller()->is_read_only() && + _cpu->controller()->is_read_only() && + _cpuacct->is_read_only() && + _cpuset->is_read_only(); +} + /* memory_usage_in_bytes * * Return the amount of used memory for this process. @@ -194,10 +222,10 @@ * -1 for unlimited * OSCONTAINER_ERROR for not supported */ -jlong CgroupV1Subsystem::memory_usage_in_bytes() { - GET_CONTAINER_INFO(jlong, _memory->controller(), "/memory.usage_in_bytes", - "Memory Usage is: ", JLONG_FORMAT, JLONG_FORMAT, memusage); - return memusage; +jlong CgroupV1MemoryController::memory_usage_in_bytes() { + julong memusage; + CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.usage_in_bytes", "Memory Usage", memusage); + return (jlong)memusage; } /* memory_max_usage_in_bytes @@ -208,37 +236,60 @@ * max memory usage in bytes or * OSCONTAINER_ERROR for not supported */ -jlong CgroupV1Subsystem::memory_max_usage_in_bytes() { - GET_CONTAINER_INFO(jlong, _memory->controller(), "/memory.max_usage_in_bytes", - "Maximum Memory Usage is: ", JLONG_FORMAT, JLONG_FORMAT, memmaxusage); - return memmaxusage; +jlong CgroupV1MemoryController::memory_max_usage_in_bytes() { + julong memmaxusage; + CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.max_usage_in_bytes", "Maximum Memory Usage", memmaxusage); + return (jlong)memmaxusage; +} + +jlong CgroupV1MemoryController::rss_usage_in_bytes() { + julong rss; + bool is_ok = reader()->read_numerical_key_value("/memory.stat", + "rss", + &rss); + if (!is_ok) { + return OSCONTAINER_ERROR; + } + log_trace(os, container)("RSS usage is: " JULONG_FORMAT, rss); + return (jlong)rss; } +jlong CgroupV1MemoryController::cache_usage_in_bytes() { + julong cache; + bool is_ok = reader()->read_numerical_key_value("/memory.stat", + "cache", + &cache); + if (!is_ok) { + return OSCONTAINER_ERROR; + } + log_trace(os, container)("Cache usage is: " JULONG_FORMAT, cache); + return (jlong)cache; +} -jlong CgroupV1Subsystem::kernel_memory_usage_in_bytes() { - GET_CONTAINER_INFO(jlong, _memory->controller(), "/memory.kmem.usage_in_bytes", - "Kernel Memory Usage is: ", JLONG_FORMAT, JLONG_FORMAT, kmem_usage); - return kmem_usage; +jlong CgroupV1MemoryController::kernel_memory_usage_in_bytes() { + julong kmem_usage; + CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.kmem.usage_in_bytes", "Kernel Memory Usage", kmem_usage); + return (jlong)kmem_usage; } -jlong CgroupV1Subsystem::kernel_memory_limit_in_bytes() { - GET_CONTAINER_INFO(julong, _memory->controller(), "/memory.kmem.limit_in_bytes", - "Kernel Memory Limit is: ", JULONG_FORMAT, JULONG_FORMAT, kmem_limit); - if (kmem_limit >= os::Linux::physical_memory()) { +jlong CgroupV1MemoryController::kernel_memory_limit_in_bytes(julong phys_mem) { + julong kmem_limit; + CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.kmem.limit_in_bytes", "Kernel Memory Limit", kmem_limit); + if (kmem_limit >= phys_mem) { return (jlong)-1; } return (jlong)kmem_limit; } -jlong CgroupV1Subsystem::kernel_memory_max_usage_in_bytes() { - GET_CONTAINER_INFO(jlong, _memory->controller(), "/memory.kmem.max_usage_in_bytes", - "Maximum Kernel Memory Usage is: ", JLONG_FORMAT, JLONG_FORMAT, kmem_max_usage); - return kmem_max_usage; +jlong CgroupV1MemoryController::kernel_memory_max_usage_in_bytes() { + julong kmem_max_usage; + CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.kmem.max_usage_in_bytes", "Maximum Kernel Memory Usage", kmem_max_usage); + return (jlong)kmem_max_usage; } -void CgroupV1Subsystem::print_version_specific_info(outputStream* st) { +void CgroupV1MemoryController::print_version_specific_info(outputStream* st, julong phys_mem) { jlong kmem_usage = kernel_memory_usage_in_bytes(); - jlong kmem_limit = kernel_memory_limit_in_bytes(); + jlong kmem_limit = kernel_memory_limit_in_bytes(phys_mem); jlong kmem_max_usage = kernel_memory_max_usage_in_bytes(); OSContainer::print_container_helper(st, kmem_limit, "kernel_memory_limit_in_bytes"); @@ -246,15 +297,15 @@ OSContainer::print_container_helper(st, kmem_max_usage, "kernel_memory_max_usage_in_bytes"); } -char * CgroupV1Subsystem::cpu_cpuset_cpus() { - GET_CONTAINER_INFO_CPTR(cptr, _cpuset, "/cpuset.cpus", - "cpuset.cpus is: %s", "%1023s", cpus, 1024); +char* CgroupV1Subsystem::cpu_cpuset_cpus() { + char cpus[1024]; + CONTAINER_READ_STRING_CHECKED(_cpuset, "/cpuset.cpus", "cpuset.cpus", cpus, 1024); return os::strdup(cpus); } -char * CgroupV1Subsystem::cpu_cpuset_memory_nodes() { - GET_CONTAINER_INFO_CPTR(cptr, _cpuset, "/cpuset.mems", - "cpuset.mems is: %s", "%1023s", mems, 1024); +char* CgroupV1Subsystem::cpu_cpuset_memory_nodes() { + char mems[1024]; + CONTAINER_READ_STRING_CHECKED(_cpuset, "/cpuset.mems", "cpuset.mems", mems, 1024); return os::strdup(mems); } @@ -268,16 +319,24 @@ * -1 for no quota * OSCONTAINER_ERROR for not supported */ -int CgroupV1Subsystem::cpu_quota() { - GET_CONTAINER_INFO(int, _cpu->controller(), "/cpu.cfs_quota_us", - "CPU Quota is: ", "%d", "%d", quota); - return quota; +int CgroupV1CpuController::cpu_quota() { + julong quota; + bool is_ok = reader()->read_number("/cpu.cfs_quota_us", "a); + if (!is_ok) { + log_trace(os, container)("CPU Quota failed: %d", OSCONTAINER_ERROR); + return OSCONTAINER_ERROR; + } + // cast to int since the read value might be negative + // and we want to avoid logging -1 as a large unsigned value. + int quota_int = (int)quota; + log_trace(os, container)("CPU Quota is: %d", quota_int); + return quota_int; } -int CgroupV1Subsystem::cpu_period() { - GET_CONTAINER_INFO(int, _cpu->controller(), "/cpu.cfs_period_us", - "CPU Period is: ", "%d", "%d", period); - return period; +int CgroupV1CpuController::cpu_period() { + julong period; + CONTAINER_READ_NUMBER_CHECKED(reader(), "/cpu.cfs_period_us", "CPU Period", period); + return (int)period; } /* cpu_shares @@ -290,20 +349,14 @@ * -1 for no share setup * OSCONTAINER_ERROR for not supported */ -int CgroupV1Subsystem::cpu_shares() { - GET_CONTAINER_INFO(int, _cpu->controller(), "/cpu.shares", - "CPU Shares is: ", "%d", "%d", shares); +int CgroupV1CpuController::cpu_shares() { + julong shares; + CONTAINER_READ_NUMBER_CHECKED(reader(), "/cpu.shares", "CPU Shares", shares); + int shares_int = (int)shares; // Convert 1024 to no shares setup - if (shares == 1024) return -1; - - return shares; -} - + if (shares_int == 1024) return -1; -char* CgroupV1Subsystem::pids_max_val() { - GET_CONTAINER_INFO_CPTR(cptr, _pids, "/pids.max", - "Maximum number of tasks is: %s", "%1023s", pidsmax, 1024); - return os::strdup(pidsmax); + return shares_int; } /* pids_max @@ -317,8 +370,9 @@ */ jlong CgroupV1Subsystem::pids_max() { if (_pids == nullptr) return OSCONTAINER_ERROR; - char * pidsmax_str = pids_max_val(); - return limit_from_str(pidsmax_str); + jlong pids_max; + CONTAINER_READ_NUMBER_CHECKED_MAX(_pids, "/pids.max", "Maximum number of tasks", pids_max); + return pids_max; } /* pids_current @@ -331,7 +385,7 @@ */ jlong CgroupV1Subsystem::pids_current() { if (_pids == nullptr) return OSCONTAINER_ERROR; - GET_CONTAINER_INFO(jlong, _pids, "/pids.current", - "Current number of tasks is: ", JLONG_FORMAT, JLONG_FORMAT, pids_current); - return pids_current; + julong pids_current; + CONTAINER_READ_NUMBER_CHECKED(_pids, "/pids.current", "Current number of tasks", pids_current); + return (jlong)pids_current; } diff -Nru openjdk-21-21.0.8+9/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp --- openjdk-21-21.0.8+9/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,57 +28,125 @@ #include "runtime/os.hpp" #include "memory/allocation.hpp" #include "cgroupSubsystem_linux.hpp" +#include "cgroupUtil_linux.hpp" // Cgroups version 1 specific implementation class CgroupV1Controller: public CgroupController { private: /* mountinfo contents */ - char *_root; - char *_mount_point; + char* _root; + bool _read_only; /* Constructed subsystem directory */ - char *_path; + char* _path; public: - CgroupV1Controller(char *root, char *mountpoint) { - _root = os::strdup(root); + CgroupV1Controller(char *root, + char *mountpoint, + bool ro) : _root(os::strdup(root)), + _read_only(ro), + _path(nullptr) { + _cgroup_path = nullptr; _mount_point = os::strdup(mountpoint); - _path = nullptr; + } + // Shallow copy constructor + CgroupV1Controller(const CgroupV1Controller& o) : _root(o._root), + _read_only(o._read_only), + _path(o._path) { + _cgroup_path = o._cgroup_path; + _mount_point = o._mount_point; + } + ~CgroupV1Controller() { + // At least one subsystem controller exists with paths to malloc'd path + // names } - virtual void set_subsystem_path(char *cgroup_path); - char *subsystem_path() { return _path; } + void set_subsystem_path(const char *cgroup_path); + const char* subsystem_path() override { return _path; } + bool is_read_only() override { return _read_only; } + bool needs_hierarchy_adjustment() override; }; -class CgroupV1MemoryController: public CgroupV1Controller { +class CgroupV1MemoryController final : public CgroupMemoryController { + private: + CgroupV1Controller _reader; + CgroupV1Controller* reader() { return &_reader; } public: - bool is_hierarchical() { return _uses_mem_hierarchy; } - void set_subsystem_path(char *cgroup_path); + void set_subsystem_path(const char *cgroup_path) override { + reader()->set_subsystem_path(cgroup_path); + } + jlong read_memory_limit_in_bytes(julong upper_bound) override; + jlong memory_usage_in_bytes() override; + jlong memory_and_swap_limit_in_bytes(julong host_mem, julong host_swap) override; + jlong memory_soft_limit_in_bytes(julong upper_bound) override; + jlong memory_max_usage_in_bytes() override; + jlong rss_usage_in_bytes() override; + jlong cache_usage_in_bytes() override; + jlong kernel_memory_usage_in_bytes(); + jlong kernel_memory_limit_in_bytes(julong host_mem); + jlong kernel_memory_max_usage_in_bytes(); + void print_version_specific_info(outputStream* st, julong host_mem) override; + bool needs_hierarchy_adjustment() override { + return reader()->needs_hierarchy_adjustment(); + } + bool is_read_only() override { + return reader()->is_read_only(); + } + const char* subsystem_path() override { return reader()->subsystem_path(); } + const char* mount_point() override { return reader()->mount_point(); } + const char* cgroup_path() override { return reader()->cgroup_path(); } private: - /* Some container runtimes set limits via cgroup - * hierarchy. If set to true consider also memory.stat - * file if everything else seems unlimited */ - bool _uses_mem_hierarchy; - jlong uses_mem_hierarchy(); - void set_hierarchical(bool value) { _uses_mem_hierarchy = value; } + jlong read_mem_swappiness(); + jlong read_mem_swap(julong host_total_memsw); public: - CgroupV1MemoryController(char *root, char *mountpoint) : CgroupV1Controller(root, mountpoint) { - _uses_mem_hierarchy = false; + CgroupV1MemoryController(const CgroupV1Controller& reader) + : _reader(reader) { + } + +}; + +class CgroupV1CpuController final : public CgroupCpuController { + + private: + CgroupV1Controller _reader; + CgroupV1Controller* reader() { return &_reader; } + public: + int cpu_quota() override; + int cpu_period() override; + int cpu_shares() override; + void set_subsystem_path(const char *cgroup_path) override { + reader()->set_subsystem_path(cgroup_path); + } + bool is_read_only() override { + return reader()->is_read_only(); + } + const char* subsystem_path() override { + return reader()->subsystem_path(); } + const char* mount_point() override { + return reader()->mount_point(); + } + bool needs_hierarchy_adjustment() override { + return reader()->needs_hierarchy_adjustment(); + } + const char* cgroup_path() override { return reader()->cgroup_path(); } + public: + CgroupV1CpuController(const CgroupV1Controller& reader) : _reader(reader) { + } }; class CgroupV1Subsystem: public CgroupSubsystem { public: - jlong read_memory_limit_in_bytes(); - jlong memory_and_swap_limit_in_bytes(); - jlong memory_soft_limit_in_bytes(); - jlong memory_usage_in_bytes(); - jlong memory_max_usage_in_bytes(); + CgroupV1Subsystem(CgroupV1Controller* cpuset, + CgroupV1CpuController* cpu, + CgroupV1Controller* cpuacct, + CgroupV1Controller* pids, + CgroupV1MemoryController* memory); jlong kernel_memory_usage_in_bytes(); jlong kernel_memory_limit_in_bytes(); @@ -87,47 +155,24 @@ char * cpu_cpuset_cpus(); char * cpu_cpuset_memory_nodes(); - int cpu_quota(); - int cpu_period(); - - int cpu_shares(); - jlong pids_max(); jlong pids_current(); - - void print_version_specific_info(outputStream* st); + bool is_containerized(); const char * container_type() { return "cgroupv1"; } - CachingCgroupController * memory_controller() { return _memory; } - CachingCgroupController * cpu_controller() { return _cpu; } + CachingCgroupController* memory_controller() { return _memory; } + CachingCgroupController* cpu_controller() { return _cpu; } private: /* controllers */ - CachingCgroupController* _memory = nullptr; + CachingCgroupController* _memory = nullptr; CgroupV1Controller* _cpuset = nullptr; - CachingCgroupController* _cpu = nullptr; + CachingCgroupController* _cpu = nullptr; CgroupV1Controller* _cpuacct = nullptr; CgroupV1Controller* _pids = nullptr; - char * pids_max_val(); - - jlong read_mem_swappiness(); - jlong read_mem_swap(); - - public: - CgroupV1Subsystem(CgroupV1Controller* cpuset, - CgroupV1Controller* cpu, - CgroupV1Controller* cpuacct, - CgroupV1Controller* pids, - CgroupV1MemoryController* memory) { - _cpuset = cpuset; - _cpu = new CachingCgroupController(cpu); - _cpuacct = cpuacct; - _pids = pids; - _memory = new CachingCgroupController(memory); - } }; #endif // CGROUP_V1_SUBSYSTEM_LINUX_HPP diff -Nru openjdk-21-21.0.8+9/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp --- openjdk-21-21.0.8+9/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -23,6 +23,23 @@ */ #include "cgroupV2Subsystem_linux.hpp" +#include "cgroupUtil_linux.hpp" + +// Constructor +CgroupV2Controller::CgroupV2Controller(char* mount_path, + char *cgroup_path, + bool ro) : _read_only(ro), + _path(construct_path(mount_path, cgroup_path)) { + _cgroup_path = os::strdup(cgroup_path); + _mount_point = os::strdup(mount_path); +} +// Shallow copy constructor +CgroupV2Controller::CgroupV2Controller(const CgroupV2Controller& o) : + _read_only(o._read_only), + _path(o._path) { + _cgroup_path = o._cgroup_path; + _mount_point = o._mount_point; +} /* cpu_shares * @@ -34,11 +51,12 @@ * -1 for no share setup * OSCONTAINER_ERROR for not supported */ -int CgroupV2Subsystem::cpu_shares() { - GET_CONTAINER_INFO(int, _unified, "/cpu.weight", - "Raw value for CPU Shares is: ", "%d", "%d", shares); +int CgroupV2CpuController::cpu_shares() { + julong shares; + CONTAINER_READ_NUMBER_CHECKED(reader(), "/cpu.weight", "Raw value for CPU Shares", shares); + int shares_int = (int)shares; // Convert default value of 100 to no shares setup - if (shares == 100) { + if (shares_int == 100) { log_debug(os, container)("CPU Shares is: %d", -1); return -1; } @@ -50,7 +68,7 @@ // Use the inverse of (x == OCI value, y == cgroupsv2 value): // ((262142 * y - 1)/9999) + 2 = x // - int x = 262142 * shares - 1; + int x = 262142 * shares_int - 1; double frac = x/9999.0; x = ((int)frac) + 2; log_trace(os, container)("Scaled CPU shares value is: %d", x); @@ -82,34 +100,55 @@ * -1 for no quota * OSCONTAINER_ERROR for not supported */ -int CgroupV2Subsystem::cpu_quota() { - char * cpu_quota_str = cpu_quota_val(); - int limit = (int)limit_from_str(cpu_quota_str); +int CgroupV2CpuController::cpu_quota() { + jlong quota_val; + bool is_ok = reader()->read_numerical_tuple_value("/cpu.max", true /* use_first */, "a_val); + if (!is_ok) { + return OSCONTAINER_ERROR; + } + int limit = (int)quota_val; log_trace(os, container)("CPU Quota is: %d", limit); return limit; } -char * CgroupV2Subsystem::cpu_cpuset_cpus() { - GET_CONTAINER_INFO_CPTR(cptr, _unified, "/cpuset.cpus", - "cpuset.cpus is: %s", "%1023s", cpus, 1024); +// Constructor +CgroupV2Subsystem::CgroupV2Subsystem(CgroupV2MemoryController * memory, + CgroupV2CpuController* cpu, + CgroupV2Controller unified) : + _unified(unified) { + CgroupUtil::adjust_controller(memory); + CgroupUtil::adjust_controller(cpu); + _memory = new CachingCgroupController(memory); + _cpu = new CachingCgroupController(cpu); +} + +bool CgroupV2Subsystem::is_containerized() { + return _unified.is_read_only() && + _memory->controller()->is_read_only() && + _cpu->controller()->is_read_only(); +} + +char* CgroupV2Subsystem::cpu_cpuset_cpus() { + char cpus[1024]; + CONTAINER_READ_STRING_CHECKED(unified(), "/cpuset.cpus", "cpuset.cpus", cpus, 1024); return os::strdup(cpus); } -char* CgroupV2Subsystem::cpu_quota_val() { - GET_CONTAINER_INFO_CPTR(cptr, _unified, "/cpu.max", - "Raw value for CPU quota is: %s", "%1023s %*d", quota, 1024); - return os::strdup(quota); -} - -char * CgroupV2Subsystem::cpu_cpuset_memory_nodes() { - GET_CONTAINER_INFO_CPTR(cptr, _unified, "/cpuset.mems", - "cpuset.mems is: %s", "%1023s", mems, 1024); +char* CgroupV2Subsystem::cpu_cpuset_memory_nodes() { + char mems[1024]; + CONTAINER_READ_STRING_CHECKED(unified(), "/cpuset.mems", "cpuset.mems", mems, 1024); return os::strdup(mems); } -int CgroupV2Subsystem::cpu_period() { - GET_CONTAINER_INFO(int, _unified, "/cpu.max", - "CPU Period is: ", "%d", "%*s %d", period); +int CgroupV2CpuController::cpu_period() { + jlong period_val; + bool is_ok = reader()->read_numerical_tuple_value("/cpu.max", false /* use_first */, &period_val); + if (!is_ok) { + log_trace(os, container)("CPU Period failed: %d", OSCONTAINER_ERROR); + return OSCONTAINER_ERROR; + } + int period = (int)period_val; + log_trace(os, container)("CPU Period is: %d", period); return period; } @@ -122,27 +161,42 @@ * -1 for unlimited * OSCONTAINER_ERROR for not supported */ -jlong CgroupV2Subsystem::memory_usage_in_bytes() { - GET_CONTAINER_INFO(jlong, _unified, "/memory.current", - "Memory Usage is: ", JLONG_FORMAT, JLONG_FORMAT, memusage); - return memusage; +jlong CgroupV2MemoryController::memory_usage_in_bytes() { + julong memusage; + CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.current", "Memory Usage", memusage); + return (jlong)memusage; } -jlong CgroupV2Subsystem::memory_soft_limit_in_bytes() { - char* mem_soft_limit_str = mem_soft_limit_val(); - return limit_from_str(mem_soft_limit_str); +jlong CgroupV2MemoryController::memory_soft_limit_in_bytes(julong phys_mem) { + jlong mem_soft_limit; + CONTAINER_READ_NUMBER_CHECKED_MAX(reader(), "/memory.low", "Memory Soft Limit", mem_soft_limit); + return mem_soft_limit; } -jlong CgroupV2Subsystem::memory_max_usage_in_bytes() { +jlong CgroupV2MemoryController::memory_max_usage_in_bytes() { // Log this string at trace level so as to make tests happy. log_trace(os, container)("Maximum Memory Usage is not supported."); return OSCONTAINER_ERROR; // not supported } -char* CgroupV2Subsystem::mem_soft_limit_val() { - GET_CONTAINER_INFO_CPTR(cptr, _unified, "/memory.low", - "Memory Soft Limit is: %s", "%1023s", mem_soft_limit_str, 1024); - return os::strdup(mem_soft_limit_str); +jlong CgroupV2MemoryController::rss_usage_in_bytes() { + julong rss; + bool is_ok = reader()->read_numerical_key_value("/memory.stat", "anon", &rss); + if (!is_ok) { + return OSCONTAINER_ERROR; + } + log_trace(os, container)("RSS usage is: " JULONG_FORMAT, rss); + return (jlong)rss; +} + +jlong CgroupV2MemoryController::cache_usage_in_bytes() { + julong cache; + bool is_ok = reader()->read_numerical_key_value("/memory.stat", "file", &cache); + if (!is_ok) { + return OSCONTAINER_ERROR; + } + log_trace(os, container)("Cache usage is: " JULONG_FORMAT, cache); + return (jlong)cache; } // Note that for cgroups v2 the actual limits set for swap and @@ -150,17 +204,19 @@ // respectively. In order to properly report a cgroup v1 like // compound value we need to sum the two values. Setting a swap limit // without also setting a memory limit is not allowed. -jlong CgroupV2Subsystem::memory_and_swap_limit_in_bytes() { - char* mem_swp_limit_str = mem_swp_limit_val(); - if (mem_swp_limit_str == nullptr) { +jlong CgroupV2MemoryController::memory_and_swap_limit_in_bytes(julong phys_mem, + julong host_swap /* unused in cg v2 */) { + jlong swap_limit; + bool is_ok = reader()->read_number_handle_max("/memory.swap.max", &swap_limit); + if (!is_ok) { // Some container tests rely on this trace logging to happen. - log_trace(os, container)("Memory and Swap Limit is: %d", OSCONTAINER_ERROR); + log_trace(os, container)("Swap Limit failed: %d", OSCONTAINER_ERROR); // swap disabled at kernel level, treat it as no swap - return read_memory_limit_in_bytes(); + return read_memory_limit_in_bytes(phys_mem); } - jlong swap_limit = limit_from_str(mem_swp_limit_str); + log_trace(os, container)("Swap Limit is: " JLONG_FORMAT, swap_limit); if (swap_limit >= 0) { - jlong memory_limit = read_memory_limit_in_bytes(); + jlong memory_limit = read_memory_limit_in_bytes(phys_mem); assert(memory_limit >= 0, "swap limit without memory limit?"); return memory_limit + swap_limit; } @@ -168,20 +224,22 @@ return swap_limit; } -char* CgroupV2Subsystem::mem_swp_limit_val() { - GET_CONTAINER_INFO_CPTR(cptr, _unified, "/memory.swap.max", - "Memory and Swap Limit is: %s", "%1023s", mem_swp_limit_str, 1024); - return os::strdup(mem_swp_limit_str); +// memory.swap.current : total amount of swap currently used by the cgroup and its descendants +static +jlong memory_swap_current_value(CgroupV2Controller* ctrl) { + julong swap_current; + CONTAINER_READ_NUMBER_CHECKED(ctrl, "/memory.swap.current", "Swap currently used", swap_current); + return (jlong)swap_current; } -// memory.swap.current : total amount of swap currently used by the cgroup and its descendants -char* CgroupV2Subsystem::mem_swp_current_val() { - GET_CONTAINER_INFO_CPTR(cptr, _unified, "/memory.swap.current", - "Swap currently used is: %s", "%1023s", mem_swp_current_str, 1024); - return os::strdup(mem_swp_current_str); +static +jlong memory_limit_value(CgroupV2Controller* ctrl) { + jlong memory_limit; + CONTAINER_READ_NUMBER_CHECKED_MAX(ctrl, "/memory.max", "Memory Limit", memory_limit); + return memory_limit; } -/* memory_limit_in_bytes +/* read_memory_limit_in_bytes * * Return the limit of available memory for this process. * @@ -189,9 +247,8 @@ * memory limit in bytes or * -1 for unlimited, OSCONTAINER_ERROR for an error */ -jlong CgroupV2Subsystem::read_memory_limit_in_bytes() { - char * mem_limit_str = mem_limit_val(); - jlong limit = limit_from_str(mem_limit_str); +jlong CgroupV2MemoryController::read_memory_limit_in_bytes(julong phys_mem) { + jlong limit = memory_limit_value(reader()); if (log_is_enabled(Trace, os, container)) { if (limit == -1) { log_trace(os, container)("Memory Limit is: Unlimited"); @@ -199,27 +256,53 @@ log_trace(os, container)("Memory Limit is: " JLONG_FORMAT, limit); } } + if (log_is_enabled(Debug, os, container)) { + julong read_limit = (julong)limit; // avoid signed/unsigned compare + if (limit < 0 || read_limit >= phys_mem) { + const char* reason; + if (limit == -1) { + reason = "unlimited"; + } else if (limit == OSCONTAINER_ERROR) { + reason = "failed"; + } else { + assert(read_limit >= phys_mem, "Expected mem limit to exceed host memory"); + reason = "ignored"; + } + log_debug(os, container)("container memory limit %s: " JLONG_FORMAT ", using host value " JLONG_FORMAT, + reason, limit, phys_mem); + } + } return limit; } -char* CgroupV2Subsystem::mem_limit_val() { - GET_CONTAINER_INFO_CPTR(cptr, _unified, "/memory.max", - "Raw value for memory limit is: %s", "%1023s", mem_limit_str, 1024); - return os::strdup(mem_limit_str); +static +jlong memory_swap_limit_value(CgroupV2Controller* ctrl) { + jlong swap_limit; + CONTAINER_READ_NUMBER_CHECKED_MAX(ctrl, "/memory.swap.max", "Swap Limit", swap_limit); + return swap_limit; +} + +void CgroupV2Controller::set_subsystem_path(const char* cgroup_path) { + if (_path != nullptr) { + os::free(_path); + } + _path = construct_path(_mount_point, cgroup_path); } -void CgroupV2Subsystem::print_version_specific_info(outputStream* st) { - char* mem_swp_current_str = mem_swp_current_val(); - jlong swap_current = limit_from_str(mem_swp_current_str); +// For cgv2 we only need hierarchy walk if the cgroup path isn't '/' (root) +bool CgroupV2Controller::needs_hierarchy_adjustment() { + return strcmp(_cgroup_path, "/") != 0; +} - char* mem_swp_limit_str = mem_swp_limit_val(); - jlong swap_limit = limit_from_str(mem_swp_limit_str); +void CgroupV2MemoryController::print_version_specific_info(outputStream* st, julong phys_mem) { + jlong swap_current = memory_swap_current_value(reader()); + jlong swap_limit = memory_swap_limit_value(reader()); OSContainer::print_container_helper(st, swap_current, "memory_swap_current_in_bytes"); OSContainer::print_container_helper(st, swap_limit, "memory_swap_max_limit_in_bytes"); } -char* CgroupV2Controller::construct_path(char* mount_path, char *cgroup_path) { +char* CgroupV2Controller::construct_path(char* mount_path, const char* cgroup_path) { stringStream ss; ss.print_raw(mount_path); if (strcmp(cgroup_path, "/") != 0) { @@ -228,12 +311,6 @@ return os::strdup(ss.base()); } -char* CgroupV2Subsystem::pids_max_val() { - GET_CONTAINER_INFO_CPTR(cptr, _unified, "/pids.max", - "Maximum number of tasks is: %s", "%1023s", pidsmax, 1024); - return os::strdup(pidsmax); -} - /* pids_max * * Return the maximum number of tasks available to the process @@ -244,8 +321,9 @@ * OSCONTAINER_ERROR for not supported */ jlong CgroupV2Subsystem::pids_max() { - char * pidsmax_str = pids_max_val(); - return limit_from_str(pidsmax_str); + jlong pids_max; + CONTAINER_READ_NUMBER_CHECKED_MAX(unified(), "/pids.max", "Maximum number of tasks", pids_max); + return pids_max; } /* pids_current @@ -257,7 +335,7 @@ * OSCONTAINER_ERROR for not supported */ jlong CgroupV2Subsystem::pids_current() { - GET_CONTAINER_INFO(jlong, _unified, "/pids.current", - "Current number of tasks is: ", JLONG_FORMAT, JLONG_FORMAT, pids_current); + julong pids_current; + CONTAINER_READ_NUMBER_CHECKED(unified(), "/pids.current", "Current number of tasks", pids_current); return pids_current; } diff -Nru openjdk-21-21.0.8+9/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp --- openjdk-21-21.0.8+9/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Red Hat Inc. + * Copyright (c) 2020, 2024, Red Hat Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,71 +26,116 @@ #define CGROUP_V2_SUBSYSTEM_LINUX_HPP #include "cgroupSubsystem_linux.hpp" +#include "cgroupUtil_linux.hpp" class CgroupV2Controller: public CgroupController { private: - /* the mount path of the cgroup v2 hierarchy */ - char *_mount_path; - /* The cgroup path for the controller */ - char *_cgroup_path; + bool _read_only; /* Constructed full path to the subsystem directory */ char *_path; - static char* construct_path(char* mount_path, char *cgroup_path); + static char* construct_path(char* mount_path, const char *cgroup_path); public: - CgroupV2Controller(char * mount_path, char *cgroup_path) { - _mount_path = mount_path; - _cgroup_path = os::strdup(cgroup_path); - _path = construct_path(mount_path, cgroup_path); + CgroupV2Controller(char* mount_path, char *cgroup_path, bool ro); + // Shallow copy constructor + CgroupV2Controller(const CgroupV2Controller& o); + ~CgroupV2Controller() { + // At least one controller exists with references to the paths } - char *subsystem_path() { return _path; } + const char* subsystem_path() override { return _path; } + bool needs_hierarchy_adjustment() override; + // Allow for optional updates of the subsystem path + void set_subsystem_path(const char* cgroup_path); + bool is_read_only() override { return _read_only; } +}; + +class CgroupV2CpuController: public CgroupCpuController { + private: + CgroupV2Controller _reader; + CgroupV2Controller* reader() { return &_reader; } + public: + CgroupV2CpuController(const CgroupV2Controller& reader) : _reader(reader) { + } + int cpu_quota() override; + int cpu_period() override; + int cpu_shares() override; + bool is_read_only() override { + return reader()->is_read_only(); + } + const char* subsystem_path() override { + return reader()->subsystem_path(); + } + bool needs_hierarchy_adjustment() override { + return reader()->needs_hierarchy_adjustment(); + } + void set_subsystem_path(const char* cgroup_path) override { + reader()->set_subsystem_path(cgroup_path); + } + const char* mount_point() override { return reader()->mount_point(); } + const char* cgroup_path() override { return reader()->cgroup_path(); } +}; + +class CgroupV2MemoryController final: public CgroupMemoryController { + private: + CgroupV2Controller _reader; + CgroupV2Controller* reader() { return &_reader; } + public: + CgroupV2MemoryController(const CgroupV2Controller& reader) : _reader(reader) { + } + + jlong read_memory_limit_in_bytes(julong upper_bound) override; + jlong memory_and_swap_limit_in_bytes(julong host_mem, julong host_swp) override; + jlong memory_soft_limit_in_bytes(julong upper_bound) override; + jlong memory_usage_in_bytes() override; + jlong memory_max_usage_in_bytes() override; + jlong rss_usage_in_bytes() override; + jlong cache_usage_in_bytes() override; + void print_version_specific_info(outputStream* st, julong host_mem) override; + bool is_read_only() override { + return reader()->is_read_only(); + } + const char* subsystem_path() override { + return reader()->subsystem_path(); + } + bool needs_hierarchy_adjustment() override { + return reader()->needs_hierarchy_adjustment(); + } + void set_subsystem_path(const char* cgroup_path) override { + reader()->set_subsystem_path(cgroup_path); + } + const char* mount_point() override { return reader()->mount_point(); } + const char* cgroup_path() override { return reader()->cgroup_path(); } }; class CgroupV2Subsystem: public CgroupSubsystem { private: /* One unified controller */ - CgroupController* _unified = nullptr; + CgroupV2Controller _unified; /* Caching wrappers for cpu/memory metrics */ - CachingCgroupController* _memory = nullptr; - CachingCgroupController* _cpu = nullptr; + CachingCgroupController* _memory = nullptr; + CachingCgroupController* _cpu = nullptr; - char *mem_limit_val(); - char *mem_swp_limit_val(); - char *mem_swp_current_val(); - char *mem_soft_limit_val(); - char *cpu_quota_val(); - char *pids_max_val(); + CgroupV2Controller* unified() { return &_unified; } public: - CgroupV2Subsystem(CgroupController * unified) { - _unified = unified; - _memory = new CachingCgroupController(unified); - _cpu = new CachingCgroupController(unified); - } - - jlong read_memory_limit_in_bytes(); - int cpu_quota(); - int cpu_period(); - int cpu_shares(); - jlong memory_and_swap_limit_in_bytes(); - jlong memory_soft_limit_in_bytes(); - jlong memory_usage_in_bytes(); - jlong memory_max_usage_in_bytes(); - - char * cpu_cpuset_cpus(); - char * cpu_cpuset_memory_nodes(); - jlong pids_max(); - jlong pids_current(); + CgroupV2Subsystem(CgroupV2MemoryController * memory, + CgroupV2CpuController* cpu, + CgroupV2Controller unified); + + char * cpu_cpuset_cpus() override; + char * cpu_cpuset_memory_nodes() override; + jlong pids_max() override; + jlong pids_current() override; - void print_version_specific_info(outputStream* st); + bool is_containerized() override; - const char * container_type() { + const char * container_type() override { return "cgroupv2"; } - CachingCgroupController * memory_controller() { return _memory; } - CachingCgroupController * cpu_controller() { return _cpu; } + CachingCgroupController* memory_controller() override { return _memory; } + CachingCgroupController* cpu_controller() override { return _cpu; } }; #endif // CGROUP_V2_SUBSYSTEM_LINUX_HPP diff -Nru openjdk-21-21.0.8+9/src/hotspot/os/linux/osContainer_linux.cpp openjdk-21-21.0.9+10/src/hotspot/os/linux/osContainer_linux.cpp --- openjdk-21-21.0.8+9/src/hotspot/os/linux/osContainer_linux.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/os/linux/osContainer_linux.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -58,8 +58,43 @@ if (cgroup_subsystem == nullptr) { return; // Required subsystem files not found or other error } - - _is_containerized = true; + /* + * In order to avoid a false positive on is_containerized() on + * Linux systems outside a container *and* to ensure compatibility + * with in-container usage, we detemine is_containerized() by two + * steps: + * 1.) Determine if all the cgroup controllers are mounted read only. + * If yes, is_containerized() == true. Otherwise, do the fallback + * in 2.) + * 2.) Query for memory and cpu limits. If any limit is set, we set + * is_containerized() == true. + * + * Step 1.) covers the basic in container use-cases. Step 2.) ensures + * that limits enforced by other means (e.g. systemd slice) are properly + * detected. + */ + const char *reason; + bool any_mem_cpu_limit_present = false; + bool controllers_read_only = cgroup_subsystem->is_containerized(); + if (controllers_read_only) { + // in-container case + reason = " because all controllers are mounted read-only (container case)"; + } else { + // We can be in one of two cases: + // 1.) On a physical Linux system without any limit + // 2.) On a physical Linux system with a limit enforced by other means (like systemd slice) + any_mem_cpu_limit_present = cgroup_subsystem->memory_limit_in_bytes() > 0 || + os::Linux::active_processor_count() != cgroup_subsystem->active_processor_count(); + if (any_mem_cpu_limit_present) { + reason = " because either a cpu or a memory limit is present"; + } else { + reason = " because no cpu or memory limit is present"; + } + } + _is_containerized = controllers_read_only || any_mem_cpu_limit_present; + log_debug(os, container)("OSContainer::init: is_containerized() = %s%s", + _is_containerized ? "true" : "false", + reason); } const char * OSContainer::container_type() { @@ -92,6 +127,16 @@ return cgroup_subsystem->memory_max_usage_in_bytes(); } +jlong OSContainer::rss_usage_in_bytes() { + assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); + return cgroup_subsystem->rss_usage_in_bytes(); +} + +jlong OSContainer::cache_usage_in_bytes() { + assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); + return cgroup_subsystem->cache_usage_in_bytes(); +} + void OSContainer::print_version_specific_info(outputStream* st) { assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); cgroup_subsystem->print_version_specific_info(st); diff -Nru openjdk-21-21.0.8+9/src/hotspot/os/linux/osContainer_linux.hpp openjdk-21-21.0.9+10/src/hotspot/os/linux/osContainer_linux.hpp --- openjdk-21-21.0.8+9/src/hotspot/os/linux/osContainer_linux.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/os/linux/osContainer_linux.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -55,6 +55,8 @@ static jlong memory_soft_limit_in_bytes(); static jlong memory_usage_in_bytes(); static jlong memory_max_usage_in_bytes(); + static jlong rss_usage_in_bytes(); + static jlong cache_usage_in_bytes(); static int active_processor_count(); diff -Nru openjdk-21-21.0.8+9/src/hotspot/os/linux/os_linux.cpp openjdk-21-21.0.9+10/src/hotspot/os/linux/os_linux.cpp --- openjdk-21-21.0.8+9/src/hotspot/os/linux/os_linux.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/os/linux/os_linux.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -2380,6 +2380,8 @@ OSContainer::print_container_helper(st, OSContainer::memory_soft_limit_in_bytes(), "memory_soft_limit_in_bytes"); OSContainer::print_container_helper(st, OSContainer::memory_usage_in_bytes(), "memory_usage_in_bytes"); OSContainer::print_container_helper(st, OSContainer::memory_max_usage_in_bytes(), "memory_max_usage_in_bytes"); + OSContainer::print_container_helper(st, OSContainer::rss_usage_in_bytes(), "rss_usage_in_bytes"); + OSContainer::print_container_helper(st, OSContainer::cache_usage_in_bytes(), "cache_usage_in_bytes"); OSContainer::print_version_specific_info(st); diff -Nru openjdk-21-21.0.8+9/src/hotspot/os/posix/signals_posix.cpp openjdk-21-21.0.9+10/src/hotspot/os/posix/signals_posix.cpp --- openjdk-21-21.0.8+9/src/hotspot/os/posix/signals_posix.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/os/posix/signals_posix.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -48,6 +48,13 @@ #include +#define SEGV_BNDERR_value 3 + +#if defined(SEGV_BNDERR) +STATIC_ASSERT(SEGV_BNDERR == SEGV_BNDERR_value); +#else +#define SEGV_BNDERR SEGV_BNDERR_value +#endif static const char* get_signal_name(int sig, char* out, size_t outlen); @@ -981,6 +988,9 @@ { SIGFPE, FPE_FLTSUB, "FPE_FLTSUB", "Subscript out of range." }, { SIGSEGV, SEGV_MAPERR, "SEGV_MAPERR", "Address not mapped to object." }, { SIGSEGV, SEGV_ACCERR, "SEGV_ACCERR", "Invalid permissions for mapped object." }, +#if defined(LINUX) + { SIGSEGV, SEGV_BNDERR, "SEGV_BNDERR", "Failed address bound checks." }, +#endif #if defined(AIX) // no explanation found what keyerr would be { SIGSEGV, SEGV_KEYERR, "SEGV_KEYERR", "key error" }, diff -Nru openjdk-21-21.0.8+9/src/hotspot/os_cpu/aix_ppc/javaThread_aix_ppc.cpp openjdk-21-21.0.9+10/src/hotspot/os_cpu/aix_ppc/javaThread_aix_ppc.cpp --- openjdk-21-21.0.8+9/src/hotspot/os_cpu/aix_ppc/javaThread_aix_ppc.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/os_cpu/aix_ppc/javaThread_aix_ppc.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2014 SAP SE. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025 SAP SE. All rights reserved. * Copyright (c) 2022, IBM Corp. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -28,6 +28,7 @@ #include "memory/metaspace.hpp" #include "runtime/frame.inline.hpp" #include "runtime/javaThread.hpp" +#include "runtime/os.inline.hpp" frame JavaThread::pd_last_frame() { assert(has_last_Java_frame(), "must have last_Java_sp() when suspended"); @@ -47,9 +48,17 @@ if (has_last_Java_frame() && frame_anchor()->walkable()) { intptr_t* sp = last_Java_sp(); address pc = _anchor.last_Java_pc(); - // pc can be seen as null because not all writers use store pc + release store sp. - // Simply discard the sample in this very rare case. - if (pc == nullptr) return false; + if (pc == nullptr) { + // This is not uncommon. Many c1/c2 runtime stubs do not set the pc in the anchor. + intptr_t* top_sp = os::Aix::ucontext_get_sp((const ucontext_t*)ucontext); + if ((uint64_t)sp <= ((frame::common_abi*)top_sp)->callers_sp) { + // The interrupt occurred either in the last java frame or in its direct callee. + // We cannot be sure that the link register LR was already saved to the + // java frame. Therefore we discard this sample. + return false; + } + // The last java pc will be found in the abi part of the last java frame. + } *fr_addr = frame(sp, pc); return true; } diff -Nru openjdk-21-21.0.8+9/src/hotspot/os_cpu/linux_ppc/javaThread_linux_ppc.cpp openjdk-21-21.0.9+10/src/hotspot/os_cpu/linux_ppc/javaThread_linux_ppc.cpp --- openjdk-21-21.0.8+9/src/hotspot/os_cpu/linux_ppc/javaThread_linux_ppc.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/os_cpu/linux_ppc/javaThread_linux_ppc.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2022 SAP SE. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "memory/metaspace.hpp" +#include "os_linux.hpp" #include "runtime/frame.inline.hpp" #include "runtime/javaThread.hpp" @@ -46,9 +47,17 @@ if (has_last_Java_frame() && frame_anchor()->walkable()) { intptr_t* sp = last_Java_sp(); address pc = _anchor.last_Java_pc(); - // pc can be seen as null because not all writers use store pc + release store sp. - // Simply discard the sample in this very rare case. - if (pc == nullptr) return false; + if (pc == nullptr) { + // This is not uncommon. Many c1/c2 runtime stubs do not set the pc in the anchor. + intptr_t* top_sp = os::Linux::ucontext_get_sp((const ucontext_t*)ucontext); + if ((uint64_t)sp <= ((frame::common_abi*)top_sp)->callers_sp) { + // The interrupt occurred either in the last java frame or in its direct callee. + // We cannot be sure that the link register LR was already saved to the + // java frame. Therefore we discard this sample. + return false; + } + // The last java pc will be found in the abi part of the last java frame. + } *fr_addr = frame(sp, pc); return true; } diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/adlc/output_h.cpp openjdk-21-21.0.9+10/src/hotspot/share/adlc/output_h.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/adlc/output_h.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/adlc/output_h.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -856,7 +856,8 @@ fprintf(fp_hpp, " }\n\n"); fprintf(fp_hpp, " void step(uint cycles) {\n"); fprintf(fp_hpp, " _used = 0;\n"); - fprintf(fp_hpp, " _mask <<= cycles;\n"); + fprintf(fp_hpp, " uint max_shift = 8 * sizeof(_mask) - 1;\n"); + fprintf(fp_hpp, " _mask <<= (cycles < max_shift) ? cycles : max_shift;\n"); fprintf(fp_hpp, " }\n\n"); fprintf(fp_hpp, " friend class Pipeline_Use;\n"); fprintf(fp_hpp, "};\n\n"); diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/c1/c1_Compilation.cpp openjdk-21-21.0.9+10/src/hotspot/share/c1/c1_Compilation.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/c1/c1_Compilation.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/c1/c1_Compilation.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -33,6 +33,7 @@ #include "c1/c1_ValueMap.hpp" #include "c1/c1_ValueStack.hpp" #include "code/debugInfoRec.hpp" +#include "compiler/compilationLog.hpp" #include "compiler/compileLog.hpp" #include "compiler/compilerDirectives.hpp" #include "memory/resourceArea.hpp" @@ -638,6 +639,13 @@ void Compilation::bailout(const char* msg) { assert(msg != nullptr, "bailout message must exist"); + // record the bailout for hserr envlog + if (CompilationLog::log() != nullptr) { + CompilerThread* thread = CompilerThread::current(); + CompileTask* task = thread->task(); + CompilationLog::log()->log_failure(thread, task, msg, nullptr); + } + if (!bailed_out()) { // keep first bailout message if (PrintCompilation || PrintBailouts) tty->print_cr("compilation bailout: %s", msg); diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/cds/classListParser.cpp openjdk-21-21.0.9+10/src/hotspot/share/cds/classListParser.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/cds/classListParser.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/cds/classListParser.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -472,7 +472,9 @@ THROW_NULL(vmSymbols::java_lang_ClassNotFoundException()); } - InstanceKlass* k = UnregisteredClasses::load_class(class_name, _source, CHECK_NULL); + ResourceMark rm; + char * source_path = os::strdup_check_oom(ClassLoader::uri_to_path(_source)); + InstanceKlass* k = UnregisteredClasses::load_class(class_name, source_path, CHECK_NULL); if (k->local_interfaces()->length() != _interfaces->length()) { print_specified_interfaces(); print_actual_interfaces(k); diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/cds/classListWriter.cpp openjdk-21-21.0.9+10/src/hotspot/share/cds/classListWriter.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/cds/classListWriter.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/cds/classListWriter.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -171,6 +171,8 @@ } } + // NB: the string following "source: " is not really a proper file name, but rather + // a truncated URI referring to a file. It must be decoded after reading. #ifdef _WINDOWS // "file:/C:/dir/foo.jar" -> "C:/dir/foo.jar" stream->print(" source: %s", cfs->source() + 6); diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/cds/filemap.cpp openjdk-21-21.0.9+10/src/hotspot/share/cds/filemap.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/cds/filemap.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/cds/filemap.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -586,7 +586,7 @@ // skip_uri_protocol was also called during dump time -- see ClassLoaderExt::process_module_table() ResourceMark rm; - const char* file = ClassLoader::skip_uri_protocol(location->as_C_string()); + const char* file = ClassLoader::uri_to_path(location->as_C_string()); for (int i = ClassLoaderExt::app_module_paths_start_index(); i < get_number_of_shared_paths(); i++) { SharedClassPathEntry* ent = shared_path(i); assert(ent->in_named_module(), "must be"); diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/ci/ciEnv.cpp openjdk-21-21.0.9+10/src/hotspot/share/ci/ciEnv.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/ci/ciEnv.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/ci/ciEnv.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -1230,6 +1230,15 @@ // ------------------------------------------------------------------ // ciEnv::record_failure() void ciEnv::record_failure(const char* reason) { + // record the bailout for hserr envlog + if (reason != nullptr) { + if (CompilationLog::log() != nullptr) { + CompilerThread* thread = CompilerThread::current(); + CompileTask* task = thread->task(); + CompilationLog::log()->log_failure(thread, task, reason, nullptr); + } + } + if (_failure_reason.get() == nullptr) { // Record the first failure reason. _failure_reason.set(reason); diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/classfile/classLoader.cpp openjdk-21-21.0.9+10/src/hotspot/share/classfile/classLoader.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/classfile/classLoader.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/classfile/classLoader.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -78,6 +78,9 @@ #include "utilities/macros.hpp" #include "utilities/utf8.hpp" +#include +#include + // Entry point in java.dll for path canonicalization typedef int (*canonicalize_fn_t)(const char *orig, char *out, int len); @@ -1224,7 +1227,7 @@ } #if INCLUDE_CDS -char* ClassLoader::skip_uri_protocol(char* source) { +static const char* skip_uri_protocol(const char* source) { if (strncmp(source, "file:", 5) == 0) { // file: protocol path could start with file:/ or file:/// // locate the char after all the forward slashes @@ -1243,6 +1246,47 @@ return source; } +static char decode_percent_encoded(const char *str, size_t& index) { + if (str[index] == '%' + && isxdigit(str[index + 1]) + && isxdigit(str[index + 2])) { + char hex[3]; + hex[0] = str[index + 1]; + hex[1] = str[index + 2]; + hex[2] = '\0'; + index += 2; + return (char) strtol(hex, NULL, 16); + } + return str[index]; +} + +char* ClassLoader::uri_to_path(const char* uri) { + const size_t len = strlen(uri) + 1; + char* path = NEW_RESOURCE_ARRAY(char, len); + + uri = skip_uri_protocol(uri); + + if (strncmp(uri, "//", 2) == 0) { + // Skip the empty "authority" part + uri += 2; + } + +#ifdef _WINDOWS + if (uri[0] == '/') { + // Absolute path name on Windows does not begin with a slash + uri += 1; + } +#endif + + size_t path_index = 0; + for (size_t i = 0; i < strlen(uri); ++i) { + char decoded = decode_percent_encoded(uri, i); + path[path_index++] = decoded; + } + path[path_index] = '\0'; + return path; +} + // Record the shared classpath index and loader type for classes loaded // by the builtin loaders at dump time. void ClassLoader::record_result(JavaThread* current, InstanceKlass* ik, @@ -1276,7 +1320,7 @@ // Save the path from the file: protocol or the module name from the jrt: protocol // if no protocol prefix is found, path is the same as stream->source(). This path // must be valid since the class has been successfully parsed. - char* path = skip_uri_protocol(src); + const char* path = ClassLoader::uri_to_path(src); assert(path != nullptr, "sanity"); for (int i = 0; i < FileMapInfo::get_number_of_shared_paths(); i++) { SharedClassPathEntry* ent = FileMapInfo::shared_path(i); diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/classfile/classLoader.hpp openjdk-21-21.0.9+10/src/hotspot/share/classfile/classLoader.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/classfile/classLoader.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/classfile/classLoader.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -370,7 +370,7 @@ // entries during shared classpath setup time. static int num_module_path_entries(); static void exit_with_path_failure(const char* error, const char* message); - static char* skip_uri_protocol(char* source); + static char* uri_to_path(const char* uri); static void record_result(JavaThread* current, InstanceKlass* ik, const ClassFileStream* stream, bool redefined); #endif diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/classfile/classLoaderExt.cpp openjdk-21-21.0.9+10/src/hotspot/share/classfile/classLoaderExt.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/classfile/classLoaderExt.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/classfile/classLoaderExt.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -98,12 +98,10 @@ ModulePathsGatherer(JavaThread* current, GrowableArray* module_paths) : _current(current), _module_paths(module_paths) {} void do_module(ModuleEntry* m) { - char* path = m->location()->as_C_string(); - if (strncmp(path, "file:", 5) == 0) { - path = ClassLoader::skip_uri_protocol(path); - char* path_copy = NEW_RESOURCE_ARRAY(char, strlen(path) + 1); - strcpy(path_copy, path); - _module_paths->append(path_copy); + char* uri = m->location()->as_C_string(); + if (strncmp(uri, "file:", 5) == 0) { + char* path = ClassLoader::uri_to_path(uri); + _module_paths->append(path); } } }; diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/classfile/javaClasses.cpp openjdk-21-21.0.9+10/src/hotspot/share/classfile/javaClasses.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/classfile/javaClasses.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/classfile/javaClasses.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -4435,28 +4435,31 @@ // Support for java_lang_invoke_CallSite int java_lang_invoke_CallSite::_target_offset; -int java_lang_invoke_CallSite::_context_offset; +int java_lang_invoke_CallSite::_vmdependencies_offset; +int java_lang_invoke_CallSite::_last_cleanup_offset; #define CALLSITE_FIELDS_DO(macro) \ macro(_target_offset, k, "target", java_lang_invoke_MethodHandle_signature, false); \ - macro(_context_offset, k, "context", java_lang_invoke_MethodHandleNatives_CallSiteContext_signature, false) void java_lang_invoke_CallSite::compute_offsets() { InstanceKlass* k = vmClasses::CallSite_klass(); CALLSITE_FIELDS_DO(FIELD_COMPUTE_OFFSET); + CALLSITE_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); } #if INCLUDE_CDS void java_lang_invoke_CallSite::serialize_offsets(SerializeClosure* f) { CALLSITE_FIELDS_DO(FIELD_SERIALIZE_OFFSET); + CALLSITE_INJECTED_FIELDS(INJECTED_FIELD_SERIALIZE_OFFSET); } #endif -oop java_lang_invoke_CallSite::context_no_keepalive(oop call_site) { +DependencyContext java_lang_invoke_CallSite::vmdependencies(oop call_site) { assert(java_lang_invoke_CallSite::is_instance(call_site), ""); - - oop dep_oop = call_site->obj_field_access(_context_offset); - return dep_oop; + nmethodBucket* volatile* vmdeps_addr = call_site->field_addr(_vmdependencies_offset); + volatile uint64_t* last_cleanup_addr = call_site->field_addr(_last_cleanup_offset); + DependencyContext dep_ctx(vmdeps_addr, last_cleanup_addr); + return dep_ctx; } // Support for java_lang_invoke_ConstantCallSite @@ -4477,30 +4480,6 @@ } #endif -// Support for java_lang_invoke_MethodHandleNatives_CallSiteContext - -int java_lang_invoke_MethodHandleNatives_CallSiteContext::_vmdependencies_offset; -int java_lang_invoke_MethodHandleNatives_CallSiteContext::_last_cleanup_offset; - -void java_lang_invoke_MethodHandleNatives_CallSiteContext::compute_offsets() { - InstanceKlass* k = vmClasses::Context_klass(); - CALLSITECONTEXT_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); -} - -#if INCLUDE_CDS -void java_lang_invoke_MethodHandleNatives_CallSiteContext::serialize_offsets(SerializeClosure* f) { - CALLSITECONTEXT_INJECTED_FIELDS(INJECTED_FIELD_SERIALIZE_OFFSET); -} -#endif - -DependencyContext java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(oop call_site) { - assert(java_lang_invoke_MethodHandleNatives_CallSiteContext::is_instance(call_site), ""); - nmethodBucket* volatile* vmdeps_addr = call_site->field_addr(_vmdependencies_offset); - volatile uint64_t* last_cleanup_addr = call_site->field_addr(_last_cleanup_offset); - DependencyContext dep_ctx(vmdeps_addr, last_cleanup_addr); - return dep_ctx; -} - // Support for java_security_AccessControlContext int java_security_AccessControlContext::_context_offset; @@ -5242,7 +5221,6 @@ f(java_lang_invoke_MethodType) \ f(java_lang_invoke_CallSite) \ f(java_lang_invoke_ConstantCallSite) \ - f(java_lang_invoke_MethodHandleNatives_CallSiteContext) \ f(java_security_AccessControlContext) \ f(java_lang_reflect_AccessibleObject) \ f(java_lang_reflect_Method) \ @@ -5316,7 +5294,6 @@ // constant pool entries, so excluding them shouldn't affect the archiving of static fields. klass == vmClasses::ResolvedMethodName_klass() || klass == vmClasses::MemberName_klass() || - klass == vmClasses::Context_klass() || // It's problematic to archive Reference objects. One of the reasons is that // Reference::discovered may pull in unwanted objects (see JDK-8284336) klass->is_subclass_of(vmClasses::Reference_klass())) { diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/classfile/javaClasses.hpp openjdk-21-21.0.9+10/src/hotspot/share/classfile/javaClasses.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/classfile/javaClasses.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/classfile/javaClasses.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -1368,13 +1368,17 @@ // Interface to java.lang.invoke.CallSite objects +#define CALLSITE_INJECTED_FIELDS(macro) \ + macro(java_lang_invoke_CallSite, vmdependencies, intptr_signature, false) \ + macro(java_lang_invoke_CallSite, last_cleanup, long_signature, false) class java_lang_invoke_CallSite: AllStatic { friend class JavaClasses; private: static int _target_offset; - static int _context_offset; + static int _vmdependencies_offset; + static int _last_cleanup_offset; static void compute_offsets(); @@ -1385,7 +1389,7 @@ static void set_target( oop site, oop target); static void set_target_volatile( oop site, oop target); - static oop context_no_keepalive(oop site); + static DependencyContext vmdependencies(oop call_site); // Testers static bool is_subclass(Klass* klass) { @@ -1395,7 +1399,6 @@ // Accessors for code generation: static int target_offset() { CHECK_INIT(_target_offset); } - static int context_offset() { CHECK_INIT(_context_offset); } }; // Interface to java.lang.invoke.ConstantCallSite objects @@ -1419,35 +1422,6 @@ } static bool is_instance(oop obj); }; - -// Interface to java.lang.invoke.MethodHandleNatives$CallSiteContext objects - -#define CALLSITECONTEXT_INJECTED_FIELDS(macro) \ - macro(java_lang_invoke_MethodHandleNatives_CallSiteContext, vmdependencies, intptr_signature, false) \ - macro(java_lang_invoke_MethodHandleNatives_CallSiteContext, last_cleanup, long_signature, false) - -class DependencyContext; - -class java_lang_invoke_MethodHandleNatives_CallSiteContext : AllStatic { - friend class JavaClasses; - -private: - static int _vmdependencies_offset; - static int _last_cleanup_offset; - - static void compute_offsets(); - -public: - static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN; - // Accessors - static DependencyContext vmdependencies(oop context); - - // Testers - static bool is_subclass(Klass* klass) { - return klass->is_subclass_of(vmClasses::Context_klass()); - } - static bool is_instance(oop obj); -}; // Interface to java.security.AccessControlContext objects diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/classfile/javaClasses.inline.hpp openjdk-21-21.0.9+10/src/hotspot/share/classfile/javaClasses.inline.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/classfile/javaClasses.inline.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/classfile/javaClasses.inline.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -259,10 +259,6 @@ return obj != nullptr && is_subclass(obj->klass()); } -inline bool java_lang_invoke_MethodHandleNatives_CallSiteContext::is_instance(oop obj) { - return obj != nullptr && is_subclass(obj->klass()); -} - inline bool java_lang_invoke_MemberName::is_instance(oop obj) { return obj != nullptr && obj->klass() == vmClasses::MemberName_klass(); } diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/classfile/javaClassesImpl.hpp openjdk-21-21.0.9+10/src/hotspot/share/classfile/javaClassesImpl.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/classfile/javaClassesImpl.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/classfile/javaClassesImpl.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -35,7 +35,7 @@ CLASSLOADER_INJECTED_FIELDS(macro) \ RESOLVEDMETHOD_INJECTED_FIELDS(macro) \ MEMBERNAME_INJECTED_FIELDS(macro) \ - CALLSITECONTEXT_INJECTED_FIELDS(macro) \ + CALLSITE_INJECTED_FIELDS(macro) \ STACKFRAMEINFO_INJECTED_FIELDS(macro) \ MODULE_INJECTED_FIELDS(macro) \ THREAD_INJECTED_FIELDS(macro) \ diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/classfile/stackMapTable.cpp openjdk-21-21.0.9+10/src/hotspot/share/classfile/stackMapTable.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/classfile/stackMapTable.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/classfile/stackMapTable.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -122,8 +122,16 @@ } void StackMapTable::check_jump_target( - StackMapFrame* frame, int32_t target, TRAPS) const { + StackMapFrame* frame, int bci, int offset, TRAPS) const { ErrorContext ctx; + // Jump targets must be within the method and the method size is limited. See JVMS 4.11 + int min_offset = -1 * max_method_code_size; + if (offset < min_offset || offset > max_method_code_size) { + frame->verifier()->verify_error(ErrorContext::bad_stackmap(bci, frame), + "Illegal target of jump or branch (bci %d + offset %d)", bci, offset); + return; + } + int target = bci + offset; bool match = match_stackmap( frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier())); if (!match || (target < 0 || target >= _code_length)) { diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/classfile/stackMapTable.hpp openjdk-21-21.0.9+10/src/hotspot/share/classfile/stackMapTable.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/classfile/stackMapTable.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/classfile/stackMapTable.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -69,7 +69,7 @@ // Check jump instructions. Make sure there are no uninitialized // instances on backward branch. - void check_jump_target(StackMapFrame* frame, int32_t target, TRAPS) const; + void check_jump_target(StackMapFrame* frame, int bci, int offset, TRAPS) const; // The following methods are only used inside this class. diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/classfile/verifier.cpp openjdk-21-21.0.9+10/src/hotspot/share/classfile/verifier.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/classfile/verifier.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/classfile/verifier.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -791,7 +791,6 @@ // Merge with the next instruction { u2 index; - int target; VerificationType type, type2; VerificationType atype; @@ -1607,9 +1606,8 @@ case Bytecodes::_ifle: current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); - target = bcs.dest(); stackmap_table.check_jump_target( - ¤t_frame, target, CHECK_VERIFY(this)); + ¤t_frame, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this)); no_control_flow = false; break; case Bytecodes::_if_acmpeq : case Bytecodes::_if_acmpne : @@ -1620,19 +1618,16 @@ case Bytecodes::_ifnonnull : current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); - target = bcs.dest(); stackmap_table.check_jump_target - (¤t_frame, target, CHECK_VERIFY(this)); + (¤t_frame, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this)); no_control_flow = false; break; case Bytecodes::_goto : - target = bcs.dest(); stackmap_table.check_jump_target( - ¤t_frame, target, CHECK_VERIFY(this)); + ¤t_frame, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_goto_w : - target = bcs.dest_w(); stackmap_table.check_jump_target( - ¤t_frame, target, CHECK_VERIFY(this)); + ¤t_frame, bcs.bci(), bcs.get_offset_s4(), CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_tableswitch : case Bytecodes::_lookupswitch : @@ -2282,15 +2277,14 @@ } } } - int target = bci + default_offset; - stackmap_table->check_jump_target(current_frame, target, CHECK_VERIFY(this)); + stackmap_table->check_jump_target(current_frame, bci, default_offset, CHECK_VERIFY(this)); for (int i = 0; i < keys; i++) { // Because check_jump_target() may safepoint, the bytecode could have // moved, which means 'aligned_bcp' is no good and needs to be recalculated. aligned_bcp = align_up(bcs->bcp() + 1, jintSize); - target = bci + (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize); + int offset = (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize); stackmap_table->check_jump_target( - current_frame, target, CHECK_VERIFY(this)); + current_frame, bci, offset, CHECK_VERIFY(this)); } NOT_PRODUCT(aligned_bcp = nullptr); // no longer valid at this point } @@ -2549,8 +2543,13 @@ break; case Bytecodes::_goto: - case Bytecodes::_goto_w: - target = (opcode == Bytecodes::_goto ? bcs.dest() : bcs.dest_w()); + case Bytecodes::_goto_w: { + int offset = (opcode == Bytecodes::_goto ? bcs.get_offset_s2() : bcs.get_offset_s4()); + int min_offset = -1 * max_method_code_size; + // Check offset for overflow + if (offset < min_offset || offset > max_method_code_size) return false; + + target = bci + offset; if (visited_branches->contains(bci)) { if (bci_stack->is_empty()) { if (handler_stack->is_empty()) { @@ -2571,6 +2570,7 @@ visited_branches->append(bci); } break; + } // Check that all switch alternatives end in 'athrow' bytecodes. Since it // is difficult to determine where each switch alternative ends, parse @@ -2607,7 +2607,10 @@ // Push the switch alternatives onto the stack. for (int i = 0; i < keys; i++) { - u4 target = bci + (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize); + int min_offset = -1 * max_method_code_size; + int offset = (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize); + if (offset < min_offset || offset > max_method_code_size) return false; + u4 target = bci + offset; if (target > code_length) return false; bci_stack->push(target); } diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/classfile/vmClassMacros.hpp openjdk-21-21.0.9+10/src/hotspot/share/classfile/vmClassMacros.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/classfile/vmClassMacros.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/classfile/vmClassMacros.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -129,7 +129,6 @@ do_klass(ABIDescriptor_klass, jdk_internal_foreign_abi_ABIDescriptor ) \ do_klass(VMStorage_klass, jdk_internal_foreign_abi_VMStorage ) \ do_klass(CallConv_klass, jdk_internal_foreign_abi_CallConv ) \ - do_klass(Context_klass, java_lang_invoke_MethodHandleNatives_CallSiteContext ) \ do_klass(ConstantCallSite_klass, java_lang_invoke_ConstantCallSite ) \ do_klass(MutableCallSite_klass, java_lang_invoke_MutableCallSite ) \ do_klass(VolatileCallSite_klass, java_lang_invoke_VolatileCallSite ) \ diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/classfile/vmSymbols.hpp openjdk-21-21.0.9+10/src/hotspot/share/classfile/vmSymbols.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/classfile/vmSymbols.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/classfile/vmSymbols.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -341,11 +341,9 @@ template(java_lang_invoke_MemberName, "java/lang/invoke/MemberName") \ template(java_lang_invoke_ResolvedMethodName, "java/lang/invoke/ResolvedMethodName") \ template(java_lang_invoke_MethodHandleNatives, "java/lang/invoke/MethodHandleNatives") \ - template(java_lang_invoke_MethodHandleNatives_CallSiteContext, "java/lang/invoke/MethodHandleNatives$CallSiteContext") \ template(java_lang_invoke_LambdaForm, "java/lang/invoke/LambdaForm") \ template(java_lang_invoke_InjectedProfile_signature, "Ljava/lang/invoke/InjectedProfile;") \ template(java_lang_invoke_LambdaForm_Compiled_signature, "Ljava/lang/invoke/LambdaForm$Compiled;") \ - template(java_lang_invoke_MethodHandleNatives_CallSiteContext_signature, "Ljava/lang/invoke/MethodHandleNatives$CallSiteContext;") \ /* internal up-calls made only by the JVM, via class sun.invoke.MethodHandleNatives: */ \ template(findMethodHandleType_name, "findMethodHandleType") \ template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;") \ diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/code/dependencyContext.cpp openjdk-21-21.0.9+10/src/hotspot/share/code/dependencyContext.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/code/dependencyContext.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/code/dependencyContext.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -168,12 +168,6 @@ } } -nmethodBucket* DependencyContext::release_and_get_next_not_unloading(nmethodBucket* b) { - nmethodBucket* next = b->next_not_unloading(); - release(b); - return next; - } - // // Invalidate all dependencies in the context void DependencyContext::remove_all_dependents() { @@ -214,18 +208,6 @@ set_dependencies(nullptr); } -void DependencyContext::remove_and_mark_for_deoptimization_all_dependents(DeoptimizationScope* deopt_scope) { - nmethodBucket* b = dependencies_not_unloading(); - set_dependencies(nullptr); - while (b != nullptr) { - nmethod* nm = b->get_nmethod(); - // Also count already (concurrently) marked nmethods to make sure - // deoptimization is triggered before execution in this thread continues. - deopt_scope->mark(nm); - b = release_and_get_next_not_unloading(b); - } -} - #ifndef PRODUCT void DependencyContext::print_dependent_nmethods(bool verbose) { int idx = 0; diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/code/dependencyContext.hpp openjdk-21-21.0.9+10/src/hotspot/share/code/dependencyContext.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/code/dependencyContext.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/code/dependencyContext.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -63,7 +63,7 @@ // // Utility class to manipulate nmethod dependency context. // Dependency context can be attached either to an InstanceKlass (_dep_context field) -// or CallSiteContext oop for call_site_target dependencies (see javaClasses.hpp). +// or CallSite oop for call_site_target dependencies (see javaClasses.hpp). // DependencyContext class operates on some location which holds a nmethodBucket* value // and uint64_t integer recording the safepoint counter at the last cleanup. // @@ -92,7 +92,6 @@ #ifdef ASSERT // Safepoints are forbidden during DC lifetime. GC can invalidate // _dependency_context_addr if it relocates the holder - // (e.g. CallSiteContext Java object). SafepointStateTracker _safepoint_tracker; DependencyContext(nmethodBucket* volatile* bucket_addr, volatile uint64_t* last_cleanup_addr) @@ -114,9 +113,7 @@ void mark_dependent_nmethods(DeoptimizationScope* deopt_scope, DepChange& changes); void add_dependent_nmethod(nmethod* nm); void remove_all_dependents(); - void remove_and_mark_for_deoptimization_all_dependents(DeoptimizationScope* deopt_scope); void clean_unloading_dependents(); - static nmethodBucket* release_and_get_next_not_unloading(nmethodBucket* b); static void purge_dependency_contexts(); static void release(nmethodBucket* b); static void cleaning_start(); diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/compiler/compilationLog.cpp openjdk-21-21.0.9+10/src/hotspot/share/compiler/compilationLog.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/compiler/compilationLog.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/compiler/compilationLog.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -52,7 +52,11 @@ void CompilationLog::log_failure(JavaThread* thread, CompileTask* task, const char* reason, const char* retry_message) { StringLogMessage lm; - lm.print("%4d COMPILE SKIPPED: %s", task->compile_id(), reason); + if (task == nullptr) { + lm.print("Id not known, task was 0; COMPILE SKIPPED: %s", reason); + } else { + lm.print("%4d COMPILE SKIPPED: %s", task->compile_id(), reason); + } if (retry_message != nullptr) { lm.append(" (%s)", retry_message); } diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/gc/g1/g1CardTableEntryClosure.hpp openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1CardTableEntryClosure.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/gc/g1/g1CardTableEntryClosure.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1CardTableEntryClosure.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,9 +39,9 @@ virtual void do_card_ptr(CardValue* card_ptr, uint worker_id) = 0; // Process all the card_ptrs in node. - void apply_to_buffer(BufferNode* node, size_t buffer_size, uint worker_id) { + void apply_to_buffer(BufferNode* node, size_t buffer_capacity, uint worker_id) { void** buffer = BufferNode::make_buffer_from_node(node); - for (size_t i = node->index(); i < buffer_size; ++i) { + for (size_t i = node->index(); i < buffer_capacity; ++i) { CardValue* card_ptr = static_cast(buffer[i]); do_card_ptr(card_ptr, worker_id); } diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -87,7 +87,7 @@ void G1DirtyCardQueueSet::flush_queue(G1DirtyCardQueue& queue) { if (queue.buffer() != nullptr) { G1ConcurrentRefineStats* stats = queue.refinement_stats(); - stats->inc_dirtied_cards(buffer_size() - queue.index()); + stats->inc_dirtied_cards(buffer_capacity() - queue.index()); } PtrQueueSet::flush_queue(queue); } @@ -106,7 +106,7 @@ BufferNode* old_node = exchange_buffer_with_new(queue); if (old_node != nullptr) { G1ConcurrentRefineStats* stats = queue.refinement_stats(); - stats->inc_dirtied_cards(buffer_size()); + stats->inc_dirtied_cards(buffer_capacity()); handle_completed_buffer(old_node, stats); } } @@ -124,7 +124,7 @@ assert(cbn != nullptr, "precondition"); // Increment _num_cards before adding to queue, so queue removal doesn't // need to deal with _num_cards possibly going negative. - Atomic::add(&_num_cards, buffer_size() - cbn->index()); + Atomic::add(&_num_cards, buffer_capacity() - cbn->index()); // Perform push in CS. The old tail may be popped while the push is // observing it (attaching it to the new buffer). We need to ensure it // can't be reused until the push completes, to avoid ABA problems. @@ -160,7 +160,7 @@ result = dequeue_completed_buffer(); if (result == nullptr) return nullptr; } - Atomic::sub(&_num_cards, buffer_size() - result->index()); + Atomic::sub(&_num_cards, buffer_capacity() - result->index()); return result; } @@ -170,7 +170,7 @@ for (BufferNode* cur = _completed.first(); !_completed.is_end(cur); cur = cur->next()) { - actual += buffer_size() - cur->index(); + actual += buffer_capacity() - cur->index(); } assert(actual == Atomic::load(&_num_cards), "Num entries in completed buffers should be " SIZE_FORMAT " but are " SIZE_FORMAT, @@ -286,7 +286,7 @@ // notification checking after the coming safepoint if it doesn't GC. // Note that this means the queue's _num_cards differs from the number // of cards in the queued buffers when there are paused buffers. - Atomic::add(&_num_cards, buffer_size() - node->index()); + Atomic::add(&_num_cards, buffer_capacity() - node->index()); _paused.add(node); } @@ -342,30 +342,30 @@ class G1RefineBufferedCards : public StackObj { BufferNode* const _node; CardTable::CardValue** const _node_buffer; - const size_t _node_buffer_size; + const size_t _node_buffer_capacity; const uint _worker_id; G1ConcurrentRefineStats* _stats; G1RemSet* const _g1rs; - static inline int compare_card(const CardTable::CardValue* p1, - const CardTable::CardValue* p2) { + static inline ptrdiff_t compare_cards(const CardTable::CardValue* p1, + const CardTable::CardValue* p2) { return p2 - p1; } - // Sorts the cards from start_index to _node_buffer_size in *decreasing* + // Sorts the cards from start_index to _node_buffer_capacity in *decreasing* // address order. Tests showed that this order is preferable to not sorting // or increasing address order. void sort_cards(size_t start_index) { QuickSort::sort(&_node_buffer[start_index], - _node_buffer_size - start_index, - compare_card, + _node_buffer_capacity - start_index, + compare_cards, false); } // Returns the index to the first clean card in the buffer. size_t clean_cards() { const size_t start = _node->index(); - assert(start <= _node_buffer_size, "invariant"); + assert(start <= _node_buffer_capacity, "invariant"); // Two-fingered compaction algorithm similar to the filtering mechanism in // SATBMarkQueue. The main difference is that clean_card_before_refine() @@ -373,7 +373,7 @@ // We don't check for SuspendibleThreadSet::should_yield(), because // cleaning and redirtying the cards is fast. CardTable::CardValue** src = &_node_buffer[start]; - CardTable::CardValue** dst = &_node_buffer[_node_buffer_size]; + CardTable::CardValue** dst = &_node_buffer[_node_buffer_capacity]; assert(src <= dst, "invariant"); for ( ; src < dst; ++src) { // Search low to high for a card to keep. @@ -392,7 +392,7 @@ // dst points to the first retained clean card, or the end of the buffer // if all the cards were discarded. const size_t first_clean = dst - _node_buffer; - assert(first_clean >= start && first_clean <= _node_buffer_size, "invariant"); + assert(first_clean >= start && first_clean <= _node_buffer_capacity, "invariant"); // Discarded cards are considered as refined. _stats->inc_refined_cards(first_clean - start); _stats->inc_precleaned_cards(first_clean - start); @@ -402,7 +402,7 @@ bool refine_cleaned_cards(size_t start_index) { bool result = true; size_t i = start_index; - for ( ; i < _node_buffer_size; ++i) { + for ( ; i < _node_buffer_capacity; ++i) { if (SuspendibleThreadSet::should_yield()) { redirty_unrefined_cards(i); result = false; @@ -416,26 +416,26 @@ } void redirty_unrefined_cards(size_t start) { - for ( ; start < _node_buffer_size; ++start) { + for ( ; start < _node_buffer_capacity; ++start) { *_node_buffer[start] = G1CardTable::dirty_card_val(); } } public: G1RefineBufferedCards(BufferNode* node, - size_t node_buffer_size, + size_t node_buffer_capacity, uint worker_id, G1ConcurrentRefineStats* stats) : _node(node), _node_buffer(reinterpret_cast(BufferNode::make_buffer_from_node(node))), - _node_buffer_size(node_buffer_size), + _node_buffer_capacity(node_buffer_capacity), _worker_id(worker_id), _stats(stats), _g1rs(G1CollectedHeap::heap()->rem_set()) {} bool refine() { size_t first_clean_index = clean_cards(); - if (first_clean_index == _node_buffer_size) { + if (first_clean_index == _node_buffer_capacity) { _node->set_index(first_clean_index); return true; } @@ -458,7 +458,7 @@ G1ConcurrentRefineStats* stats) { Ticks start_time = Ticks::now(); G1RefineBufferedCards buffered_cards(node, - buffer_size(), + buffer_capacity(), worker_id, stats); bool result = buffered_cards.refine(); @@ -469,12 +469,12 @@ void G1DirtyCardQueueSet::handle_refined_buffer(BufferNode* node, bool fully_processed) { if (fully_processed) { - assert(node->index() == buffer_size(), + assert(node->index() == buffer_capacity(), "Buffer not fully consumed: index: " SIZE_FORMAT ", size: " SIZE_FORMAT, - node->index(), buffer_size()); + node->index(), buffer_capacity()); deallocate_buffer(node); } else { - assert(node->index() < buffer_size(), "Buffer fully consumed."); + assert(node->index() < buffer_capacity(), "Buffer fully consumed."); // Buffer incompletely processed because there is a pending safepoint. // Record partially processed buffer, to be finished later. record_paused_buffer(node); @@ -577,7 +577,7 @@ // Flush the buffer if non-empty. Flush before accumulating and // resetting stats, since flushing may modify the stats. if ((queue.buffer() != nullptr) && - (queue.index() != buffer_size())) { + (queue.index() != buffer_capacity())) { flush_queue(queue); } diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -195,7 +195,7 @@ void abandon_completed_buffers(); - // Refine the cards in "node" from its index to buffer_size. + // Refine the cards in "node" from its index to buffer_capacity. // Stops processing if SuspendibleThreadSet::should_yield() is true. // Returns true if the entire buffer was processed, false if there // is a pending yield request. The node's index is updated to exclude diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -374,7 +374,7 @@ } } -#define TIME_FORMAT "%.1lfms" +#define TIME_FORMAT "%.2lfms" void G1GCPhaseTimes::info_time(const char* name, double value) const { log_info(gc, phases)(" %s: " TIME_FORMAT, name, value); diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/gc/g1/g1Policy.cpp openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1Policy.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/gc/g1/g1Policy.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1Policy.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -338,41 +338,47 @@ _reserve_regions, max_to_eat_into_reserve); + uint survivor_regions_count = _g1h->survivor_regions_count(); + uint desired_eden_length = desired_young_length - survivor_regions_count; + uint allocated_eden_length = allocated_young_length - survivor_regions_count; + if (_free_regions_at_end_of_collection <= _reserve_regions) { // Fully eat (or already eating) into the reserve, hand back at most absolute_min_length regions. - uint receiving_young = MIN3(_free_regions_at_end_of_collection, - desired_young_length, + uint receiving_eden = MIN3(_free_regions_at_end_of_collection, + desired_eden_length, max_to_eat_into_reserve); + // Ensure that we provision for at least one Eden region. + receiving_eden = MAX2(receiving_eden, 1u); // We could already have allocated more regions than what we could get // above. - receiving_additional_eden = allocated_young_length < receiving_young ? - receiving_young - allocated_young_length : 0; + receiving_additional_eden = allocated_eden_length < receiving_eden ? + receiving_eden - allocated_eden_length : 0; log_trace(gc, ergo, heap)("Young target length: Fully eat into reserve " - "receiving young %u receiving additional eden %u", - receiving_young, - receiving_additional_eden); - } else if (_free_regions_at_end_of_collection < (desired_young_length + _reserve_regions)) { + "receiving eden %u receiving additional eden %u", + receiving_eden, receiving_additional_eden); + } else if (_free_regions_at_end_of_collection < (desired_eden_length + _reserve_regions)) { // Partially eat into the reserve, at most max_to_eat_into_reserve regions. uint free_outside_reserve = _free_regions_at_end_of_collection - _reserve_regions; - assert(free_outside_reserve < desired_young_length, + assert(free_outside_reserve < desired_eden_length, "must be %u %u", - free_outside_reserve, desired_young_length); + free_outside_reserve, desired_eden_length); - uint receiving_within_reserve = MIN2(desired_young_length - free_outside_reserve, + uint receiving_within_reserve = MIN2(desired_eden_length - free_outside_reserve, max_to_eat_into_reserve); - uint receiving_young = free_outside_reserve + receiving_within_reserve; + uint receiving_eden = free_outside_reserve + receiving_within_reserve; + // Again, we could have already allocated more than we could get. - receiving_additional_eden = allocated_young_length < receiving_young ? - receiving_young - allocated_young_length : 0; + receiving_additional_eden = allocated_eden_length < receiving_eden ? + receiving_eden - allocated_eden_length : 0; log_trace(gc, ergo, heap)("Young target length: Partially eat into reserve " "free outside reserve %u " "receiving within reserve %u " - "receiving young %u " + "receiving eden %u " "receiving additional eden %u", free_outside_reserve, receiving_within_reserve, - receiving_young, receiving_additional_eden); + receiving_eden, receiving_additional_eden); } else { // No need to use the reserve. receiving_additional_eden = desired_young_length - allocated_young_length; diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.cpp openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -47,7 +47,7 @@ #endif // ASSERT void G1RedirtyCardsLocalQueueSet::enqueue_completed_buffer(BufferNode* node) { - _buffers._entry_count += buffer_size() - node->index(); + _buffers._entry_count += buffer_capacity() - node->index(); node->set_next(_buffers._head); _buffers._head = node; if (_buffers._tail == nullptr) { @@ -131,7 +131,7 @@ void G1RedirtyCardsQueueSet::enqueue_completed_buffer(BufferNode* node) { assert(_collecting, "precondition"); - Atomic::add(&_entry_count, buffer_size() - node->index()); + Atomic::add(&_entry_count, buffer_capacity() - node->index()); _list.push(*node); update_tail(node); } diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/gc/g1/g1RemSet.cpp openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1RemSet.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/gc/g1/g1RemSet.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1RemSet.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -1283,9 +1283,9 @@ void apply_closure_to_dirty_card_buffers(G1MergeLogBufferCardsClosure* cl, uint worker_id) { G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); - size_t buffer_size = dcqs.buffer_size(); + size_t buffer_capacity = dcqs.buffer_capacity(); while (BufferNode* node = _dirty_card_buffers.pop()) { - cl->apply_to_buffer(node, buffer_size, worker_id); + cl->apply_to_buffer(node, buffer_capacity, worker_id); dcqs.deallocate_buffer(node); } } @@ -1588,7 +1588,7 @@ *card_ptr = G1CardTable::dirty_card_val(); G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); void** buffer = dcqs.allocate_buffer(); - size_t index = dcqs.buffer_size() - 1; + size_t index = dcqs.buffer_capacity() - 1; buffer[index] = card_ptr; dcqs.enqueue_completed_buffer(BufferNode::make_node_from_buffer(buffer, index)); } diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -398,13 +398,13 @@ void do_work(uint worker_id) override { RedirtyLoggedCardTableEntryClosure cl(G1CollectedHeap::heap(), _evac_failure_regions); - const size_t buffer_size = _rdcqs->buffer_size(); + const size_t buffer_capacity = _rdcqs->buffer_capacity(); BufferNode* next = Atomic::load(&_nodes); while (next != nullptr) { BufferNode* node = next; next = Atomic::cmpxchg(&_nodes, node, node->next()); if (next == node) { - cl.apply_to_buffer(node, buffer_size, worker_id); + cl.apply_to_buffer(node, buffer_capacity, worker_id); next = node->next(); } } diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/gc/g1/g1YoungGCPreEvacuateTasks.cpp openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1YoungGCPreEvacuateTasks.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/gc/g1/g1YoungGCPreEvacuateTasks.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/gc/g1/g1YoungGCPreEvacuateTasks.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -167,11 +167,11 @@ ResourceMark rm; struct Verifier : public ThreadClosure { - size_t _buffer_size; - Verifier() : _buffer_size(G1BarrierSet::dirty_card_queue_set().buffer_size()) {} + size_t _buffer_capacity; + Verifier() : _buffer_capacity(G1BarrierSet::dirty_card_queue_set().buffer_capacity()) {} void do_thread(Thread* t) override { G1DirtyCardQueue& queue = G1ThreadLocalData::dirty_card_queue(t); - assert((queue.buffer() == nullptr) || (queue.index() == _buffer_size), + assert((queue.buffer() == nullptr) || (queue.index() == _buffer_capacity), "non-empty dirty card queue for thread %s", t->name()); } } verifier; diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/gc/shared/bufferNode.cpp openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/bufferNode.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/gc/shared/bufferNode.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/bufferNode.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -29,10 +29,10 @@ #include -BufferNode::AllocatorConfig::AllocatorConfig(size_t size) : _buffer_size(size) {} +BufferNode::AllocatorConfig::AllocatorConfig(size_t size) : _buffer_capacity(size) {} void* BufferNode::AllocatorConfig::allocate() { - size_t byte_size = _buffer_size * sizeof(void*); + size_t byte_size = _buffer_capacity * sizeof(void*); return NEW_C_HEAP_ARRAY(char, buffer_offset() + byte_size, mtGC); } @@ -41,8 +41,8 @@ FREE_C_HEAP_ARRAY(char, node); } -BufferNode::Allocator::Allocator(const char* name, size_t buffer_size) : - _config(buffer_size), +BufferNode::Allocator::Allocator(const char* name, size_t buffer_capacity) : + _config(buffer_capacity), _free_list(name, &_config) {} diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/gc/shared/bufferNode.hpp openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/bufferNode.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/gc/shared/bufferNode.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/bufferNode.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -78,7 +78,7 @@ // We use BufferNode::AllocatorConfig to set the allocation options for the // FreeListAllocator. class BufferNode::AllocatorConfig : public FreeListConfig { - const size_t _buffer_size; + const size_t _buffer_capacity; public: explicit AllocatorConfig(size_t size); @@ -88,7 +88,7 @@ void deallocate(void* node) override; - size_t buffer_size() const { return _buffer_size; } + size_t buffer_capacity() const { return _buffer_capacity; } }; class BufferNode::Allocator { @@ -100,10 +100,10 @@ NONCOPYABLE(Allocator); public: - Allocator(const char* name, size_t buffer_size); + Allocator(const char* name, size_t buffer_capacity); ~Allocator() = default; - size_t buffer_size() const { return _config.buffer_size(); } + size_t buffer_capacity() const { return _config.buffer_capacity(); } size_t free_count() const; BufferNode* allocate(); void release(BufferNode* node); diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/gc/shared/gcArguments.cpp openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/gcArguments.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/gc/shared/gcArguments.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/gcArguments.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -30,6 +30,7 @@ #include "runtime/arguments.hpp" #include "runtime/globals.hpp" #include "runtime/globals_extension.hpp" +#include "utilities/formatBuffer.hpp" #include "utilities/macros.hpp" size_t HeapAlignment = 0; @@ -170,6 +171,13 @@ FLAG_SET_ERGO(MinHeapDeltaBytes, align_up(MinHeapDeltaBytes, SpaceAlignment)); + if (checked_cast(ObjectAlignmentInBytes) > GCCardSizeInBytes) { + err_msg message("ObjectAlignmentInBytes %u is larger than GCCardSizeInBytes %u", + ObjectAlignmentInBytes, GCCardSizeInBytes); + vm_exit_during_initialization("Invalid combination of GCCardSizeInBytes and ObjectAlignmentInBytes", + message); + } + DEBUG_ONLY(assert_flags();) } diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/gc/shared/locationPrinter.inline.hpp openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/locationPrinter.inline.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/gc/shared/locationPrinter.inline.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/locationPrinter.inline.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -27,6 +27,7 @@ #include "gc/shared/locationPrinter.hpp" +#include "memory/resourceArea.inline.hpp" #include "oops/compressedOops.inline.hpp" #include "oops/oopsHierarchy.hpp" @@ -51,6 +52,7 @@ template bool BlockLocationPrinter::print_location(outputStream* st, void* addr) { + ResourceMark rm; // Check if addr points into Java heap. if (CollectedHeapT::heap()->is_in(addr)) { oop o = base_oop_or_null(addr); diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/gc/shared/ptrQueue.cpp openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/ptrQueue.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/gc/shared/ptrQueue.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/ptrQueue.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -28,7 +28,7 @@ PtrQueue::PtrQueue(PtrQueueSet* qset) : _index(0), - _capacity_in_bytes(index_to_byte_index(qset->buffer_size())), + _capacity_in_bytes(index_to_byte_index(qset->buffer_capacity())), _buf(nullptr) {} @@ -37,7 +37,6 @@ } - PtrQueueSet::PtrQueueSet(BufferNode::Allocator* allocator) : _allocator(allocator) {} @@ -46,7 +45,7 @@ void PtrQueueSet::reset_queue(PtrQueue& queue) { if (queue.buffer() != nullptr) { - queue.set_index(buffer_size()); + queue.set_index(buffer_capacity()); } } @@ -57,7 +56,7 @@ queue.set_buffer(nullptr); queue.set_index(0); BufferNode* node = BufferNode::make_node_from_buffer(buffer, index); - if (index == buffer_size()) { + if (index == buffer_capacity()) { deallocate_buffer(node); } else { enqueue_completed_buffer(node); @@ -95,7 +94,7 @@ void PtrQueueSet::install_new_buffer(PtrQueue& queue) { queue.set_buffer(allocate_buffer()); - queue.set_index(buffer_size()); + queue.set_index(buffer_capacity()); } void** PtrQueueSet::allocate_buffer() { diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/gc/shared/ptrQueue.hpp openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/ptrQueue.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/gc/shared/ptrQueue.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/ptrQueue.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -155,11 +155,11 @@ // Return the associated BufferNode allocator. BufferNode::Allocator* allocator() const { return _allocator; } - // Return the buffer for a BufferNode of size buffer_size(). + // Return the buffer for a BufferNode of size buffer_capacity(). void** allocate_buffer(); // Return an empty buffer to the free list. The node is required - // to have been allocated with a size of buffer_size(). + // to have been allocated with a size of buffer_capacity(). void deallocate_buffer(BufferNode* node); // A completed buffer is a buffer the mutator is finished with, and @@ -168,8 +168,8 @@ // Adds node to the completed buffer list. virtual void enqueue_completed_buffer(BufferNode* node) = 0; - size_t buffer_size() const { - return _allocator->buffer_size(); + size_t buffer_capacity() const { + return _allocator->buffer_capacity(); } }; diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/gc/shared/satbMarkQueue.cpp openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/satbMarkQueue.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/gc/shared/satbMarkQueue.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/satbMarkQueue.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -124,7 +124,7 @@ void SATBMarkQueueSet::set_buffer_enqueue_threshold_percentage(uint value) { // Minimum threshold of 1 ensures enqueuing of completely full buffers. - size_t size = buffer_size(); + size_t size = buffer_capacity(); size_t enqueue_qty = (size * value) / 100; _buffer_enqueue_threshold = MAX2(size - enqueue_qty, (size_t)1); } @@ -194,9 +194,9 @@ virtual void do_thread(Thread* t) { SATBMarkQueue& queue = _qset->satb_queue_for_thread(t); if (queue.buffer() != nullptr) { - assert(!_active || queue.index() == _qset->buffer_size(), + assert(!_active || queue.index() == _qset->buffer_capacity(), "queues should be empty when activated"); - queue.set_index(_qset->buffer_size()); + queue.set_index(_qset->buffer_capacity()); } queue.set_active(_active); } @@ -209,7 +209,7 @@ if (nd != nullptr) { void **buf = BufferNode::make_buffer_from_node(nd); size_t index = nd->index(); - size_t size = buffer_size(); + size_t size = buffer_capacity(); assert(index <= size, "invariant"); cl->do_buffer(buf + index, size - index); deallocate_buffer(nd); @@ -255,9 +255,9 @@ // Ensure we'll enqueue completely full buffers. assert(threshold > 0, "enqueue threshold = 0"); // Ensure we won't enqueue empty buffers. - assert(threshold <= buffer_size(), + assert(threshold <= buffer_capacity(), "enqueue threshold %zu exceeds capacity %zu", - threshold, buffer_size()); + threshold, buffer_capacity()); return queue.index() < threshold; } @@ -310,7 +310,7 @@ while (nd != nullptr) { void** buf = BufferNode::make_buffer_from_node(nd); os::snprintf(buffer, SATB_PRINTER_BUFFER_SIZE, "Enqueued: %d", i); - print_satb_buffer(buffer, buf, nd->index(), buffer_size()); + print_satb_buffer(buffer, buf, nd->index(), buffer_capacity()); nd = nd->next(); i += 1; } diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/gc/shared/satbMarkQueue.hpp openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/satbMarkQueue.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/gc/shared/satbMarkQueue.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/satbMarkQueue.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -181,7 +181,7 @@ // Two-fingered compaction toward the end. void** src = &buf[queue.index()]; - void** dst = &buf[buffer_size()]; + void** dst = &buf[buffer_capacity()]; assert(src <= dst, "invariant"); for ( ; src < dst; ++src) { // Search low to high for an entry to keep. diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/gc/shared/weakProcessorTimes.cpp openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/weakProcessorTimes.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/gc/shared/weakProcessorTimes.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/weakProcessorTimes.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -173,7 +173,7 @@ return indents[MIN2(i, max_indents_index)]; } -#define TIME_FORMAT "%.1lfms" +#define TIME_FORMAT "%.2lfms" void WeakProcessorTimes::log_summary(OopStorageSet::WeakId id, uint indent) const { LogTarget(Debug, gc, phases) lt; diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/gc/shared/workerDataArray.cpp openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/workerDataArray.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/gc/shared/workerDataArray.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/gc/shared/workerDataArray.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -36,11 +36,14 @@ return -1.0; } +#define WDA_TIME_FORMAT "%4.2lf" + template <> void WorkerDataArray::WDAPrinter::summary(outputStream* out, double min, double avg, double max, double diff, double sum, bool print_sum) { - out->print(" Min: %4.1lf, Avg: %4.1lf, Max: %4.1lf, Diff: %4.1lf", min * MILLIUNITS, avg * MILLIUNITS, max * MILLIUNITS, diff* MILLIUNITS); + out->print(" Min: " WDA_TIME_FORMAT ", Avg: " WDA_TIME_FORMAT ", Max: " WDA_TIME_FORMAT ", Diff: " WDA_TIME_FORMAT, + min * MILLIUNITS, avg * MILLIUNITS, max * MILLIUNITS, diff* MILLIUNITS); if (print_sum) { - out->print(", Sum: %4.1lf", sum * MILLIUNITS); + out->print(", Sum: " WDA_TIME_FORMAT, sum * MILLIUNITS); } } @@ -58,7 +61,7 @@ for (uint i = 0; i < phase->_length; ++i) { double value = phase->get(i); if (value != phase->uninitialized()) { - out->print(" %4.1lf", phase->get(i) * 1000.0); + out->print(" " WDA_TIME_FORMAT, phase->get(i) * 1000.0); } else { out->print(" -"); } diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp openjdk-21-21.0.9+10/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -639,6 +639,34 @@ } #endif +bool ShenandoahBarrierC2Support::is_anti_dependent_load_at_control(PhaseIdealLoop* phase, Node* maybe_load, Node* store, + Node* control) { + return maybe_load->is_Load() && phase->C->can_alias(store->adr_type(), phase->C->get_alias_index(maybe_load->adr_type())) && + phase->ctrl_or_self(maybe_load) == control; +} + +void ShenandoahBarrierC2Support::maybe_push_anti_dependent_loads(PhaseIdealLoop* phase, Node* maybe_store, Node* control, Unique_Node_List &wq) { + if (!maybe_store->is_Store() && !maybe_store->is_LoadStore()) { + return; + } + Node* mem = maybe_store->in(MemNode::Memory); + for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) { + Node* u = mem->fast_out(i); + if (is_anti_dependent_load_at_control(phase, u, maybe_store, control)) { + wq.push(u); + } + } +} + +void ShenandoahBarrierC2Support::push_data_inputs_at_control(PhaseIdealLoop* phase, Node* n, Node* ctrl, Unique_Node_List &wq) { + for (uint i = 0; i < n->req(); i++) { + Node* in = n->in(i); + if (in != nullptr && (ShenandoahIUBarrier ? (phase->ctrl_or_self(in) == ctrl) : (phase->has_ctrl(in) && phase->get_ctrl(in) == ctrl))) { + wq.push(in); + } + } +} + bool ShenandoahBarrierC2Support::is_dominator_same_ctrl(Node* c, Node* d, Node* n, PhaseIdealLoop* phase) { // That both nodes have the same control is not sufficient to prove // domination, verify that there's no path from d to n @@ -653,22 +681,9 @@ if (m->is_Phi() && m->in(0)->is_Loop()) { assert(phase->ctrl_or_self(m->in(LoopNode::EntryControl)) != c, "following loop entry should lead to new control"); } else { - if (m->is_Store() || m->is_LoadStore()) { - // Take anti-dependencies into account - Node* mem = m->in(MemNode::Memory); - for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) { - Node* u = mem->fast_out(i); - if (u->is_Load() && phase->C->can_alias(m->adr_type(), phase->C->get_alias_index(u->adr_type())) && - phase->ctrl_or_self(u) == c) { - wq.push(u); - } - } - } - for (uint i = 0; i < m->req(); i++) { - if (m->in(i) != nullptr && phase->ctrl_or_self(m->in(i)) == c) { - wq.push(m->in(i)); - } - } + // Take anti-dependencies into account + maybe_push_anti_dependent_loads(phase, m, c, wq); + push_data_inputs_at_control(phase, m, c, wq); } } return true; @@ -1020,7 +1035,20 @@ phase->register_new_node(val, ctrl); } -void ShenandoahBarrierC2Support::fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& uses_to_ignore, uint last, PhaseIdealLoop* phase) { +void ShenandoahBarrierC2Support::collect_nodes_above_barrier(Unique_Node_List &nodes_above_barrier, PhaseIdealLoop* phase, Node* ctrl, Node* init_raw_mem) { + nodes_above_barrier.clear(); + if (phase->has_ctrl(init_raw_mem) && phase->get_ctrl(init_raw_mem) == ctrl && !init_raw_mem->is_Phi()) { + nodes_above_barrier.push(init_raw_mem); + } + for (uint next = 0; next < nodes_above_barrier.size(); next++) { + Node* n = nodes_above_barrier.at(next); + // Take anti-dependencies into account + maybe_push_anti_dependent_loads(phase, n, ctrl, nodes_above_barrier); + push_data_inputs_at_control(phase, n, ctrl, nodes_above_barrier); + } +} + +void ShenandoahBarrierC2Support::fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& nodes_above_barrier, uint last, PhaseIdealLoop* phase) { Node* ctrl = phase->get_ctrl(barrier); Node* init_raw_mem = fixer.find_mem(ctrl, barrier); @@ -1031,30 +1059,17 @@ // control will be after the expanded barrier. The raw memory (if // its memory is control dependent on the barrier's input control) // must stay above the barrier. - uses_to_ignore.clear(); - if (phase->has_ctrl(init_raw_mem) && phase->get_ctrl(init_raw_mem) == ctrl && !init_raw_mem->is_Phi()) { - uses_to_ignore.push(init_raw_mem); - } - for (uint next = 0; next < uses_to_ignore.size(); next++) { - Node *n = uses_to_ignore.at(next); - for (uint i = 0; i < n->req(); i++) { - Node* in = n->in(i); - if (in != nullptr && phase->has_ctrl(in) && phase->get_ctrl(in) == ctrl) { - uses_to_ignore.push(in); - } - } - } + collect_nodes_above_barrier(nodes_above_barrier, phase, ctrl, init_raw_mem); for (DUIterator_Fast imax, i = ctrl->fast_outs(imax); i < imax; i++) { Node* u = ctrl->fast_out(i); if (u->_idx < last && u != barrier && !u->depends_only_on_test() && // preserve dependency on test - !uses_to_ignore.member(u) && + !nodes_above_barrier.member(u) && (u->in(0) != ctrl || (!u->is_Region() && !u->is_Phi())) && (ctrl->Opcode() != Op_CatchProj || u->Opcode() != Op_CreateEx)) { Node* old_c = phase->ctrl_or_self(u); - Node* c = old_c; - if (c != ctrl || + if (old_c != ctrl || is_dominator_same_ctrl(old_c, barrier, u, phase) || ShenandoahBarrierSetC2::is_shenandoah_state_load(u)) { phase->igvn().rehash_node_delayed(u); @@ -1170,8 +1185,9 @@ } } } + // Load barrier on the control output of a call if ((ctrl->is_Proj() && ctrl->in(0)->is_CallJava()) || ctrl->is_CallJava()) { - CallNode* call = ctrl->is_Proj() ? ctrl->in(0)->as_CallJava() : ctrl->as_CallJava(); + CallJavaNode* call = ctrl->is_Proj() ? ctrl->in(0)->as_CallJava() : ctrl->as_CallJava(); if (call->entry_point() == OptoRuntime::rethrow_stub()) { // The rethrow call may have too many projections to be // properly handled here. Given there's no reason for a @@ -1207,6 +1223,14 @@ CallProjections projs; call->extract_projections(&projs, false, false); + // If this is a runtime call, it doesn't have an exception handling path + if (projs.fallthrough_catchproj == nullptr) { + assert(call->method() == nullptr, "should be runtime call"); + assert(projs.catchall_catchproj == nullptr, "runtime call should not have catch all projection"); + continue; + } + + // Otherwise, clone the barrier so there's one for the fallthrough and one for the exception handling path #ifdef ASSERT VectorSet cloned; #endif @@ -1334,7 +1358,7 @@ // Expand load-reference-barriers MemoryGraphFixer fixer(Compile::AliasIdxRaw, true, phase); - Unique_Node_List uses_to_ignore; + Unique_Node_List nodes_above_barriers; for (int i = state->load_reference_barriers_count() - 1; i >= 0; i--) { ShenandoahLoadReferenceBarrierNode* lrb = state->load_reference_barrier(i); uint last = phase->C->unique(); @@ -1429,7 +1453,7 @@ Node* out_val = val_phi; phase->register_new_node(val_phi, region); - fix_ctrl(lrb, region, fixer, uses, uses_to_ignore, last, phase); + fix_ctrl(lrb, region, fixer, uses, nodes_above_barriers, last, phase); ctrl = orig_ctrl; @@ -1585,7 +1609,7 @@ phase->register_control(region, loop, heap_stable_ctrl->in(0)); phase->register_new_node(phi, region); - fix_ctrl(barrier, region, fixer, uses, uses_to_ignore, last, phase); + fix_ctrl(barrier, region, fixer, uses, nodes_above_barriers, last, phase); for(uint next = 0; next < uses.size(); next++ ) { Node *n = uses.at(next); assert(phase->get_ctrl(n) == init_ctrl, "bad control"); diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp openjdk-21-21.0.9+10/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -62,12 +62,16 @@ PhaseIdealLoop* phase, int flags); static void call_lrb_stub(Node*& ctrl, Node*& val, Node* load_addr, DecoratorSet decorators, PhaseIdealLoop* phase); + + static void collect_nodes_above_barrier(Unique_Node_List &nodes_above_barrier, PhaseIdealLoop* phase, Node* ctrl, + Node* init_raw_mem); + static void test_in_cset(Node*& ctrl, Node*& not_cset_ctrl, Node* val, Node* raw_mem, PhaseIdealLoop* phase); static void move_gc_state_test_out_of_loop(IfNode* iff, PhaseIdealLoop* phase); static void merge_back_to_back_tests(Node* n, PhaseIdealLoop* phase); static bool merge_point_safe(Node* region); static bool identical_backtoback_ifs(Node *n, PhaseIdealLoop* phase); - static void fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& uses_to_ignore, uint last, PhaseIdealLoop* phase); + static void fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& nodes_above_barrier, uint last, PhaseIdealLoop* phase); static IfNode* find_unswitching_candidate(const IdealLoopTree *loop, PhaseIdealLoop* phase); static Node* get_load_addr(PhaseIdealLoop* phase, VectorSet& visited, Node* lrb); @@ -82,6 +86,11 @@ static void pin_and_expand(PhaseIdealLoop* phase); static void optimize_after_expansion(VectorSet& visited, Node_Stack& nstack, Node_List& old_new, PhaseIdealLoop* phase); + static void push_data_inputs_at_control(PhaseIdealLoop* phase, Node* n, Node* ctrl, + Unique_Node_List &wq); + static bool is_anti_dependent_load_at_control(PhaseIdealLoop* phase, Node* maybe_load, Node* store, Node* control); + + static void maybe_push_anti_dependent_loads(PhaseIdealLoop* phase, Node* maybe_store, Node* control, Unique_Node_List &wq); #ifdef ASSERT static void verify(RootNode* root); #endif diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/include/jvm.h openjdk-21-21.0.9+10/src/hotspot/share/include/jvm.h --- openjdk-21-21.0.8+9/src/hotspot/share/include/jvm.h 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/include/jvm.h 2025-10-13 07:49:24.000000000 +0000 @@ -150,6 +150,9 @@ JNIEXPORT jboolean JNICALL JVM_IsUseContainerSupport(void); +JNIEXPORT jboolean JNICALL +JVM_IsContainerized(void); + JNIEXPORT void * JNICALL JVM_LoadZipLibrary(); diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/interpreter/bytecodeStream.hpp openjdk-21-21.0.9+10/src/hotspot/share/interpreter/bytecodeStream.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/interpreter/bytecodeStream.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/interpreter/bytecodeStream.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -100,8 +100,23 @@ void set_next_bci(int bci) { assert(0 <= bci && bci <= method()->code_size(), "illegal bci"); _next_bci = bci; } // Bytecode-specific attributes - int dest() const { return bci() + bytecode().get_offset_s2(raw_code()); } - int dest_w() const { return bci() + bytecode().get_offset_s4(raw_code()); } + int get_offset_s2() const { return bytecode().get_offset_s2(raw_code()); } + int get_offset_s4() const { return bytecode().get_offset_s4(raw_code()); } + + // These methods are not safe to use before or during verification as they may + // have large offsets and cause overflows + int dest() const { + int min_offset = -1 * max_method_code_size; + int offset = bytecode().get_offset_s2(raw_code()); + guarantee(offset >= min_offset && offset <= max_method_code_size, "must be"); + return bci() + offset; + } + int dest_w() const { + int min_offset = -1 * max_method_code_size; + int offset = bytecode().get_offset_s4(raw_code()); + guarantee(offset >= min_offset && offset <= max_method_code_size, "must be"); + return bci() + offset; + } // One-byte indices. int get_index_u1() const { assert_raw_index_size(1); return *(jubyte*)(bcp()+1); } diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/jfr/support/jfrSymbolTable.cpp openjdk-21-21.0.9+10/src/hotspot/share/jfr/support/jfrSymbolTable.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/jfr/support/jfrSymbolTable.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/jfr/support/jfrSymbolTable.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,11 +23,10 @@ */ #include "precompiled.hpp" -#include "classfile/javaClasses.inline.hpp" #include "classfile/classLoaderData.hpp" +#include "classfile/javaClasses.hpp" #include "jfr/support/jfrSymbolTable.hpp" -#include "oops/instanceKlass.hpp" -#include "oops/oop.inline.hpp" +#include "oops/klass.hpp" #include "oops/symbol.hpp" #include "runtime/mutexLocker.hpp" @@ -200,7 +199,7 @@ traceid JfrSymbolTable::mark(const Symbol* sym, bool leakp /* false */) { assert(sym != nullptr, "invariant"); - return mark((uintptr_t)sym->identity_hash(), sym, leakp); + return mark(sym->identity_hash(), sym, leakp); } traceid JfrSymbolTable::mark(uintptr_t hash, const Symbol* sym, bool leakp) { @@ -236,59 +235,25 @@ } /* -* hidden classes symbol is the external name + -* the address of its InstanceKlass slash appended: -* java.lang.invoke.LambdaForm$BMH/22626602 -* -* caller needs ResourceMark -*/ - -uintptr_t JfrSymbolTable::hidden_klass_name_hash(const InstanceKlass* ik) { - assert(ik != nullptr, "invariant"); - assert(ik->is_hidden(), "invariant"); - const oop mirror = ik->java_mirror_no_keepalive(); - assert(mirror != nullptr, "invariant"); - return (uintptr_t)mirror->identity_hash(); -} - -static const char* create_hidden_klass_symbol(const InstanceKlass* ik, uintptr_t hash) { - assert(ik != nullptr, "invariant"); - assert(ik->is_hidden(), "invariant"); - assert(hash != 0, "invariant"); - char* hidden_symbol = nullptr; - const oop mirror = ik->java_mirror_no_keepalive(); - assert(mirror != nullptr, "invariant"); - char hash_buf[40]; - os::snprintf_checked(hash_buf, sizeof(hash_buf), "/" UINTX_FORMAT, hash); - const size_t hash_len = strlen(hash_buf); - const size_t result_len = ik->name()->utf8_length(); - hidden_symbol = NEW_RESOURCE_ARRAY(char, result_len + hash_len + 1); - ik->name()->as_klass_external_name(hidden_symbol, (int)result_len + 1); - assert(strlen(hidden_symbol) == result_len, "invariant"); - strcpy(hidden_symbol + result_len, hash_buf); - assert(strlen(hidden_symbol) == result_len + hash_len, "invariant"); - return hidden_symbol; -} - -bool JfrSymbolTable::is_hidden_klass(const Klass* k) { + * The hidden class symbol is the external name with the + * address of its Klass slash appended. + * + * "java.lang.invoke.LambdaForm$DMH/0x0000000037144c00" + * + * Caller needs ResourceMark. + */ +traceid JfrSymbolTable::mark_hidden_klass_name(const Klass* k, bool leakp) { assert(k != nullptr, "invariant"); - return k->is_instance_klass() && ((const InstanceKlass*)k)->is_hidden(); -} - -traceid JfrSymbolTable::mark_hidden_klass_name(const InstanceKlass* ik, bool leakp) { - assert(ik != nullptr, "invariant"); - assert(ik->is_hidden(), "invariant"); - const uintptr_t hash = hidden_klass_name_hash(ik); - const char* const hidden_symbol = create_hidden_klass_symbol(ik, hash); - return mark(hash, hidden_symbol, leakp); + assert(k->is_hidden(), "invariant"); + const uintptr_t hash = k->name()->identity_hash(); + return mark(hash, k->external_name(), leakp); } traceid JfrSymbolTable::mark(const Klass* k, bool leakp) { assert(k != nullptr, "invariant"); traceid symbol_id = 0; - if (is_hidden_klass(k)) { - assert(k->is_instance_klass(), "invariant"); - symbol_id = mark_hidden_klass_name((const InstanceKlass*)k, leakp); + if (k->is_hidden()) { + symbol_id = mark_hidden_klass_name(k, leakp); } else { Symbol* const sym = k->name(); if (sym != nullptr) { diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/jfr/support/jfrSymbolTable.hpp openjdk-21-21.0.9+10/src/hotspot/share/jfr/support/jfrSymbolTable.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/jfr/support/jfrSymbolTable.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/jfr/support/jfrSymbolTable.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -100,16 +100,13 @@ traceid mark(const Symbol* sym, bool leakp = false); traceid mark(const char* str, bool leakp = false); traceid mark(uintptr_t hash, const char* str, bool leakp); + traceid mark_hidden_klass_name(const Klass* k, bool leakp); traceid bootstrap_name(bool leakp); bool has_entries() const { return has_symbol_entries() || has_string_entries(); } bool has_symbol_entries() const { return _symbol_list != nullptr; } bool has_string_entries() const { return _string_list != nullptr; } - traceid mark_hidden_klass_name(const InstanceKlass* k, bool leakp); - bool is_hidden_klass(const Klass* k); - uintptr_t hidden_klass_name_hash(const InstanceKlass* ik); - // hashtable(s) callbacks void on_link(const SymbolEntry* entry); bool on_equals(uintptr_t hash, const SymbolEntry* entry); diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/oops/cpCache.hpp openjdk-21-21.0.9+10/src/hotspot/share/oops/cpCache.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/oops/cpCache.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/oops/cpCache.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -444,7 +444,14 @@ Array* resolved_indy_entries() { return _resolved_indy_entries; } ResolvedIndyEntry* resolved_indy_entry_at(int index) const { return _resolved_indy_entries->adr_at(index); } - int resolved_indy_entries_length() const { return _resolved_indy_entries->length(); } + + int resolved_indy_entries_length() const { + if (_resolved_indy_entries == nullptr) { + return 0; + } + return _resolved_indy_entries->length(); + } + void print_resolved_indy_entries(outputStream* st) const { for (int i = 0; i < _resolved_indy_entries->length(); i++) { _resolved_indy_entries->at(i).print_on(st); diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/opto/convertnode.cpp openjdk-21-21.0.9+10/src/hotspot/share/opto/convertnode.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/opto/convertnode.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/opto/convertnode.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -77,6 +77,11 @@ assert(false, "Unrecognized comparison for Conv2B: %s", NodeClassNames[in(1)->Opcode()]); } + // Skip the transformation if input is unexpected. + if (cmp == nullptr) { + return nullptr; + } + // Replace Conv2B with the cmove Node* bol = phase->transform(new BoolNode(cmp, BoolTest::eq)); return new CMoveINode(bol, phase->intcon(1), phase->intcon(0), TypeInt::BOOL); diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/opto/loopnode.cpp openjdk-21-21.0.9+10/src/hotspot/share/opto/loopnode.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/opto/loopnode.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/opto/loopnode.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -701,14 +701,24 @@ // We can only use that safepoint if there's no side effect between the backedge and the safepoint. - // mm is used for book keeping + // mm is the memory state at the safepoint (when it's a MergeMem) + // no_side_effect_since_safepoint() goes over the memory state at the backedge. It resets the mm input for each + // component of the memory state it encounters so it points to the base memory. Once no_side_effect_since_safepoint() + // is done, if no side effect after the safepoint was found, mm should transform to the base memory: the states at + // the backedge and safepoint are the same so all components of the memory state at the safepoint should have been + // reset. MergeMemNode* mm = nullptr; #ifdef ASSERT if (mem->is_MergeMem()) { mm = mem->clone()->as_MergeMem(); _igvn._worklist.push(mm); for (MergeMemStream mms(mem->as_MergeMem()); mms.next_non_empty(); ) { - if (mms.alias_idx() != Compile::AliasIdxBot && loop != get_loop(ctrl_or_self(mms.memory()))) { + // Loop invariant memory state won't be reset by no_side_effect_since_safepoint(). Do it here. + // Escape Analysis can add state to mm that it doesn't add to the backedge memory Phis, breaking verification + // code that relies on mm. Clear that extra state here. + if (mms.alias_idx() != Compile::AliasIdxBot && + (loop != get_loop(ctrl_or_self(mms.memory())) || + (mms.adr_type()->isa_oop_ptr() && mms.adr_type()->is_known_instance()))) { mm->set_memory_at(mms.alias_idx(), mem->as_MergeMem()->base_memory()); } } diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/opto/loopopts.cpp openjdk-21-21.0.9+10/src/hotspot/share/opto/loopopts.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/opto/loopopts.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/opto/loopopts.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -1849,10 +1849,11 @@ // Sinking a node from a pre loop to its main loop pins the node between the pre and main loops. If that node is input // to a check that's eliminated by range check elimination, it becomes input to an expression that feeds into the exit // test of the pre loop above the point in the graph where it's pinned. - if (n_loop->_head->is_CountedLoop() && n_loop->_head->as_CountedLoop()->is_pre_loop() && - u_loop->_head->is_CountedLoop() && u_loop->_head->as_CountedLoop()->is_main_loop() && - n_loop->_next == get_loop(u_loop->_head->as_CountedLoop()->skip_strip_mined())) { - return false; + if (n_loop->_head->is_CountedLoop() && n_loop->_head->as_CountedLoop()->is_pre_loop()) { + CountedLoopNode* pre_loop = n_loop->_head->as_CountedLoop(); + if (is_dominator(pre_loop->loopexit(), ctrl)) { + return false; + } } return true; } diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/opto/mulnode.cpp openjdk-21-21.0.9+10/src/hotspot/share/opto/mulnode.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/opto/mulnode.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/opto/mulnode.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -245,7 +245,7 @@ // Check for negative constant; if so negate the final result bool sign_flip = false; - unsigned int abs_con = uabs(con); + unsigned int abs_con = g_uabs(con); if (abs_con != (unsigned int)con) { sign_flip = true; } @@ -480,7 +480,7 @@ // Check for negative constant; if so negate the final result bool sign_flip = false; - julong abs_con = uabs(con); + julong abs_con = g_uabs(con); if (abs_con != (julong)con) { sign_flip = true; } diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/opto/reg_split.cpp openjdk-21-21.0.9+10/src/hotspot/share/opto/reg_split.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/opto/reg_split.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/opto/reg_split.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -503,7 +503,6 @@ uint bidx, pidx, slidx, insidx, inpidx, twoidx; uint non_phi = 1, spill_cnt = 0; Node *n1, *n2, *n3; - Node_List *defs,*phis; bool *UPblock; bool u1, u2, u3; Block *b, *pred; @@ -519,9 +518,6 @@ //----------Setup Code---------- // Create a convenient mapping from lrg numbers to reaches/leaves indices uint *lrg2reach = NEW_SPLIT_ARRAY(uint, maxlrg); - // Keep track of DEFS & Phis for later passes - defs = new Node_List(); - phis = new Node_List(); // Gather info on which LRG's are spilling, and build maps for (bidx = 1; bidx < maxlrg; bidx++) { if (lrgs(bidx).alive() && lrgs(bidx).reg() >= LRG::SPILL_REG) { @@ -569,8 +565,14 @@ #undef NEW_SPLIT_ARRAY // Initialize to array of empty vectorsets - for( slidx = 0; slidx < spill_cnt; slidx++ ) - UP_entry[slidx] = new VectorSet(split_arena); + // Each containing at most spill_cnt * _cfg.number_of_blocks() entries. + for (slidx = 0; slidx < spill_cnt; slidx++) { + UP_entry[slidx] = new(split_arena) VectorSet(split_arena); + } + + // Keep track of DEFS & Phis for later passes + Node_List defs(split_arena, 8); + Node_List phis(split_arena, 16); //----------PASS 1---------- //----------Propagation & Node Insertion Code---------- @@ -702,7 +704,7 @@ } // end if not found correct phi // Here you have either found or created the Phi, so record it assert(phi != nullptr,"Must have a Phi Node here"); - phis->push(phi); + phis.push(phi); // PhiNodes should either force the LRG UP or DOWN depending // on its inputs and the register pressure in the Phi's block. UPblock[slidx] = true; // Assume new DEF is UP @@ -1189,7 +1191,7 @@ if( deflrg.reg() >= LRG::SPILL_REG ) { // Spilled? uint slidx = lrg2reach[defidx]; // Add to defs list for later assignment of new live range number - defs->push(n); + defs.push(n); // Set a flag on the Node indicating it has already spilled. // Only do it for capacity spills not conflict spills. if( !deflrg._direct_conflict ) @@ -1308,9 +1310,9 @@ //----------PASS 2---------- // Reset all DEF live range numbers here - for( insidx = 0; insidx < defs->size(); insidx++ ) { + for( insidx = 0; insidx < defs.size(); insidx++ ) { // Grab the def - n1 = defs->at(insidx); + n1 = defs.at(insidx); // Set new lidx for DEF new_lrg(n1, maxlrg++); } @@ -1320,8 +1322,8 @@ // info for each spilled LRG and update edges. // Walk the phis list to patch inputs, split phis, and name phis uint lrgs_before_phi_split = maxlrg; - for( insidx = 0; insidx < phis->size(); insidx++ ) { - Node *phi = phis->at(insidx); + for( insidx = 0; insidx < phis.size(); insidx++ ) { + Node *phi = phis.at(insidx); assert(phi->is_Phi(),"This list must only contain Phi Nodes"); Block *b = _cfg.get_block_for_node(phi); // Grab the live range number @@ -1389,8 +1391,8 @@ //----------PASS 3---------- // Pass over all Phi's to union the live ranges - for( insidx = 0; insidx < phis->size(); insidx++ ) { - Node *phi = phis->at(insidx); + for( insidx = 0; insidx < phis.size(); insidx++ ) { + Node *phi = phis.at(insidx); assert(phi->is_Phi(),"This list must only contain Phi Nodes"); // Walk all inputs to Phi and Union input live range with Phi live range for( uint i = 1; i < phi->req(); i++ ) { @@ -1408,9 +1410,9 @@ } // End for all inputs to the Phi Node } // End for all Phi Nodes // Now union all two address instructions - for (insidx = 0; insidx < defs->size(); insidx++) { + for (insidx = 0; insidx < defs.size(); insidx++) { // Grab the def - n1 = defs->at(insidx); + n1 = defs.at(insidx); // Set new lidx for DEF & handle 2-addr instructions if (n1->is_Mach() && ((twoidx = n1->as_Mach()->two_adr()) != 0)) { assert(_lrg_map.find(n1->in(twoidx)) < maxlrg,"Assigning bad live range index"); diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/opto/subnode.cpp openjdk-21-21.0.9+10/src/hotspot/share/opto/subnode.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/opto/subnode.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/opto/subnode.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -1899,14 +1899,14 @@ case Type::Int: { const TypeInt* ti = t1->is_int(); if (ti->is_con()) { - return TypeInt::make(uabs(ti->get_con())); + return TypeInt::make(g_uabs(ti->get_con())); } break; } case Type::Long: { const TypeLong* tl = t1->is_long(); if (tl->is_con()) { - return TypeLong::make(uabs(tl->get_con())); + return TypeLong::make(g_uabs(tl->get_con())); } break; } diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/opto/type.cpp openjdk-21-21.0.9+10/src/hotspot/share/opto/type.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/opto/type.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/opto/type.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -3125,8 +3125,8 @@ return (TypeRawPtr*)(new TypeRawPtr(ptr,0))->hashcons(); } -const TypeRawPtr *TypeRawPtr::make( address bits ) { - assert( bits, "Use TypePtr for null" ); +const TypeRawPtr *TypeRawPtr::make(address bits) { + assert(bits != nullptr, "Use TypePtr for null"); return (TypeRawPtr*)(new TypeRawPtr(Constant,bits))->hashcons(); } @@ -3215,15 +3215,21 @@ case TypePtr::BotPTR: case TypePtr::NotNull: return this; - case TypePtr::Null: case TypePtr::Constant: { - address bits = _bits+offset; - if ( bits == 0 ) return TypePtr::NULL_PTR; - return make( bits ); + uintptr_t bits = (uintptr_t)_bits; + uintptr_t sum = bits + offset; + if (( offset < 0 ) + ? ( sum > bits ) // Underflow? + : ( sum < bits )) { // Overflow? + return BOTTOM; + } else if ( sum == 0 ) { + return TypePtr::NULL_PTR; + } else { + return make( (address)sum ); + } } default: ShouldNotReachHere(); } - return nullptr; // Lint noise } //------------------------------eq--------------------------------------------- diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/prims/jvm.cpp openjdk-21-21.0.9+10/src/hotspot/share/prims/jvm.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/prims/jvm.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/prims/jvm.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -110,6 +110,9 @@ #if INCLUDE_MANAGEMENT #include "services/finalizerService.hpp" #endif +#ifdef LINUX +#include "osContainer_linux.hpp" +#endif #include @@ -493,6 +496,15 @@ return JNI_FALSE; JVM_END +JVM_LEAF(jboolean, JVM_IsContainerized(void)) +#ifdef LINUX + if (OSContainer::is_containerized()) { + return JNI_TRUE; + } +#endif + return JNI_FALSE; +JVM_END + // java.lang.Throwable ////////////////////////////////////////////////////// JVM_ENTRY(void, JVM_FillInStackTrace(JNIEnv *env, jobject receiver)) @@ -2955,9 +2967,10 @@ // We must release the Threads_lock before we can post a jvmti event // in Thread::start. { + MutexLocker throttle_ml(UseThreadsLockThrottleLock ? ThreadsLockThrottle_lock : nullptr); // Ensure that the C++ Thread and OSThread structures aren't freed before // we operate. - MutexLocker mu(Threads_lock); + MutexLocker ml(Threads_lock); // Since JDK 5 the java.lang.Thread threadStatus is used to prevent // re-starting an already started thread, so we should usually find diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/prims/methodHandles.cpp openjdk-21-21.0.9+10/src/hotspot/share/prims/methodHandles.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/prims/methodHandles.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/prims/methodHandles.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -934,19 +934,12 @@ void MethodHandles::add_dependent_nmethod(oop call_site, nmethod* nm) { assert_locked_or_safepoint(CodeCache_lock); - oop context = java_lang_invoke_CallSite::context_no_keepalive(call_site); - DependencyContext deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context); - // Try to purge stale entries on updates. - // Since GC doesn't clean dependency contexts rooted at CallSiteContext objects, - // in order to avoid memory leak, stale entries are purged whenever a dependency list - // is changed (both on addition and removal). Though memory reclamation is delayed, - // it avoids indefinite memory usage growth. + DependencyContext deps = java_lang_invoke_CallSite::vmdependencies(call_site); deps.add_dependent_nmethod(nm); } void MethodHandles::clean_dependency_context(oop call_site) { - oop context = java_lang_invoke_CallSite::context_no_keepalive(call_site); - DependencyContext deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context); + DependencyContext deps = java_lang_invoke_CallSite::vmdependencies(call_site); deps.clean_unloading_dependents(); } @@ -958,8 +951,7 @@ NoSafepointVerifier nsv; MutexLocker ml(CodeCache_lock, Mutex::_no_safepoint_check_flag); - oop context = java_lang_invoke_CallSite::context_no_keepalive(call_site()); - DependencyContext deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context); + DependencyContext deps = java_lang_invoke_CallSite::vmdependencies(call_site()); deps.mark_dependent_nmethods(deopt_scope, changes); } } @@ -1323,23 +1315,6 @@ } JVM_END -// It is called by a Cleaner object which ensures that dropped CallSites properly -// deallocate their dependency information. -JVM_ENTRY(void, MHN_clearCallSiteContext(JNIEnv* env, jobject igcls, jobject context_jh)) { - Handle context(THREAD, JNIHandles::resolve_non_null(context_jh)); - DeoptimizationScope deopt_scope; - { - NoSafepointVerifier nsv; - MutexLocker ml(THREAD, CodeCache_lock, Mutex::_no_safepoint_check_flag); - DependencyContext deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context()); - deps.remove_and_mark_for_deoptimization_all_dependents(&deopt_scope); - // This is assumed to be an 'atomic' operation by verification. - // So keep it under lock for now. - deopt_scope.deoptimize_marked(); - } -} -JVM_END - /** * Throws a java/lang/UnsupportedOperationException unconditionally. * This is required by the specification of MethodHandle.invoke if @@ -1374,7 +1349,6 @@ #define MT JLINV "MethodType;" #define MH JLINV "MethodHandle;" #define MEM JLINV "MemberName;" -#define CTX JLINV "MethodHandleNatives$CallSiteContext;" #define CC (char*) /*cast a literal from (const char*)*/ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) @@ -1390,7 +1364,6 @@ {CC "setCallSiteTargetNormal", CC "(" CS "" MH ")V", FN_PTR(MHN_setCallSiteTargetNormal)}, {CC "setCallSiteTargetVolatile", CC "(" CS "" MH ")V", FN_PTR(MHN_setCallSiteTargetVolatile)}, {CC "copyOutBootstrapArguments", CC "(" CLS "[III[" OBJ "IZ" OBJ ")V", FN_PTR(MHN_copyOutBootstrapArguments)}, - {CC "clearCallSiteContext", CC "(" CTX ")V", FN_PTR(MHN_clearCallSiteContext)}, {CC "staticFieldOffset", CC "(" MEM ")J", FN_PTR(MHN_staticFieldOffset)}, {CC "staticFieldBase", CC "(" MEM ")" OBJ, FN_PTR(MHN_staticFieldBase)}, {CC "getMemberVMInfo", CC "(" MEM ")" OBJ, FN_PTR(MHN_getMemberVMInfo)} diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/prims/whitebox.cpp openjdk-21-21.0.9+10/src/hotspot/share/prims/whitebox.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/prims/whitebox.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/prims/whitebox.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -1049,6 +1049,22 @@ } #endif +bool WhiteBox::is_asan_enabled() { +#ifdef ADDRESS_SANITIZER + return true; +#else + return false; +#endif +} + +bool WhiteBox::is_ubsan_enabled() { +#ifdef UNDEFINED_BEHAVIOR_SANITIZER + return true; +#else + return false; +#endif +} + bool WhiteBox::compile_method(Method* method, int comp_level, int bci, JavaThread* THREAD) { // Screen for unavailable/bad comp level or null method AbstractCompiler* comp = CompileBroker::compiler(comp_level); @@ -1832,6 +1848,14 @@ return (jboolean) obj_oop->mark().has_monitor(); WB_END +WB_ENTRY(jboolean, WB_IsAsanEnabled(JNIEnv* env)) + return (jboolean) WhiteBox::is_asan_enabled(); +WB_END + +WB_ENTRY(jboolean, WB_IsUbsanEnabled(JNIEnv* env)) + return (jboolean) WhiteBox::is_ubsan_enabled(); +WB_END + WB_ENTRY(jboolean, WB_DeflateIdleMonitors(JNIEnv* env, jobject wb)) log_info(monitorinflation)("WhiteBox initiated DeflateIdleMonitors"); return ObjectSynchronizer::request_deflate_idle_monitors_from_wb(); @@ -2418,6 +2442,13 @@ return ret; WB_END +// Available cpus of the host machine, Linux only. +// Used in container testing. +WB_ENTRY(jint, WB_HostCPUs(JNIEnv* env, jobject o)) + LINUX_ONLY(return os::Linux::active_processor_count();) + return -1; // Not used/implemented on other platforms +WB_END + WB_ENTRY(void, WB_PrintOsInfo(JNIEnv* env, jobject o)) os::print_os_info(tty); WB_END @@ -2751,6 +2782,8 @@ (void*)&WB_AddModuleExportsToAll }, {CC"deflateIdleMonitors", CC"()Z", (void*)&WB_DeflateIdleMonitors }, {CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated }, + {CC"isAsanEnabled", CC"()Z", (void*)&WB_IsAsanEnabled }, + {CC"isUbsanEnabled", CC"()Z", (void*)&WB_IsUbsanEnabled }, {CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint }, {CC"forceClassLoaderStatsSafepoint", CC"()V", (void*)&WB_ForceClassLoaderStatsSafepoint }, {CC"getConstantPool0", CC"(Ljava/lang/Class;)J", (void*)&WB_GetConstantPool }, @@ -2824,6 +2857,7 @@ (void*)&WB_ValidateCgroup }, {CC"hostPhysicalMemory", CC"()J", (void*)&WB_HostPhysicalMemory }, {CC"hostPhysicalSwap", CC"()J", (void*)&WB_HostPhysicalSwap }, + {CC"hostCPUs", CC"()I", (void*)&WB_HostCPUs }, {CC"printOsInfo", CC"()V", (void*)&WB_PrintOsInfo }, {CC"disableElfSectionCache", CC"()V", (void*)&WB_DisableElfSectionCache }, {CC"resolvedMethodItemsCount", CC"()J", (void*)&WB_ResolvedMethodItemsCount }, diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/prims/whitebox.hpp openjdk-21-21.0.9+10/src/hotspot/share/prims/whitebox.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/prims/whitebox.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/prims/whitebox.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,6 +71,9 @@ #ifdef LINUX static bool validate_cgroup(const char* proc_cgroups, const char* proc_self_cgroup, const char* proc_self_mountinfo, u1* cg_flags); #endif + // provide info about enabling of Address Sanitizer / Undefined Behavior Sanitizer + static bool is_asan_enabled(); + static bool is_ubsan_enabled(); }; #endif // SHARE_PRIMS_WHITEBOX_HPP diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/runtime/globals.hpp openjdk-21-21.0.9+10/src/hotspot/share/runtime/globals.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/runtime/globals.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/runtime/globals.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -1990,6 +1990,10 @@ "(default) disables native heap trimming.") \ range(0, UINT_MAX) \ \ + product(bool, UseThreadsLockThrottleLock, true, DIAGNOSTIC, \ + "Use an extra lock during Thread start and exit to alleviate" \ + "contention on Threads_lock.") \ + \ product(bool, UseSecondarySupersCache, true, DIAGNOSTIC, \ "Use secondary supers cache during subtype checks.") \ \ diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/runtime/mutexLocker.cpp openjdk-21-21.0.9+10/src/hotspot/share/runtime/mutexLocker.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/runtime/mutexLocker.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/runtime/mutexLocker.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -66,6 +66,7 @@ Mutex* TouchedMethodLog_lock = nullptr; Mutex* RetData_lock = nullptr; Monitor* VMOperation_lock = nullptr; +Monitor* ThreadsLockThrottle_lock = nullptr; Monitor* Threads_lock = nullptr; Mutex* NonJavaThreadsList_lock = nullptr; Mutex* NonJavaThreadsListSync_lock = nullptr; @@ -326,6 +327,8 @@ MUTEX_DEFN(JVMCIRuntime_lock , PaddedMonitor, safepoint, true); #endif + MUTEX_DEFN(ThreadsLockThrottle_lock , PaddedMonitor, safepoint); + // These locks have relative rankings, and inherit safepoint checking attributes from that rank. MUTEX_DEFL(InlineCacheBuffer_lock , PaddedMutex , CompiledIC_lock); MUTEX_DEFL(VtableStubs_lock , PaddedMutex , CompiledIC_lock); // Also holds DumpTimeTable_lock diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/runtime/mutexLocker.hpp openjdk-21-21.0.9+10/src/hotspot/share/runtime/mutexLocker.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/runtime/mutexLocker.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/runtime/mutexLocker.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -61,6 +61,8 @@ extern Mutex* TouchedMethodLog_lock; // a lock on allocation of LogExecutedMethods info extern Mutex* RetData_lock; // a lock on installation of RetData inside method data extern Monitor* VMOperation_lock; // a lock on queue of vm_operations waiting to execute +extern Monitor* ThreadsLockThrottle_lock; // used by Thread start/exit to reduce competition for Threads_lock, + // so a VM thread calling a safepoint is prioritized extern Monitor* Threads_lock; // a lock on the Threads table of active Java threads // (also used by Safepoints too to block threads creation/destruction) extern Mutex* NonJavaThreadsList_lock; // a lock on the NonJavaThreads list diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/runtime/os.cpp openjdk-21-21.0.9+10/src/hotspot/share/runtime/os.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/runtime/os.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/runtime/os.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -1472,6 +1472,56 @@ return false; } +static char* _image_release_file_content = nullptr; + +void os::read_image_release_file() { + assert(_image_release_file_content == nullptr, "release file content must not be already set"); + const char* home = Arguments::get_java_home(); + stringStream ss; + ss.print("%s/release", home); + + FILE* file = fopen(ss.base(), "rb"); + if (file == nullptr) { + return; + } + fseek(file, 0, SEEK_END); + long sz = ftell(file); + if (sz == -1) { + return; + } + fseek(file, 0, SEEK_SET); + + char* tmp = (char*) os::malloc(sz + 1, mtInternal); + if (tmp == nullptr) { + fclose(file); + return; + } + + size_t elements_read = fread(tmp, 1, sz, file); + if (elements_read < (size_t)sz) { + tmp[elements_read] = '\0'; + } else { + tmp[sz] = '\0'; + } + // issues with \r in line endings on Windows, so better replace those + for (size_t i = 0; i < elements_read; i++) { + if (tmp[i] == '\r') { + tmp[i] = ' '; + } + } + Atomic::release_store(&_image_release_file_content, tmp); + fclose(file); +} + +void os::print_image_release_file(outputStream* st) { + char* ifrc = Atomic::load_acquire(&_image_release_file_content); + if (ifrc != nullptr) { + st->print_cr("%s", ifrc); + } else { + st->print_cr(""); + } +} + bool os::file_exists(const char* filename) { struct stat statbuf; if (filename == nullptr || strlen(filename) == 0) { diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/runtime/os.hpp openjdk-21-21.0.9+10/src/hotspot/share/runtime/os.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/runtime/os.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/runtime/os.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -640,6 +640,11 @@ static FILE* fopen(const char* path, const char* mode); static jlong lseek(int fd, jlong offset, int whence); static bool file_exists(const char* file); + + // read/store and print the release file of the image + static void read_image_release_file(); + static void print_image_release_file(outputStream* st); + // This function, on Windows, canonicalizes a given path (see os_windows.cpp for details). // On Posix, this function is a noop: it does not change anything and just returns // the input pointer. diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/runtime/threads.cpp openjdk-21-21.0.9+10/src/hotspot/share/runtime/threads.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/runtime/threads.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/runtime/threads.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -408,6 +408,19 @@ initialize_class(vmSymbols::java_lang_invoke_MethodHandleNatives(), CHECK); } +// One-shot PeriodicTask subclass for reading the release file +class ReadReleaseFileTask : public PeriodicTask { + public: + ReadReleaseFileTask() : PeriodicTask(100) {} + + virtual void task() { + os::read_image_release_file(); + + // Reclaim our storage and disenroll ourself. + delete this; + } +}; + jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { extern void JDK_Version_init(); @@ -555,6 +568,10 @@ return status; } + // Have the WatcherThread read the release file in the background. + ReadReleaseFileTask* read_task = new ReadReleaseFileTask(); + read_task->enroll(); + // Create WatcherThread as soon as we can since we need it in case // of hangs during error reporting. WatcherThread::start(); @@ -1017,7 +1034,9 @@ void Threads::remove(JavaThread* p, bool is_daemon) { // Extra scope needed for Thread_lock, so we can check // that we do not remove thread without safepoint code notice - { MonitorLocker ml(Threads_lock); + { + MutexLocker throttle_ml(UseThreadsLockThrottleLock ? ThreadsLockThrottle_lock : nullptr); + MonitorLocker ml(Threads_lock); if (ThreadIdTable::is_initialized()) { // This cleanup must be done before the current thread's GC barrier @@ -1065,7 +1084,7 @@ // Notify threads waiting in EscapeBarriers EscapeBarrier::thread_removed(p); - } // unlock Threads_lock + } // unlock Threads_lock and ThreadsLockThrottle_lock // Reduce the ObjectMonitor ceiling for the exiting thread. ObjectSynchronizer::dec_in_use_list_ceiling(); diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/sanitizers/ub.hpp openjdk-21-21.0.9+10/src/hotspot/share/sanitizers/ub.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/sanitizers/ub.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/sanitizers/ub.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2024 SAP SE. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,10 @@ // Useful if the function or method is known to do something special or even 'dangerous', for // example causing desired signals/crashes. #ifdef UNDEFINED_BEHAVIOR_SANITIZER -#if defined(__clang__) || defined(__GNUC__) +#if defined(__clang__) +#define ATTRIBUTE_NO_UBSAN __attribute__((no_sanitize("undefined","float-divide-by-zero"))) +#endif +#if defined(__GNUC__) && !defined(__clang__) #define ATTRIBUTE_NO_UBSAN __attribute__((no_sanitize("undefined"))) #endif #endif diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/services/memReporter.cpp openjdk-21-21.0.9+10/src/hotspot/share/services/memReporter.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/services/memReporter.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/services/memReporter.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -516,8 +516,9 @@ const char* scale = current_scale(); outputStream* out = output(); out->print("arena=" SIZE_FORMAT "%s", amount_in_current_scale(current_amount), scale); - if (diff_in_current_scale(current_amount, early_amount) != 0) { - out->print(" " INT64_PLUS_FORMAT "d", diff_in_current_scale(current_amount, early_amount)); + int64_t amount_diff = diff_in_current_scale(current_amount, early_amount); + if (amount_diff != 0) { + out->print(" " INT64_PLUS_FORMAT "%s", amount_diff, scale); } out->print(" #" SIZE_FORMAT "", current_count); diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/utilities/globalDefinitions.hpp openjdk-21-21.0.9+10/src/hotspot/share/utilities/globalDefinitions.hpp --- openjdk-21-21.0.8+9/src/hotspot/share/utilities/globalDefinitions.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/utilities/globalDefinitions.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -1164,7 +1164,7 @@ // abs methods which cannot overflow and so are well-defined across // the entire domain of integer types. -static inline unsigned int uabs(unsigned int n) { +static inline unsigned int g_uabs(unsigned int n) { union { unsigned int result; int value; @@ -1173,7 +1173,7 @@ if (value < 0) result = 0-result; return result; } -static inline julong uabs(julong n) { +static inline julong g_uabs(julong n) { union { julong result; jlong value; @@ -1182,8 +1182,8 @@ if (value < 0) result = 0-result; return result; } -static inline julong uabs(jlong n) { return uabs((julong)n); } -static inline unsigned int uabs(int n) { return uabs((unsigned int)n); } +static inline julong g_uabs(jlong n) { return g_uabs((julong)n); } +static inline unsigned int g_uabs(int n) { return g_uabs((unsigned int)n); } // "to" should be greater than "from." inline intx byte_size(void* from, void* to) { diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/utilities/spinYield.cpp openjdk-21-21.0.9+10/src/hotspot/share/utilities/spinYield.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/utilities/spinYield.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/utilities/spinYield.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -66,7 +66,7 @@ if (_sleep_time.value() != 0) { // Report sleep duration, if slept. separator = print_separator(s, separator); s->print("sleep = " UINT64_FORMAT " usecs", - _sleep_time.milliseconds()); + _sleep_time.microseconds()); } if (separator == initial_separator) { s->print("no waiting"); diff -Nru openjdk-21-21.0.8+9/src/hotspot/share/utilities/vmError.cpp openjdk-21-21.0.9+10/src/hotspot/share/utilities/vmError.cpp --- openjdk-21-21.0.8+9/src/hotspot/share/utilities/vmError.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/hotspot/share/utilities/vmError.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -1291,6 +1291,10 @@ LogConfiguration::describe_current_configuration(st); st->cr(); + STEP_IF("printing release file content", _verbose) + st->print_cr("Release file:"); + os::print_image_release_file(st); + STEP_IF("printing all environment variables", _verbose) os::print_environment_variables(st, env_list); st->cr(); @@ -1466,6 +1470,10 @@ LogConfiguration::describe(st); st->cr(); + // STEP("printing release file content") + st->print_cr("Release file:"); + os::print_image_release_file(st); + // STEP("printing all environment variables") os::print_environment_variables(st, env_list); diff -Nru openjdk-21-21.0.8+9/src/java.base/linux/classes/jdk/internal/platform/CgroupMetrics.java openjdk-21-21.0.9+10/src/java.base/linux/classes/jdk/internal/platform/CgroupMetrics.java --- openjdk-21-21.0.8+9/src/java.base/linux/classes/jdk/internal/platform/CgroupMetrics.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/linux/classes/jdk/internal/platform/CgroupMetrics.java 2025-10-13 07:49:24.000000000 +0000 @@ -36,6 +36,11 @@ } @Override + public boolean isContainerized() { + return isContainerized0(); + } + + @Override public String getProvider() { return subsystem.getProvider(); } @@ -194,6 +199,7 @@ } private static native boolean isUseContainerSupport(); + private static native boolean isContainerized0(); private static native long getTotalMemorySize0(); private static native long getTotalSwapSize0(); diff -Nru openjdk-21-21.0.8+9/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystem.java openjdk-21-21.0.9+10/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystem.java --- openjdk-21-21.0.8+9/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystem.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystem.java 2025-10-13 07:49:24.000000000 +0000 @@ -31,6 +31,11 @@ */ public interface CgroupSubsystem extends Metrics { + + default boolean isContainerized() { + return false; // This default impl is never used + } + /** * Returned for metrics of type long if the underlying implementation * has determined that no limit is being imposed. diff -Nru openjdk-21-21.0.8+9/src/java.base/linux/native/libjava/CgroupMetrics.c openjdk-21-21.0.9+10/src/java.base/linux/native/libjava/CgroupMetrics.c --- openjdk-21-21.0.8+9/src/java.base/linux/native/libjava/CgroupMetrics.c 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/linux/native/libjava/CgroupMetrics.c 2025-10-13 07:49:24.000000000 +0000 @@ -36,6 +36,12 @@ return JVM_IsUseContainerSupport(); } +JNIEXPORT jboolean JNICALL +Java_jdk_internal_platform_CgroupMetrics_isContainerized0(JNIEnv *env, jclass ignored) +{ + return JVM_IsContainerized(); +} + JNIEXPORT jlong JNICALL Java_jdk_internal_platform_CgroupMetrics_getTotalMemorySize0 (JNIEnv *env, jclass ignored) diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/java/lang/AbstractStringBuilder.java openjdk-21-21.0.9+10/src/java.base/share/classes/java/lang/AbstractStringBuilder.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/java/lang/AbstractStringBuilder.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/java/lang/AbstractStringBuilder.java 2025-10-13 07:49:24.000000000 +0000 @@ -1313,8 +1313,8 @@ ensureCapacityInternal(count + len); shift(dstOffset, len); count += len; - if (s instanceof String) { - putStringAt(dstOffset, (String) s, start, end); + if (s instanceof String str && str.length() == len) { + putStringAt(dstOffset, str); } else { putCharsAt(dstOffset, s, start, end); } @@ -1741,11 +1741,6 @@ } } - private void putStringAt(int index, String str, int off, int end) { - inflateIfNeededFor(str); - str.getBytes(value, off, index, coder, end - off); - } - private void putStringAt(int index, String str) { inflateIfNeededFor(str); str.getBytes(value, index, coder); diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/java/lang/Class.java openjdk-21-21.0.9+10/src/java.base/share/classes/java/lang/Class.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/java/lang/Class.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/java/lang/Class.java 2025-10-13 07:49:24.000000000 +0000 @@ -55,7 +55,9 @@ import java.lang.constant.Constable; import java.net.URL; import java.security.AccessController; +import java.security.Permissions; import java.security.PrivilegedAction; +import java.security.ProtectionDomain; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -3142,10 +3144,6 @@ return true; } - - /** protection domain returned when the internal domain is null */ - private static java.security.ProtectionDomain allPermDomain; - /** * Returns the {@code ProtectionDomain} of this class. If there is a * security manager installed, this method first calls the security @@ -3166,7 +3164,7 @@ * @see java.lang.RuntimePermission * @since 1.2 */ - public java.security.ProtectionDomain getProtectionDomain() { + public ProtectionDomain getProtectionDomain() { @SuppressWarnings("removal") SecurityManager sm = System.getSecurityManager(); if (sm != null) { @@ -3175,26 +3173,30 @@ return protectionDomain(); } + /** Holder for the protection domain returned when the internal domain is null */ + private static class Holder { + private static final ProtectionDomain allPermDomain; + static { + Permissions perms = new Permissions(); + perms.add(SecurityConstants.ALL_PERMISSION); + allPermDomain = new ProtectionDomain(null, perms); + } + } + // package-private - java.security.ProtectionDomain protectionDomain() { - java.security.ProtectionDomain pd = getProtectionDomain0(); + ProtectionDomain protectionDomain() { + ProtectionDomain pd = getProtectionDomain0(); if (pd == null) { - if (allPermDomain == null) { - java.security.Permissions perms = - new java.security.Permissions(); - perms.add(SecurityConstants.ALL_PERMISSION); - allPermDomain = - new java.security.ProtectionDomain(null, perms); - } - pd = allPermDomain; + return Holder.allPermDomain; + } else { + return pd; } - return pd; } /** * Returns the ProtectionDomain of this class. */ - private native java.security.ProtectionDomain getProtectionDomain0(); + private native ProtectionDomain getProtectionDomain0(); /* * Return the Virtual Machine's Class object for the named diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/java/lang/invoke/CallSite.java openjdk-21-21.0.9+10/src/java.base/share/classes/java/lang/invoke/CallSite.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/java/lang/invoke/CallSite.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/java/lang/invoke/CallSite.java 2025-10-13 07:49:24.000000000 +0000 @@ -139,12 +139,6 @@ } /** - * {@code CallSite} dependency context. - * JVM uses CallSite.context to store nmethod dependencies on the call site target. - */ - private final MethodHandleNatives.CallSiteContext context = MethodHandleNatives.CallSiteContext.make(this); - - /** * Returns the type of this call site's target. * Although targets may change, any call site's type is permanent, and can never change to an unequal type. * The {@code setTarget} method enforces this invariant by refusing any new target that does diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java openjdk-21-21.0.9+10/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java 2025-10-13 07:49:24.000000000 +0000 @@ -71,31 +71,6 @@ boolean resolve, Object ifNotAvailable); - /** Represents a context to track nmethod dependencies on CallSite instance target. */ - static class CallSiteContext implements Runnable { - //@Injected JVM_nmethodBucket* vmdependencies; - //@Injected jlong last_cleanup; - - static CallSiteContext make(CallSite cs) { - final CallSiteContext newContext = new CallSiteContext(); - // CallSite instance is tracked by a Cleanable which clears native - // structures allocated for CallSite context. Though the CallSite can - // become unreachable, its Context is retained by the Cleanable instance - // (which is referenced from Cleaner instance which is referenced from - // CleanerFactory class) until cleanup is performed. - CleanerFactory.cleaner().register(cs, newContext); - return newContext; - } - - @Override - public void run() { - MethodHandleNatives.clearCallSiteContext(this); - } - } - - /** Invalidate all recorded nmethods. */ - private static native void clearCallSiteContext(CallSiteContext context); - private static native void registerNatives(); static { registerNatives(); diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/java/math/BigInteger.java openjdk-21-21.0.9+10/src/java.base/share/classes/java/math/BigInteger.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/java/math/BigInteger.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/java/math/BigInteger.java 2025-10-13 07:49:24.000000000 +0000 @@ -315,12 +315,18 @@ throw new NumberFormatException("Zero length BigInteger"); } Objects.checkFromIndexSize(off, len, val.length); + if (len == 0) { + mag = ZERO.mag; + signum = ZERO.signum; + return; + } - if (val[off] < 0) { - mag = makePositive(val, off, len); + int b = val[off]; + if (b < 0) { + mag = makePositive(b, val, off, len); signum = -1; } else { - mag = stripLeadingZeroBytes(val, off, len); + mag = stripLeadingZeroBytes(b, val, off, len); signum = (mag.length == 0 ? 0 : 1); } if (mag.length >= MAX_MAG_LENGTH) { @@ -4568,77 +4574,167 @@ return keep == 0 ? val : java.util.Arrays.copyOfRange(val, keep, vlen); } - /** + private static int[] stripLeadingZeroBytes(byte[] a, int from, int len) { + return stripLeadingZeroBytes(Integer.MIN_VALUE, a, from, len); + } + + /* * Returns a copy of the input array stripped of any leading zero bytes. + * The returned array is either empty, or its 0-th element is non-zero, + * meeting the "minimal" requirement for field mag (see comment on mag). + * + * The range [from, from + len) must be well-formed w.r.t. array a. + * + * b < -128 means that a[from] has not yet been read. + * Otherwise, b must be a[from], have been read only once before invoking + * this method, and len > 0 must hold. */ - private static int[] stripLeadingZeroBytes(byte[] a, int off, int len) { - int indexBound = off + len; - int keep; - - // Find first nonzero byte - for (keep = off; keep < indexBound && a[keep] == 0; keep++) - ; - - // Allocate new array and copy relevant part of input array - int intLength = ((indexBound - keep) + 3) >>> 2; - int[] result = new int[intLength]; - int b = indexBound - 1; - for (int i = intLength-1; i >= 0; i--) { - result[i] = a[b--] & 0xff; - int bytesRemaining = b - keep + 1; - int bytesToTransfer = Math.min(3, bytesRemaining); - for (int j=8; j <= (bytesToTransfer << 3); j += 8) - result[i] |= ((a[b--] & 0xff) << j); + private static int[] stripLeadingZeroBytes(int b, byte[] a, int from, int len) { + /* + * Except for the first byte, each read access to the input array a + * is of the form a[from++]. + * The index from is never otherwise altered, except right below, + * and only increases in steps of 1, always up to index to. + * Hence, each byte in the array is read exactly once, from lower to + * higher indices (from most to least significant byte). + */ + if (len == 0) { + return ZERO.mag; } - return result; + int to = from + len; + if (b < -128) { + b = a[from]; + } + /* Either way, a[from] has now been read exactly once, skip to next. */ + ++from; + /* + * Set up the shortest int[] for the sequence of the bytes + * b, a[from+1], ..., a[to-1] (len > 0) + * Shortest means first skipping leading zeros. + */ + for (; b == 0 && from < to; b = a[from++]) + ; //empty body + if (b == 0) { + /* Here, from == to as well. All bytes are zeros. */ + return ZERO.mag; + } + /* + * Allocate just enough ints to hold (to - from + 1) bytes, that is + * ((to - from + 1) + 3) / 4 = (to - from) / 4 + 1 + */ + int[] res = new int[((to - from) >> 2) + 1]; + /* + * A "digit" is a group of 4 adjacent bytes aligned w.r.t. index to. + * (Implied 0 bytes are prepended as needed.) + * b is the most significant byte not 0. + * Digit d0 spans the range of indices that includes current (from - 1). + */ + int d0 = b & 0xFF; + while (((to - from) & 0x3) != 0) { + d0 = d0 << 8 | a[from++] & 0xFF; + } + res[0] = d0; + /* + * Prepare the remaining digits. + * (to - from) is a multiple of 4, so prepare an int for every 4 bytes. + * This is a candidate for Unsafe.copy[Swap]Memory(). + */ + int i = 1; + while (from < to) { + res[i++] = a[from++] << 24 | (a[from++] & 0xFF) << 16 + | (a[from++] & 0xFF) << 8 | (a[from++] & 0xFF); + } + return res; } - /** + /* * Takes an array a representing a negative 2's-complement number and * returns the minimal (no leading zero bytes) unsigned whose value is -a. + * + * len > 0 must hold. + * The range [from, from + len) must be well-formed w.r.t. array a. + * b is assumed to be the result of reading a[from] and to meet b < 0. */ - private static int[] makePositive(byte[] a, int off, int len) { - int keep, k; - int indexBound = off + len; - - // Find first non-sign (0xff) byte of input - for (keep=off; keep < indexBound && a[keep] == -1; keep++) - ; - - - /* Allocate output array. If all non-sign bytes are 0x00, we must - * allocate space for one extra output byte. */ - for (k=keep; k < indexBound && a[k] == 0; k++) - ; - - int extraByte = (k == indexBound) ? 1 : 0; - int intLength = ((indexBound - keep + extraByte) + 3) >>> 2; - int result[] = new int[intLength]; - - /* Copy one's complement of input into output, leaving extra - * byte (if it exists) == 0x00 */ - int b = indexBound - 1; - for (int i = intLength-1; i >= 0; i--) { - result[i] = a[b--] & 0xff; - int numBytesToTransfer = Math.min(3, b-keep+1); - if (numBytesToTransfer < 0) - numBytesToTransfer = 0; - for (int j=8; j <= 8*numBytesToTransfer; j += 8) - result[i] |= ((a[b--] & 0xff) << j); - - // Mask indicates which bits must be complemented - int mask = -1 >>> (8*(3-numBytesToTransfer)); - result[i] = ~result[i] & mask; - } - - // Add one to one's complement to generate two's complement - for (int i=result.length-1; i >= 0; i--) { - result[i] = (int)((result[i] & LONG_MASK) + 1); - if (result[i] != 0) - break; + private static int[] makePositive(int b, byte[] a, int from, int len) { + /* + * By assumption, b == a[from] < 0 and len > 0. + * + * First collect the bytes into the resulting array res. + * Then convert res to two's complement. + * + * Except for b == a[from], each read access to the input array a + * is of the form a[from++]. + * The index from is never otherwise altered, except right below, + * and only increases in steps of 1, always up to index to. + * Hence, each byte in the array is read exactly once, from lower to + * higher indices (from most to least significant byte). + */ + int to = from + len; + /* b == a[from] has been read exactly once, skip to next index. */ + ++from; + /* Skip leading -1 bytes. */ + for (; b == -1 && from < to; b = a[from++]) + ; //empty body + /* + * A "digit" is a group of 4 adjacent bytes aligned w.r.t. index to. + * b is the most significant byte not -1, or -1 only if from == to. + * Digit d0 spans the range of indices that includes current (from - 1). + * (Implied -1 bytes are prepended to array a as needed.) + * It usually corresponds to res[0], except for the special case below. + */ + int d0 = -1 << 8 | b & 0xFF; + while (((to - from) & 0x3) != 0) { + d0 = d0 << 8 | (b = a[from++]) & 0xFF; + } + int f = from; // keeps the current from for sizing purposes later + /* Skip zeros adjacent to d0, if at all. */ + for (; b == 0 && from < to; b = a[from++]) + ; //empty body + /* + * b is the most significant non-zero byte at or after (f - 1), + * or 0 only if from == to. + * Digit d spans the range of indices that includes (f - 1). + */ + int d = b & 0xFF; + while (((to - from) & 0x3) != 0) { + d = d << 8 | a[from++] & 0xFF; } - - return result; + /* + * If the situation here is like this: + * index: f to == from + * ..., -1,-1, 0,0,0,0, 0,0,0,0, ..., 0,0,0,0 + * digit: d0 d + * then, as shown, the number of zeros is a positive multiple of 4. + * The array res needs a minimal length of (1 + 1 + (to - f) / 4) + * to accommodate the two's complement, including a leading 1. + * In any other case, there is at least one byte that is non-zero. + * The array for the two's complement has length (0 + 1 + (to - f) / 4). + * c is 1, resp., 0 for the two situations. + */ + int c = (to - from | d0 | d) == 0 ? 1 : 0; + int[] res = new int[c + 1 + ((to - f) >> 2)]; + res[0] = c == 0 ? d0 : -1; + int i = res.length - ((to - from) >> 2); + if (i > 1) { + res[i - 1] = d; + } + /* + * Prepare the remaining digits. + * (to - from) is a multiple of 4, so prepare an int for every 4 bytes. + * This is a candidate for Unsafe.copy[Swap]Memory(). + */ + while (from < to) { + res[i++] = a[from++] << 24 | (a[from++] & 0xFF) << 16 + | (a[from++] & 0xFF) << 8 | (a[from++] & 0xFF); + } + /* Convert to two's complement. Here, i == res.length */ + while (--i >= 0 && res[i] == 0) + ; // empty body + res[i] = -res[i]; + while (--i >= 0) { + res[i] = ~res[i]; + } + return res; } /** diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/java/text/MessageFormat.java openjdk-21-21.0.9+10/src/java.base/share/classes/java/text/MessageFormat.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/java/text/MessageFormat.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/java/text/MessageFormat.java 2025-10-13 07:49:24.000000000 +0000 @@ -1662,7 +1662,7 @@ // Check the correctness of arguments and offsets if (isValid) { - int lastOffset = patt.length() + 1; + int lastOffset = patt.length(); for (int i = maxOff; i >= 0; --i) { if (argNums[i] < 0 || argNums[i] >= MAX_ARGUMENT_INDEX || offs[i] < 0 || offs[i] > lastOffset) { diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/java/util/Currency.java openjdk-21-21.0.9+10/src/java.base/share/classes/java/util/Currency.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/java/util/Currency.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/java/util/Currency.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -108,7 +108,7 @@ * with {@code Currency} or monetary values as it provides better handling of floating * point numbers and their operations. * - * @spec http://www.iso.org/iso/home/standards/currency_codes.htm ISO - ISO 4217 - Currency codes + * @spec https://www.iso.org/iso-4217-currency-codes.html ISO - ISO 4217 - Currency codes * @see java.math.BigDecimal * @since 1.4 */ @@ -319,7 +319,8 @@ // or in the list of other currencies. boolean found = false; if (currencyCode.length() != 3) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException( + "The input currency code: \"%s\" must have a length of 3 characters".formatted(currencyCode)); } char char1 = currencyCode.charAt(0); char char2 = currencyCode.charAt(1); @@ -342,7 +343,8 @@ if (!found) { OtherCurrencyEntry ocEntry = OtherCurrencyEntry.findEntry(currencyCode); if (ocEntry == null) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException( + "The input currency code: \"%s\" is not a valid ISO 4217 code".formatted(currencyCode)); } defaultFractionDigits = ocEntry.fraction; numericCode = ocEntry.numericCode; @@ -397,7 +399,8 @@ String country = CalendarDataUtility.findRegionOverride(locale).getCountry(); if (country == null || !country.matches("^[a-zA-Z]{2}$")) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException( + "The country of the input locale: \"%s\" is not a valid ISO 3166 country code".formatted(locale)); } char char1 = country.charAt(0); @@ -414,7 +417,8 @@ } else { // special cases if (tableEntry == INVALID_COUNTRY_ENTRY) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException( + "The country of the input locale: \"%s\" is not a valid ISO 3166 country code".formatted(locale)); } if (tableEntry == COUNTRY_WITHOUT_CURRENCY_ENTRY) { return null; @@ -679,7 +683,8 @@ */ private static int getMainTableEntry(char char1, char char2) { if (char1 < 'A' || char1 > 'Z' || char2 < 'A' || char2 > 'Z') { - throw new IllegalArgumentException(); + throw new IllegalArgumentException( + "The country code: \"%c%c\" is not a valid ISO 3166 code".formatted(char1, char2)); } return mainTable[(char1 - 'A') * A_TO_Z + (char2 - 'A')]; } @@ -690,7 +695,8 @@ */ private static void setMainTableEntry(char char1, char char2, int entry) { if (char1 < 'A' || char1 > 'Z' || char2 < 'A' || char2 > 'Z') { - throw new IllegalArgumentException(); + throw new IllegalArgumentException( + "The country code: \"%c%c\" is not a valid ISO 3166 code".formatted(char1, char2)); } mainTable[(char1 - 'A') * A_TO_Z + (char2 - 'A')] = entry; } diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/java/util/Formatter.java openjdk-21-21.0.9+10/src/java.base/share/classes/java/util/Formatter.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/java/util/Formatter.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/java/util/Formatter.java 2025-10-13 07:49:24.000000000 +0000 @@ -4765,9 +4765,9 @@ DECIMAL_FLOAT, HEXADECIMAL_FLOAT, HEXADECIMAL_FLOAT_UPPER, - LINE_SEPARATOR, - PERCENT_SIGN -> true; - default -> false; + LINE_SEPARATOR -> true; + // Don't put PERCENT_SIGN inside switch, as that will make the method size exceed 325 and cannot be inlined. + default -> c == PERCENT_SIGN; }; } diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java openjdk-21-21.0.9+10/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java 2025-10-13 07:49:24.000000000 +0000 @@ -1059,7 +1059,7 @@ final Subscriber subscriber; final BiConsumer, ? super Throwable> onNextHandler; Executor executor; // null on error - Thread waiter; // blocked producer thread + volatile Thread waiter; // blocked producer thread Throwable pendingError; // holds until onError issued BufferedSubscription next; // used only by publisher BufferedSubscription nextRetry; // used only by publisher diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java openjdk-21-21.0.9+10/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java 2025-10-13 07:49:24.000000000 +0000 @@ -278,6 +278,40 @@ } /** + * Repeatedly invokes acquire, if its execution throws an Error or a Runtime Exception, + * using an Unsafe.park-based backoff + * @param node which to reacquire + * @param arg the acquire argument + */ + private final void reacquire(Node node, long arg) { + try { + acquire(node, arg, false, false, false, 0L); + } catch (Error | RuntimeException firstEx) { + // While we currently do not emit an JFR events in this situation, mainly + // because the conditions under which this happens are such that it + // cannot be presumed to be possible to actually allocate an event, and + // using a preconstructed one would have limited value in serviceability. + // Having said that, the following place would be the more appropriate + // place to put such logic: + // emit JFR event + + for (long nanos = 1L;;) { + U.park(false, nanos); // must use Unsafe park to sleep + if (nanos < 1L << 30) // max about 1 second + nanos <<= 1; + + try { + acquire(node, arg, false, false, false, 0L); + } catch (Error | RuntimeException ignored) { + continue; + } + + throw firstEx; + } + } + } + + /** * Main acquire method, invoked by all exported acquire methods. * * @param node null unless a reacquiring Condition @@ -1294,7 +1328,7 @@ } LockSupport.setCurrentBlocker(null); node.clearStatus(); - acquire(node, savedState, false, false, false, 0L); + reacquire(node, savedState); if (interrupted) Thread.currentThread().interrupt(); } @@ -1341,7 +1375,7 @@ } LockSupport.setCurrentBlocker(null); node.clearStatus(); - acquire(node, savedState, false, false, false, 0L); + reacquire(node, savedState); if (interrupted) { if (cancelled) { unlinkCancelledWaiters(node); @@ -1384,7 +1418,7 @@ LockSupport.parkNanos(this, nanos); } node.clearStatus(); - acquire(node, savedState, false, false, false, 0L); + reacquire(node, savedState); if (cancelled) { unlinkCancelledWaiters(node); if (interrupted) @@ -1428,7 +1462,7 @@ LockSupport.parkUntil(this, abstime); } node.clearStatus(); - acquire(node, savedState, false, false, false, 0L); + reacquire(node, savedState); if (cancelled) { unlinkCancelledWaiters(node); if (interrupted) @@ -1473,7 +1507,7 @@ LockSupport.parkNanos(this, nanos); } node.clearStatus(); - acquire(node, savedState, false, false, false, 0L); + reacquire(node, savedState); if (cancelled) { unlinkCancelledWaiters(node); if (interrupted) diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java openjdk-21-21.0.9+10/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java 2025-10-13 07:49:24.000000000 +0000 @@ -657,6 +657,40 @@ } /** + * Repeatedly invokes acquire, if its execution throws an Error or a Runtime Exception, + * using an Unsafe.park-based backoff + * @param node which to reacquire + * @param arg the acquire argument + */ + private final void reacquire(Node node, int arg) { + try { + acquire(node, arg, false, false, false, 0L); + } catch (Error | RuntimeException firstEx) { + // While we currently do not emit an JFR events in this situation, mainly + // because the conditions under which this happens are such that it + // cannot be presumed to be possible to actually allocate an event, and + // using a preconstructed one would have limited value in serviceability. + // Having said that, the following place would be the more appropriate + // place to put such logic: + // emit JFR event + + for (long nanos = 1L;;) { + U.park(false, nanos); // must use Unsafe park to sleep + if (nanos < 1L << 30) // max about 1 second + nanos <<= 1; + + try { + acquire(node, arg, false, false, false, 0L); + } catch (Error | RuntimeException ignored) { + continue; + } + + throw firstEx; + } + } + } + + /** * Main acquire method, invoked by all exported acquire methods. * * @param node null unless a reacquiring Condition @@ -1673,7 +1707,7 @@ } LockSupport.setCurrentBlocker(null); node.clearStatus(); - acquire(node, savedState, false, false, false, 0L); + reacquire(node, savedState); if (interrupted) Thread.currentThread().interrupt(); } @@ -1720,7 +1754,7 @@ } LockSupport.setCurrentBlocker(null); node.clearStatus(); - acquire(node, savedState, false, false, false, 0L); + reacquire(node, savedState); if (interrupted) { if (cancelled) { unlinkCancelledWaiters(node); @@ -1763,7 +1797,7 @@ LockSupport.parkNanos(this, nanos); } node.clearStatus(); - acquire(node, savedState, false, false, false, 0L); + reacquire(node, savedState); if (cancelled) { unlinkCancelledWaiters(node); if (interrupted) @@ -1807,7 +1841,7 @@ LockSupport.parkUntil(this, abstime); } node.clearStatus(); - acquire(node, savedState, false, false, false, 0L); + reacquire(node, savedState); if (cancelled) { unlinkCancelledWaiters(node); if (interrupted) @@ -1852,7 +1886,7 @@ LockSupport.parkNanos(this, nanos); } node.clearStatus(); - acquire(node, savedState, false, false, false, 0L); + reacquire(node, savedState); if (cancelled) { unlinkCancelledWaiters(node); if (interrupted) diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/java/util/zip/GZIPInputStream.java openjdk-21-21.0.9+10/src/java.base/share/classes/java/util/zip/GZIPInputStream.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/java/util/zip/GZIPInputStream.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/java/util/zip/GZIPInputStream.java 2025-10-13 07:49:24.000000000 +0000 @@ -256,23 +256,17 @@ (readUInt(in) != (inf.getBytesWritten() & 0xffffffffL))) throw new ZipException("Corrupt GZIP trailer"); - // If there are more bytes available in "in" or - // the leftover in the "inf" is > 26 bytes: - // this.trailer(8) + next.header.min(10) + next.trailer(8) // try concatenated case - if (this.in.available() > 0 || n > 26) { - int m = 8; // this.trailer - try { - m += readHeader(in); // next.header - } catch (IOException ze) { - return true; // ignore any malformed, do nothing - } - inf.reset(); - if (n > m) - inf.setInput(buf, len - n + m, n - m); - return false; + int m = 8; // this.trailer + try { + m += readHeader(in); // next.header + } catch (IOException ze) { + return true; // ignore any malformed, do nothing } - return true; + inf.reset(); + if (n > m) + inf.setInput(buf, len - n + m, n - m); + return false; } /* diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/jdk/internal/platform/Metrics.java openjdk-21-21.0.9+10/src/java.base/share/classes/jdk/internal/platform/Metrics.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/jdk/internal/platform/Metrics.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/jdk/internal/platform/Metrics.java 2025-10-13 07:49:24.000000000 +0000 @@ -71,6 +71,23 @@ */ public String getProvider(); + /** + * Determines whether or not the underlying system + * has useful metrics (a.k.a. is containerized). + * + * @implNote + * Note that Metrics on some systems aren't useful. + * For example on a regular Linux system with cgroups + * present, with no limits enforced and not running in + * a container, Metric aren't useful. This can be used + * in order to determine if the system is containerized. + * + * @return true when the JVM runs in containerized mode. + * false otherwise. + * + */ + public boolean isContainerized(); + /***************************************************************** * CPU Accounting Subsystem diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/sun/launcher/LauncherHelper.java openjdk-21-21.0.9+10/src/java.base/share/classes/sun/launcher/LauncherHelper.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/sun/launcher/LauncherHelper.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/sun/launcher/LauncherHelper.java 2025-10-13 07:49:24.000000000 +0000 @@ -71,6 +71,7 @@ import java.util.Properties; import java.util.ResourceBundle; import java.util.Set; +import java.util.TimeZone; import java.util.TreeSet; import java.util.jar.Attributes; import java.util.jar.JarFile; @@ -295,6 +296,8 @@ Locale.getDefault(Category.DISPLAY).getDisplayName()); ostream.println(INDENT + "default format locale = " + Locale.getDefault(Category.FORMAT).getDisplayName()); + ostream.println(INDENT + "default timezone = " + + TimeZone.getDefault().getID()); ostream.println(INDENT + "tzdata version = " + ZoneInfoFile.getVersion()); if (!summaryMode) { @@ -347,6 +350,10 @@ final long longRetvalNotSupported = -2; ostream.println(INDENT + "Provider: " + c.getProvider()); + if (!c.isContainerized()) { + ostream.println(INDENT + "System not containerized."); + return; + } ostream.println(INDENT + "Effective CPU Count: " + c.getEffectiveCpuCount()); ostream.println(formatCpuVal(c.getCpuPeriod(), INDENT + "CPU Period: ", longRetvalNotSupported)); ostream.println(formatCpuVal(c.getCpuQuota(), INDENT + "CPU Quota: ", longRetvalNotSupported)); diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java openjdk-21-21.0.9+10/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java 2025-10-13 07:49:24.000000000 +0000 @@ -418,6 +418,10 @@ calls getInputStream after disconnect */ private Exception rememberedException = null; + /* Remembered Exception, we will throw it again if somebody + calls getOutputStream after disconnect or error */ + private Exception rememberedExceptionOut = null; + /* If we decide we want to reuse a client, we put it here */ private HttpClient reuseClient = null; @@ -1445,6 +1449,14 @@ + " if doOutput=false - call setDoOutput(true)"); } + if (rememberedExceptionOut != null) { + if (rememberedExceptionOut instanceof RuntimeException) { + throw new RuntimeException(rememberedExceptionOut); + } else { + throw getChainedException((IOException) rememberedExceptionOut); + } + } + if (method.equals("GET")) { method = "POST"; // Backward compatibility } @@ -1504,9 +1516,11 @@ int i = responseCode; disconnectInternal(); responseCode = i; + rememberedExceptionOut = e; throw e; } catch (RuntimeException | IOException e) { disconnectInternal(); + rememberedExceptionOut = e; throw e; } } diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/sun/nio/cs/Unicode.java openjdk-21-21.0.9+10/src/java.base/share/classes/sun/nio/cs/Unicode.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/sun/nio/cs/Unicode.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/sun/nio/cs/Unicode.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,6 +45,12 @@ || (cs instanceof UTF_16BE) || (cs instanceof UTF_16LE) || (cs instanceof UTF_16LE_BOM) + || (cs instanceof CESU_8) + || (cs instanceof UTF_32) + || (cs instanceof UTF_32BE) + || (cs instanceof UTF_32BE_BOM) + || (cs instanceof UTF_32LE) + || (cs instanceof UTF_32LE_BOM) || (cs.name().equals("GBK")) || (cs.name().equals("GB18030")) || (cs.name().equals("ISO-8859-2")) diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/Alert.java openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/Alert.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/Alert.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/Alert.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -123,13 +123,13 @@ } if (cause instanceof IOException) { - return new SSLException(reason, cause); + return new SSLException("(" + description + ") " + reason, cause); } else if ((this == UNEXPECTED_MESSAGE)) { - return new SSLProtocolException(reason, cause); + return new SSLProtocolException("(" + description + ") " + reason, cause); } else if (handshakeOnly) { - return new SSLHandshakeException(reason, cause); + return new SSLHandshakeException("(" + description + ") " + reason, cause); } else { - return new SSLException(reason, cause); + return new SSLException("(" + description + ") " + reason, cause); } } diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/CertSignAlgsExtension.java openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/CertSignAlgsExtension.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/CertSignAlgsExtension.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/CertSignAlgsExtension.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package sun.security.ssl; +import static sun.security.ssl.SignatureScheme.CERTIFICATE_SCOPE; + import java.io.IOException; import java.nio.ByteBuffer; import java.util.List; @@ -97,26 +99,21 @@ } // Produce the extension. - if (chc.localSupportedSignAlgs == null) { - chc.localSupportedSignAlgs = - SignatureScheme.getSupportedAlgorithms( - chc.sslConfig, - chc.algorithmConstraints, chc.activeProtocols); - } + SignatureScheme.updateHandshakeLocalSupportedAlgs(chc); int vectorLen = SignatureScheme.sizeInRecord() * - chc.localSupportedSignAlgs.size(); + chc.localSupportedCertSignAlgs.size(); byte[] extData = new byte[vectorLen + 2]; ByteBuffer m = ByteBuffer.wrap(extData); Record.putInt16(m, vectorLen); - for (SignatureScheme ss : chc.localSupportedSignAlgs) { + for (SignatureScheme ss : chc.localSupportedCertSignAlgs) { Record.putInt16(m, ss.id); } // Update the context. chc.handshakeExtensions.put( SSLExtension.CH_SIGNATURE_ALGORITHMS_CERT, - new SignatureSchemesSpec(chc.localSupportedSignAlgs)); + new SignatureSchemesSpec(chc.localSupportedCertSignAlgs)); return extData; } @@ -191,7 +188,9 @@ SignatureScheme.getSupportedAlgorithms( shc.sslConfig, shc.algorithmConstraints, shc.negotiatedProtocol, - spec.signatureSchemes); + spec.signatureSchemes, + CERTIFICATE_SCOPE); + shc.peerRequestedCertSignSchemes = schemes; shc.handshakeSession.setPeerSupportedSignatureAlgorithms(schemes); @@ -240,24 +239,21 @@ } // Produce the extension. - List sigAlgs = - SignatureScheme.getSupportedAlgorithms( - shc.sslConfig, - shc.algorithmConstraints, - List.of(shc.negotiatedProtocol)); - - int vectorLen = SignatureScheme.sizeInRecord() * sigAlgs.size(); + // localSupportedCertSignAlgs has been already updated when we set + // the negotiated protocol. + int vectorLen = SignatureScheme.sizeInRecord() + * shc.localSupportedCertSignAlgs.size(); byte[] extData = new byte[vectorLen + 2]; ByteBuffer m = ByteBuffer.wrap(extData); Record.putInt16(m, vectorLen); - for (SignatureScheme ss : sigAlgs) { + for (SignatureScheme ss : shc.localSupportedCertSignAlgs) { Record.putInt16(m, ss.id); } // Update the context. shc.handshakeExtensions.put( SSLExtension.CR_SIGNATURE_ALGORITHMS_CERT, - new SignatureSchemesSpec(shc.localSupportedSignAlgs)); + new SignatureSchemesSpec(shc.localSupportedCertSignAlgs)); return extData; } @@ -331,7 +327,9 @@ SignatureScheme.getSupportedAlgorithms( chc.sslConfig, chc.algorithmConstraints, chc.negotiatedProtocol, - spec.signatureSchemes); + spec.signatureSchemes, + CERTIFICATE_SCOPE); + chc.peerRequestedCertSignSchemes = schemes; chc.handshakeSession.setPeerSupportedSignatureAlgorithms(schemes); } diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java 2025-10-13 07:49:24.000000000 +0000 @@ -381,7 +381,7 @@ if (shc.sslConfig.clientAuthType != ClientAuthType.CLIENT_AUTH_REQUESTED) { // unexpected or require client authentication - throw shc.conContext.fatal(Alert.BAD_CERTIFICATE, + throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, "Empty client certificate chain"); } else { return; @@ -693,46 +693,6 @@ } } - /** - * When a failure happens during certificate checking from an - * {@link X509TrustManager}, determine what TLS alert description - * to use. - * - * @param cexc The exception thrown by the {@link X509TrustManager} - * - * @return A byte value corresponding to a TLS alert description number. - */ - private static Alert getCertificateAlert( - ClientHandshakeContext chc, CertificateException cexc) { - // The specific reason for the failure will determine how to - // set the alert description value - Alert alert = Alert.CERTIFICATE_UNKNOWN; - - Throwable baseCause = cexc.getCause(); - if (baseCause instanceof CertPathValidatorException cpve) { - Reason reason = cpve.getReason(); - if (reason == BasicReason.REVOKED) { - alert = chc.staplingActive ? - Alert.BAD_CERT_STATUS_RESPONSE : - Alert.CERTIFICATE_REVOKED; - } else if ( - reason == BasicReason.UNDETERMINED_REVOCATION_STATUS) { - alert = chc.staplingActive ? - Alert.BAD_CERT_STATUS_RESPONSE : - Alert.CERTIFICATE_UNKNOWN; - } else if (reason == BasicReason.ALGORITHM_CONSTRAINED) { - alert = Alert.UNSUPPORTED_CERTIFICATE; - } else if (reason == BasicReason.EXPIRED) { - alert = Alert.CERTIFICATE_EXPIRED; - } else if (reason == BasicReason.INVALID_SIGNATURE || - reason == BasicReason.NOT_YET_VALID) { - alert = Alert.BAD_CERTIFICATE; - } - } - - return alert; - } - } /** @@ -1163,7 +1123,7 @@ shc.handshakeConsumers.remove( SSLHandshake.CERTIFICATE_VERIFY.id); if (shc.sslConfig.clientAuthType == CLIENT_AUTH_REQUIRED) { - throw shc.conContext.fatal(Alert.BAD_CERTIFICATE, + throw shc.conContext.fatal(Alert.CERTIFICATE_REQUIRED, "Empty client certificate chain"); } else { // optional client authentication @@ -1187,7 +1147,7 @@ T13CertificateMessage certificateMessage )throws IOException { if (certificateMessage.certEntries == null || certificateMessage.certEntries.isEmpty()) { - throw chc.conContext.fatal(Alert.BAD_CERTIFICATE, + throw chc.conContext.fatal(Alert.DECODE_ERROR, "Empty server certificate chain"); } @@ -1330,37 +1290,57 @@ return certs; } - /** - * When a failure happens during certificate checking from an - * {@link X509TrustManager}, determine what TLS alert description - * to use. - * - * @param cexc The exception thrown by the {@link X509TrustManager} - * - * @return A byte value corresponding to a TLS alert description number. - */ - private static Alert getCertificateAlert( - ClientHandshakeContext chc, CertificateException cexc) { - // The specific reason for the failure will determine how to - // set the alert description value - Alert alert = Alert.CERTIFICATE_UNKNOWN; - - Throwable baseCause = cexc.getCause(); - if (baseCause instanceof CertPathValidatorException cpve) { - Reason reason = cpve.getReason(); - if (reason == BasicReason.REVOKED) { - alert = chc.staplingActive ? - Alert.BAD_CERT_STATUS_RESPONSE : - Alert.CERTIFICATE_REVOKED; - } else if ( - reason == BasicReason.UNDETERMINED_REVOCATION_STATUS) { - alert = chc.staplingActive ? - Alert.BAD_CERT_STATUS_RESPONSE : - Alert.CERTIFICATE_UNKNOWN; + } + + /** + * When a failure happens during certificate checking from an + * {@link X509TrustManager}, determine what TLS alert description + * to use. + * + * @param cexc The exception thrown by the {@link X509TrustManager} + * @return A byte value corresponding to a TLS alert description number. + */ + private static Alert getCertificateAlert( + ClientHandshakeContext chc, CertificateException cexc) { + // The specific reason for the failure will determine how to + // set the alert description value + Alert alert = Alert.CERTIFICATE_UNKNOWN; + + Throwable baseCause = cexc.getCause(); + if (baseCause instanceof CertPathValidatorException cpve) { + Reason reason = cpve.getReason(); + if (reason == BasicReason.REVOKED) { + alert = chc.staplingActive ? + Alert.BAD_CERT_STATUS_RESPONSE : + Alert.CERTIFICATE_REVOKED; + } else if (reason == BasicReason.UNDETERMINED_REVOCATION_STATUS) { + alert = chc.staplingActive ? + Alert.BAD_CERT_STATUS_RESPONSE : + Alert.CERTIFICATE_UNKNOWN; + } else if (reason == BasicReason.EXPIRED) { + alert = Alert.CERTIFICATE_EXPIRED; + } else if (reason == BasicReason.INVALID_SIGNATURE + || reason == BasicReason.NOT_YET_VALID) { + alert = Alert.BAD_CERTIFICATE; + } else if (reason == BasicReason.ALGORITHM_CONSTRAINED) { + alert = Alert.UNSUPPORTED_CERTIFICATE; + + // Per TLSv1.3 RFC we MUST abort the handshake with a + // "bad_certificate" alert if we reject certificate + // because of the signature using MD5 or SHA1 algorithm. + if (chc.negotiatedProtocol != null + && chc.negotiatedProtocol.useTLS13PlusSpec()) { + final String exMsg = cexc.getMessage().toUpperCase(); + + if (exMsg.contains("MD5WITH") + || exMsg.contains("SHA1WITH")) { + alert = Alert.BAD_CERTIFICATE; + } } } - - return alert; } + + return alert; } + } diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,9 @@ package sun.security.ssl; +import static sun.security.ssl.SignatureScheme.CERTIFICATE_SCOPE; +import static sun.security.ssl.SignatureScheme.HANDSHAKE_SCOPE; + import java.io.IOException; import java.nio.ByteBuffer; import java.security.PrivateKey; @@ -396,7 +399,6 @@ iae); } - if (clientAlias == null) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { SSLLogger.warning("No available client authentication"); @@ -632,15 +634,18 @@ public byte[] produce(ConnectionContext context, HandshakeMessage message) throws IOException { // The producing happens in server side only. - ServerHandshakeContext shc = (ServerHandshakeContext)context; - if (shc.localSupportedSignAlgs == null) { - shc.localSupportedSignAlgs = - SignatureScheme.getSupportedAlgorithms( - shc.sslConfig, - shc.algorithmConstraints, shc.activeProtocols); - } + ServerHandshakeContext shc = (ServerHandshakeContext) context; + + // According to TLSv1.2 RFC, CertificateRequest message must + // contain signature schemes supported for both: + // handshake signatures and certificate signatures. + // localSupportedSignAlgs and localSupportedCertSignAlgs have been + // already updated when we set the negotiated protocol. + List certReqSignAlgs = + new ArrayList<>(shc.localSupportedSignAlgs); + certReqSignAlgs.retainAll(shc.localSupportedCertSignAlgs); - if (shc.localSupportedSignAlgs.isEmpty()) { + if (certReqSignAlgs.isEmpty()) { throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, "No supported signature algorithm"); } @@ -649,7 +654,7 @@ shc.sslContext.getX509TrustManager().getAcceptedIssuers(); T12CertificateRequestMessage crm = new T12CertificateRequestMessage( shc, caCerts, shc.negotiatedCipherSuite.keyExchange, - shc.localSupportedSignAlgs); + certReqSignAlgs); if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { SSLLogger.fine( "Produced CertificateRequest handshake message", crm); @@ -730,19 +735,29 @@ chc.handshakeProducers.put(SSLHandshake.CERTIFICATE.id, SSLHandshake.CERTIFICATE); - List sss = + List signAlgs = SignatureScheme.getSupportedAlgorithms( chc.sslConfig, chc.algorithmConstraints, chc.negotiatedProtocol, - crm.algorithmIds); - if (sss.isEmpty()) { + crm.algorithmIds, + HANDSHAKE_SCOPE); + + List signCertAlgs = + SignatureScheme.getSupportedAlgorithms( + chc.sslConfig, + chc.algorithmConstraints, chc.negotiatedProtocol, + crm.algorithmIds, + CERTIFICATE_SCOPE); + + if (signAlgs.isEmpty() || signCertAlgs.isEmpty()) { throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE, "No supported signature algorithm"); } - chc.peerRequestedSignatureSchemes = sss; - chc.peerRequestedCertSignSchemes = sss; // use the same schemes - chc.handshakeSession.setPeerSupportedSignatureAlgorithms(sss); + chc.peerRequestedSignatureSchemes = signAlgs; + chc.peerRequestedCertSignSchemes = signCertAlgs; + chc.handshakeSession.setPeerSupportedSignatureAlgorithms(signCertAlgs); + try { chc.peerSupportedAuthorities = crm.getAuthorities(); } catch (IllegalArgumentException iae) { diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/ClientHello.java openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/ClientHello.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/ClientHello.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/ClientHello.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -825,6 +825,10 @@ "Negotiated protocol version: " + negotiatedProtocol.name); } + // Protocol version is negotiated, update locally supported + // signature schemes according to the protocol being used. + SignatureScheme.updateHandshakeLocalSupportedAlgs(context); + // Consume the handshake message for the specific protocol version. if (negotiatedProtocol.isDTLS) { if (negotiatedProtocol.useTLS13PlusSpec()) { diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,7 +72,7 @@ // consolidated parameters final List activeProtocols; final List activeCipherSuites; - final AlgorithmConstraints algorithmConstraints; + final SSLAlgorithmConstraints algorithmConstraints; final ProtocolVersion maximumActiveProtocol; // output stream @@ -127,6 +127,7 @@ // SignatureScheme List localSupportedSignAlgs; + List localSupportedCertSignAlgs; List peerRequestedSignatureSchemes; List peerRequestedCertSignSchemes; diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/PostHandshakeContext.java openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/PostHandshakeContext.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/PostHandshakeContext.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/PostHandshakeContext.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,7 @@ "Post-handshake not supported in " + negotiatedProtocol.name); } - this.localSupportedSignAlgs = new ArrayList<>( + this.localSupportedCertSignAlgs = new ArrayList<>( context.conSession.getLocalSupportedSignatureSchemes()); // Add the potential post-handshake consumers. diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -440,16 +440,11 @@ result = false; } - // Make sure that the server handshake context's localSupportedSignAlgs - // field is populated. This is particularly important when - // client authentication was used in an initial session, and it is - // now being resumed. - if (shc.localSupportedSignAlgs == null) { - shc.localSupportedSignAlgs = - SignatureScheme.getSupportedAlgorithms( - shc.sslConfig, - shc.algorithmConstraints, shc.activeProtocols); - } + // Make sure that the server handshake context's + // localSupportedCertSignAlgs field is populated. This is particularly + // important when client authentication was used in an initial session, + // and it is now being resumed. + SignatureScheme.updateHandshakeLocalSupportedAlgs(shc); // Validate the required client authentication. if (result && @@ -470,7 +465,7 @@ Collection sessionSigAlgs = s.getLocalSupportedSignatureSchemes(); if (result && - !shc.localSupportedSignAlgs.containsAll(sessionSigAlgs)) { + !shc.localSupportedCertSignAlgs.containsAll(sessionSigAlgs)) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { SSLLogger.fine("Can't resume. Session uses different " + @@ -664,7 +659,7 @@ // Make sure the list of supported signature algorithms matches Collection sessionSigAlgs = chc.resumingSession.getLocalSupportedSignatureSchemes(); - if (!chc.localSupportedSignAlgs.containsAll(sessionSigAlgs)) { + if (!chc.localSupportedCertSignAlgs.containsAll(sessionSigAlgs)) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { SSLLogger.fine("Existing session uses different " + "signature algorithms"); diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,11 +42,11 @@ */ final class SSLAlgorithmConstraints implements AlgorithmConstraints { - private static final AlgorithmConstraints tlsDisabledAlgConstraints = + private static final DisabledAlgorithmConstraints tlsDisabledAlgConstraints = new DisabledAlgorithmConstraints(PROPERTY_TLS_DISABLED_ALGS, new SSLAlgorithmDecomposer()); - private static final AlgorithmConstraints x509DisabledAlgConstraints = + private static final DisabledAlgorithmConstraints x509DisabledAlgConstraints = new DisabledAlgorithmConstraints(PROPERTY_CERTPATH_DISABLED_ALGS, new SSLAlgorithmDecomposer(true)); @@ -56,11 +56,11 @@ private final boolean enabledX509DisabledAlgConstraints; // the default algorithm constraints - static final AlgorithmConstraints DEFAULT = + static final SSLAlgorithmConstraints DEFAULT = new SSLAlgorithmConstraints(null, true); // the default SSL only algorithm constraints - static final AlgorithmConstraints DEFAULT_SSL_ONLY = + static final SSLAlgorithmConstraints DEFAULT_SSL_ONLY = new SSLAlgorithmConstraints(null, false); private SSLAlgorithmConstraints(AlgorithmConstraints userSpecifiedConstraints, @@ -84,11 +84,11 @@ * @param userSpecifiedConstraints additional constraints to check * @return a SSLAlgorithmConstraints instance */ - static AlgorithmConstraints wrap(AlgorithmConstraints userSpecifiedConstraints) { + static SSLAlgorithmConstraints wrap(AlgorithmConstraints userSpecifiedConstraints) { return wrap(userSpecifiedConstraints, true); } - private static AlgorithmConstraints wrap( + private static SSLAlgorithmConstraints wrap( AlgorithmConstraints userSpecifiedConstraints, boolean withDefaultCertPathConstraints) { if (nullIfDefault(userSpecifiedConstraints) == null) { @@ -199,22 +199,22 @@ if (peerSpecifiedConstraints != null) { permitted = peerSpecifiedConstraints.permits( - primitives, algorithm, parameters); + primitives, algorithm, parameters); } if (permitted && userSpecifiedConstraints != null) { permitted = userSpecifiedConstraints.permits( - primitives, algorithm, parameters); + primitives, algorithm, parameters); } if (permitted) { permitted = tlsDisabledAlgConstraints.permits( - primitives, algorithm, parameters); + primitives, algorithm, parameters); } if (permitted && enabledX509DisabledAlgConstraints) { permitted = x509DisabledAlgConstraints.permits( - primitives, algorithm, parameters); + primitives, algorithm, parameters); } return permitted; @@ -252,27 +252,31 @@ if (peerSpecifiedConstraints != null) { permitted = peerSpecifiedConstraints.permits( - primitives, algorithm, key, parameters); + primitives, algorithm, key, parameters); } if (permitted && userSpecifiedConstraints != null) { permitted = userSpecifiedConstraints.permits( - primitives, algorithm, key, parameters); + primitives, algorithm, key, parameters); } if (permitted) { permitted = tlsDisabledAlgConstraints.permits( - primitives, algorithm, key, parameters); + primitives, algorithm, key, parameters); } if (permitted && enabledX509DisabledAlgConstraints) { permitted = x509DisabledAlgConstraints.permits( - primitives, algorithm, key, parameters); + primitives, algorithm, key, parameters); } return permitted; } + // Checks if algorithm is disabled for the given TLS scopes. + boolean permits(String algorithm, Set scopes) { + return tlsDisabledAlgConstraints.permits(algorithm, scopes); + } private static class SupportedSignatureAlgorithmConstraints implements AlgorithmConstraints { diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/SSLLogger.java openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/SSLLogger.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/SSLLogger.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/SSLLogger.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -143,8 +143,10 @@ if (property.contains("all")) { return true; } else { - int offset = property.indexOf("ssl"); - if (offset != -1 && property.indexOf("sslctx", offset) != -1) { + // remove first occurrence of "sslctx" since + // it interferes with search for "ssl" + String modified = property.replaceFirst("sslctx", ""); + if (modified.contains("ssl")) { // don't enable data and plaintext options by default if (!(option.equals("data") || option.equals("packet") diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/SSLScope.java openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/SSLScope.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/SSLScope.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/SSLScope.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.ssl; + +/* + * Scopes defining different parts of TLS protocol. + */ + +public enum SSLScope { + // Handshake signature scope as in signature_algorithms extension. + HANDSHAKE_SIGNATURE("HandshakeSignature"), + + // Certificate signature scope as in signature_algorithms_cert extension. + CERTIFICATE_SIGNATURE("CertificateSignature"); + + private final String name; + + SSLScope(String name) { + this.name = name; + } + + // Note: the SSLScope name is case-insensitive. + public static SSLScope nameOf(String scopeName) { + for (SSLScope scope : SSLScope.values()) { + if (scope.name.equalsIgnoreCase(scopeName)) { + return scope; + } + } + + return null; + } +} diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.math.BigInteger; import java.net.InetAddress; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.security.Principal; import java.security.PrivateKey; import java.security.cert.X509Certificate; @@ -193,10 +194,10 @@ this.sessionId = id; this.host = hc.conContext.transport.getPeerHost(); this.port = hc.conContext.transport.getPeerPort(); - this.localSupportedSignAlgs = hc.localSupportedSignAlgs == null ? + this.localSupportedSignAlgs = hc.localSupportedCertSignAlgs == null ? Collections.emptySet() : Collections.unmodifiableCollection( - new ArrayList<>(hc.localSupportedSignAlgs)); + new ArrayList<>(hc.localSupportedCertSignAlgs)); this.serverNameIndication = hc.negotiatedServerName; this.requestedServerNames = List.copyOf(hc.getRequestedServerNames()); if (hc.sslConfig.isClientMode) { @@ -309,113 +310,90 @@ SSLSessionImpl(HandshakeContext hc, ByteBuffer buf) throws IOException { boundValues = new ConcurrentHashMap<>(); this.protocolVersion = - ProtocolVersion.valueOf(Short.toUnsignedInt(buf.getShort())); + ProtocolVersion.valueOf(Record.getInt16(buf)); // The CH session id may reset this if it's provided this.sessionId = new SessionId(true, hc.sslContext.getSecureRandom()); this.cipherSuite = - CipherSuite.valueOf(Short.toUnsignedInt(buf.getShort())); + CipherSuite.valueOf(Record.getInt16(buf)); // Local Supported signature algorithms ArrayList list = new ArrayList<>(); - int i = Byte.toUnsignedInt(buf.get()); + int i = Record.getInt8(buf); while (i-- > 0) { list.add(SignatureScheme.valueOf( - Short.toUnsignedInt(buf.getShort()))); + Record.getInt16(buf))); } this.localSupportedSignAlgs = Collections.unmodifiableCollection(list); // Peer Supported signature algorithms - i = Byte.toUnsignedInt(buf.get()); + i = Record.getInt8(buf); list.clear(); while (i-- > 0) { list.add(SignatureScheme.valueOf( - Short.toUnsignedInt(buf.getShort()))); + Record.getInt16(buf))); } this.peerSupportedSignAlgs = Collections.unmodifiableCollection(list); // PSK - byte[] b; - i = Short.toUnsignedInt(buf.getShort()); - if (i > 0) { - b = new byte[i]; - // Get algorithm string - buf.get(b, 0, i); - // Encoded length - i = Short.toUnsignedInt(buf.getShort()); - // Encoded SecretKey - b = new byte[i]; - buf.get(b); + byte[] b = Record.getBytes16(buf); + if (b.length > 0) { + b = Record.getBytes16(buf); this.preSharedKey = new SecretKeySpec(b, "TlsMasterSecret"); } else { this.preSharedKey = null; } // PSK identity - i = buf.get(); - if (i > 0) { - b = new byte[i]; - buf.get(b); + b = Record.getBytes8(buf); + if (b.length > 0) { this.pskIdentity = b; } else { this.pskIdentity = null; } // Master secret length of secret key algorithm (one byte) - i = buf.get(); - if (i > 0) { - b = new byte[i]; - // Get algorithm string - buf.get(b, 0, i); - // Encoded length - i = Short.toUnsignedInt(buf.getShort()); - // Encoded SecretKey - b = new byte[i]; - buf.get(b); + b = Record.getBytes8(buf); + if (b.length > 0) { + b = Record.getBytes16(buf); this.masterSecret = new SecretKeySpec(b, "TlsMasterSecret"); } else { this.masterSecret = null; } + // Use extended master secret - this.useExtendedMasterSecret = (buf.get() != 0); + this.useExtendedMasterSecret = (Record.getInt8(buf) != 0); // Identification Protocol - i = buf.get(); - if (i == 0) { + b = Record.getBytes8(buf); + if (b.length == 0) { identificationProtocol = null; } else { - b = new byte[i]; - buf.get(b); identificationProtocol = new String(b); } // SNI - i = buf.get(); // length - if (i == 0) { + b = Record.getBytes8(buf); + if (b.length == 0) { serverNameIndication = null; } else { - b = new byte[i]; - buf.get(b, 0, b.length); serverNameIndication = new SNIHostName(b); } // List of SNIServerName - int len = Short.toUnsignedInt(buf.getShort()); + int len = Record.getInt16(buf); if (len == 0) { this.requestedServerNames = Collections.emptyList(); } else { requestedServerNames = new ArrayList<>(); while (len > 0) { - int l = buf.get(); - b = new byte[l]; - buf.get(b, 0, l); + b = Record.getBytes8(buf); requestedServerNames.add(new SNIHostName(new String(b))); len--; } } - maximumPacketSize = buf.getInt(); negotiatedMaxFragLen = buf.getInt(); @@ -425,31 +403,28 @@ // Get Buffer sizes // Status Response - len = Short.toUnsignedInt(buf.getShort()); + len = Record.getInt16(buf); if (len == 0) { statusResponses = Collections.emptyList(); } else { statusResponses = new ArrayList<>(); } while (len-- > 0) { - b = new byte[Short.toUnsignedInt(buf.getShort())]; - buf.get(b); + b = Record.getBytes16(buf); statusResponses.add(b); } // Get Peer host & port - i = Byte.toUnsignedInt(buf.get()); - if (i == 0) { + b = Record.getBytes8(buf); + if (b.length == 0) { this.host = ""; } else { - b = new byte[i]; - buf.get(b, 0, i); this.host = new String(b); } - this.port = Short.toUnsignedInt(buf.getShort()); + this.port = Record.getInt16(buf); // Peer certs - i = buf.get(); + i = Record.getInt8(buf); if (i == 0) { this.peerCerts = null; } else { @@ -468,7 +443,7 @@ } // Get local certs of PSK - switch (buf.get()) { + switch (Record.getInt8(buf)) { case 0: break; case 1: @@ -490,19 +465,13 @@ case 2: // pre-shared key // Length of pre-shared key algorithm (one byte) - i = buf.get(); - b = new byte[i]; - buf.get(b, 0 , i); + b = Record.getBytes8(buf); String alg = new String(b); - // Get length of encoding - i = Short.toUnsignedInt(buf.getShort()); // Get encoding - b = new byte[i]; - buf.get(b); + b = Record.getBytes16(buf); this.preSharedKey = new SecretKeySpec(b, alg); // Get identity len - this.pskIdentity = new byte[buf.get()]; - buf.get(pskIdentity); + this.pskIdentity = Record.getBytes8(buf); break; default: throw new SSLException("Failed local certs of session."); @@ -513,6 +482,7 @@ this.lastUsedTime = System.currentTimeMillis(); } + // Some situations we cannot provide a stateless ticket, but after it // has been negotiated boolean isStatelessable() { diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/ServerHello.java openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/ServerHello.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/ServerHello.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/ServerHello.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -269,13 +269,6 @@ "Not resumption, and no new session is allowed"); } - if (shc.localSupportedSignAlgs == null) { - shc.localSupportedSignAlgs = - SignatureScheme.getSupportedAlgorithms( - shc.sslConfig, - shc.algorithmConstraints, shc.activeProtocols); - } - SSLSessionImpl session = new SSLSessionImpl(shc, CipherSuite.C_NULL); session.setMaximumPacketSize(shc.sslConfig.maximumPacketSize); @@ -510,13 +503,6 @@ "Not resumption, and no new session is allowed"); } - if (shc.localSupportedSignAlgs == null) { - shc.localSupportedSignAlgs = - SignatureScheme.getSupportedAlgorithms( - shc.sslConfig, - shc.algorithmConstraints, shc.activeProtocols); - } - SSLSessionImpl session = new SSLSessionImpl(shc, CipherSuite.C_NULL); session.setMaximumPacketSize(shc.sslConfig.maximumPacketSize); @@ -938,6 +924,10 @@ "Negotiated protocol version: " + serverVersion.name); } + // Protocol version is negotiated, update locally supported + // signature schemes according to the protocol being used. + SignatureScheme.updateHandshakeLocalSupportedAlgs(chc); + // TLS 1.3 key share extension may have produced client // possessions for TLS 1.3 key exchanges. // @@ -989,6 +979,10 @@ "Negotiated protocol version: " + serverVersion.name); } + // Protocol version is negotiated, update locally supported + // signature schemes according to the protocol being used. + SignatureScheme.updateHandshakeLocalSupportedAlgs(chc); + if (serverHello.serverRandom.isVersionDowngrade(chc)) { throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER, "A potential protocol version downgrade attack"); diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/SessionTicketExtension.java openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/SessionTicketExtension.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/SessionTicketExtension.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/SessionTicketExtension.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -354,12 +354,7 @@ return new byte[0]; } - if (chc.localSupportedSignAlgs == null) { - chc.localSupportedSignAlgs = - SignatureScheme.getSupportedAlgorithms( - chc.sslConfig, - chc.algorithmConstraints, chc.activeProtocols); - } + SignatureScheme.updateHandshakeLocalSupportedAlgs(chc); return chc.resumingSession.getPskIdentity(); } diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,12 +25,16 @@ package sun.security.ssl; +import static sun.security.ssl.SignatureScheme.CERTIFICATE_SCOPE; +import static sun.security.ssl.SignatureScheme.HANDSHAKE_SCOPE; + import java.io.IOException; import java.nio.ByteBuffer; import java.text.MessageFormat; import java.util.Arrays; import java.util.List; import java.util.Locale; +import javax.net.ssl.SSLException; import javax.net.ssl.SSLProtocolException; import sun.security.ssl.SSLExtension.ExtensionConsumer; import sun.security.ssl.SSLExtension.SSLExtensionSpec; @@ -185,12 +189,7 @@ } // Produce the extension. - if (chc.localSupportedSignAlgs == null) { - chc.localSupportedSignAlgs = - SignatureScheme.getSupportedAlgorithms( - chc.sslConfig, - chc.algorithmConstraints, chc.activeProtocols); - } + SignatureScheme.updateHandshakeLocalSupportedAlgs(chc); int vectorLen = SignatureScheme.sizeInRecord() * chc.localSupportedSignAlgs.size(); @@ -273,28 +272,8 @@ return; } - // update the context - List sss = - SignatureScheme.getSupportedAlgorithms( - shc.sslConfig, - shc.algorithmConstraints, shc.negotiatedProtocol, - spec.signatureSchemes); - if (sss == null || sss.isEmpty()) { - throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, - "No supported signature algorithm"); - } - shc.peerRequestedSignatureSchemes = sss; - - // If no "signature_algorithms_cert" extension is present, then - // the "signature_algorithms" extension also applies to - // signatures appearing in certificates. - SignatureSchemesSpec certSpec = - (SignatureSchemesSpec)shc.handshakeExtensions.get( - SSLExtension.CH_SIGNATURE_ALGORITHMS_CERT); - if (certSpec == null) { - shc.peerRequestedCertSignSchemes = sss; - shc.handshakeSession.setPeerSupportedSignatureAlgorithms(sss); - } + updateHandshakeContext(shc, spec.signatureSchemes, + SSLExtension.CH_SIGNATURE_ALGORITHMS_CERT); if (!shc.isResumption && shc.negotiatedProtocol.useTLS13PlusSpec()) { @@ -412,17 +391,14 @@ } // Produce the extension. - List sigAlgs = - SignatureScheme.getSupportedAlgorithms( - shc.sslConfig, - shc.algorithmConstraints, - List.of(shc.negotiatedProtocol)); - - int vectorLen = SignatureScheme.sizeInRecord() * sigAlgs.size(); + // localSupportedSignAlgs has been already updated when we + // set the negotiated protocol. + int vectorLen = SignatureScheme.sizeInRecord() + * shc.localSupportedSignAlgs.size(); byte[] extData = new byte[vectorLen + 2]; ByteBuffer m = ByteBuffer.wrap(extData); Record.putInt16(m, vectorLen); - for (SignatureScheme ss : sigAlgs) { + for (SignatureScheme ss : shc.localSupportedSignAlgs) { Record.putInt16(m, ss.id); } @@ -501,28 +477,8 @@ return; } - // update the context - List sss = - SignatureScheme.getSupportedAlgorithms( - chc.sslConfig, - chc.algorithmConstraints, chc.negotiatedProtocol, - spec.signatureSchemes); - if (sss == null || sss.isEmpty()) { - throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE, - "No supported signature algorithm"); - } - chc.peerRequestedSignatureSchemes = sss; - - // If no "signature_algorithms_cert" extension is present, then - // the "signature_algorithms" extension also applies to - // signatures appearing in certificates. - SignatureSchemesSpec certSpec = - (SignatureSchemesSpec)chc.handshakeExtensions.get( - SSLExtension.CR_SIGNATURE_ALGORITHMS_CERT); - if (certSpec == null) { - chc.peerRequestedCertSignSchemes = sss; - chc.handshakeSession.setPeerSupportedSignatureAlgorithms(sss); - } + updateHandshakeContext(chc, spec.signatureSchemes, + SSLExtension.CR_SIGNATURE_ALGORITHMS_CERT); } } @@ -545,4 +501,49 @@ "received CertificateRequest handshake message"); } } + + // Updates given HandshakeContext with peer signature schemes. + private static void updateHandshakeContext(HandshakeContext hc, + int[] signatureSchemes, SSLExtension signatureAlgorithmsCertExt) + throws SSLException { + List handshakeSS = + SignatureScheme.getSupportedAlgorithms( + hc.sslConfig, + hc.algorithmConstraints, + hc.negotiatedProtocol, + signatureSchemes, + HANDSHAKE_SCOPE); + + if (handshakeSS.isEmpty()) { + throw hc.conContext.fatal(Alert.HANDSHAKE_FAILURE, + "No supported signature algorithm"); + } + + hc.peerRequestedSignatureSchemes = handshakeSS; + + // If no "signature_algorithms_cert" extension is present, then + // the "signature_algorithms" extension also applies to + // signatures appearing in certificates. + SignatureSchemesSpec certSpec = + (SignatureSchemesSpec) hc.handshakeExtensions.get( + signatureAlgorithmsCertExt); + + if (certSpec == null) { + List certSS = + SignatureScheme.getSupportedAlgorithms( + hc.sslConfig, + hc.algorithmConstraints, + hc.negotiatedProtocol, + signatureSchemes, + CERTIFICATE_SCOPE); + + if (certSS.isEmpty()) { + throw hc.conContext.fatal(Alert.HANDSHAKE_FAILURE, + "No supported signature algorithm"); + } + + hc.peerRequestedCertSignSchemes = certSS; + hc.handshakeSession.setPeerSupportedSignatureAlgorithms(certSS); + } + } } diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.EnumSet; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -218,10 +217,17 @@ } } - // performance optimization - private static final Set SIGNATURE_PRIMITIVE_SET = - Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE)); + // Handshake signature scope. + static final Set HANDSHAKE_SCOPE = + Set.of(SSLScope.HANDSHAKE_SIGNATURE); + + // Certificate signature scope. + static final Set CERTIFICATE_SCOPE = + Set.of(SSLScope.CERTIFICATE_SIGNATURE); + // Non-TLS specific SIGNATURE CryptoPrimitive. + private static final Set SIGNATURE_PRIMITIVE_SET = + Set.of(CryptoPrimitive.SIGNATURE); SignatureScheme(int id, String name, String algorithm, String keyAlgorithm, @@ -355,24 +361,56 @@ return 2; } - private boolean isPermitted(AlgorithmConstraints constraints) { - return constraints.permits(SIGNATURE_PRIMITIVE_SET, - this.name, null) && - constraints.permits(SIGNATURE_PRIMITIVE_SET, - this.keyAlgorithm, null) && - constraints.permits(SIGNATURE_PRIMITIVE_SET, - this.algorithm, (signAlgParams != null ? - signAlgParams.parameters : null)) && - (namedGroup == null || - namedGroup.isPermitted(constraints)); + private boolean isPermitted( + SSLAlgorithmConstraints constraints, Set scopes) { + return constraints.permits(this.name, scopes) + && constraints.permits(this.keyAlgorithm, scopes) + && constraints.permits(this.algorithm, scopes) + && constraints.permits(SIGNATURE_PRIMITIVE_SET, this.name, null) + && constraints.permits(SIGNATURE_PRIMITIVE_SET, this.keyAlgorithm, null) + && constraints.permits(SIGNATURE_PRIMITIVE_SET, this.algorithm, + (signAlgParams != null ? signAlgParams.parameters : null)) + && (namedGroup == null || namedGroup.isPermitted(constraints)); + } + + // Helper method to update all locally supported signature schemes for + // a given HandshakeContext. + static void updateHandshakeLocalSupportedAlgs(HandshakeContext hc) { + // To improve performance we only update when necessary. + // No need to do anything if we already computed the local supported + // algorithms and either there is no negotiated protocol yet or the + // only active protocol ends up to be the negotiated protocol. + if (hc.localSupportedSignAlgs != null + && hc.localSupportedCertSignAlgs != null + && (hc.negotiatedProtocol == null + || hc.activeProtocols.size() == 1)) { + return; + } + + List protocols = hc.negotiatedProtocol != null ? + List.of(hc.negotiatedProtocol) : + hc.activeProtocols; + + hc.localSupportedSignAlgs = getSupportedAlgorithms( + hc.sslConfig, + hc.algorithmConstraints, + protocols, + HANDSHAKE_SCOPE); + + hc.localSupportedCertSignAlgs = getSupportedAlgorithms( + hc.sslConfig, + hc.algorithmConstraints, + protocols, + CERTIFICATE_SCOPE); } // Get local supported algorithm collection complying to algorithm - // constraints. - static List getSupportedAlgorithms( + // constraints and SSL scopes. + private static List getSupportedAlgorithms( SSLConfiguration config, - AlgorithmConstraints constraints, - List activeProtocols) { + SSLAlgorithmConstraints constraints, + List activeProtocols, + Set scopes) { List supported = new LinkedList<>(); List schemesToCheck = @@ -392,14 +430,14 @@ boolean isMatch = false; for (ProtocolVersion pv : activeProtocols) { - if (ss.supportedProtocols.contains(pv)) { + if (ss.isSupportedProtocol(pv, scopes)) { isMatch = true; break; } } if (isMatch) { - if (ss.isPermitted(constraints)) { + if (ss.isPermitted(constraints, scopes)) { supported.add(ss); } else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake,verbose")) { @@ -418,8 +456,10 @@ static List getSupportedAlgorithms( SSLConfiguration config, - AlgorithmConstraints constraints, - ProtocolVersion protocolVersion, int[] algorithmIds) { + SSLAlgorithmConstraints constraints, + ProtocolVersion protocolVersion, + int[] algorithmIds, + Set scopes) { List supported = new LinkedList<>(); for (int ssid : algorithmIds) { SignatureScheme ss = SignatureScheme.valueOf(ssid); @@ -429,11 +469,9 @@ "Unsupported signature scheme: " + SignatureScheme.nameOf(ssid)); } - } else if (ss.isAvailable && - ss.supportedProtocols.contains(protocolVersion) && - (config.signatureSchemes == null || - Utilities.contains(config.signatureSchemes, ss.name)) && - ss.isPermitted(constraints)) { + } else if ((config.signatureSchemes == null + || Utilities.contains(config.signatureSchemes, ss.name)) + && ss.isAllowed(constraints, protocolVersion, scopes)) { supported.add(ss); } else { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { @@ -447,16 +485,14 @@ } static SignatureScheme getPreferableAlgorithm( - AlgorithmConstraints constraints, + SSLAlgorithmConstraints constraints, List schemes, String keyAlgorithm, ProtocolVersion version) { for (SignatureScheme ss : schemes) { - if (ss.isAvailable && - ss.handshakeSupportedProtocols.contains(version) && - keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm) && - ss.isPermitted(constraints)) { + if (keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm) + && ss.isAllowed(constraints, version, HANDSHAKE_SCOPE)) { return ss; } } @@ -466,7 +502,7 @@ static Map.Entry getSignerOfPreferableAlgorithm( SSLConfiguration sslConfig, - AlgorithmConstraints constraints, + SSLAlgorithmConstraints constraints, List schemes, X509Possession x509Possession, ProtocolVersion version) { @@ -482,10 +518,9 @@ keySize = Integer.MAX_VALUE; } for (SignatureScheme ss : schemes) { - if (ss.isAvailable && (keySize >= ss.minimalKeySize) && - ss.handshakeSupportedProtocols.contains(version) && + if (keySize >= ss.minimalKeySize && keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm) && - ss.isPermitted(constraints)) { + ss.isAllowed(constraints, version, HANDSHAKE_SCOPE)) { if ((ss.namedGroup != null) && (ss.namedGroup.spec == NamedGroupSpec.NAMED_GROUP_ECDHE)) { ECParameterSpec params = @@ -545,6 +580,26 @@ return null; } + // Returns true if this signature scheme is supported for the given + // protocol version and SSL scopes. + private boolean isSupportedProtocol( + ProtocolVersion version, Set scopes) { + if (scopes != null && scopes.equals(HANDSHAKE_SCOPE)) { + return this.handshakeSupportedProtocols.contains(version); + } else { + return this.supportedProtocols.contains(version); + } + } + + // Returns true if this signature scheme is available, supported and + // permitted for the given constraints, protocol version and SSL scopes. + private boolean isAllowed(SSLAlgorithmConstraints constraints, + ProtocolVersion version, Set scopes) { + return isAvailable + && isSupportedProtocol(version, scopes) + && isPermitted(constraints, scopes); + } + static String[] getAlgorithmNames(Collection schemes) { if (schemes != null) { ArrayList names = new ArrayList<>(schemes.size()); diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/util/DerValue.java openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/util/DerValue.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/util/DerValue.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/util/DerValue.java 2025-10-13 07:49:24.000000000 +0000 @@ -857,6 +857,22 @@ } /** + * Checks that the BMPString does not contain any surrogate characters, + * which are outside the Basic Multilingual Plane. + * + * @throws IOException if illegal characters are detected + */ + public void validateBMPString() throws IOException { + String bmpString = getBMPString(); + for (int i = 0; i < bmpString.length(); i++) { + if (Character.isSurrogate(bmpString.charAt(i))) { + throw new IOException( + "Illegal character in BMPString, index: " + i); + } + } + } + + /** * Reads the ASN.1 NULL value */ public void getNull() throws IOException { diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package sun.security.util; +import sun.security.ssl.SSLScope; import sun.security.validator.Validator; import java.lang.ref.SoftReference; @@ -42,21 +43,22 @@ import java.security.spec.PSSParameterSpec; import java.time.DateTimeException; import java.time.Instant; -import java.time.ZonedDateTime; import java.time.ZoneId; +import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; -import java.util.Collection; import java.util.StringTokenizer; import java.util.concurrent.ConcurrentHashMap; -import java.util.regex.Pattern; import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Algorithm constraints for disabled algorithms property @@ -101,6 +103,7 @@ } private final Set disabledAlgorithms; + private final List disabledPatterns; private final Constraints algorithmConstraints; private volatile SoftReference> cacheRef = new SoftReference<>(null); @@ -136,6 +139,13 @@ super(decomposer); disabledAlgorithms = getAlgorithms(propertyName); + // Support patterns only for jdk.tls.disabledAlgorithms + if (PROPERTY_TLS_DISABLED_ALGS.equals(propertyName)) { + disabledPatterns = getDisabledPatterns(); + } else { + disabledPatterns = null; + } + // Check for alias for (String s : disabledAlgorithms) { Matcher matcher = INCLUDE_PATTERN.matcher(s); @@ -175,6 +185,12 @@ return true; } + // Checks if algorithm is disabled for the given TLS scopes. + public boolean permits(String algorithm, Set scopes) { + List list = algorithmConstraints.getConstraints(algorithm); + return list == null || list.stream().allMatch(c -> c.permits(scopes)); + } + /* * Checks if the key algorithm has been disabled or constraints have been * placed on the key. @@ -424,7 +440,7 @@ denyAfterLimit = true; } else if (entry.startsWith("usage")) { String[] s = (entry.substring(5)).trim().split(" "); - c = new UsageConstraint(algorithm, s); + c = new UsageConstraint(algorithm, s, propertyName); if (debug != null) { debug.println("Constraints usage length is " + s.length); } @@ -596,6 +612,17 @@ } /** + * Check if the algorithm constraint permits the given TLS scopes. + * + * @param scopes TLS scopes + * @return 'true' if TLS scopes are allowed, + * 'false' otherwise. + */ + public boolean permits(Set scopes) { + return true; + } + + /** * Check if an algorithm constraint is permitted with a given * ConstraintsParameters. * @@ -772,14 +799,49 @@ /* * The usage constraint is for the "usage" keyword. It checks against the - * variant value in ConstraintsParameters. + * variant value in ConstraintsParameters and against TLS scopes. */ private static class UsageConstraint extends Constraint { String[] usages; + Set scopes; - UsageConstraint(String algorithm, String[] usages) { + UsageConstraint( + String algorithm, String[] usages, String propertyName) { this.algorithm = algorithm; - this.usages = usages; + + // Support TLS scopes only for jdk.tls.disabledAlgorithms property. + if (PROPERTY_TLS_DISABLED_ALGS.equals(propertyName)) { + for (String usage : usages) { + SSLScope scope = SSLScope.nameOf(usage); + + if (scope != null) { + if (this.scopes == null) { + this.scopes = new HashSet<>(usages.length); + } + this.scopes.add(scope); + } else { + this.usages = usages; + } + } + + if (this.scopes != null && this.usages != null) { + throw new IllegalArgumentException( + "Can't mix TLS protocol specific constraints" + + " with other usage constraints"); + } + + } else { + this.usages = usages; + } + } + + @Override + public boolean permits(Set scopes) { + if (this.scopes == null || scopes == null) { + return true; + } + + return Collections.disjoint(this.scopes, scopes); } @Override @@ -967,11 +1029,48 @@ if (result != null) { return result; } - result = checkAlgorithm(disabledAlgorithms, algorithm, decomposer); + // We won't check patterns if algorithm check fails. + result = checkAlgorithm(disabledAlgorithms, algorithm, decomposer) + && checkDisabledPatterns(algorithm); cache.put(algorithm, result); return result; } + private boolean checkDisabledPatterns(final String algorithm) { + return disabledPatterns == null || disabledPatterns.stream().noneMatch( + p -> p.matcher(algorithm).matches()); + } + + private List getDisabledPatterns() { + List ret = null; + List patternStrings = new ArrayList<>(4); + + for (String p : disabledAlgorithms) { + if (p.contains("*")) { + if (!p.startsWith("TLS_")) { + throw new IllegalArgumentException( + "Wildcard pattern must start with \"TLS_\""); + } + patternStrings.add(p); + } + } + + if (!patternStrings.isEmpty()) { + ret = new ArrayList<>(patternStrings.size()); + + for (String p : patternStrings) { + // Exclude patterns from algorithm code flow. + disabledAlgorithms.remove(p); + + // Ignore all regex characters but asterisk. + ret.add(Pattern.compile( + "^\\Q" + p.replace("*", "\\E.*\\Q") + "\\E$")); + } + } + + return ret; + } + /* * This constraint is used for the complete disabling of the algorithm. */ diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/validator/EntrustTLSPolicy.java openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/validator/EntrustTLSPolicy.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/validator/EntrustTLSPolicy.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/validator/EntrustTLSPolicy.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,19 +71,7 @@ // OU=(c) 1999 Entrust.net Limited, // OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), // O=Entrust.net - "6DC47172E01CBCB0BF62580D895FE2B8AC9AD4F873801E0C10B9C837D21EB177", - // cacerts alias: affirmtrustcommercialca - // DN: CN=AffirmTrust Commercial, O=AffirmTrust, C=US - "0376AB1D54C5F9803CE4B2E201A0EE7EEF7B57B636E8A93C9B8D4860C96F5FA7", - // cacerts alias: affirmtrustnetworkingca - // DN: CN=AffirmTrust Networking, O=AffirmTrust, C=US - "0A81EC5A929777F145904AF38D5D509F66B5E2C58FCDB531058B0E17F3F0B41B", - // cacerts alias: affirmtrustpremiumca - // DN: CN=AffirmTrust Premium, O=AffirmTrust, C=US - "70A73F7F376B60074248904534B11482D5BF0E698ECC498DF52577EBF2E93B9A", - // cacerts alias: affirmtrustpremiumeccca - // DN: CN=AffirmTrust Premium ECC, O=AffirmTrust, C=US - "BD71FDF6DA97E4CF62D1647ADD2581B07D79ADF8397EB4ECBA9C5E8488821423" + "6DC47172E01CBCB0BF62580D895FE2B8AC9AD4F873801E0C10B9C837D21EB177" ); // Any TLS Server certificate that is anchored by one of the Entrust diff -Nru openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/x509/AVA.java openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/x509/AVA.java --- openjdk-21-21.0.8+9/src/java.base/share/classes/sun/security/x509/AVA.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/classes/sun/security/x509/AVA.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,10 +28,13 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.Reader; +import java.nio.charset.Charset; import java.text.Normalizer; import java.util.*; +import static java.nio.charset.StandardCharsets.ISO_8859_1; import static java.nio.charset.StandardCharsets.UTF_8; +import static java.nio.charset.StandardCharsets.UTF_16BE; import sun.security.action.GetBooleanAction; import sun.security.util.*; @@ -590,6 +593,10 @@ throw new IOException("AVA, extra bytes = " + derval.data.available()); } + + if (value.tag == DerValue.tag_BMPString) { + value.validateBMPString(); + } } AVA(DerInputStream in) throws IOException { @@ -714,7 +721,8 @@ * NOTE: this implementation only emits DirectoryStrings of the * types returned by isDerString(). */ - String valStr = new String(value.getDataBytes(), UTF_8); + String valStr = + new String(value.getDataBytes(), getCharset(value, false)); /* * 2.4 (cont): If the UTF-8 string does not have any of the @@ -839,7 +847,8 @@ * NOTE: this implementation only emits DirectoryStrings of the * types returned by isDerString(). */ - String valStr = new String(value.getDataBytes(), UTF_8); + String valStr = + new String(value.getDataBytes(), getCharset(value, true)); /* * 2.4 (cont): If the UTF-8 string does not have any of the @@ -942,6 +951,39 @@ } } + /* + * Returns the charset that should be used to decode each DN string type. + * + * This method ensures that multi-byte (UTF8String and BMPString) types + * are decoded using the correct charset and the String forms represent + * the correct characters. For 8-bit ASCII-based types (PrintableString + * and IA5String), we return ISO_8859_1 rather than ASCII, so that the + * complete range of characters can be represented, as many certificates + * do not comply with the Internationalized Domain Name ACE format. + * + * NOTE: this method only supports DirectoryStrings of the types returned + * by isDerString(). + */ + private static Charset getCharset(DerValue value, boolean canonical) { + if (canonical) { + return switch (value.tag) { + case DerValue.tag_PrintableString -> ISO_8859_1; + case DerValue.tag_UTF8String -> UTF_8; + default -> throw new Error("unexpected tag: " + value.tag); + }; + } + + return switch (value.tag) { + case DerValue.tag_PrintableString, + DerValue.tag_T61String, + DerValue.tag_IA5String, + DerValue.tag_GeneralString -> ISO_8859_1; + case DerValue.tag_BMPString -> UTF_16BE; + case DerValue.tag_UTF8String -> UTF_8; + default -> throw new Error("unexpected tag: " + value.tag); + }; + } + boolean hasRFC2253Keyword() { return AVAKeyword.hasKeyword(oid, RFC2253); } diff -Nru openjdk-21-21.0.8+9/src/java.base/share/conf/security/java.security openjdk-21-21.0.9+10/src/java.base/share/conf/security/java.security --- openjdk-21-21.0.8+9/src/java.base/share/conf/security/java.security 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/conf/security/java.security 2025-10-13 07:49:24.000000000 +0000 @@ -750,6 +750,29 @@ # See the specification of "jdk.certpath.disabledAlgorithms" for the # syntax of the disabled algorithm string. # +# Additional TLS-specific syntax supported by this property: +# +# - TLS cipher suites can be disabled with this property using one or more +# "*" wildcard characters. For example, "TLS_RSA_*" disables all cipher +# suites that start with "TLS_RSA_". Only cipher suites starting with +# "TLS_" are allowed to have wildcard characters. +# +# - TLS protocol specific usage constraints are supported by this property: +# +# UsageConstraint: +# usage UsageType { UsageType } +# +# UsageType: +# HandshakeSignature | CertificateSignature +# +# HandshakeSignature restricts the use of the algorithm in TLS handshake +# signatures. CertificateSignature restricts the use of the algorithm in +# certificate signatures. An algorithm with this constraint cannot include +# other usage types defined in the jdk.certpath.disabledAlgorithms +# property. The usage type follows the keyword and more than one usage type +# can be specified with a whitespace delimiter. +# Example: "rsa_pkcs1_sha1 usage HandshakeSignature" +# # Note: The algorithm restrictions do not apply to trust anchors or # self-signed certificates. # @@ -758,7 +781,7 @@ # # Example: # jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048, \ -# rsa_pkcs1_sha1, secp224r1 +# rsa_pkcs1_sha1, secp224r1, TLS_RSA_* jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, DTLSv1.0, RC4, DES, \ MD5withRSA, DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \ ECDH diff -Nru openjdk-21-21.0.8+9/src/java.base/share/data/cacerts/affirmtrustcommercialca openjdk-21-21.0.9+10/src/java.base/share/data/cacerts/affirmtrustcommercialca --- openjdk-21-21.0.8+9/src/java.base/share/data/cacerts/affirmtrustcommercialca 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/data/cacerts/affirmtrustcommercialca 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -Owner: CN=AffirmTrust Commercial, O=AffirmTrust, C=US -Issuer: CN=AffirmTrust Commercial, O=AffirmTrust, C=US -Serial number: 7777062726a9b17c -Valid from: Fri Jan 29 14:06:06 GMT 2010 until: Tue Dec 31 14:06:06 GMT 2030 -Signature algorithm name: SHA256withRSA -Subject Public Key Algorithm: 2048-bit RSA key -Version: 3 ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz -dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL -MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp -cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP -Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr -ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL -MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 -yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr -VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ -nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ -KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG -XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj -vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt -Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g -N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC -nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= ------END CERTIFICATE----- diff -Nru openjdk-21-21.0.8+9/src/java.base/share/data/cacerts/affirmtrustnetworkingca openjdk-21-21.0.9+10/src/java.base/share/data/cacerts/affirmtrustnetworkingca --- openjdk-21-21.0.8+9/src/java.base/share/data/cacerts/affirmtrustnetworkingca 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/data/cacerts/affirmtrustnetworkingca 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -Owner: CN=AffirmTrust Networking, O=AffirmTrust, C=US -Issuer: CN=AffirmTrust Networking, O=AffirmTrust, C=US -Serial number: 7c4f04391cd4992d -Valid from: Fri Jan 29 14:08:24 GMT 2010 until: Tue Dec 31 14:08:24 GMT 2030 -Signature algorithm name: SHA1withRSA -Subject Public Key Algorithm: 2048-bit RSA key -Version: 3 ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz -dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL -MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp -cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y -YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua -kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL -QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp -6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG -yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i -QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ -KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO -tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu -QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ -Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u -olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 -x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= ------END CERTIFICATE----- diff -Nru openjdk-21-21.0.8+9/src/java.base/share/data/cacerts/affirmtrustpremiumca openjdk-21-21.0.9+10/src/java.base/share/data/cacerts/affirmtrustpremiumca --- openjdk-21-21.0.8+9/src/java.base/share/data/cacerts/affirmtrustpremiumca 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/data/cacerts/affirmtrustpremiumca 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -Owner: CN=AffirmTrust Premium, O=AffirmTrust, C=US -Issuer: CN=AffirmTrust Premium, O=AffirmTrust, C=US -Serial number: 6d8c1446b1a60aee -Valid from: Fri Jan 29 14:10:36 GMT 2010 until: Mon Dec 31 14:10:36 GMT 2040 -Signature algorithm name: SHA384withRSA -Subject Public Key Algorithm: 4096-bit RSA key -Version: 3 ------BEGIN CERTIFICATE----- -MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz -dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG -A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U -cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf -qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ -JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ -+jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS -s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 -HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 -70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG -V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S -qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S -5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia -C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX -OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE -FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ -BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 -KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg -Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B -8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ -MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc -0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ -u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF -u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH -YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 -GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO -RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e -KeC2uAloGRwYQw== ------END CERTIFICATE----- diff -Nru openjdk-21-21.0.8+9/src/java.base/share/data/cacerts/affirmtrustpremiumeccca openjdk-21-21.0.9+10/src/java.base/share/data/cacerts/affirmtrustpremiumeccca --- openjdk-21-21.0.8+9/src/java.base/share/data/cacerts/affirmtrustpremiumeccca 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/data/cacerts/affirmtrustpremiumeccca 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -Owner: CN=AffirmTrust Premium ECC, O=AffirmTrust, C=US -Issuer: CN=AffirmTrust Premium ECC, O=AffirmTrust, C=US -Serial number: 7497258ac73f7a54 -Valid from: Fri Jan 29 14:20:24 GMT 2010 until: Mon Dec 31 14:20:24 GMT 2040 -Signature algorithm name: SHA384withECDSA -Subject Public Key Algorithm: 384-bit EC (secp384r1) key -Version: 3 ------BEGIN CERTIFICATE----- -MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC -VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ -cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ -BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt -VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D -0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 -ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G -A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs -aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I -flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== ------END CERTIFICATE----- diff -Nru openjdk-21-21.0.8+9/src/java.base/share/data/currency/CurrencyData.properties openjdk-21-21.0.9+10/src/java.base/share/data/currency/CurrencyData.properties --- openjdk-21-21.0.8+9/src/java.base/share/data/currency/CurrencyData.properties 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/data/currency/CurrencyData.properties 2025-10-13 07:49:24.000000000 +0000 @@ -32,7 +32,7 @@ # Version of the currency code information in this class. # It is a serial number that accompanies with each amendment. -dataVersion=179 +dataVersion=180 # List of all valid ISO 4217 currency codes. # To ensure compatibility, do not remove codes. @@ -147,7 +147,7 @@ # BRUNEI DARUSSALAM BN=BND # BULGARIA -BG=BGN +BG=BGN;2025-12-31-22-00-00;EUR # BURKINA FASO BF=XOF # BURUNDI @@ -193,7 +193,7 @@ # CUBA CU=CUP # Cura\u00e7ao -CW=ANG;2025-04-01-04-00-00;XCG +CW=XCG # CYPRUS CY=EUR # CZECHIA @@ -510,7 +510,7 @@ # SVALBARD AND JAN MAYEN SJ=NOK # Sint Maarten (Dutch part) -SX=ANG;2025-04-01-04-00-00;XCG +SX=XCG # ESWATINI SZ=SZL # SWEDEN diff -Nru openjdk-21-21.0.8+9/src/java.base/share/data/lsrdata/language-subtag-registry.txt openjdk-21-21.0.9+10/src/java.base/share/data/lsrdata/language-subtag-registry.txt --- openjdk-21-21.0.8+9/src/java.base/share/data/lsrdata/language-subtag-registry.txt 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/data/lsrdata/language-subtag-registry.txt 2025-10-13 07:49:24.000000000 +0000 @@ -1,4 +1,4 @@ -File-Date: 2024-11-19 +File-Date: 2025-05-15 %% Type: language Subtag: aa @@ -5950,6 +5950,7 @@ %% Type: language Subtag: bql +Description: Karian Description: Bilakura Added: 2009-07-29 %% @@ -9083,6 +9084,7 @@ %% Type: language Subtag: daz +Description: Moi-Wadea Description: Dao Added: 2009-07-29 %% @@ -9290,6 +9292,8 @@ Subtag: dek Description: Dek Added: 2009-07-29 +Deprecated: 2024-12-12 +Preferred-Value: sqm %% Type: language Subtag: del @@ -14082,6 +14086,12 @@ Macrolanguage: hmn %% Type: language +Subtag: hnm +Description: Hainanese +Added: 2024-12-12 +Macrolanguage: zh +%% +Type: language Subtag: hnn Description: Hanunoo Added: 2009-07-29 @@ -16421,6 +16431,7 @@ %% Type: language Subtag: kci +Description: Ngyian Description: Kamantan Added: 2009-07-29 %% @@ -21081,6 +21092,12 @@ Added: 2009-07-29 %% Type: language +Subtag: luh +Description: Leizhou Chinese +Added: 2024-12-12 +Macrolanguage: zh +%% +Type: language Subtag: lui Description: Luiseno Added: 2005-10-16 @@ -22850,6 +22867,8 @@ %% Type: language Subtag: mmi +Description: Hember Avu +Description: Amben Description: Musar Added: 2009-07-29 %% @@ -25197,8 +25216,9 @@ %% Type: language Subtag: new -Description: Newari Description: Nepal Bhasa +Description: Newar +Description: Newari Added: 2005-10-16 %% Type: language @@ -26641,6 +26661,8 @@ Subtag: nte Description: Nathembo Added: 2009-07-29 +Deprecated: 2024-12-12 +Preferred-Value: eko %% Type: language Subtag: ntg @@ -27185,6 +27207,12 @@ Added: 2009-07-29 %% Type: language +Subtag: oak +Description: Noakhali +Description: Noakhailla +Added: 2025-05-14 +%% +Type: language Subtag: oar Description: Old Aramaic (up to 700 BCE) Description: Ancient Aramaic (up to 700 BCE) @@ -32147,6 +32175,12 @@ Added: 2009-07-29 %% Type: language +Subtag: sjc +Description: Shaojiang Chinese +Added: 2024-12-12 +Macrolanguage: zh +%% +Type: language Subtag: sjd Description: Kildin Sami Added: 2009-07-29 @@ -41302,6 +41336,11 @@ Added: 2009-07-29 %% Type: language +Subtag: ynb +Description: Yamben +Added: 2025-02-06 +%% +Type: language Subtag: ynd Description: Yandruwandha Added: 2009-07-29 @@ -43616,6 +43655,14 @@ Prefix: sgn %% Type: extlang +Subtag: hnm +Description: Hainanese +Added: 2024-12-12 +Preferred-Value: hnm +Prefix: zh +Macrolanguage: zh +%% +Type: extlang Subtag: hos Description: Ho Chi Minh City Sign Language Added: 2009-07-29 @@ -43958,6 +44005,14 @@ Macrolanguage: lv %% Type: extlang +Subtag: luh +Description: Leizhou Chinese +Added: 2024-12-12 +Preferred-Value: luh +Prefix: zh +Macrolanguage: zh +%% +Type: extlang Subtag: lvs Description: Standard Latvian Added: 2010-03-11 @@ -44393,6 +44448,14 @@ Macrolanguage: ar %% Type: extlang +Subtag: sjc +Description: Shaojiang Chinese +Added: 2024-12-12 +Preferred-Value: sjc +Prefix: zh +Macrolanguage: zh +%% +Type: extlang Subtag: slf Description: Swiss-Italian Sign Language Added: 2009-07-29 @@ -44844,6 +44907,11 @@ Added: 2005-10-16 %% Type: script +Subtag: Berf +Description: Beria Erfe +Added: 2025-02-06 +%% +Type: script Subtag: Bhks Description: Bhaiksuki Added: 2015-07-24 @@ -45132,6 +45200,12 @@ Added: 2017-08-13 %% Type: script +Subtag: Hntl +Description: Han (Traditional variant) with Latin (alias for Hant + + Latn) +Added: 2025-05-14 +%% +Type: script Subtag: Hrkt Description: Japanese syllabaries (alias for Hiragana + Katakana) Added: 2005-10-16 @@ -45636,6 +45710,12 @@ Added: 2006-07-21 %% Type: script +Subtag: Seal +Description: Seal +Description: Small Seal +Added: 2025-05-14 +%% +Type: script Subtag: Sgnw Description: SignWriting Added: 2006-10-17 @@ -47919,6 +47999,12 @@ dóu Po, Escolo Gaston Febus, and others %% Type: variant +Subtag: hanoi +Description: The Hà Ná»™i variant of Vietnamese +Added: 2025-03-10 +Prefix: vi +%% +Type: variant Subtag: hepburn Description: Hepburn romanization Added: 2009-10-01 @@ -47949,6 +48035,12 @@ Prefix: eo %% Type: variant +Subtag: huett +Description: The Huế (province Thừa Thiên) variant of Vietnamese +Added: 2025-03-10 +Prefix: vi +%% +Type: variant Subtag: ijekavsk Description: Serbian with Ijekavian pronunciation Prefix: sr @@ -48024,6 +48116,13 @@ Comments: Preferred tag is cls %% Type: variant +Subtag: leidentr +Description: Ancient Egyptian in Leiden Unified Transliteration +Added: 2025-02-06 +Prefix: egy +Comments: Recommended by the International Association of Egyptologists +%% +Type: variant Subtag: lemosin Description: Limousin Added: 2018-04-22 @@ -48068,6 +48167,19 @@ orthographic reforms %% Type: variant +Subtag: mdcegyp +Description: Ancient Egyptian hieroglyphs encoded in Manuel de Codage +Added: 2025-02-06 +Prefix: egy +%% +Type: variant +Subtag: mdctrans +Description: Ancient Egyptian transliteration encoded in Manuel de + Codage +Added: 2025-02-06 +Prefix: egy +%% +Type: variant Subtag: metelko Description: Slovene in Metelko alphabet Added: 2012-06-27 @@ -48255,6 +48367,12 @@ Comments: Supraregional Romansh written standard %% Type: variant +Subtag: saigon +Description: The Sài Gòn variant of Vietnamese +Added: 2025-03-10 +Prefix: vi +%% +Type: variant Subtag: scotland Description: Scottish Standard English Added: 2007-08-31 diff -Nru openjdk-21-21.0.8+9/src/java.base/share/native/launcher/main.c openjdk-21-21.0.9+10/src/java.base/share/native/launcher/main.c --- openjdk-21-21.0.8+9/src/java.base/share/native/launcher/main.c 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/native/launcher/main.c 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -110,7 +110,25 @@ } } } - JLI_CmdToArgs(GetCommandLine()); + + // Obtain the command line in UTF-16, then convert it to ANSI code page + // without the "best-fit" option + LPWSTR wcCmdline = GetCommandLineW(); + int mbSize = WideCharToMultiByte(CP_ACP, + WC_NO_BEST_FIT_CHARS | WC_COMPOSITECHECK | WC_DEFAULTCHAR, + wcCmdline, -1, NULL, 0, NULL, NULL); + // If the call to WideCharToMultiByte() fails, it returns 0, which + // will then make the following JLI_MemAlloc() to issue exit(1) + LPSTR mbCmdline = JLI_MemAlloc(mbSize); + if (WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS | WC_COMPOSITECHECK | WC_DEFAULTCHAR, + wcCmdline, -1, mbCmdline, mbSize, NULL, NULL) == 0) { + perror("command line encoding conversion failure"); + exit(1); + } + + JLI_CmdToArgs(mbCmdline); + JLI_MemFree(mbCmdline); + margc = JLI_GetStdArgc(); // add one more to mark the end margv = (char **)JLI_MemAlloc((margc + 1) * (sizeof(char *))); diff -Nru openjdk-21-21.0.8+9/src/java.base/share/native/libjava/ub.h openjdk-21-21.0.9+10/src/java.base/share/native/libjava/ub.h --- openjdk-21-21.0.8+9/src/java.base/share/native/libjava/ub.h 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/native/libjava/ub.h 2025-10-13 07:49:24.000000000 +0000 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2024 SAP SE. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,10 @@ * following function or method. */ #ifdef UNDEFINED_BEHAVIOR_SANITIZER -#if defined(__clang__) || defined(__GNUC__) +#if defined(__clang__) +#define ATTRIBUTE_NO_UBSAN __attribute__((no_sanitize("undefined","float-divide-by-zero"))) +#endif +#if defined(__GNUC__) && !defined(__clang__) #define ATTRIBUTE_NO_UBSAN __attribute__((no_sanitize("undefined"))) #endif #endif diff -Nru openjdk-21-21.0.8+9/src/java.base/share/native/libjli/java.c openjdk-21-21.0.9+10/src/java.base/share/native/libjli/java.c --- openjdk-21-21.0.8+9/src/java.base/share/native/libjli/java.c 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/native/libjli/java.c 2025-10-13 07:49:24.000000000 +0000 @@ -598,7 +598,14 @@ ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1; LEAVE(); +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wreturn-type" +#endif } +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif /* * Test if the given name is one of the class path options. diff -Nru openjdk-21-21.0.8+9/src/java.base/share/native/libverify/check_code.c openjdk-21-21.0.9+10/src/java.base/share/native/libverify/check_code.c --- openjdk-21-21.0.8+9/src/java.base/share/native/libverify/check_code.c 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/share/native/libverify/check_code.c 2025-10-13 07:49:24.000000000 +0000 @@ -395,7 +395,8 @@ static void initialize_exception_table(context_type *); static int instruction_length(unsigned char *iptr, unsigned char *end); -static jboolean isLegalTarget(context_type *, int offset); +static jboolean isLegalOffset(context_type *, int bci, int offset); +static jboolean isLegalTarget(context_type *, int target); static void verify_constant_pool_type(context_type *, int, unsigned); static void initialize_dataflow(context_type *); @@ -1154,9 +1155,9 @@ case JVM_OPC_goto: { /* Set the ->operand to be the instruction number of the target. */ int jump = (((signed char)(code[offset+1])) << 8) + code[offset+2]; - int target = offset + jump; - if (!isLegalTarget(context, target)) + if (!isLegalOffset(context, offset, jump)) CCerror(context, "Illegal target of jump or branch"); + int target = offset + jump; this_idata->operand.i = code_data[target]; break; } @@ -1170,9 +1171,9 @@ int jump = (((signed char)(code[offset+1])) << 24) + (code[offset+2] << 16) + (code[offset+3] << 8) + (code[offset + 4]); - int target = offset + jump; - if (!isLegalTarget(context, target)) + if (!isLegalOffset(context, offset, jump)) CCerror(context, "Illegal target of jump or branch"); + int target = offset + jump; this_idata->operand.i = code_data[target]; break; } @@ -1211,13 +1212,16 @@ } } saved_operand = NEW(int, keys + 2); - if (!isLegalTarget(context, offset + _ck_ntohl(lpc[0]))) + int jump = _ck_ntohl(lpc[0]); + if (!isLegalOffset(context, offset, jump)) CCerror(context, "Illegal default target in switch"); - saved_operand[keys + 1] = code_data[offset + _ck_ntohl(lpc[0])]; + int target = offset + jump; + saved_operand[keys + 1] = code_data[target]; for (k = keys, lptr = &lpc[3]; --k >= 0; lptr += delta) { - int target = offset + _ck_ntohl(lptr[0]); - if (!isLegalTarget(context, target)) + jump = _ck_ntohl(lptr[0]); + if (!isLegalOffset(context, offset, jump)) CCerror(context, "Illegal branch in tableswitch"); + target = offset + jump; saved_operand[k + 1] = code_data[target]; } saved_operand[0] = keys + 1; /* number of successors */ @@ -1746,11 +1750,24 @@ /* Given the target of a branch, make sure that it's a legal target. */ static jboolean -isLegalTarget(context_type *context, int offset) +isLegalTarget(context_type *context, int target) +{ + int code_length = context->code_length; + int *code_data = context->code_data; + return (target >= 0 && target < code_length && code_data[target] >= 0); +} + +/* Given a bci and offset, make sure the offset is valid and the target is legal */ +static jboolean +isLegalOffset(context_type *context, int bci, int offset) { int code_length = context->code_length; int *code_data = context->code_data; - return (offset >= 0 && offset < code_length && code_data[offset] >= 0); + int max_offset = 65535; // JVMS 4.11 + int min_offset = -65535; + if (offset < min_offset || offset > max_offset) return JNI_FALSE; + int target = bci + offset; + return (target >= 0 && target < code_length && code_data[target] >= 0); } diff -Nru openjdk-21-21.0.8+9/src/java.base/unix/native/libjava/java_props_md.c openjdk-21-21.0.9+10/src/java.base/unix/native/libjava/java_props_md.c --- openjdk-21-21.0.8+9/src/java.base/unix/native/libjava/java_props_md.c 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.base/unix/native/libjava/java_props_md.c 2025-10-13 07:49:24.000000000 +0000 @@ -239,6 +239,7 @@ if (language != NULL && mapLookup(language_names, language, std_language) == 0) { *std_language = malloc(strlen(language)+1); if (*std_language == NULL) { + free(temp); free(encoding_variant); JNU_ThrowOutOfMemoryError(env, NULL); return 0; @@ -252,6 +253,7 @@ if (mapLookup(country_names, country, std_country) == 0) { *std_country = malloc(strlen(country)+1); if (*std_country == NULL) { + free(temp); free(encoding_variant); JNU_ThrowOutOfMemoryError(env, NULL); return 0; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java openjdk-21-21.0.9+10/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java --- openjdk-21-21.0.8+9/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,9 +60,11 @@ import javax.swing.JComponent; import javax.swing.JEditorPane; import javax.swing.JLabel; +import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JTextArea; import javax.swing.JList; +import javax.swing.JPopupMenu; import javax.swing.JTree; import javax.swing.KeyStroke; @@ -862,6 +864,34 @@ }, c); } + private static Accessible getCurrentAccessiblePopupMenu(Accessible a, Component c) { + if (a == null) return null; + + return invokeAndWait(new Callable() { + @Override + public Accessible call() throws Exception { + return traversePopupMenu(a); + } + }, c); + } + + private static Accessible traversePopupMenu(Accessible a) { + // a is root level popupmenu + AccessibleContext ac = a.getAccessibleContext(); + if (ac != null) { + for (int i = 0; i < ac.getAccessibleChildrenCount(); i++) { + Accessible child = ac.getAccessibleChild(i); + if (child instanceof JMenu subMenu) { + JPopupMenu popup = subMenu.getPopupMenu(); + if (popup.isVisible()) { + return traversePopupMenu((Accessible) popup); + } + } + } + } + return a; + } + @Native private static final int JAVA_AX_ROWS = 1; @Native private static final int JAVA_AX_COLS = 2; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java openjdk-21-21.0.9+10/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java --- openjdk-21-21.0.8+9/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,6 +64,7 @@ import sun.awt.AWTAccessor.ComponentAccessor; import sun.awt.AWTAccessor.WindowAccessor; import sun.java2d.SurfaceData; +import sun.lwawt.LWKeyboardFocusManagerPeer; import sun.lwawt.LWLightweightFramePeer; import sun.lwawt.LWToolkit; import sun.lwawt.LWWindowPeer; @@ -1057,6 +1058,11 @@ } execute(ptr -> nativeSetEnabled(ptr, !blocked)); + + Window currFocus = LWKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow(); + if (!blocked && (target == currFocus)) { + requestWindowFocus(); + } checkBlockingAndOrder(); } diff -Nru openjdk-21-21.0.8+9/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/MenuAccessibility.m openjdk-21-21.0.9+10/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/MenuAccessibility.m --- openjdk-21-21.0.8+9/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/MenuAccessibility.m 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/MenuAccessibility.m 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,10 @@ */ #import "MenuAccessibility.h" +#import "ThreadUtilities.h" +#import "sun_lwawt_macosx_CAccessibility.h" + +static jclass sjc_CAccessibility = NULL; /* * Implementing a protocol that represents menus both as submenu and as a @@ -51,4 +55,31 @@ return NULL; } +/* + * Return all non-ignored children. + */ +- (NSArray *)accessibilityChildren { + JNIEnv *env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBILITY_CLASS_RETURN(nil); + DECLARE_STATIC_METHOD_RETURN(sjm_getCurrentAccessiblePopupMenu, sjc_CAccessibility, + "getCurrentAccessiblePopupMenu", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/Accessible;", nil); + jobject axComponent = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, + sjm_getCurrentAccessiblePopupMenu, + fAccessible, fComponent); + + CommonComponentAccessibility *currentElement = [CommonComponentAccessibility createWithAccessible:axComponent + withEnv:env withView:self->fView isCurrent:YES]; + + NSArray *children = [CommonComponentAccessibility childrenOfParent:currentElement + withEnv:env + withChildrenCode:sun_lwawt_macosx_CAccessibility_JAVA_AX_ALL_CHILDREN + allowIgnored:NO]; + + if ([children count] == 0) { + return nil; + } else { + return children; + } +} @end diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/classes/com/sun/beans/introspect/MethodInfo.java openjdk-21-21.0.9+10/src/java.desktop/share/classes/com/sun/beans/introspect/MethodInfo.java --- openjdk-21-21.0.8+9/src/java.desktop/share/classes/com/sun/beans/introspect/MethodInfo.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/classes/com/sun/beans/introspect/MethodInfo.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,10 +31,11 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; +import java.util.ArrayDeque; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.Comparator; +import java.util.Deque; import java.util.List; import java.util.Set; @@ -105,13 +106,16 @@ } } - // Add default methods inherited from interfaces - for (Class iface : type.getInterfaces()) { + // Add methods inherited from interfaces + Deque> ifaceDeque = new ArrayDeque<>(List.of(type.getInterfaces())); + while (!ifaceDeque.isEmpty()) { + Class iface = ifaceDeque.removeLast(); if (IGNORABLE_INTERFACES.contains(iface)) { continue; } + ifaceDeque.addAll(List.of(iface.getInterfaces())); for (Method method : iface.getMethods()) { - if (!Modifier.isAbstract(method.getModifiers())) { + if (!Modifier.isAbstract(method.getModifiers()) && !method.isBridge()) { (list = createIfNeeded(list)).add(method); } } diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/classes/com/sun/beans/introspect/PropertyInfo.java openjdk-21-21.0.9+10/src/java.desktop/share/classes/com/sun/beans/introspect/PropertyInfo.java --- openjdk-21-21.0.8+9/src/java.desktop/share/classes/com/sun/beans/introspect/PropertyInfo.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/classes/com/sun/beans/introspect/PropertyInfo.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -78,7 +78,8 @@ } if (!isInitedToIsGetter && this.readList != null) { for (MethodInfo info : this.readList) { - if ((this.read == null) || this.read.type.isAssignableFrom(info.type)) { + if ((this.read == null) || (!info.method.isDefault() + && this.read.type.isAssignableFrom(info.type))) { this.read = info; this.type = info.type; } @@ -91,6 +92,9 @@ if (writeType == null) { this.write = info; writeType = info.type; + } else if (isParentOfIncoming(this.write, info)) { + this.write = info; + writeType = info.type; } else if (writeType.isAssignableFrom(info.type)) { if ((this.write == null) || this.write.type.isAssignableFrom(info.type)) { this.write = info; @@ -307,4 +311,16 @@ ? Collections.unmodifiableMap(map) : Collections.emptyMap(); } + + private static boolean isParentOfIncoming(MethodInfo current, MethodInfo incoming) { + if (null == current) { + return false; + } + Class currentClass = current.method.getDeclaringClass(); + Class incomingClass = incoming.method.getDeclaringClass(); + if (currentClass == incomingClass) { + return false; + } + return currentClass.isAssignableFrom(incomingClass); + } } diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java openjdk-21-21.0.9+10/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java --- openjdk-21-21.0.8+9/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,10 +26,13 @@ package com.sun.java.swing; import java.applet.Applet; +import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Graphics; import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Rectangle; import java.awt.Stroke; import java.awt.Window; import java.awt.geom.AffineTransform; @@ -37,11 +40,16 @@ import java.util.Map; import java.util.WeakHashMap; +import javax.swing.ButtonModel; +import javax.swing.Icon; import javax.swing.JComponent; +import javax.swing.JMenu; import javax.swing.RepaintManager; import sun.awt.AppContext; import sun.awt.SunToolkit; +import sun.swing.MenuItemLayoutHelper; +import sun.swing.SwingUtilities2; import static sun.java2d.pipe.Region.clipRound; @@ -143,6 +151,119 @@ return delegate; } + public static void applyInsets(Rectangle rect, Insets insets) { + if (insets != null) { + rect.x += insets.left; + rect.y += insets.top; + rect.width -= (insets.right + rect.x); + rect.height -= (insets.bottom + rect.y); + } + } + + public static void paintCheckIcon(Graphics g, MenuItemLayoutHelper lh, + MenuItemLayoutHelper.LayoutResult lr, + Color holdc, Color foreground) { + if (lh.getCheckIcon() != null) { + ButtonModel model = lh.getMenuItem().getModel(); + if (model.isArmed() || (lh.getMenuItem() instanceof JMenu + && model.isSelected())) { + g.setColor(foreground); + } else { + g.setColor(holdc); + } + if (lh.useCheckAndArrow()) { + lh.getCheckIcon().paintIcon(lh.getMenuItem(), g, + lr.getCheckRect().x, lr.getCheckRect().y); + } + g.setColor(holdc); + } + } + + public static void paintIcon(Graphics g, MenuItemLayoutHelper lh, + MenuItemLayoutHelper.LayoutResult lr, Color holdc) { + if (lh.getIcon() != null) { + Icon icon; + ButtonModel model = lh.getMenuItem().getModel(); + if (!model.isEnabled()) { + icon = lh.getMenuItem().getDisabledIcon(); + } else if (model.isPressed() && model.isArmed()) { + icon = lh.getMenuItem().getPressedIcon(); + if (icon == null) { + // Use default icon + icon = lh.getMenuItem().getIcon(); + } + } else { + icon = lh.getMenuItem().getIcon(); + } + + if (icon != null) { + icon.paintIcon(lh.getMenuItem(), g, lr.getIconRect().x, + lr.getIconRect().y); + g.setColor(holdc); + } + } + } + + + public static void paintAccText(Graphics g, MenuItemLayoutHelper lh, + MenuItemLayoutHelper.LayoutResult lr, + Color disabledForeground, + Color acceleratorSelectionForeground, + Color acceleratorForeground) { + if (!lh.getAccText().isEmpty()) { + ButtonModel model = lh.getMenuItem().getModel(); + g.setFont(lh.getAccFontMetrics().getFont()); + if (!model.isEnabled()) { + + // paint the accText disabled + if (disabledForeground != null) { + g.setColor(disabledForeground); + SwingUtilities2.drawString(lh.getMenuItem(), g, + lh.getAccText(), lr.getAccRect().x, + lr.getAccRect().y + lh.getAccFontMetrics().getAscent()); + } else { + g.setColor(lh.getMenuItem().getBackground().brighter()); + SwingUtilities2.drawString(lh.getMenuItem(), g, + lh.getAccText(), lr.getAccRect().x, + lr.getAccRect().y + lh.getAccFontMetrics().getAscent()); + g.setColor(lh.getMenuItem().getBackground().darker()); + SwingUtilities2.drawString(lh.getMenuItem(), g, + lh.getAccText(), lr.getAccRect().x - 1, + lr.getAccRect().y + lh.getFontMetrics().getAscent() - 1); + } + } else { + + // paint the accText normally + if (model.isArmed() + || (lh.getMenuItem() instanceof JMenu + && model.isSelected())) { + g.setColor(acceleratorSelectionForeground); + } else { + g.setColor(acceleratorForeground); + } + SwingUtilities2.drawString(lh.getMenuItem(), g, lh.getAccText(), + lr.getAccRect().x, lr.getAccRect().y + + lh.getAccFontMetrics().getAscent()); + } + } + } + + public static void paintArrowIcon(Graphics g, MenuItemLayoutHelper lh, + MenuItemLayoutHelper.LayoutResult lr, + Color foreground) { + if (lh.getArrowIcon() != null) { + ButtonModel model = lh.getMenuItem().getModel(); + if (model.isArmed() || (lh.getMenuItem() instanceof JMenu + && model.isSelected())) { + g.setColor(foreground); + } + if (lh.useCheckAndArrow()) { + lh.getArrowIcon().paintIcon(lh.getMenuItem(), g, + lr.getArrowRect().x, lr.getArrowRect().y); + } + } + } + /** * A task which paints an unscaled border after {@code Graphics} * transforms are removed. It's used with the diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/classes/com/sun/media/sound/StandardMidiFileReader.java openjdk-21-21.0.9+10/src/java.desktop/share/classes/com/sun/media/sound/StandardMidiFileReader.java --- openjdk-21-21.0.8+9/src/java.desktop/share/classes/com/sun/media/sound/StandardMidiFileReader.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/classes/com/sun/media/sound/StandardMidiFileReader.java 2025-10-13 07:49:24.000000000 +0000 @@ -313,10 +313,10 @@ // reset current tick to 0 long tick = 0; - // reset current status byte to 0 (invalid value). + // reset current running status byte to 0 (invalid value). // this should cause us to throw an InvalidMidiDataException if we don't // get a valid status byte from the beginning of the track. - int status = 0; + int runningStatus = 0; boolean endOfTrackFound = false; while (!trackFinished() && !endOfTrackFound) { @@ -333,10 +333,17 @@ // check for new status int byteValue = readUnsigned(); + int status; if (byteValue >= 0x80) { status = byteValue; + + // update running status (only for channel messages) + if ((status & 0xF0) != 0xF0) { + runningStatus = status; + } } else { - data1 = byteValue; + status = runningStatus; + data1 = byteValue; } switch (status & 0xF0) { diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/classes/java/awt/AWTEventMulticaster.java openjdk-21-21.0.9+10/src/java.desktop/share/classes/java/awt/AWTEventMulticaster.java --- openjdk-21-21.0.8+9/src/java.desktop/share/classes/java/awt/AWTEventMulticaster.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/classes/java/awt/AWTEventMulticaster.java 2025-10-13 07:49:24.000000000 +0000 @@ -110,6 +110,8 @@ TextListener, InputMethodListener, HierarchyListener, HierarchyBoundsListener, MouseWheelListener { + private static final int MAX_UNBALANCED_TOP_NODES = 100; + /** * A variable in the event chain (listener-a) */ @@ -954,6 +956,7 @@ * If listener-b is null, it returns listener-a * If neither are null, then it creates and returns * a new AWTEventMulticaster instance which chains a with b. + * * @param a event listener-a * @param b event listener-b * @return the resulting listener @@ -961,7 +964,64 @@ protected static EventListener addInternal(EventListener a, EventListener b) { if (a == null) return b; if (b == null) return a; - return new AWTEventMulticaster(a, b); + AWTEventMulticaster n = new AWTEventMulticaster(a, b); + if (!needsRebalance(n)) { + return n; + } + + EventListener[] array = getListeners(n, EventListener.class); + return rebalance(array, 0, array.length - 1); + } + + /** + * Return true if the argument represents a binary tree that needs to be rebalanced. + */ + private static boolean needsRebalance(AWTEventMulticaster l) { + int level = 0; + while (true) { + // The criteria for when we need a rebalance is subjective. This method checks + // up to a given threshold of the topmost nodes of a AWTEventMulticaster. If + // they all include one leaf node, then this method returns true. This criteria + // will be met after several consecutive iterations of `addInternal(a, b)` + if (++level > MAX_UNBALANCED_TOP_NODES) { + return true; + } + if (l.a instanceof AWTEventMulticaster aMulti) { + if (l.b instanceof AWTEventMulticaster) { + // we reached a node where both children are AWTEventMulticaster: let's assume + // the current node marks the start of a well-balanced subtree + return false; + } + l = aMulti; + } else if (l.b instanceof AWTEventMulticaster bMulti) { + l = bMulti; + } else { + return false; + } + } + } + + /** + * Recursively create a balanced tree that includes a given range of EventListeners. + * + * @param array the array of the EventListeners to consult + * @param index0 the lowest index (inclusive) that the return value must include + * @param index1 the highest index (inclusive) that the return value must include. + * + * @return a balanced tree. If index0 equals index1 then this returns an EventListener from + * the array provided. Otherwise this returns an AWTEventMulticaster. + */ + private static EventListener rebalance(EventListener[] array, int index0, int index1) { + if (index0 == index1) { + return array[index0]; + } + if (index0 == index1 - 1) { + return new AWTEventMulticaster(array[index0], array[index1]); + } + int mid = (index0 + index1) / 2; + return new AWTEventMulticaster( + rebalance(array, index0, mid), + rebalance(array, mid + 1, index1)); } /** diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/classes/java/beans/Introspector.java openjdk-21-21.0.9+10/src/java.desktop/share/classes/java/beans/Introspector.java --- openjdk-21-21.0.8+9/src/java.desktop/share/classes/java/beans/Introspector.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/classes/java/beans/Introspector.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1068,8 +1068,12 @@ } } if (match) { - MethodDescriptor composite = new MethodDescriptor(old, md); - methods.put(name, composite); + Class oldClass = old.getMethod().getDeclaringClass(); + Class mdClass = md.getMethod().getDeclaringClass(); + if (oldClass == mdClass || oldClass.isAssignableFrom(mdClass) || !mdClass.isAssignableFrom(oldClass)) { + MethodDescriptor composite = new MethodDescriptor(old, md); + methods.put(name, composite); + } return; } diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java openjdk-21-21.0.9+10/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java --- openjdk-21-21.0.8+9/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,17 +25,52 @@ package javax.swing.plaf.basic; -import java.awt.*; -import java.awt.event.*; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import javax.swing.*; -import javax.swing.event.*; -import javax.swing.plaf.*; +import javax.swing.ButtonModel; +import javax.swing.Icon; +import javax.swing.InputMap; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JComponent; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.KeyStroke; +import javax.swing.LookAndFeel; +import javax.swing.MenuElement; +import javax.swing.MenuSelectionManager; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.event.MenuDragMouseEvent; +import javax.swing.event.MenuDragMouseListener; +import javax.swing.event.MenuKeyListener; + +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ComponentInputMapUIResource; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.MenuItemUI; +import javax.swing.plaf.UIResource; import javax.swing.text.View; -import sun.swing.*; +import com.sun.java.swing.SwingUtilities3; +import sun.swing.MenuItemCheckIconFactory; +import sun.swing.MenuItemLayoutHelper; +import sun.swing.SwingUtilities2; +import sun.swing.UIAction; + /** * BasicMenuItem implementation @@ -670,84 +705,21 @@ private void paintIcon(Graphics g, MenuItemLayoutHelper lh, MenuItemLayoutHelper.LayoutResult lr, Color holdc) { - if (lh.getIcon() != null) { - Icon icon; - ButtonModel model = lh.getMenuItem().getModel(); - if (!model.isEnabled()) { - icon = lh.getMenuItem().getDisabledIcon(); - } else if (model.isPressed() && model.isArmed()) { - icon = lh.getMenuItem().getPressedIcon(); - if (icon == null) { - // Use default icon - icon = lh.getMenuItem().getIcon(); - } - } else { - icon = lh.getMenuItem().getIcon(); - } - - if (icon != null) { - icon.paintIcon(lh.getMenuItem(), g, lr.getIconRect().x, - lr.getIconRect().y); - g.setColor(holdc); - } - } + SwingUtilities3.paintIcon(g, lh, lr, holdc); } private void paintCheckIcon(Graphics g, MenuItemLayoutHelper lh, MenuItemLayoutHelper.LayoutResult lr, Color holdc, Color foreground) { - if (lh.getCheckIcon() != null) { - ButtonModel model = lh.getMenuItem().getModel(); - if (model.isArmed() || (lh.getMenuItem() instanceof JMenu - && model.isSelected())) { - g.setColor(foreground); - } else { - g.setColor(holdc); - } - if (lh.useCheckAndArrow()) { - lh.getCheckIcon().paintIcon(lh.getMenuItem(), g, - lr.getCheckRect().x, lr.getCheckRect().y); - } - g.setColor(holdc); - } + SwingUtilities3.paintCheckIcon(g, lh, lr, holdc, foreground); } private void paintAccText(Graphics g, MenuItemLayoutHelper lh, MenuItemLayoutHelper.LayoutResult lr) { - if (!lh.getAccText().isEmpty()) { - ButtonModel model = lh.getMenuItem().getModel(); - g.setFont(lh.getAccFontMetrics().getFont()); - if (!model.isEnabled()) { - // *** paint the accText disabled - if (disabledForeground != null) { - g.setColor(disabledForeground); - SwingUtilities2.drawString(lh.getMenuItem(), g, - lh.getAccText(), lr.getAccRect().x, - lr.getAccRect().y + lh.getAccFontMetrics().getAscent()); - } else { - g.setColor(lh.getMenuItem().getBackground().brighter()); - SwingUtilities2.drawString(lh.getMenuItem(), g, - lh.getAccText(), lr.getAccRect().x, - lr.getAccRect().y + lh.getAccFontMetrics().getAscent()); - g.setColor(lh.getMenuItem().getBackground().darker()); - SwingUtilities2.drawString(lh.getMenuItem(), g, - lh.getAccText(), lr.getAccRect().x - 1, - lr.getAccRect().y + lh.getFontMetrics().getAscent() - 1); - } - } else { - // *** paint the accText normally - if (model.isArmed() - || (lh.getMenuItem() instanceof JMenu - && model.isSelected())) { - g.setColor(acceleratorSelectionForeground); - } else { - g.setColor(acceleratorForeground); - } - SwingUtilities2.drawString(lh.getMenuItem(), g, lh.getAccText(), - lr.getAccRect().x, lr.getAccRect().y + - lh.getAccFontMetrics().getAscent()); - } - } + SwingUtilities3.paintAccText(g, lh, lr, + disabledForeground, + acceleratorSelectionForeground, + acceleratorForeground); } private void paintText(Graphics g, MenuItemLayoutHelper lh, @@ -766,26 +738,11 @@ private void paintArrowIcon(Graphics g, MenuItemLayoutHelper lh, MenuItemLayoutHelper.LayoutResult lr, Color foreground) { - if (lh.getArrowIcon() != null) { - ButtonModel model = lh.getMenuItem().getModel(); - if (model.isArmed() || (lh.getMenuItem() instanceof JMenu - && model.isSelected())) { - g.setColor(foreground); - } - if (lh.useCheckAndArrow()) { - lh.getArrowIcon().paintIcon(lh.getMenuItem(), g, - lr.getArrowRect().x, lr.getArrowRect().y); - } - } + SwingUtilities3.paintArrowIcon(g, lh, lr, foreground); } private void applyInsets(Rectangle rect, Insets insets) { - if(insets != null) { - rect.x += insets.left; - rect.y += insets.top; - rect.width -= (insets.right + rect.x); - rect.height -= (insets.bottom + rect.y); - } + SwingUtilities3.applyInsets(rect, insets); } /** diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/classes/sun/awt/datatransfer/SunClipboard.java openjdk-21-21.0.9+10/src/java.desktop/share/classes/sun/awt/datatransfer/SunClipboard.java --- openjdk-21-21.0.8+9/src/java.desktop/share/classes/sun/awt/datatransfer/SunClipboard.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/classes/sun/awt/datatransfer/SunClipboard.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -204,8 +204,9 @@ byte[] data = null; Transferable localeTransferable = null; + openClipboard(null); + try { - openClipboard(null); long[] formats = getClipboardFormats(); Long lFormat = DataTransferer.getInstance(). @@ -318,12 +319,7 @@ * @since 1.5 */ protected long[] getClipboardFormatsOpenClose() { - try { - openClipboard(null); - return getClipboardFormats(); - } finally { - closeClipboard(); - } + return getClipboardFormats(); } /** @@ -356,15 +352,7 @@ flavorListeners.add(listener); if (numberOfFlavorListeners++ == 0) { - long[] currentFormats = null; - try { - openClipboard(null); - currentFormats = getClipboardFormats(); - } catch (final IllegalStateException ignored) { - } finally { - closeClipboard(); - } - this.currentFormats = currentFormats; + this.currentFormats = getClipboardFormats(); registerClipboardViewerChecked(); } diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/classes/sun/font/FileFontStrike.java openjdk-21-21.0.9+10/src/java.desktop/share/classes/sun/font/FileFontStrike.java --- openjdk-21-21.0.8+9/src/java.desktop/share/classes/sun/font/FileFontStrike.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/classes/sun/font/FileFontStrike.java 2025-10-13 07:49:24.000000000 +0000 @@ -202,7 +202,6 @@ this.disposer = new FontStrikeDisposer(fileFont, desc); initGlyphCache(); pScalerContext = NullFontScaler.getNullScalerContext(); - SunFontManager.getInstance().deRegisterBadFont(fileFont); return; } /* First, see if native code should be used to create the glyph. diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/legal/harfbuzz.md openjdk-21-21.0.9+10/src/java.desktop/share/legal/harfbuzz.md --- openjdk-21-21.0.8+9/src/java.desktop/share/legal/harfbuzz.md 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/legal/harfbuzz.md 2025-10-13 07:49:24.000000000 +0000 @@ -1,4 +1,4 @@ -## Harfbuzz v10.4.0 +## Harfbuzz 11.2.0 ### Harfbuzz License diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libfontmanager/freetypeScaler.c openjdk-21-21.0.9+10/src/java.desktop/share/native/libfontmanager/freetypeScaler.c --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libfontmanager/freetypeScaler.c 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libfontmanager/freetypeScaler.c 2025-10-13 07:49:24.000000000 +0000 @@ -518,7 +518,6 @@ if (context == NULL) { free(context); - invalidateJavaScaler(env, scaler, NULL); return (jlong) 0; } (*env)->GetDoubleArrayRegion(env, matrix, 0, 4, dmat); diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/OT/Color/CBDT/CBDT.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Color/CBDT/CBDT.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/OT/Color/CBDT/CBDT.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Color/CBDT/CBDT.hh 2025-10-13 07:49:24.000000000 +0000 @@ -949,25 +949,25 @@ hb_glyph_extents_t extents; hb_glyph_extents_t pixel_extents; - hb_blob_t *blob = reference_png (font, glyph); - - if (unlikely (blob == hb_blob_get_empty ())) + if (unlikely (!font->get_glyph_extents (glyph, &extents, false))) return false; - if (unlikely (!hb_font_get_glyph_extents (font, glyph, &extents))) + if (unlikely (!get_extents (font, glyph, &pixel_extents, false))) return false; - if (unlikely (!get_extents (font, glyph, &pixel_extents, false))) + hb_blob_t *blob = reference_png (font, glyph); + if (unlikely (hb_blob_is_immutable (blob))) return false; bool ret = funcs->image (data, blob, pixel_extents.width, -pixel_extents.height, HB_PAINT_IMAGE_FORMAT_PNG, - font->slant_xy, + 0.f, &extents); hb_blob_destroy (blob); + return ret; } diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh 2025-10-13 07:49:24.000000000 +0000 @@ -33,6 +33,7 @@ #include "../../../hb-open-type.hh" #include "../../../hb-ot-var-common.hh" #include "../../../hb-paint.hh" +#include "../../../hb-paint-bounded.hh" #include "../../../hb-paint-extents.hh" #include "../CPAL/CPAL.hh" @@ -47,6 +48,12 @@ struct hb_paint_context_t; } +struct hb_colr_scratch_t +{ + hb_paint_bounded_context_t paint_bounded; + hb_paint_extents_context_t paint_extents; +}; + namespace OT { struct COLR; @@ -90,12 +97,27 @@ font (font_), palette ( #ifndef HB_NO_COLOR - font->face->table.CPAL->get_palette_colors (palette_) + // https://github.com/harfbuzz/harfbuzz/issues/5116 + font->face->table.CPAL->get_palette_colors (palette_ < font->face->table.CPAL->get_palette_count () ? palette_ : 0) #endif ), foreground (foreground_), instancer (instancer_) - { } + { + if (font->is_synthetic ()) + { + font = hb_font_create_sub_font (font); + hb_font_set_synthetic_bold (font, 0, 0, true); + hb_font_set_synthetic_slant (font, 0); + } + else + hb_font_reference (font); + } + + ~hb_paint_context_t () + { + hb_font_destroy (font); + } hb_color_t get_color (unsigned int color_index, float alpha, hb_bool_t *is_foreground) { @@ -932,9 +954,9 @@ void paint_glyph (hb_paint_context_t *c) const { TRACE_PAINT (this); - c->funcs->push_inverse_root_transform (c->data, c->font); + c->funcs->push_inverse_font_transform (c->data, c->font); c->funcs->push_clip_glyph (c->data, gid, c->font); - c->funcs->push_root_transform (c->data, c->font); + c->funcs->push_font_transform (c->data, c->font); c->recurse (this+paint); c->funcs->pop_transform (c->data); c->funcs->pop_clip (c->data); @@ -1511,10 +1533,12 @@ void paint_glyph (hb_paint_context_t *c) const { TRACE_PAINT (this); + c->funcs->push_group (c->data); c->recurse (this+backdrop); c->funcs->push_group (c->data); c->recurse (this+src); c->funcs->pop_group (c->data, (hb_paint_composite_mode_t) (int) mode); + c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER); } HBUINT8 format; /* format = 32 */ @@ -1612,7 +1636,7 @@ void closurev1 (hb_colrv1_closure_context_t* c) const { switch (u.format) { - case 2: u.format2.closurev1 (c); + case 2: u.format2.closurev1 (c); return; default:return; } } @@ -2079,6 +2103,8 @@ { static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR; + bool has_data () const { return has_v0_data () || version; } + bool has_v0_data () const { return numBaseGlyphs; } bool has_v1_data () const { @@ -2112,7 +2138,53 @@ { accelerator_t (hb_face_t *face) { colr = hb_sanitize_context_t ().reference_table (face); } - ~accelerator_t () { this->colr.destroy (); } + + ~accelerator_t () + { + auto *scratch = cached_scratch.get_relaxed (); + if (scratch) + { + scratch->~hb_colr_scratch_t (); + hb_free (scratch); + } + + colr.destroy (); + } + + + bool has_data () const { return colr->has_data (); } + +#ifndef HB_NO_PAINT + bool + get_extents (hb_font_t *font, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents) const + { + if (unlikely (!has_data ())) return false; + + hb_colr_scratch_t *scratch = acquire_scratch (); + if (unlikely (!scratch)) return true; + bool ret = colr->get_extents (font, glyph, extents, *scratch); + release_scratch (scratch); + return ret; + } + + bool paint_glyph (hb_font_t *font, + hb_codepoint_t glyph, + hb_paint_funcs_t *funcs, void *data, + unsigned int palette_index, + hb_color_t foreground, + bool clip = true) const + { + if (unlikely (!has_data ())) return false; + + hb_colr_scratch_t *scratch = acquire_scratch (); + if (unlikely (!scratch)) return true; + bool ret = colr->paint_glyph (font, glyph, funcs, data, palette_index, foreground, clip, *scratch); + release_scratch (scratch); + return ret; + } +#endif bool is_valid () { return colr.get_blob ()->length; } @@ -2148,7 +2220,33 @@ { return colr->get_delta_set_index_map_ptr (); } private: + + hb_colr_scratch_t *acquire_scratch () const + { + hb_colr_scratch_t *scratch = cached_scratch.get_acquire (); + + if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr))) + { + scratch = (hb_colr_scratch_t *) hb_calloc (1, sizeof (hb_colr_scratch_t)); + if (unlikely (!scratch)) + return nullptr; + } + + return scratch; + } + void release_scratch (hb_colr_scratch_t *scratch) const + { + if (!cached_scratch.cmpexch (nullptr, scratch)) + { + scratch->~hb_colr_scratch_t (); + hb_free (scratch); + } + } + + public: hb_blob_ptr_t colr; + private: + mutable hb_atomic_t cached_scratch; }; void closure_glyphs (hb_codepoint_t glyph, @@ -2520,7 +2618,10 @@ #ifndef HB_NO_PAINT bool - get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const + get_extents (hb_font_t *font, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents, + hb_colr_scratch_t &scratch) const { ItemVarStoreInstancer instancer (get_var_store_ptr (), @@ -2534,10 +2635,10 @@ } auto *extents_funcs = hb_paint_extents_get_funcs (); - hb_paint_extents_context_t extents_data; - bool ret = paint_glyph (font, glyph, extents_funcs, &extents_data, 0, HB_COLOR(0,0,0,0)); + scratch.paint_extents.clear (); + bool ret = paint_glyph (font, glyph, extents_funcs, &scratch.paint_extents, 0, HB_COLOR(0,0,0,0), true, scratch); - hb_extents_t e = extents_data.get_extents (); + auto e = scratch.paint_extents.get_extents (); if (e.is_void ()) { extents->x_bearing = 0; @@ -2583,7 +2684,12 @@ #ifndef HB_NO_PAINT bool - paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, unsigned int palette_index, hb_color_t foreground, bool clip = true) const + paint_glyph (hb_font_t *font, + hb_codepoint_t glyph, + hb_paint_funcs_t *funcs, void *data, + unsigned int palette_index, hb_color_t foreground, + bool clip, + hb_colr_scratch_t &scratch) const { ItemVarStoreInstancer instancer (get_var_store_ptr (), get_delta_set_index_map_ptr (), @@ -2617,26 +2723,26 @@ } else { - auto *extents_funcs = hb_paint_extents_get_funcs (); - hb_paint_extents_context_t extents_data; + clip = false; + is_bounded = false; + } + + if (!is_bounded) + { + auto *bounded_funcs = hb_paint_bounded_get_funcs (); + scratch.paint_bounded.clear (); paint_glyph (font, glyph, - extents_funcs, &extents_data, + bounded_funcs, &scratch.paint_bounded, palette_index, foreground, - false); - - hb_extents_t extents = extents_data.get_extents (); - is_bounded = extents_data.is_bounded (); + false, + scratch); - c.funcs->push_clip_rectangle (c.data, - extents.xmin, - extents.ymin, - extents.xmax, - extents.ymax); + is_bounded = scratch.paint_bounded.is_bounded (); } } - c.funcs->push_root_transform (c.data, font); + c.funcs->push_font_transform (c.data, font); if (is_bounded) c.recurse (*paint); @@ -2714,9 +2820,7 @@ return; const Paint &paint = paint_offset_lists.get_paint (i); - c->funcs->push_group (c->data); c->recurse (paint); - c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER); } } @@ -2728,7 +2832,7 @@ if (unlikely (!node.visit (gid))) return; - c->funcs->push_inverse_root_transform (c->data, c->font); + c->funcs->push_inverse_font_transform (c->data, c->font); if (c->funcs->color_glyph (c->data, gid, c->font)) { c->funcs->pop_transform (c->data); diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh 2025-10-13 07:49:24.000000000 +0000 @@ -237,27 +237,28 @@ int x_offset = 0, y_offset = 0; unsigned int strike_ppem = 0; - hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem); hb_glyph_extents_t extents; hb_glyph_extents_t pixel_extents; - if (blob == hb_blob_get_empty ()) + if (!font->get_glyph_extents (glyph, &extents, false)) return false; - if (!hb_font_get_glyph_extents (font, glyph, &extents)) + if (unlikely (!get_extents (font, glyph, &pixel_extents, false))) return false; - if (unlikely (!get_extents (font, glyph, &pixel_extents, false))) + hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem); + if (hb_blob_is_immutable (blob)) return false; bool ret = funcs->image (data, blob, pixel_extents.width, -pixel_extents.height, HB_PAINT_IMAGE_FORMAT_PNG, - font->slant_xy, + 0.f, &extents); hb_blob_destroy (blob); + return ret; } diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh 2025-10-13 07:49:24.000000000 +0000 @@ -104,15 +104,16 @@ if (blob == hb_blob_get_empty ()) return false; - funcs->image (data, - blob, - 0, 0, - HB_PAINT_IMAGE_FORMAT_SVG, - font->slant_xy, - nullptr); + bool ret = funcs->image (data, + blob, + 0, 0, + HB_PAINT_IMAGE_FORMAT_SVG, + 0.f, + nullptr); hb_blob_destroy (blob); - return true; + + return ret; } private: diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat1.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat1.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat1.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat1.hh 2025-10-13 07:49:24.000000000 +0000 @@ -77,7 +77,7 @@ bool intersects (const hb_set_t *glyphs) const { - if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len) / 2) + if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len)) { for (auto g : *glyphs) if (get_coverage (g) != NOT_COVERED) diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat2.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat2.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat2.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat2.hh 2025-10-13 07:49:24.000000000 +0000 @@ -120,7 +120,7 @@ bool intersects (const hb_set_t *glyphs) const { - if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2) + if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len)) { for (auto g : *glyphs) if (get_coverage (g) != NOT_COVERED) diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/OT/Layout/GDEF/GDEF.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/GDEF/GDEF.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/OT/Layout/GDEF/GDEF.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/GDEF/GDEF.hh 2025-10-13 07:49:24.000000000 +0000 @@ -205,20 +205,19 @@ unsigned varidx = (this+deviceTable).get_variation_index (); hb_pair_t *new_varidx_delta; - if (!c->plan->layout_variation_idx_delta_map.has (varidx, &new_varidx_delta)) - return_trace (false); + if (c->plan->layout_variation_idx_delta_map.has (varidx, &new_varidx_delta)) { + uint32_t new_varidx = hb_first (*new_varidx_delta); + int delta = hb_second (*new_varidx_delta); + if (delta != 0) + { + if (!c->serializer->check_assign (out->coordinate, coordinate + delta, HB_SERIALIZE_ERROR_INT_OVERFLOW)) + return_trace (false); + } - uint32_t new_varidx = hb_first (*new_varidx_delta); - int delta = hb_second (*new_varidx_delta); - if (delta != 0) - { - if (!c->serializer->check_assign (out->coordinate, coordinate + delta, HB_SERIALIZE_ERROR_INT_OVERFLOW)) - return_trace (false); + if (new_varidx == HB_OT_LAYOUT_NO_VARIATIONS_INDEX) + return_trace (c->serializer->check_assign (out->caretValueFormat, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW)); } - if (new_varidx == HB_OT_LAYOUT_NO_VARIATIONS_INDEX) - return_trace (c->serializer->check_assign (out->caretValueFormat, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW)); - if (!c->serializer->embed (deviceTable)) return_trace (false); @@ -1015,7 +1014,8 @@ hb_blob_ptr_t table; #ifndef HB_NO_GDEF_CACHE hb_vector_t mark_glyph_set_digests; - mutable hb_cache_t<21, 3, 8> glyph_props_cache; + mutable hb_cache_t<21, 3> glyph_props_cache; + static_assert (sizeof (glyph_props_cache) == 512, ""); #endif }; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/GPOS.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/GPOS.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/GPOS.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/GPOS.hh 2025-10-13 07:49:24.000000000 +0000 @@ -152,8 +152,11 @@ for (unsigned i = 0; i < len; i++) propagate_attachment_offsets (pos, len, i, direction); - if (unlikely (font->slant)) + if (unlikely (font->slant_xy) && + HB_DIRECTION_IS_HORIZONTAL (direction)) { + /* Slanting shaping results is only supported for horizontal text, + * as it gets weird otherwise. */ for (unsigned i = 0; i < len; i++) if (unlikely (pos[i].y_offset)) pos[i].x_offset += roundf (font->slant_xy * pos[i].y_offset); diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh 2025-10-13 07:49:24.000000000 +0000 @@ -54,7 +54,7 @@ { auto &cov = this+coverage; - if (pairSet.len > glyphs->get_population () * hb_bit_storage ((unsigned) pairSet.len) / 4) + if (pairSet.len > glyphs->get_population () * hb_bit_storage ((unsigned) pairSet.len)) { for (hb_codepoint_t g : glyphs->iter()) { diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/VARC.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/VARC.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/VARC.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/VARC.hh 2025-10-13 07:49:24.000000000 +0000 @@ -21,6 +21,24 @@ #ifndef HB_NO_VAR_COMPOSITES +struct hb_varc_scratch_t +{ + hb_vector_t axisIndices; + hb_vector_t axisValues; + hb_glyf_scratch_t glyf_scratch; +}; + +struct hb_varc_context_t +{ + hb_font_t *font; + hb_draw_session_t *draw_session; + hb_extents_t *extents; + mutable hb_decycler_t decycler; + mutable signed edges_left; + mutable signed depth_left; + hb_varc_scratch_t &scratch; +}; + struct VarComponent { enum class flags_t : uint32_t @@ -44,41 +62,32 @@ }; HB_INTERNAL hb_ubytes_t - get_path_at (hb_font_t *font, + get_path_at (const hb_varc_context_t &c, hb_codepoint_t parent_gid, - hb_draw_session_t &draw_session, hb_array_t coords, hb_transform_t transform, hb_ubytes_t record, - hb_decycler_t *decycler, - signed *edges_left, - signed depth_left, - hb_glyf_scratch_t &scratch, VarRegionList::cache_t *cache = nullptr) const; }; struct VarCompositeGlyph { static void - get_path_at (hb_font_t *font, - hb_codepoint_t glyph, - hb_draw_session_t &draw_session, + get_path_at (const hb_varc_context_t &c, + hb_codepoint_t gid, hb_array_t coords, hb_transform_t transform, hb_ubytes_t record, - hb_decycler_t *decycler, - signed *edges_left, - signed depth_left, - hb_glyf_scratch_t &scratch, - VarRegionList::cache_t *cache = nullptr) + VarRegionList::cache_t *cache) { while (record) { const VarComponent &comp = * (const VarComponent *) (record.arrayZ); - record = comp.get_path_at (font, glyph, - draw_session, coords, transform, + record = comp.get_path_at (c, + gid, + coords, transform, record, - decycler, edges_left, depth_left, scratch, cache); + cache); } } }; @@ -92,36 +101,47 @@ static constexpr hb_tag_t tableTag = HB_TAG ('V', 'A', 'R', 'C'); HB_INTERNAL bool - get_path_at (hb_font_t *font, - hb_codepoint_t glyph, - hb_draw_session_t &draw_session, + get_path_at (const hb_varc_context_t &c, + hb_codepoint_t gid, hb_array_t coords, - hb_transform_t transform, - hb_codepoint_t parent_glyph, - hb_decycler_t *decycler, - signed *edges_left, - signed depth_left, - hb_glyf_scratch_t &scratch) const; + hb_transform_t transform = HB_TRANSFORM_IDENTITY, + hb_codepoint_t parent_gid = HB_CODEPOINT_INVALID, + VarRegionList::cache_t *parent_cache = nullptr) const; bool get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session, - hb_glyf_scratch_t &scratch) const + hb_varc_scratch_t &scratch) const + { + hb_varc_context_t c {font, + &draw_session, + nullptr, + hb_decycler_t {}, + HB_MAX_GRAPH_EDGE_COUNT, + HB_MAX_NESTING_LEVEL, + scratch}; + + return get_path_at (c, gid, + hb_array (font->coords, font->num_coords)); + } + + bool + get_extents (hb_font_t *font, + hb_codepoint_t gid, + hb_extents_t *extents, + hb_varc_scratch_t &scratch) const { - hb_decycler_t decycler; - signed edges = HB_MAX_GRAPH_EDGE_COUNT; + hb_varc_context_t c {font, + nullptr, + extents, + hb_decycler_t {}, + HB_MAX_GRAPH_EDGE_COUNT, + HB_MAX_NESTING_LEVEL, + scratch}; - return get_path_at (font, - gid, - draw_session, - hb_array (font->coords, font->num_coords), - HB_TRANSFORM_IDENTITY, - HB_CODEPOINT_INVALID, - &decycler, - &edges, - HB_MAX_NESTING_LEVEL, - scratch); + return get_path_at (c, gid, + hb_array (font->coords, font->num_coords)); } bool sanitize (hb_sanitize_context_t *c) const @@ -150,7 +170,7 @@ auto *scratch = cached_scratch.get_relaxed (); if (scratch) { - scratch->~hb_glyf_scratch_t (); + scratch->~hb_varc_scratch_t (); hb_free (scratch); } @@ -162,34 +182,60 @@ { if (!table->has_data ()) return false; - hb_glyf_scratch_t *scratch; + auto *scratch = acquire_scratch (); + if (unlikely (!scratch)) return true; + bool ret = table->get_path (font, gid, draw_session, *scratch); + release_scratch (scratch); + return ret; + } - // Borrow the cached strach buffer. + bool + get_extents (hb_font_t *font, + hb_codepoint_t gid, + hb_glyph_extents_t *extents) const + { + if (!table->has_data ()) return false; + + hb_extents_t f_extents; + + auto *scratch = acquire_scratch (); + if (unlikely (!scratch)) return true; + bool ret = table->get_extents (font, gid, &f_extents, *scratch); + release_scratch (scratch); + + if (ret) + *extents = f_extents.to_glyph_extents (font->x_scale < 0, font->y_scale < 0); + + return ret; + } + + private: + + hb_varc_scratch_t *acquire_scratch () const + { + hb_varc_scratch_t *scratch = cached_scratch.get_acquire (); + + if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr))) { - scratch = cached_scratch.get_acquire (); - if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr))) - { - scratch = (hb_glyf_scratch_t *) hb_calloc (1, sizeof (hb_glyf_scratch_t)); - if (unlikely (!scratch)) - return true; - } + scratch = (hb_varc_scratch_t *) hb_calloc (1, sizeof (hb_varc_scratch_t)); + if (unlikely (!scratch)) + return nullptr; } - bool ret = table->get_path (font, gid, draw_session, *scratch); - - // Put it back. + return scratch; + } + void release_scratch (hb_varc_scratch_t *scratch) const + { if (!cached_scratch.cmpexch (nullptr, scratch)) { - scratch->~hb_glyf_scratch_t (); + scratch->~hb_varc_scratch_t (); hb_free (scratch); } - - return ret; } private: hb_blob_ptr_t table; - hb_atomic_ptr_t cached_scratch; + mutable hb_atomic_t cached_scratch; }; bool has_data () const { return version.major != 0; } diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh 2025-10-13 07:49:24.000000000 +0000 @@ -429,16 +429,27 @@ } public: - bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const + + bool get_extents (hb_font_t *font, + hb_codepoint_t gid, + hb_glyph_extents_t *extents) const + { return get_extents_at (font, gid, extents, hb_array (font->coords, font->num_coords)); } + + bool get_extents_at (hb_font_t *font, + hb_codepoint_t gid, + hb_glyph_extents_t *extents, + hb_array_t coords) const { if (unlikely (gid >= num_glyphs)) return false; #ifndef HB_NO_VAR - if (font->num_coords) + if (coords) { hb_glyf_scratch_t scratch; - return get_points (font, gid, points_aggregator_t (font, extents, nullptr, true), - hb_array (font->coords, font->num_coords), + return get_points (font, + gid, + points_aggregator_t (font, extents, nullptr, true), + coords, scratch); } #endif @@ -532,7 +543,7 @@ unsigned int num_glyphs; hb_blob_ptr_t loca_table; hb_blob_ptr_t glyf_table; - hb_atomic_ptr_t cached_scratch; + mutable hb_atomic_t cached_scratch; }; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh 2025-10-13 07:49:24.000000000 +0000 @@ -29,6 +29,8 @@ #include "hb-aat-layout.hh" #include "hb-aat-map.hh" +#include "hb-ot-layout-common.hh" +#include "hb-ot-layout-gdef-table.hh" #include "hb-open-type.hh" #include "hb-cache.hh" #include "hb-bit-set.hh" @@ -48,6 +50,61 @@ using hb_aat_class_cache_t = hb_cache_t<15, 8, 7>; static_assert (sizeof (hb_aat_class_cache_t) == 256, ""); +struct hb_aat_scratch_t +{ + hb_aat_scratch_t () = default; + hb_aat_scratch_t (const hb_aat_scratch_t &) = delete; + + hb_aat_scratch_t (hb_aat_scratch_t &&o) + { + buffer_glyph_set.set_relaxed (o.buffer_glyph_set.get_relaxed ()); + o.buffer_glyph_set.set_relaxed (nullptr); + } + hb_aat_scratch_t & operator = (hb_aat_scratch_t &&o) + { + buffer_glyph_set.set_relaxed (o.buffer_glyph_set.get_relaxed ()); + o.buffer_glyph_set.set_relaxed (nullptr); + return *this; + } + ~hb_aat_scratch_t () + { + auto *s = buffer_glyph_set.get_relaxed (); + if (unlikely (!s)) + return; + s->fini (); + hb_free (s); + } + + hb_bit_set_t *create_buffer_glyph_set () const + { + hb_bit_set_t *s = buffer_glyph_set.get_acquire (); + if (s && buffer_glyph_set.cmpexch (s, nullptr)) + return s; + + s = (hb_bit_set_t *) hb_calloc (1, sizeof (hb_bit_set_t)); + if (unlikely (!s)) + return nullptr; + s->init (); + + return s; + } + void destroy_buffer_glyph_set (hb_bit_set_t *s) const + { + if (unlikely (!s)) + return; + if (buffer_glyph_set.cmpexch (nullptr, s)) + return; + s->fini (); + hb_free (s); + } + + mutable hb_atomic_t buffer_glyph_set; +}; + +enum { DELETED_GLYPH = 0xFFFF }; + +#define HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED HB_BUFFER_SCRATCH_FLAG_SHAPER0 + struct hb_aat_apply_context_t : hb_dispatch_context_t { @@ -64,10 +121,11 @@ hb_buffer_t *buffer; hb_sanitize_context_t sanitizer; const ankr *ankr_table; - const OT::GDEF *gdef_table; + const OT::GDEF &gdef; + bool has_glyph_classes; const hb_sorted_vector_t *range_flags = nullptr; bool using_buffer_glyph_set = false; - hb_bit_set_t buffer_glyph_set; + hb_bit_set_t *buffer_glyph_set = nullptr; const hb_bit_set_t *left_set = nullptr; const hb_bit_set_t *right_set = nullptr; const hb_bit_set_t *machine_glyph_set = nullptr; @@ -90,15 +148,15 @@ void setup_buffer_glyph_set () { - using_buffer_glyph_set = buffer->len >= 4; + using_buffer_glyph_set = buffer->len >= 4 && buffer_glyph_set; - if (using_buffer_glyph_set) - buffer->collect_codepoints (buffer_glyph_set); + if (likely (using_buffer_glyph_set)) + buffer->collect_codepoints (*buffer_glyph_set); } bool buffer_intersects_machine () const { - if (using_buffer_glyph_set) - return buffer_glyph_set.intersects (*machine_glyph_set); + if (likely (using_buffer_glyph_set)) + return buffer_glyph_set->intersects (*machine_glyph_set); // Faster for shorter buffers. for (unsigned i = 0; i < buffer->len; i++) @@ -106,6 +164,69 @@ return true; return false; } + + template + HB_NODISCARD bool output_glyphs (unsigned int count, + const T *glyphs) + { + if (likely (using_buffer_glyph_set)) + buffer_glyph_set->add_array (glyphs, count); + for (unsigned int i = 0; i < count; i++) + { + if (glyphs[i] == DELETED_GLYPH) + { + buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED; + _hb_glyph_info_set_aat_deleted (&buffer->cur()); + } + else + { +#ifndef HB_NO_OT_LAYOUT + if (has_glyph_classes) + _hb_glyph_info_set_glyph_props (&buffer->cur(), + gdef.get_glyph_props (glyphs[i])); +#endif + } + if (unlikely (!buffer->output_glyph (glyphs[i]))) return false; + } + return true; + } + + HB_NODISCARD bool replace_glyph (hb_codepoint_t glyph) + { + if (glyph == DELETED_GLYPH) + { + buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED; + _hb_glyph_info_set_aat_deleted (&buffer->cur()); + } + + if (likely (using_buffer_glyph_set)) + buffer_glyph_set->add (glyph); +#ifndef HB_NO_OT_LAYOUT + if (has_glyph_classes) + _hb_glyph_info_set_glyph_props (&buffer->cur(), + gdef.get_glyph_props (glyph)); +#endif + return buffer->replace_glyph (glyph); + } + + HB_NODISCARD bool delete_glyph () + { + buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED; + _hb_glyph_info_set_aat_deleted (&buffer->cur()); + return buffer->replace_glyph (DELETED_GLYPH); + } + + void replace_glyph_inplace (unsigned i, hb_codepoint_t glyph) + { + buffer->info[i].codepoint = glyph; + if (likely (using_buffer_glyph_set)) + buffer_glyph_set->add (glyph); +#ifndef HB_NO_OT_LAYOUT + if (has_glyph_classes) + _hb_glyph_info_set_glyph_props (&buffer->info[i], + gdef.get_glyph_props (glyph)); +#endif + } }; @@ -113,8 +234,6 @@ * Lookup Table */ -enum { DELETED_GLYPH = 0xFFFF }; - template struct Lookup; template @@ -179,6 +298,7 @@ template void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const { + if (first == DELETED_GLYPH) return; if (!filter (value)) return; glyphs.add_range (first, last); } @@ -268,6 +388,7 @@ template void collect_glyphs_filtered (set_t &glyphs, const void *base, const filter_t &filter) const { + if (first == DELETED_GLYPH) return; const auto &values = base+valuesZ; for (hb_codepoint_t i = first; i <= last; i++) if (filter (values[i - first])) @@ -368,6 +489,7 @@ template void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const { + if (glyph == DELETED_GLYPH) return; if (!filter (value)) return; glyphs.add (glyph); } @@ -746,6 +868,10 @@ } // And glyphs in those classes. + + if (filter (CLASS_DELETED_GLYPH)) + glyphs.add (DELETED_GLYPH); + (this+classTable).collect_glyphs_filtered (glyphs, num_glyphs, filter); } diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh 2025-10-13 07:49:24.000000000 +0000 @@ -185,6 +185,9 @@ DEFINE_SIZE_STATIC (2); }; + static bool initiateAction (const Entry &entry) + { return entry.flags & Push; } + static bool performAction (const Entry &entry) { return entry.data.kernActionIndex != 0xFFFF; } @@ -325,8 +328,9 @@ } else if (buffer->info[idx].mask & kern_mask) { - o.x_advance += c->font->em_scale_x (v); - o.x_offset += c->font->em_scale_x (v); + auto scaled = c->font->em_scale_x (v); + o.x_advance += scaled; + o.x_offset += scaled; } } else @@ -394,10 +398,8 @@ template void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const { - set_t set; - machine.collect_glyphs (set, num_glyphs); - left_set.union_ (set); - right_set.union_ (set); + machine.collect_initial_glyphs (left_set, num_glyphs, *this); + //machine.collect_glyphs (right_set, num_glyphs); // right_set is unused for machine kerning } protected: @@ -671,10 +673,8 @@ template void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const { - set_t set; - machine.collect_glyphs (set, num_glyphs); - left_set.union_ (set); - right_set.union_ (set); + machine.collect_initial_glyphs (left_set, num_glyphs, *this); + //machine.collect_glyphs (right_set, num_glyphs); // right_set is unused for machine kerning } protected: @@ -921,7 +921,18 @@ * The 'kerx' Table */ -using kern_accelerator_data_t = hb_vector_t>; +struct kern_subtable_accelerator_data_t +{ + hb_bit_set_t left_set; + hb_bit_set_t right_set; + mutable hb_aat_class_cache_t class_cache; +}; + +struct kern_accelerator_data_t +{ + hb_vector_t subtable_accels; + hb_aat_scratch_t scratch; +}; template struct KerxTable @@ -985,6 +996,8 @@ { c->buffer->unsafe_to_concat (); + c->setup_buffer_glyph_set (); + typedef typename T::SubTable SubTable; bool ret = false; @@ -996,12 +1009,25 @@ { bool reverse; + auto &subtable_accel = accel_data.subtable_accels[i]; + if (!T::Types::extended && (st->u.header.coverage & st->u.header.Variation)) goto skip; if (HB_DIRECTION_IS_HORIZONTAL (c->buffer->props.direction) != st->u.header.is_horizontal ()) goto skip; + c->left_set = &subtable_accel.left_set; + c->right_set = &subtable_accel.right_set; + c->machine_glyph_set = &subtable_accel.left_set; + c->machine_class_cache = &subtable_accel.class_cache; + + if (!c->buffer_intersects_machine ()) + { + (void) c->buffer->message (c->font, "skipped subtable %u because no glyph matches", c->lookup_index); + goto skip; + } + reverse = bool (st->u.header.coverage & st->u.header.Backwards) != HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction); @@ -1028,9 +1054,6 @@ if (reverse) c->buffer->reverse (); - c->left_set = &accel_data[i].first; - c->right_set = &accel_data[i].second; - { /* See comment in sanitize() for conditional here. */ hb_sanitize_with_object_t with (&c->sanitizer, i < count - 1 ? st : (const SubTable *) nullptr); @@ -1106,9 +1129,13 @@ unsigned int count = thiz()->tableCount; for (unsigned int i = 0; i < count; i++) { - hb_bit_set_t left_set, right_set; - st->collect_glyphs (left_set, right_set, num_glyphs); - accel_data.push (hb_pair (left_set, right_set)); + auto &subtable_accel = *accel_data.subtable_accels.push (); + if (unlikely (accel_data.subtable_accels.in_error ())) + return accel_data; + + st->collect_glyphs (subtable_accel.left_set, subtable_accel.right_set, num_glyphs); + subtable_accel.class_cache.clear (); + st = &StructAfter (*st); } @@ -1137,6 +1164,7 @@ hb_blob_ptr_t table; kern_accelerator_data_t accel_data; + hb_aat_scratch_t scratch; }; }; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh 2025-10-13 07:49:24.000000000 +0000 @@ -30,8 +30,6 @@ #include "hb-open-type.hh" #include "hb-aat-layout-common.hh" #include "hb-ot-layout.hh" -#include "hb-ot-layout-common.hh" -#include "hb-ot-layout-gdef-table.hh" #include "hb-aat-map.hh" /* @@ -178,12 +176,6 @@ StateTableDriver driver (machine, c->face); - if (!c->buffer_intersects_machine ()) - { - (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches"); - return_trace (false); - } - driver.drive (&dc, c); return_trace (dc.ret); @@ -242,9 +234,7 @@ ret (false), c (c_), table (table_), - gdef (*c->gdef_table), mark_set (false), - has_glyph_classes (gdef.has_glyph_classes ()), mark (0), subs (table+table->substitutionTables) {} @@ -281,12 +271,7 @@ if (replacement) { buffer->unsafe_to_break (mark, hb_min (buffer->idx + 1, buffer->len)); - hb_codepoint_t glyph = *replacement; - buffer->info[mark].codepoint = glyph; - c->buffer_glyph_set.add (glyph); - if (has_glyph_classes) - _hb_glyph_info_set_glyph_props (&buffer->info[mark], - gdef.get_glyph_props (*replacement)); + c->replace_glyph_inplace (mark, *replacement); ret = true; } @@ -312,12 +297,7 @@ } if (replacement) { - hb_codepoint_t glyph = *replacement; - buffer->info[idx].codepoint = glyph; - c->buffer_glyph_set.add (glyph); - if (has_glyph_classes) - _hb_glyph_info_set_glyph_props (&buffer->info[idx], - gdef.get_glyph_props (*replacement)); + c->replace_glyph_inplace (idx, *replacement); ret = true; } @@ -333,9 +313,7 @@ hb_aat_apply_context_t *c; const ContextualSubtable *table; private: - const OT::GDEF &gdef; bool mark_set; - bool has_glyph_classes; unsigned int mark; const UnsizedListOfOffset16To, HBUINT, void, false> &subs; }; @@ -348,12 +326,6 @@ StateTableDriver driver (machine, c->face); - if (!c->buffer_intersects_machine ()) - { - (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches"); - return_trace (false); - } - driver.drive (&dc, c); return_trace (dc.ret); @@ -581,7 +553,7 @@ hb_codepoint_t lig = ligatureData; DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig); - if (unlikely (!buffer->replace_glyph (lig))) return; + if (unlikely (!c->replace_glyph (lig))) return; unsigned int lig_end = match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] + 1u; /* Now go and delete all subsequent components. */ @@ -589,8 +561,7 @@ { DEBUG_MSG (APPLY, nullptr, "Skipping ligature component"); if (unlikely (!buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]))) return; - _hb_glyph_info_set_default_ignorable (&buffer->cur()); - if (unlikely (!buffer->replace_glyph (DELETED_GLYPH))) return; + if (!c->delete_glyph ()) return; } if (unlikely (!buffer->move_to (lig_end))) return; @@ -624,12 +595,6 @@ StateTableDriver driver (machine, c->face); - if (!c->buffer_intersects_machine ()) - { - (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches"); - return_trace (false); - } - driver.drive (&dc, c); return_trace (dc.ret); @@ -665,15 +630,6 @@ { TRACE_APPLY (this); - if (!c->buffer_intersects_machine ()) - { - (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches"); - return_trace (false); - } - - const OT::GDEF &gdef (*c->gdef_table); - bool has_glyph_classes = gdef.has_glyph_classes (); - bool ret = false; unsigned int num_glyphs = c->face->get_num_glyphs (); @@ -703,12 +659,7 @@ const HBGlyphID16 *replacement = substitute.get_value (info[i].codepoint, num_glyphs); if (replacement) { - hb_codepoint_t glyph = *replacement; - info[i].codepoint = glyph; - c->buffer_glyph_set.add (glyph); - if (has_glyph_classes) - _hb_glyph_info_set_glyph_props (&info[i], - gdef.get_glyph_props (*replacement)); + c->replace_glyph_inplace (i, *replacement); ret = true; } } @@ -850,9 +801,7 @@ if (buffer->idx < buffer->len && !before) if (unlikely (!buffer->copy_glyph ())) return; /* TODO We ignore KashidaLike setting. */ - if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return; - for (unsigned int i = 0; i < count; i++) - c->buffer_glyph_set.add (glyphs[i]); + if (unlikely (!c->output_glyphs (count, glyphs))) return; ret = true; if (buffer->idx < buffer->len && !before) buffer->skip_glyph (); @@ -881,7 +830,8 @@ if (buffer->idx < buffer->len && !before) if (unlikely (!buffer->copy_glyph ())) return; /* TODO We ignore KashidaLike setting. */ - if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return; + if (unlikely (!c->output_glyphs (count, glyphs))) return; + ret = true; if (buffer->idx < buffer->len && !before) buffer->skip_glyph (); @@ -921,12 +871,6 @@ StateTableDriver driver (machine, c->face); - if (!c->buffer_intersects_machine ()) - { - (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches"); - return_trace (false); - } - driver.drive (&dc, c); return_trace (dc.ret); @@ -1224,6 +1168,7 @@ if (hb_none (hb_iter (c->range_flags) | hb_map ([subtable_flags] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable_flags & (_.flags); }))) goto skip; + c->subtable_flags = subtable_flags; c->machine_glyph_set = accel ? &accel->subtables[i].glyph_set : &Null(hb_bit_set_t); c->machine_class_cache = accel ? &accel->subtables[i].class_cache : nullptr; @@ -1233,6 +1178,12 @@ bool (coverage & ChainSubtable::Vertical)) goto skip; + if (!c->buffer_intersects_machine ()) + { + (void) c->buffer->message (c->font, "skipped chainsubtable %u because no glyph matches", c->lookup_index); + goto skip; + } + /* Buffer contents is always in logical direction. Determine if * we need to reverse before applying this subtable. We reverse * back after if we did reverse indeed. @@ -1376,7 +1327,7 @@ this->chain_count = table->get_chain_count (); - this->accels = (hb_atomic_ptr_t *) hb_calloc (this->chain_count, sizeof (*accels)); + this->accels = (hb_atomic_t *) hb_calloc (this->chain_count, sizeof (*accels)); if (unlikely (!this->accels)) { this->chain_count = 0; @@ -1423,7 +1374,8 @@ hb_blob_ptr_t table; unsigned int chain_count; - hb_atomic_ptr_t *accels; + hb_atomic_t *accels; + hb_aat_scratch_t scratch; }; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh 2025-10-13 07:49:24.000000000 +0000 @@ -31,6 +31,7 @@ #include "hb-aat-layout-common.hh" #include "hb-ot-layout.hh" #include "hb-open-type.hh" +#include "hb-ot-stat-table.hh" /* * trak -- Tracking @@ -115,7 +116,7 @@ protected: F16DOT16 track; /* Track value for this record. */ - NameID trackNameID; /* The 'name' table index for this track. + OT::NameID trackNameID; /* The 'name' table index for this track. * (a short word or phrase like "loose" * or "very tight") */ NNOffset16To> @@ -142,9 +143,9 @@ unsigned j = count - 1; // Find the two entries that track is between. - while (i + 1 < count && trackTable[i + 1].get_track_value () < track) + while (i + 1 < count && trackTable[i + 1].get_track_value () <= track) i++; - while (j > 0 && trackTable[j - 1].get_track_value () > track) + while (j > 0 && trackTable[j - 1].get_track_value () >= track) j--; // Exact match. @@ -200,6 +201,46 @@ float ptem = font->ptem > 0.f ? font->ptem : HB_CORETEXT_DEFAULT_FONT_SIZE; return font->em_scalef_y ((this+vertData).get_tracking (this, ptem, track)); } + hb_position_t get_tracking (hb_font_t *font, hb_direction_t dir, float track = 0.f) const + { +#ifndef HB_NO_STYLE + if (!font->face->table.STAT->has_data ()) + return 0; + return HB_DIRECTION_IS_HORIZONTAL (dir) ? + get_h_tracking (font, track) : + get_v_tracking (font, track); +#else + return 0; +#endif + } + + bool apply (hb_aat_apply_context_t *c, float track = 0.f) const + { + TRACE_APPLY (this); + + float ptem = c->font->ptem; + if (unlikely (ptem <= 0.f)) + { + /* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */ + ptem = HB_CORETEXT_DEFAULT_FONT_SIZE; + } + + hb_buffer_t *buffer = c->buffer; + if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) + { + hb_position_t advance_to_add = get_h_tracking (c->font, track); + foreach_grapheme (buffer, start, end) + buffer->pos[start].x_advance += advance_to_add; + } + else + { + hb_position_t advance_to_add = get_v_tracking (c->font, track); + foreach_grapheme (buffer, start, end) + buffer->pos[start].y_advance += advance_to_add; + } + + return_trace (true); + } bool sanitize (hb_sanitize_context_t *c) const { diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc 2025-10-13 07:49:24.000000000 +0000 @@ -34,7 +34,7 @@ #include "hb-aat-layout-just-table.hh" // Just so we compile it; unused otherwise. #include "hb-aat-layout-kerx-table.hh" #include "hb-aat-layout-morx-table.hh" -#include "hb-aat-layout-trak-table.hh" // Just so we compile it; unused otherwise. +#include "hb-aat-layout-trak-table.hh" #include "hb-aat-ltag-table.hh" #include "hb-ot-layout-gsub-table.hh" @@ -58,13 +58,14 @@ buffer (buffer_), sanitizer (), ankr_table (&Null (AAT::ankr)), - gdef_table ( + gdef ( #ifndef HB_NO_OT_LAYOUT - face->table.GDEF->table + *face->table.GDEF->table #else - &Null (GDEF) + Null (GDEF) #endif ), + has_glyph_classes (gdef.has_glyph_classes ()), lookup_index (0) { sanitizer.init (blob); @@ -203,7 +204,7 @@ #endif -#ifndef HB_NO_AAT +#ifndef HB_NO_AAT_SHAPE /* * mort/morx/kerx/trak @@ -287,11 +288,14 @@ const hb_feature_t *features, unsigned num_features) { - hb_aat_map_builder_t builder (font->face, plan->props); - for (unsigned i = 0; i < num_features; i++) - builder.add_feature (features[i]); hb_aat_map_t map; - builder.compile (map); + if (num_features) + { + hb_aat_map_builder_t builder (font->face, plan->props); + for (unsigned i = 0; i < num_features; i++) + builder.add_feature (features[i]); + builder.compile (map); + } { auto &accel = *font->face->table.morx; @@ -300,7 +304,10 @@ { AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ()); if (!buffer->message (font, "start table morx")) return; - morx.apply (&c, map, accel); + c.buffer_glyph_set = accel.scratch.create_buffer_glyph_set (); + morx.apply (&c, num_features ? map : plan->aat_map, accel); + accel.scratch.destroy_buffer_glyph_set (c.buffer_glyph_set); + c.buffer_glyph_set = nullptr; (void) buffer->message (font, "end table morx"); return; } @@ -313,34 +320,24 @@ { AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ()); if (!buffer->message (font, "start table mort")) return; - mort.apply (&c, map, accel); + mort.apply (&c, num_features ? map : plan->aat_map, accel); (void) buffer->message (font, "end table mort"); return; } } } -void -hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer) -{ - unsigned int count = buffer->len; - hb_glyph_info_t *info = buffer->info; - hb_glyph_position_t *pos = buffer->pos; - for (unsigned int i = 0; i < count; i++) - if (unlikely (info[i].codepoint == AAT::DELETED_GLYPH)) - pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0; -} - static bool is_deleted_glyph (const hb_glyph_info_t *info) { - return info->codepoint == AAT::DELETED_GLYPH; + return _hb_glyph_info_is_aat_deleted (info); } void hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer) { - buffer->delete_glyphs_inplace (is_deleted_glyph); + if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED) + buffer->delete_glyphs_inplace (is_deleted_glyph); } /** @@ -371,8 +368,11 @@ AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ()); if (!buffer->message (font, "start table kerx")) return; + c.buffer_glyph_set = accel.scratch.create_buffer_glyph_set (); c.set_ankr_table (font->face->table.ankr.get ()); accel.apply (&c); + accel.scratch.destroy_buffer_glyph_set (c.buffer_glyph_set); + c.buffer_glyph_set = nullptr; (void) buffer->message (font, "end table kerx"); } @@ -394,6 +394,17 @@ return face->table.trak->has_data (); } +void +hb_aat_layout_track (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) +{ + const AAT::trak& trak = *font->face->table.trak; + + AAT::hb_aat_apply_context_t c (plan, font, buffer); + trak.apply (&c); +} + /** * hb_aat_layout_get_feature_types: * @face: #hb_face_t to work upon diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.hh 2025-10-13 07:49:24.000000000 +0000 @@ -61,9 +61,6 @@ unsigned num_features); HB_INTERNAL void -hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer); - -HB_INTERNAL void hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer); HB_INTERNAL void @@ -71,5 +68,10 @@ hb_font_t *font, hb_buffer_t *buffer); +HB_INTERNAL void +hb_aat_layout_track (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); + #endif /* HB_AAT_LAYOUT_HH */ diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-aat-map.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-aat-map.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-aat-map.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-aat-map.cc 2025-10-13 07:49:24.000000000 +0000 @@ -85,6 +85,11 @@ hb_aat_map_builder_t::compile (hb_aat_map_t &m) { /* Compute active features per range, and compile each. */ + if (!features.length) + { + hb_aat_layout_compile_map (this, &m); + return; + } /* Sort features by start/end events. */ hb_vector_t feature_events; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh 2025-10-13 07:49:24.000000000 +0000 @@ -80,15 +80,14 @@ #include -#define _hb_memory_barrier() std::atomic_thread_fence(std::memory_order_ack_rel) #define _hb_memory_r_barrier() std::atomic_thread_fence(std::memory_order_acquire) #define _hb_memory_w_barrier() std::atomic_thread_fence(std::memory_order_release) -#define hb_atomic_int_impl_add(AI, V) (reinterpret_cast::type> *> (AI)->fetch_add ((V), std::memory_order_acq_rel)) -#define hb_atomic_int_impl_set_relaxed(AI, V) (reinterpret_cast::type> *> (AI)->store ((V), std::memory_order_relaxed)) -#define hb_atomic_int_impl_set(AI, V) (reinterpret_cast::type> *> (AI)->store ((V), std::memory_order_release)) -#define hb_atomic_int_impl_get_relaxed(AI) (reinterpret_cast::type> const *> (AI)->load (std::memory_order_relaxed)) -#define hb_atomic_int_impl_get(AI) (reinterpret_cast::type> const *> (AI)->load (std::memory_order_acquire)) +#define hb_atomic_int_impl_add(AI, V) (reinterpret_cast::type> *> (AI)->fetch_add ((V), std::memory_order_acq_rel)) +#define hb_atomic_int_impl_set_relaxed(AI, V) (reinterpret_cast::type> *> (AI)->store ((V), std::memory_order_relaxed)) +#define hb_atomic_int_impl_set(AI, V) (reinterpret_cast::type> *> (AI)->store ((V), std::memory_order_release)) +#define hb_atomic_int_impl_get_relaxed(AI) (reinterpret_cast::type> const *> (AI)->load (std::memory_order_relaxed)) +#define hb_atomic_int_impl_get(AI) (reinterpret_cast::type> const *> (AI)->load (std::memory_order_acquire)) #define hb_atomic_ptr_impl_set_relaxed(P, V) (reinterpret_cast *> (P)->store ((V), std::memory_order_relaxed)) #define hb_atomic_ptr_impl_get_relaxed(P) (reinterpret_cast const *> (P)->load (std::memory_order_relaxed)) @@ -149,68 +148,53 @@ #define hb_atomic_ptr_impl_get_relaxed(P) (*(P)) #endif #ifndef hb_atomic_int_impl_set -inline void hb_atomic_int_impl_set (int *AI, int v) { _hb_memory_w_barrier (); *AI = v; } -inline void hb_atomic_int_impl_set (short *AI, short v) { _hb_memory_w_barrier (); *AI = v; } +template +inline void hb_atomic_int_impl_set (T *AI, T v) { _hb_memory_w_barrier (); *AI = v; } #endif #ifndef hb_atomic_int_impl_get -inline int hb_atomic_int_impl_get (const int *AI) { int v = *AI; _hb_memory_r_barrier (); return v; } -inline short hb_atomic_int_impl_get (const short *AI) { short v = *AI; _hb_memory_r_barrier (); return v; } +template +inline T hb_atomic_int_impl_get (const T *AI) { T v = *AI; _hb_memory_r_barrier (); return v; } #endif #ifndef hb_atomic_ptr_impl_get inline void *hb_atomic_ptr_impl_get (void ** const P) { void *v = *P; _hb_memory_r_barrier (); return v; } #endif -struct hb_atomic_short_t +template +struct hb_atomic_t { - hb_atomic_short_t () = default; - constexpr hb_atomic_short_t (short v) : v (v) {} + hb_atomic_t () = default; + constexpr hb_atomic_t (T v) : v (v) {} - hb_atomic_short_t& operator = (short v_) { set_relaxed (v_); return *this; } - operator short () const { return get_relaxed (); } + hb_atomic_t& operator = (T v_) { set_relaxed (v_); return *this; } + operator T () const { return get_relaxed (); } - void set_relaxed (short v_) { hb_atomic_int_impl_set_relaxed (&v, v_); } - void set_release (short v_) { hb_atomic_int_impl_set (&v, v_); } - short get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); } - short get_acquire () const { return hb_atomic_int_impl_get (&v); } - short inc () { return hb_atomic_int_impl_add (&v, 1); } - short dec () { return hb_atomic_int_impl_add (&v, -1); } + void set_relaxed (T v_) { hb_atomic_int_impl_set_relaxed (&v, v_); } + void set_release (T v_) { hb_atomic_int_impl_set (&v, v_); } + T get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); } + T get_acquire () const { return hb_atomic_int_impl_get (&v); } + T inc () { return hb_atomic_int_impl_add (&v, 1); } + T dec () { return hb_atomic_int_impl_add (&v, -1); } + + int operator ++ (int) { return inc (); } + int operator -- (int) { return dec (); } + long operator |= (long v_) { set_relaxed (get_relaxed () | v_); return *this; } - short v = 0; + T v = 0; }; -struct hb_atomic_int_t +template +struct hb_atomic_t { - hb_atomic_int_t () = default; - constexpr hb_atomic_int_t (int v) : v (v) {} - - hb_atomic_int_t& operator = (int v_) { set_relaxed (v_); return *this; } - operator int () const { return get_relaxed (); } - - void set_relaxed (int v_) { hb_atomic_int_impl_set_relaxed (&v, v_); } - void set_release (int v_) { hb_atomic_int_impl_set (&v, v_); } - int get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); } - int get_acquire () const { return hb_atomic_int_impl_get (&v); } - int inc () { return hb_atomic_int_impl_add (&v, 1); } - int dec () { return hb_atomic_int_impl_add (&v, -1); } - - int v = 0; -}; - -template -struct hb_atomic_ptr_t -{ - typedef hb_remove_pointer

T; - - hb_atomic_ptr_t () = default; - constexpr hb_atomic_ptr_t (T* v) : v (v) {} - hb_atomic_ptr_t (const hb_atomic_ptr_t &other) = delete; + hb_atomic_t () = default; + constexpr hb_atomic_t (T* v) : v (v) {} + hb_atomic_t (const hb_atomic_t &other) = delete; void init (T* v_ = nullptr) { set_relaxed (v_); } void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); } T *get_relaxed () const { return (T *) hb_atomic_ptr_impl_get_relaxed (&v); } T *get_acquire () const { return (T *) hb_atomic_ptr_impl_get ((void **) &v); } - bool cmpexch (const T *old, T *new_) const { return hb_atomic_ptr_impl_cmpexch ((void **) &v, (void *) old, (void *) new_); } + bool cmpexch (const T *old, T *new_) { return hb_atomic_ptr_impl_cmpexch ((void **) &v, (void *) old, (void *) new_); } operator bool () const { return get_acquire () != nullptr; } T * operator -> () const { return get_acquire (); } diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh 2025-10-13 07:49:24.000000000 +0000 @@ -77,7 +77,7 @@ bool successful = true; /* Allocations successful */ mutable unsigned int population = 0; - mutable hb_atomic_int_t last_page_lookup = 0; + mutable hb_atomic_t last_page_lookup = 0; hb_sorted_vector_t page_map; hb_vector_t pages; @@ -88,7 +88,7 @@ { if (unlikely (!successful)) return false; - if (pages.length < count && count <= 2) + if (pages.length < count && (unsigned) pages.allocated < count && count <= 2) exact_size = true; // Most sets are small and local if (unlikely (!pages.resize (count, clear, exact_size) || diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-bit-vector.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-bit-vector.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-bit-vector.hh 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-bit-vector.hh 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,195 @@ +/* + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Author(s): Behdad Esfahbod + */ + +#ifndef HB_BIT_VECTOR_HH +#define HB_BIT_VECTOR_HH + +#include "hb.hh" + +#include "hb-atomic.hh" + +struct hb_min_max_t +{ + void add (hb_codepoint_t v) { min_v = hb_min (min_v, v); max_v = hb_max (max_v, v); } + void add_range (hb_codepoint_t a, hb_codepoint_t b) + { + min_v = hb_min (min_v, a); + max_v = hb_max (max_v, b); + } + + template + void union_ (const set_t &set) + { + hb_codepoint_t set_min = set.get_min (); + if (unlikely (set_min == HB_CODEPOINT_INVALID)) + return; + hb_codepoint_t set_max = set.get_max (); + min_v = hb_min (min_v, set_min); + max_v = hb_max (max_v, set_max); + } + + hb_codepoint_t get_min () const { return min_v; } + hb_codepoint_t get_max () const { return max_v; } + + private: + hb_codepoint_t min_v = HB_CODEPOINT_INVALID; + hb_codepoint_t max_v = 0; +}; + +template +struct hb_bit_vector_t +{ + using int_t = uint64_t; + using elt_t = typename std::conditional, int_t>::type; + + hb_bit_vector_t () = delete; + hb_bit_vector_t (const hb_bit_vector_t &other) = delete; + hb_bit_vector_t &operator= (const hb_bit_vector_t &other) = delete; + + // Move + hb_bit_vector_t (hb_bit_vector_t &&other) + : min_v (other.min_v), max_v (other.max_v), count (other.count), elts (other.elts) + { + other.min_v = other.max_v = other.count = 0; + other.elts = nullptr; + } + hb_bit_vector_t &operator= (hb_bit_vector_t &&other) + { + hb_swap (min_v, other.min_v); + hb_swap (max_v, other.max_v); + hb_swap (count, other.count); + hb_swap (elts, other.elts); + return *this; + } + + hb_bit_vector_t (unsigned min_v, unsigned max_v) + : min_v (min_v), max_v (max_v) + { + if (unlikely (min_v >= max_v)) + { + min_v = max_v = count = 0; + return; + } + + unsigned num = (max_v - min_v + sizeof (int_t) * 8) / (sizeof (int_t) * 8); + elts = (elt_t *) hb_calloc (num, sizeof (int_t)); + if (unlikely (!elts)) + { + min_v = max_v = count = 0; + return; + } + + count = max_v - min_v + 1; + } + ~hb_bit_vector_t () + { + hb_free (elts); + } + + void add (hb_codepoint_t g) { elt (g) |= mask (g); } + void del (hb_codepoint_t g) { elt (g) &= ~mask (g); } + void set (hb_codepoint_t g, bool value) { if (value) add (g); else del (g); } + bool get (hb_codepoint_t g) const { return elt (g) & mask (g); } + bool has (hb_codepoint_t g) const { return get (g); } + bool may_have (hb_codepoint_t g) const { return get (g); } + + bool operator [] (hb_codepoint_t g) const { return get (g); } + bool operator () (hb_codepoint_t g) const { return get (g); } + + void add_range (hb_codepoint_t a, hb_codepoint_t b) + { + if (unlikely (!count || a > b || a < min_v || b > max_v)) + return; + + elt_t *la = &elt (a); + elt_t *lb = &elt (b); + if (la == lb) + *la |= (mask (b) << 1) - mask(a); + else + { + *la |= ~(mask (a) - 1llu); + la++; + + hb_memset (la, 0xff, (char *) lb - (char *) la); + + *lb |= ((mask (b) << 1) - 1llu); + } + } + void del_range (hb_codepoint_t a, hb_codepoint_t b) + { + if (unlikely (!count || a > b || a < min_v || b > max_v)) + return; + + elt_t *la = &elt (a); + elt_t *lb = &elt (b); + if (la == lb) + *la &= ~((mask (b) << 1llu) - mask(a)); + else + { + *la &= mask (a) - 1; + la++; + + hb_memset (la, 0, (char *) lb - (char *) la); + + *lb &= ~((mask (b) << 1) - 1llu); + } + } + void set_range (hb_codepoint_t a, hb_codepoint_t b, bool v) + { if (v) add_range (a, b); else del_range (a, b); } + + template + void union_ (const set_t &set) + { + for (hb_codepoint_t g : set) + add (g); + } + + static const unsigned int ELT_BITS = sizeof (elt_t) * 8; + static constexpr unsigned ELT_MASK = ELT_BITS - 1; + + static constexpr elt_t zero = 0; + + elt_t &elt (hb_codepoint_t g) + { + g -= min_v; + if (unlikely (g >= count)) + return Crap(elt_t); + return elts[g / ELT_BITS]; + } + const elt_t& elt (hb_codepoint_t g) const + { + g -= min_v; + if (unlikely (g >= count)) + return Null(elt_t); + return elts[g / ELT_BITS]; + } + + static constexpr int_t mask (hb_codepoint_t g) { return elt_t (1) << (g & ELT_MASK); } + + hb_codepoint_t min_v = 0, max_v = 0, count = 0; + elt_t *elts = nullptr; +}; + + +#endif /* HB_BIT_VECTOR_HH */ diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh 2025-10-13 07:49:24.000000000 +0000 @@ -32,62 +32,68 @@ #include "hb.hh" -#line 36 "hb-buffer-deserialize-json.hh" +#line 33 "hb-buffer-deserialize-json.hh" static const unsigned char _deserialize_json_trans_keys[] = { - 0u, 0u, 9u, 123u, 9u, 123u, 9u, 34u, 97u, 117u, 120u, 121u, 34u, 34u, 9u, 58u, - 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, - 48u, 57u, 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, - 9u, 125u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, - 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, - 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 34u, 92u, - 9u, 125u, 34u, 92u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, - 9u, 93u, 9u, 123u, 0u, 0u, 0 + 0u, 0u, 9u, 34u, 97u, 121u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, + 9u, 125u, 9u, 125u, 9u, 93u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, + 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u, + 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, + 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, + 9u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 34u, 92u, 9u, 125u, + 34u, 92u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, + 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 98u, 98u, 9u, 123u, 9u, 123u, 9u, 123u, + 0 }; static const char _deserialize_json_key_spans[] = { - 0, 115, 115, 26, 21, 2, 1, 50, - 49, 10, 117, 117, 117, 1, 50, 49, - 10, 117, 117, 1, 1, 50, 49, 117, - 117, 2, 1, 50, 49, 10, 117, 117, - 1, 50, 49, 10, 117, 117, 1, 1, - 50, 49, 117, 117, 1, 50, 49, 59, - 117, 59, 117, 117, 1, 50, 49, 117, - 85, 115, 0 + 0, 26, 25, 2, 1, 50, 49, 10, + 117, 117, 85, 117, 1, 50, 49, 10, + 117, 117, 1, 1, 50, 49, 117, 117, + 2, 1, 50, 49, 10, 117, 117, 1, + 50, 49, 10, 117, 117, 1, 1, 50, + 49, 117, 117, 1, 50, 49, 59, 117, + 59, 117, 117, 1, 50, 49, 10, 117, + 1, 50, 49, 117, 1, 115, 115, 115 }; static const short _deserialize_json_index_offsets[] = { - 0, 0, 116, 232, 259, 281, 284, 286, - 337, 387, 398, 516, 634, 752, 754, 805, - 855, 866, 984, 1102, 1104, 1106, 1157, 1207, - 1325, 1443, 1446, 1448, 1499, 1549, 1560, 1678, - 1796, 1798, 1849, 1899, 1910, 2028, 2146, 2148, - 2150, 2201, 2251, 2369, 2487, 2489, 2540, 2590, - 2650, 2768, 2828, 2946, 3064, 3066, 3117, 3167, - 3285, 3371, 3487 + 0, 0, 27, 53, 56, 58, 109, 159, + 170, 288, 406, 492, 610, 612, 663, 713, + 724, 842, 960, 962, 964, 1015, 1065, 1183, + 1301, 1304, 1306, 1357, 1407, 1418, 1536, 1654, + 1656, 1707, 1757, 1768, 1886, 2004, 2006, 2008, + 2059, 2109, 2227, 2345, 2347, 2398, 2448, 2508, + 2626, 2686, 2804, 2922, 2924, 2975, 3025, 3036, + 3154, 3156, 3207, 3257, 3375, 3377, 3493, 3609 }; static const char _deserialize_json_indicies[] = { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 2, 1, 3, 1, 4, 5, + 1, 6, 7, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 9, 1, 8, 10, 10, 1, 11, 12, + 1, 13, 1, 13, 13, 13, 13, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 14, 1, 14, 14, + 14, 14, 14, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 2, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 3, 1, 2, 2, 2, - 2, 2, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 14, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 15, 1, 1, 16, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 1, + 18, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 1, 20, 20, 20, 20, 20, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 20, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 21, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -95,48 +101,41 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 3, - 1, 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 4, 1, 5, 1, 6, 1, 7, 8, - 1, 9, 10, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 22, + 1, 23, 23, 23, 23, 23, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 11, 1, 12, 13, 1, 14, 1, 14, - 14, 14, 14, 14, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 14, 1, + 23, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 15, 1, 15, 15, 15, 15, 15, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 15, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 16, 1, - 1, 17, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 1, 19, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 1, 21, - 21, 21, 21, 21, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 21, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 22, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 24, 1, 24, + 24, 24, 24, 24, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 24, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 25, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 23, 1, 24, 24, 24, - 24, 24, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 25, 1, 20, 20, 20, + 20, 20, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 24, 1, 1, 1, + 1, 1, 1, 1, 20, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 4, 1, 1, 1, 1, 1, 1, 1, + 21, 1, 1, 1, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -145,43 +144,42 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 22, 1, 26, 1, 26, 26, 26, + 26, 26, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 25, 1, 21, 21, 21, 21, 21, + 1, 1, 1, 1, 26, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 21, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 22, 1, - 1, 1, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 27, 1, + 27, 27, 27, 27, 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 27, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 28, 1, 1, 29, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 1, 31, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 1, 33, 33, 33, + 33, 33, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 33, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 34, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 23, - 1, 26, 1, 26, 26, 26, 26, 26, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 26, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 27, 1, 27, 27, - 27, 27, 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 28, 1, 1, 29, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 1, - 31, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 1, 33, 33, 33, 33, 33, + 1, 35, 1, 33, 33, 33, 33, 33, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 33, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 34, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -190,39 +188,41 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 35, - 1, 33, 33, 33, 33, 33, 1, 1, + 1, 36, 1, 37, 1, 37, 37, 37, + 37, 37, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 37, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 33, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 34, 1, 1, 1, - 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 38, 1, + 38, 38, 38, 38, 38, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 38, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 39, + 40, 40, 40, 40, 40, 40, 40, 40, + 40, 1, 41, 41, 41, 41, 41, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 41, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 42, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 35, 1, 36, - 1, 37, 1, 37, 37, 37, 37, 37, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 37, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 38, 1, 38, 38, - 38, 38, 38, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 38, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 39, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 1, + 1, 1, 1, 1, 1, 1, 43, 1, 41, 41, 41, 41, 41, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 41, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 42, 1, 1, 1, 1, + 1, 1, 1, 42, 1, 1, 1, 44, + 44, 44, 44, 44, 44, 44, 44, 44, + 44, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -230,43 +230,43 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 43, 1, 45, 46, + 1, 47, 1, 47, 47, 47, 47, 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 43, 1, 41, 41, - 41, 41, 41, 1, 1, 1, 1, 1, + 1, 1, 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 41, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 42, 1, 1, 1, 44, 44, 44, - 44, 44, 44, 44, 44, 44, 44, 1, + 1, 1, 1, 1, 48, 1, 48, 48, + 48, 48, 48, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 48, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 49, 1, 1, 50, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 1, + 52, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 1, 54, 54, 54, 54, 54, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 54, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 55, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 43, 1, 45, 46, 1, 47, - 1, 47, 47, 47, 47, 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 48, 1, 48, 48, 48, 48, - 48, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 48, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 49, 1, 1, 50, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 1, 52, 53, - 53, 53, 53, 53, 53, 53, 53, 53, + 1, 1, 1, 1, 1, 1, 1, 56, 1, 54, 54, 54, 54, 54, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 54, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 55, 1, 1, 1, + 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -274,44 +274,42 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 56, 1, 57, + 1, 57, 57, 57, 57, 57, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 56, 1, 54, - 54, 54, 54, 54, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 54, 1, + 57, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 55, 1, 1, 1, 53, 53, - 53, 53, 53, 53, 53, 53, 53, 53, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 58, 1, 58, 58, 58, 58, + 58, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 58, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 59, 1, 1, 60, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 1, 62, 63, + 63, 63, 63, 63, 63, 63, 63, 63, + 1, 64, 64, 64, 64, 64, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 64, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 65, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 56, 1, 57, 1, 57, - 57, 57, 57, 57, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 57, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 58, 1, 58, 58, 58, 58, 58, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 58, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 59, 1, - 1, 60, 61, 61, 61, 61, 61, 61, - 61, 61, 61, 1, 62, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 1, 64, + 1, 1, 1, 1, 1, 66, 1, 64, 64, 64, 64, 64, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 64, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 65, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 65, 1, 1, 1, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -320,39 +318,41 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 66, 1, 64, 64, 64, - 64, 64, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 66, 1, 67, 1, 68, + 1, 68, 68, 68, 68, 68, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 64, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 65, 1, 1, 1, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 1, 1, + 68, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 69, 1, 69, 69, 69, 69, + 69, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 69, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 70, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 1, 72, 72, + 72, 72, 72, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 72, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 73, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 66, 1, 67, 1, 68, 1, 68, - 68, 68, 68, 68, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 68, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 69, 1, 69, 69, 69, 69, 69, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 69, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 70, 71, 71, 71, 71, 71, 71, - 71, 71, 71, 1, 72, 72, 72, 72, + 1, 1, 74, 1, 72, 72, 72, 72, 72, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 72, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 73, + 1, 1, 1, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -361,71 +361,70 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 74, 1, 76, 1, 76, 76, 76, 76, + 76, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 76, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 74, 1, 72, 72, 72, 72, 72, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 77, 1, 77, + 77, 77, 77, 77, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 72, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 73, 1, 1, - 1, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 77, 1, + 78, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 79, 80, + 80, 80, 80, 80, 80, 80, 80, 80, + 1, 82, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 83, 81, 84, 84, 84, + 84, 84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 85, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 74, 1, - 76, 1, 76, 76, 76, 76, 76, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 76, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 77, 1, 77, 77, 77, - 77, 77, 1, 1, 1, 1, 1, 1, + 1, 86, 1, 81, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 77, 1, 78, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 79, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 1, 82, - 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81, - 81, 83, 81, 84, 84, 84, 84, 84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 84, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 85, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 81, 1, 87, + 87, 87, 87, 87, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 87, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 88, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 86, - 1, 81, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 81, 1, 87, 87, 87, + 1, 1, 1, 89, 1, 87, 87, 87, 87, 87, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 87, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 88, 1, 1, 1, 1, 1, 1, 1, + 88, 1, 1, 1, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -434,118 +433,151 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 89, 1, 91, 1, 91, 91, 91, + 91, 91, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 89, 1, 87, 87, 87, 87, 87, + 1, 1, 1, 1, 91, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 87, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 88, 1, - 1, 1, 90, 90, 90, 90, 90, 90, - 90, 90, 90, 90, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 92, 1, + 92, 92, 92, 92, 92, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 92, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 93, 1, 1, 94, + 95, 95, 95, 95, 95, 95, 95, 95, + 95, 1, 23, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 1, 23, 23, 23, + 23, 23, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 23, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 89, - 1, 91, 1, 91, 91, 91, 91, 91, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 91, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 92, 1, 92, 92, - 92, 92, 92, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 92, 1, 1, + 1, 24, 1, 97, 1, 97, 97, 97, + 97, 97, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 93, 94, 94, - 94, 94, 94, 94, 94, 94, 94, 1, - 87, 87, 87, 87, 87, 1, 1, 1, + 1, 1, 1, 1, 97, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 87, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 88, 1, 1, 1, 95, - 95, 95, 95, 95, 95, 95, 95, 95, - 95, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 98, 1, + 98, 98, 98, 98, 98, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 98, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 99, + 100, 100, 100, 100, 100, 100, 100, 100, + 100, 1, 87, 87, 87, 87, 87, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 87, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 88, 1, 1, + 1, 101, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 89, 1, + 8, 1, 102, 102, 102, 102, 102, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 102, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 103, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 89, 1, 96, 96, - 96, 96, 96, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 96, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 97, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 104, 1, 103, 103, + 103, 103, 103, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 103, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 98, 1, 2, 2, 2, 2, - 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 104, 1, 25, 25, 25, 25, 25, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 25, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 3, 1, - 1, 0 + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 104, 1, 0 }; static const char _deserialize_json_trans_targs[] = { - 1, 0, 2, 3, 3, 4, 5, 19, - 25, 38, 44, 52, 6, 13, 7, 8, - 9, 10, 12, 10, 12, 11, 3, 56, - 11, 56, 14, 15, 16, 17, 18, 17, - 18, 11, 3, 56, 20, 21, 22, 23, - 24, 11, 3, 56, 24, 26, 32, 27, - 28, 29, 30, 31, 30, 31, 11, 3, - 56, 33, 34, 35, 36, 37, 36, 37, - 11, 3, 56, 39, 40, 41, 42, 43, - 11, 3, 56, 43, 45, 46, 47, 50, - 51, 47, 48, 49, 11, 3, 56, 11, - 3, 56, 51, 53, 54, 50, 55, 55, - 56, 57, 58 + 1, 0, 2, 3, 18, 24, 37, 43, + 51, 56, 60, 4, 12, 5, 6, 7, + 8, 11, 8, 11, 9, 1, 10, 9, + 10, 63, 13, 14, 15, 16, 17, 16, + 17, 9, 1, 10, 19, 20, 21, 22, + 23, 9, 1, 10, 23, 25, 31, 26, + 27, 28, 29, 30, 29, 30, 9, 1, + 10, 32, 33, 34, 35, 36, 35, 36, + 9, 1, 10, 38, 39, 40, 41, 42, + 9, 1, 10, 42, 44, 45, 46, 49, + 50, 46, 47, 48, 9, 1, 10, 9, + 1, 10, 50, 52, 53, 54, 9, 55, + 55, 57, 58, 49, 59, 59, 61, 62, + 1 }; static const char _deserialize_json_trans_actions[] = { - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 2, 2, 0, 0, 3, 3, 4, - 0, 5, 0, 0, 2, 2, 2, 0, - 0, 6, 6, 7, 0, 0, 0, 2, - 2, 8, 8, 9, 0, 0, 0, 0, - 0, 2, 2, 2, 0, 0, 10, 10, - 11, 0, 0, 2, 2, 2, 0, 0, - 12, 12, 13, 0, 0, 0, 2, 2, - 14, 14, 15, 0, 0, 0, 2, 16, - 16, 0, 17, 0, 18, 18, 19, 20, - 20, 21, 17, 0, 0, 22, 22, 23, - 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 0, 0, 2, 2, 2, 0, + 0, 3, 0, 0, 1, 1, 1, 0, + 0, 4, 4, 4, 0, 0, 0, 1, + 1, 5, 5, 5, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 6, 6, + 6, 0, 0, 1, 1, 1, 0, 0, + 7, 7, 7, 0, 0, 0, 1, 1, + 8, 8, 8, 0, 0, 0, 1, 9, + 9, 0, 10, 0, 11, 11, 11, 12, + 12, 12, 10, 0, 0, 1, 1, 1, + 0, 0, 0, 13, 13, 14, 0, 0, + 15 }; -static const int deserialize_json_start = 1; -static const int deserialize_json_first_final = 56; +static const int deserialize_json_start = 61; +static const int deserialize_json_first_final = 61; static const int deserialize_json_error = 0; -static const int deserialize_json_en_main = 1; +static const int deserialize_json_en_main = 61; -#line 111 "hb-buffer-deserialize-json.rl" +#line 115 "hb-buffer-deserialize-json.rl" static hb_bool_t @@ -565,12 +597,12 @@ hb_glyph_info_t info = {0}; hb_glyph_position_t pos = {0}; -#line 569 "hb-buffer-deserialize-json.hh" +#line 594 "hb-buffer-deserialize-json.hh" { cs = deserialize_json_start; } -#line 574 "hb-buffer-deserialize-json.hh" +#line 597 "hb-buffer-deserialize-json.hh" { int _slen; int _trans; @@ -595,14 +627,14 @@ goto _again; switch ( _deserialize_json_trans_actions[_trans] ) { - case 1: + case 15: #line 38 "hb-buffer-deserialize-json.rl" { hb_memset (&info, 0, sizeof (info)); hb_memset (&pos , 0, sizeof (pos )); } break; - case 5: + case 3: #line 43 "hb-buffer-deserialize-json.rl" { buffer->add_info (info); @@ -612,21 +644,21 @@ *end_ptr = p; } break; - case 2: + case 1: #line 51 "hb-buffer-deserialize-json.rl" { tok = p; } break; - case 17: + case 10: #line 55 "hb-buffer-deserialize-json.rl" { if (unlikely (!buffer->ensure_glyphs ())) return false; } break; - case 23: + case 14: #line 56 "hb-buffer-deserialize-json.rl" { if (unlikely (!buffer->ensure_unicode ())) return false; } break; - case 18: + case 11: #line 58 "hb-buffer-deserialize-json.rl" { /* TODO Unescape \" and \\ if found. */ @@ -636,35 +668,35 @@ return false; } break; - case 20: + case 12: #line 66 "hb-buffer-deserialize-json.rl" { if (!parse_uint (tok, p, &info.codepoint)) return false; } break; - case 8: + case 5: #line 67 "hb-buffer-deserialize-json.rl" { if (!parse_uint (tok, p, &info.cluster )) return false; } break; - case 10: + case 6: #line 68 "hb-buffer-deserialize-json.rl" { if (!parse_int (tok, p, &pos.x_offset )) return false; } break; - case 12: + case 7: #line 69 "hb-buffer-deserialize-json.rl" { if (!parse_int (tok, p, &pos.y_offset )) return false; } break; - case 3: + case 2: #line 70 "hb-buffer-deserialize-json.rl" { if (!parse_int (tok, p, &pos.x_advance)) return false; } break; - case 6: + case 4: #line 71 "hb-buffer-deserialize-json.rl" { if (!parse_int (tok, p, &pos.y_advance)) return false; } break; - case 14: + case 8: #line 72 "hb-buffer-deserialize-json.rl" { if (!parse_uint (tok, p, &info.mask )) return false; } break; - case 16: + case 9: #line 51 "hb-buffer-deserialize-json.rl" { tok = p; @@ -672,7 +704,7 @@ #line 55 "hb-buffer-deserialize-json.rl" { if (unlikely (!buffer->ensure_glyphs ())) return false; } break; - case 22: + case 13: #line 51 "hb-buffer-deserialize-json.rl" { tok = p; @@ -680,109 +712,7 @@ #line 56 "hb-buffer-deserialize-json.rl" { if (unlikely (!buffer->ensure_unicode ())) return false; } break; - case 19: -#line 58 "hb-buffer-deserialize-json.rl" - { - /* TODO Unescape \" and \\ if found. */ - if (!hb_font_glyph_from_string (font, - tok+1, p - tok - 2, /* Skip "" */ - &info.codepoint)) - return false; -} -#line 43 "hb-buffer-deserialize-json.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 21: -#line 66 "hb-buffer-deserialize-json.rl" - { if (!parse_uint (tok, p, &info.codepoint)) return false; } -#line 43 "hb-buffer-deserialize-json.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 9: -#line 67 "hb-buffer-deserialize-json.rl" - { if (!parse_uint (tok, p, &info.cluster )) return false; } -#line 43 "hb-buffer-deserialize-json.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 11: -#line 68 "hb-buffer-deserialize-json.rl" - { if (!parse_int (tok, p, &pos.x_offset )) return false; } -#line 43 "hb-buffer-deserialize-json.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 13: -#line 69 "hb-buffer-deserialize-json.rl" - { if (!parse_int (tok, p, &pos.y_offset )) return false; } -#line 43 "hb-buffer-deserialize-json.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 4: -#line 70 "hb-buffer-deserialize-json.rl" - { if (!parse_int (tok, p, &pos.x_advance)) return false; } -#line 43 "hb-buffer-deserialize-json.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 7: -#line 71 "hb-buffer-deserialize-json.rl" - { if (!parse_int (tok, p, &pos.y_advance)) return false; } -#line 43 "hb-buffer-deserialize-json.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 15: -#line 72 "hb-buffer-deserialize-json.rl" - { if (!parse_uint (tok, p, &info.mask )) return false; } -#line 43 "hb-buffer-deserialize-json.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; -#line 786 "hb-buffer-deserialize-json.hh" +#line 689 "hb-buffer-deserialize-json.hh" } _again: @@ -794,12 +724,12 @@ _out: {} } -#line 132 "hb-buffer-deserialize-json.rl" +#line 136 "hb-buffer-deserialize-json.rl" *end_ptr = p; - return p == pe && *(p-1) != ']'; + return p == pe; } #endif /* HB_BUFFER_DESERIALIZE_JSON_HH */ diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-glyphs.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-glyphs.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-glyphs.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-glyphs.hh 2025-10-13 07:49:24.000000000 +0000 @@ -32,287 +32,344 @@ #include "hb.hh" -#line 36 "hb-buffer-deserialize-text-glyphs.hh" +#line 33 "hb-buffer-deserialize-text-glyphs.hh" static const unsigned char _deserialize_text_glyphs_trans_keys[] = { - 0u, 0u, 48u, 57u, 45u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 48u, 57u, 45u, 57u, - 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u, 43u, 124u, 9u, 124u, 9u, 124u, - 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, - 9u, 124u, 9u, 124u, 9u, 124u, 0 + 0u, 0u, 35u, 124u, 48u, 57u, 60u, 124u, 45u, 57u, 48u, 57u, 44u, 44u, 45u, 57u, + 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 62u, 62u, + 93u, 124u, 45u, 57u, 48u, 57u, 35u, 124u, 45u, 57u, 48u, 57u, 35u, 124u, 35u, 124u, + 35u, 124u, 35u, 124u, 35u, 124u, 35u, 124u, 48u, 57u, 35u, 124u, 45u, 57u, 48u, 57u, + 44u, 44u, 45u, 57u, 48u, 57u, 35u, 124u, 35u, 124u, 44u, 57u, 35u, 124u, 43u, 124u, + 35u, 124u, 48u, 62u, 44u, 57u, 44u, 57u, 44u, 57u, 48u, 124u, 35u, 124u, 35u, 124u, + 35u, 124u, 0 }; static const char _deserialize_text_glyphs_key_spans[] = { - 0, 10, 13, 10, 13, 10, 10, 13, - 10, 1, 13, 10, 14, 82, 116, 116, - 116, 116, 116, 116, 116, 116, 116, 116, - 116, 116, 116 + 0, 90, 10, 65, 13, 10, 1, 13, + 10, 1, 13, 10, 1, 13, 10, 1, + 32, 13, 10, 90, 13, 10, 90, 90, + 90, 90, 90, 90, 10, 90, 13, 10, + 1, 13, 10, 90, 90, 14, 90, 82, + 90, 15, 14, 14, 14, 77, 90, 90, + 90 }; static const short _deserialize_text_glyphs_index_offsets[] = { - 0, 0, 11, 25, 36, 50, 61, 72, - 86, 97, 99, 113, 124, 139, 222, 339, - 456, 573, 690, 807, 924, 1041, 1158, 1275, - 1392, 1509, 1626 + 0, 0, 91, 102, 168, 182, 193, 195, + 209, 220, 222, 236, 247, 249, 263, 274, + 276, 309, 323, 334, 425, 439, 450, 541, + 632, 723, 814, 905, 996, 1007, 1098, 1112, + 1123, 1125, 1139, 1150, 1241, 1332, 1347, 1438, + 1521, 1612, 1628, 1643, 1658, 1673, 1751, 1842, + 1933 }; static const char _deserialize_text_glyphs_indicies[] = { - 0, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 1, 3, 1, 1, 4, - 5, 5, 5, 5, 5, 5, 5, 5, - 5, 1, 6, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 1, 8, 1, 1, - 9, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 1, 11, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 1, 13, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 1, 15, 1, 1, 16, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 1, 18, + 1, 0, 0, 0, 0, 0, 0, + 0, 2, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 5, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7, 8, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 9, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 3, 11, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 12, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 12, + 3, 13, 3, 3, 14, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 3, 14, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 3, 16, 3, 17, 3, 3, 18, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 1, 20, 1, 21, 1, 1, 22, - 23, 23, 23, 23, 23, 23, 23, 23, - 23, 1, 24, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 1, 20, 1, 1, - 1, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 1, 26, 26, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 26, 1, - 1, 26, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 26, 26, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 26, 1, 28, - 28, 28, 28, 28, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 28, 27, - 27, 29, 27, 27, 27, 27, 27, 27, - 27, 30, 1, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 31, 27, 27, 32, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 33, 1, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 28, 27, 34, 34, 34, 34, - 34, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 34, 26, 26, 35, 26, - 26, 26, 26, 26, 26, 26, 36, 1, - 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, - 37, 26, 26, 38, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 39, - 1, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 40, - 26, 41, 41, 41, 41, 41, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 41, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 42, 1, 43, 43, - 43, 43, 43, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 43, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 44, 1, 41, 41, 41, 41, 41, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 41, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 42, 1, - 46, 46, 46, 46, 46, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 46, - 1, 1, 47, 1, 1, 1, 1, 1, - 1, 1, 1, 48, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 49, 1, 50, 50, 50, - 50, 50, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 50, 1, 1, 51, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 52, 1, 50, 50, 50, 50, 50, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 50, 1, 1, 51, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 52, 1, 46, - 46, 46, 46, 46, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 46, 1, - 1, 47, 1, 1, 1, 1, 1, 1, - 1, 1, 48, 1, 1, 1, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 49, 1, 53, 53, 53, 53, - 53, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 53, 1, 1, 54, 1, - 1, 1, 1, 1, 1, 1, 55, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 56, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 57, - 1, 58, 58, 58, 58, 58, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 58, 1, 1, 59, 1, 1, 1, 1, - 1, 1, 1, 60, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 61, 1, 58, 58, - 58, 58, 58, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 58, 1, 1, - 59, 1, 1, 1, 1, 1, 1, 1, - 60, 1, 1, 1, 1, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 61, 1, 53, 53, 53, 53, 53, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 53, 1, 1, 54, 1, 1, - 1, 1, 1, 1, 1, 55, 1, 1, - 1, 1, 62, 62, 62, 62, 62, 62, - 62, 62, 62, 62, 1, 1, 1, 1, - 1, 1, 56, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 57, 1, - 0 + 19, 3, 18, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 3, 20, 3, 21, + 3, 3, 22, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 3, 22, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 3, + 24, 3, 25, 3, 3, 26, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 3, + 26, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 3, 28, 3, 29, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 29, 3, 30, 3, + 3, 31, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 3, 33, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 3, 35, + 3, 3, 3, 3, 3, 3, 3, 3, + 36, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 37, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 38, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 38, 3, 39, 3, 3, 40, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 3, + 42, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 3, 44, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 45, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 46, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 46, 3, 44, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 3, 3, 45, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 46, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 46, + 3, 35, 3, 3, 3, 3, 3, 3, + 3, 3, 36, 3, 3, 3, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, + 3, 3, 37, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 38, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 38, 3, 1, 0, 0, 0, + 0, 0, 0, 0, 2, 3, 47, 0, + 0, 48, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 0, 0, 4, 5, 0, + 0, 6, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7, 8, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 8, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 2, + 3, 0, 0, 0, 48, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 0, 0, + 4, 5, 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7, 8, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 2, 16, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 5, 0, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 0, 50, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 3, + 52, 3, 3, 3, 3, 3, 3, 3, + 53, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 54, 3, 3, 3, 55, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 56, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 56, 3, 57, 3, 3, 58, 59, + 59, 59, 59, 59, 59, 59, 59, 59, + 3, 60, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 3, 62, 3, 63, 3, + 3, 64, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 3, 66, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 3, 68, + 3, 3, 3, 3, 3, 3, 3, 69, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 70, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 71, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 71, 3, 68, 3, 3, 3, 3, 3, + 3, 3, 69, 3, 3, 3, 3, 67, + 67, 67, 67, 67, 67, 67, 67, 67, + 67, 3, 3, 70, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 71, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 71, 3, 62, 3, 3, + 3, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 3, 52, 3, 3, 3, + 3, 3, 3, 3, 53, 3, 3, 3, + 3, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 3, 3, 54, 3, 3, + 3, 55, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 56, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 56, 3, 0, + 0, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 0, 3, 3, 0, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 0, 0, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 0, 3, 1, 0, 0, 0, 0, 0, + 0, 0, 2, 16, 0, 0, 0, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 0, 0, 4, 5, 0, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 0, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 3, + 3, 3, 3, 28, 3, 24, 3, 3, + 3, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 3, 20, 3, 3, 3, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 3, 16, 3, 3, 3, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 3, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 3, 3, 11, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 12, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 12, 3, + 75, 74, 74, 74, 74, 74, 74, 74, + 76, 3, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 77, 78, 74, 74, 79, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 80, 81, 82, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 82, 74, 84, 83, 83, 83, 83, + 83, 83, 83, 85, 3, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 86, 87, 83, 83, + 88, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 89, 90, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 90, 83, 91, 74, + 74, 74, 74, 74, 74, 74, 92, 3, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 93, + 94, 74, 74, 95, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 81, + 96, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 96, + 74, 0 }; static const char _deserialize_text_glyphs_trans_targs[] = { - 16, 0, 18, 3, 19, 22, 19, 22, - 5, 20, 21, 20, 21, 23, 26, 8, - 9, 12, 9, 12, 10, 11, 24, 25, - 24, 25, 15, 15, 14, 1, 2, 6, - 7, 13, 15, 1, 2, 6, 7, 13, - 14, 17, 14, 17, 14, 18, 17, 1, - 4, 14, 17, 1, 14, 17, 1, 2, - 7, 14, 17, 1, 2, 14, 26 + 1, 2, 17, 0, 25, 28, 30, 39, + 47, 3, 45, 4, 47, 5, 6, 44, + 7, 8, 9, 43, 10, 11, 12, 42, + 13, 14, 15, 41, 16, 47, 18, 19, + 24, 19, 24, 2, 20, 4, 47, 21, + 22, 23, 22, 23, 2, 4, 47, 26, + 27, 40, 29, 38, 2, 17, 4, 30, + 47, 31, 32, 37, 32, 37, 33, 34, + 35, 36, 35, 36, 2, 17, 4, 47, + 38, 45, 1, 2, 17, 25, 28, 30, + 48, 39, 47, 1, 2, 17, 25, 28, + 30, 39, 47, 2, 17, 25, 28, 30, + 47 }; static const char _deserialize_text_glyphs_trans_actions[] = { - 1, 0, 1, 1, 1, 1, 0, 0, - 1, 1, 1, 0, 0, 1, 1, 1, - 1, 1, 0, 0, 2, 1, 1, 1, - 0, 0, 0, 4, 3, 5, 5, 5, - 5, 4, 6, 7, 7, 7, 7, 0, - 6, 8, 8, 0, 0, 0, 9, 10, - 10, 9, 11, 12, 11, 13, 14, 14, - 14, 13, 15, 16, 16, 15, 0 + 0, 1, 1, 0, 1, 1, 1, 0, + 1, 2, 2, 3, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 2, + 2, 0, 0, 4, 4, 4, 4, 2, + 2, 2, 0, 0, 5, 5, 5, 0, + 0, 0, 2, 2, 6, 6, 6, 6, + 6, 2, 2, 2, 0, 0, 7, 2, + 2, 2, 0, 0, 8, 8, 8, 8, + 0, 0, 9, 10, 10, 10, 10, 10, + 9, 9, 10, 12, 13, 13, 13, 13, + 13, 12, 13, 14, 14, 14, 14, 14, + 14 }; static const char _deserialize_text_glyphs_eof_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3, 6, - 8, 0, 8, 9, 11, 11, 9, 13, - 15, 15, 13 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 11, + 0 }; -static const int deserialize_text_glyphs_start = 14; -static const int deserialize_text_glyphs_first_final = 14; +static const int deserialize_text_glyphs_start = 46; +static const int deserialize_text_glyphs_first_final = 46; static const int deserialize_text_glyphs_error = 0; -static const int deserialize_text_glyphs_en_main = 14; +static const int deserialize_text_glyphs_en_main = 46; -#line 98 "hb-buffer-deserialize-text-glyphs.rl" +#line 101 "hb-buffer-deserialize-text-glyphs.rl" static hb_bool_t @@ -322,39 +379,22 @@ const char **end_ptr, hb_font_t *font) { - const char *p = buf, *pe = buf + buf_len, *eof = pe, *orig_pe = pe; + const char *p = buf, *pe = buf + buf_len, *eof = pe; /* Ensure we have positions. */ (void) hb_buffer_get_glyph_positions (buffer, nullptr); - while (p < pe && ISSPACE (*p)) - p++; - if (p < pe && *p == (buffer->len ? '|' : '[')) - *end_ptr = ++p; - - const char *end = strchr ((char *) p, ']'); - if (end) - pe = eof = end; - else - { - end = strrchr ((char *) p, '|'); - if (end) - pe = eof = end; - else - pe = eof = p; - } - const char *tok = nullptr; int cs; hb_glyph_info_t info = {0}; hb_glyph_position_t pos = {0}; -#line 353 "hb-buffer-deserialize-text-glyphs.hh" +#line 386 "hb-buffer-deserialize-text-glyphs.hh" { cs = deserialize_text_glyphs_start; } -#line 358 "hb-buffer-deserialize-text-glyphs.hh" +#line 389 "hb-buffer-deserialize-text-glyphs.hh" { int _slen; int _trans; @@ -379,14 +419,14 @@ goto _again; switch ( _deserialize_text_glyphs_trans_actions[_trans] ) { - case 1: -#line 51 "hb-buffer-deserialize-text-glyphs.rl" + case 2: +#line 50 "hb-buffer-deserialize-text-glyphs.rl" { tok = p; } break; - case 7: -#line 55 "hb-buffer-deserialize-text-glyphs.rl" + case 1: +#line 54 "hb-buffer-deserialize-text-glyphs.rl" { /* TODO Unescape delimiters. */ if (!hb_font_glyph_from_string (font, @@ -395,145 +435,115 @@ return false; } break; - case 14: -#line 63 "hb-buffer-deserialize-text-glyphs.rl" + case 6: +#line 62 "hb-buffer-deserialize-text-glyphs.rl" { if (!parse_uint (tok, p, &info.cluster )) return false; } break; - case 2: -#line 64 "hb-buffer-deserialize-text-glyphs.rl" + case 7: +#line 63 "hb-buffer-deserialize-text-glyphs.rl" { if (!parse_int (tok, p, &pos.x_offset )) return false; } break; - case 16: -#line 65 "hb-buffer-deserialize-text-glyphs.rl" + case 8: +#line 64 "hb-buffer-deserialize-text-glyphs.rl" { if (!parse_int (tok, p, &pos.y_offset )) return false; } break; - case 10: -#line 66 "hb-buffer-deserialize-text-glyphs.rl" + case 4: +#line 65 "hb-buffer-deserialize-text-glyphs.rl" { if (!parse_int (tok, p, &pos.x_advance)) return false; } break; - case 12: -#line 67 "hb-buffer-deserialize-text-glyphs.rl" + case 5: +#line 66 "hb-buffer-deserialize-text-glyphs.rl" { if (!parse_int (tok, p, &pos.y_advance)) return false; } break; - case 4: + case 3: +#line 67 "hb-buffer-deserialize-text-glyphs.rl" + { if (!parse_uint (tok, p, &info.mask )) return false; } + break; + case 9: #line 38 "hb-buffer-deserialize-text-glyphs.rl" { hb_memset (&info, 0, sizeof (info)); hb_memset (&pos , 0, sizeof (pos )); } -#line 51 "hb-buffer-deserialize-text-glyphs.rl" +#line 50 "hb-buffer-deserialize-text-glyphs.rl" { tok = p; } break; - case 6: -#line 55 "hb-buffer-deserialize-text-glyphs.rl" + case 10: +#line 38 "hb-buffer-deserialize-text-glyphs.rl" { - /* TODO Unescape delimiters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; + hb_memset (&info, 0, sizeof (info)); + hb_memset (&pos , 0, sizeof (pos )); } -#line 43 "hb-buffer-deserialize-text-glyphs.rl" +#line 50 "hb-buffer-deserialize-text-glyphs.rl" { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; + tok = p; } - break; - case 13: -#line 63 "hb-buffer-deserialize-text-glyphs.rl" - { if (!parse_uint (tok, p, &info.cluster )) return false; } -#line 43 "hb-buffer-deserialize-text-glyphs.rl" +#line 54 "hb-buffer-deserialize-text-glyphs.rl" { - buffer->add_info (info); - if (unlikely (!buffer->successful)) + /* TODO Unescape delimiters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; } break; - case 15: -#line 65 "hb-buffer-deserialize-text-glyphs.rl" - { if (!parse_int (tok, p, &pos.y_offset )) return false; } + case 12: #line 43 "hb-buffer-deserialize-text-glyphs.rl" { - buffer->add_info (info); + buffer->add_info_and_pos (info, pos); if (unlikely (!buffer->successful)) return false; - buffer->pos[buffer->len - 1] = pos; *end_ptr = p; } - break; - case 9: -#line 66 "hb-buffer-deserialize-text-glyphs.rl" - { if (!parse_int (tok, p, &pos.x_advance)) return false; } -#line 43 "hb-buffer-deserialize-text-glyphs.rl" +#line 38 "hb-buffer-deserialize-text-glyphs.rl" { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; + hb_memset (&info, 0, sizeof (info)); + hb_memset (&pos , 0, sizeof (pos )); } - break; - case 11: -#line 67 "hb-buffer-deserialize-text-glyphs.rl" - { if (!parse_int (tok, p, &pos.y_advance)) return false; } -#line 43 "hb-buffer-deserialize-text-glyphs.rl" +#line 50 "hb-buffer-deserialize-text-glyphs.rl" { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; + tok = p; } break; - case 8: -#line 68 "hb-buffer-deserialize-text-glyphs.rl" - { if (!parse_uint (tok, p, &info.mask )) return false; } -#line 43 "hb-buffer-deserialize-text-glyphs.rl" + case 14: +#line 54 "hb-buffer-deserialize-text-glyphs.rl" { - buffer->add_info (info); - if (unlikely (!buffer->successful)) + /* TODO Unescape delimiters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; } - break; - case 5: #line 38 "hb-buffer-deserialize-text-glyphs.rl" { hb_memset (&info, 0, sizeof (info)); hb_memset (&pos , 0, sizeof (pos )); } -#line 51 "hb-buffer-deserialize-text-glyphs.rl" +#line 50 "hb-buffer-deserialize-text-glyphs.rl" { tok = p; } -#line 55 "hb-buffer-deserialize-text-glyphs.rl" + break; + case 13: +#line 43 "hb-buffer-deserialize-text-glyphs.rl" { - /* TODO Unescape delimiters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) + buffer->add_info_and_pos (info, pos); + if (unlikely (!buffer->successful)) return false; + *end_ptr = p; } - break; - case 3: #line 38 "hb-buffer-deserialize-text-glyphs.rl" { hb_memset (&info, 0, sizeof (info)); hb_memset (&pos , 0, sizeof (pos )); } -#line 51 "hb-buffer-deserialize-text-glyphs.rl" +#line 50 "hb-buffer-deserialize-text-glyphs.rl" { tok = p; } -#line 55 "hb-buffer-deserialize-text-glyphs.rl" +#line 54 "hb-buffer-deserialize-text-glyphs.rl" { /* TODO Unescape delimiters. */ if (!hb_font_glyph_from_string (font, @@ -541,16 +551,8 @@ &info.codepoint)) return false; } -#line 43 "hb-buffer-deserialize-text-glyphs.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} break; -#line 554 "hb-buffer-deserialize-text-glyphs.hh" +#line 523 "hb-buffer-deserialize-text-glyphs.hh" } _again: @@ -562,127 +564,24 @@ if ( p == eof ) { switch ( _deserialize_text_glyphs_eof_actions[cs] ) { - case 6: -#line 55 "hb-buffer-deserialize-text-glyphs.rl" - { - /* TODO Unescape delimiters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; -} -#line 43 "hb-buffer-deserialize-text-glyphs.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 13: -#line 63 "hb-buffer-deserialize-text-glyphs.rl" - { if (!parse_uint (tok, p, &info.cluster )) return false; } -#line 43 "hb-buffer-deserialize-text-glyphs.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 15: -#line 65 "hb-buffer-deserialize-text-glyphs.rl" - { if (!parse_int (tok, p, &pos.y_offset )) return false; } -#line 43 "hb-buffer-deserialize-text-glyphs.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 9: -#line 66 "hb-buffer-deserialize-text-glyphs.rl" - { if (!parse_int (tok, p, &pos.x_advance)) return false; } -#line 43 "hb-buffer-deserialize-text-glyphs.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; case 11: -#line 67 "hb-buffer-deserialize-text-glyphs.rl" - { if (!parse_int (tok, p, &pos.y_advance)) return false; } -#line 43 "hb-buffer-deserialize-text-glyphs.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 8: -#line 68 "hb-buffer-deserialize-text-glyphs.rl" - { if (!parse_uint (tok, p, &info.mask )) return false; } -#line 43 "hb-buffer-deserialize-text-glyphs.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 3: -#line 38 "hb-buffer-deserialize-text-glyphs.rl" - { - hb_memset (&info, 0, sizeof (info)); - hb_memset (&pos , 0, sizeof (pos )); -} -#line 51 "hb-buffer-deserialize-text-glyphs.rl" - { - tok = p; -} -#line 55 "hb-buffer-deserialize-text-glyphs.rl" - { - /* TODO Unescape delimiters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; -} #line 43 "hb-buffer-deserialize-text-glyphs.rl" { - buffer->add_info (info); + buffer->add_info_and_pos (info, pos); if (unlikely (!buffer->successful)) return false; - buffer->pos[buffer->len - 1] = pos; *end_ptr = p; } break; -#line 671 "hb-buffer-deserialize-text-glyphs.hh" +#line 542 "hb-buffer-deserialize-text-glyphs.hh" } } _out: {} } -#line 136 "hb-buffer-deserialize-text-glyphs.rl" - +#line 122 "hb-buffer-deserialize-text-glyphs.rl" - if (pe < orig_pe && *pe == ']') - { - pe++; - if (p == pe) - p++; - } *end_ptr = p; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-unicode.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-unicode.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-unicode.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-unicode.hh 2025-10-13 07:49:24.000000000 +0000 @@ -34,135 +34,106 @@ #line 36 "hb-buffer-deserialize-text-unicode.hh" static const unsigned char _deserialize_text_unicode_trans_keys[] = { - 0u, 0u, 9u, 117u, 43u, 102u, 48u, 102u, 48u, 57u, 9u, 124u, 9u, 124u, 9u, 124u, - 9u, 124u, 0 + 0u, 0u, 43u, 102u, 48u, 102u, 48u, 124u, 48u, 57u, 62u, 124u, 48u, 124u, 60u, 117u, + 85u, 117u, 85u, 117u, 0 }; static const char _deserialize_text_unicode_key_spans[] = { - 0, 109, 60, 55, 10, 116, 116, 116, - 116 + 0, 60, 55, 77, 10, 63, 77, 58, + 33, 33 }; static const short _deserialize_text_unicode_index_offsets[] = { - 0, 0, 110, 171, 227, 238, 355, 472, - 589 + 0, 0, 61, 117, 195, 206, 270, 348, + 407, 441 }; static const char _deserialize_text_unicode_indicies[] = { - 0, 0, 0, 0, 0, 1, 1, + 0, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 1, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 1, 1, 1, 4, 5, 1, 1, 3, + 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 3, + 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 5, 1, 6, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 1, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 2, 1, 3, - 1, 1, 1, 1, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 1, 1, - 1, 1, 1, 1, 1, 4, 4, 4, - 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 4, 4, 4, - 4, 4, 4, 1, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 1, 1, - 1, 1, 1, 1, 1, 4, 4, 4, - 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 4, 4, 4, - 4, 4, 4, 1, 5, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 1, 7, - 7, 7, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 7, 1, + 1, 1, 1, 1, 1, 8, 1, 9, + 9, 9, 9, 9, 9, 9, 9, 9, + 9, 1, 1, 1, 1, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 1, 1, 1, 9, 1, 1, 1, 8, - 8, 8, 8, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 8, - 8, 8, 8, 8, 8, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 10, 1, 11, 11, 11, 11, - 11, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 11, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 0, - 1, 12, 12, 12, 12, 12, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 8, 1, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 13, 1, 12, 12, - 12, 12, 12, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 12, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 11, 1, + 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 11, 1, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 13, 1, 0 + 1, 1, 12, 1, 0 }; static const char _deserialize_text_unicode_trans_targs[] = { - 1, 0, 2, 3, 5, 7, 8, 6, - 5, 4, 1, 6, 6, 1, 8 + 2, 0, 3, 3, 4, 9, 5, 6, + 9, 6, 8, 1, 1 }; static const char _deserialize_text_unicode_trans_actions[] = { - 0, 0, 1, 0, 2, 2, 2, 3, - 0, 4, 3, 0, 5, 5, 0 + 0, 0, 1, 0, 2, 2, 1, 1, + 3, 0, 0, 4, 6 }; static const char _deserialize_text_unicode_eof_actions[] = { - 0, 0, 0, 0, 0, 3, 0, 5, - 5 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5 }; -static const int deserialize_text_unicode_start = 1; -static const int deserialize_text_unicode_first_final = 5; +static const int deserialize_text_unicode_start = 7; +static const int deserialize_text_unicode_first_final = 7; static const int deserialize_text_unicode_error = 0; -static const int deserialize_text_unicode_en_main = 1; +static const int deserialize_text_unicode_en_main = 7; -#line 79 "hb-buffer-deserialize-text-unicode.rl" +#line 80 "hb-buffer-deserialize-text-unicode.rl" static hb_bool_t @@ -172,37 +143,19 @@ const char **end_ptr, hb_font_t *font) { - const char *p = buf, *pe = buf + buf_len, *eof = pe, *orig_pe = pe; - - while (p < pe && ISSPACE (*p)) - p++; - if (p < pe && *p == (buffer->len ? '|' : '<')) - *end_ptr = ++p; - - const char *end = strchr ((char *) p, '>'); - if (end) - pe = eof = end; - else - { - end = strrchr ((char *) p, '|'); - if (end) - pe = eof = end; - else - pe = eof = p; - } - + const char *p = buf, *pe = buf + buf_len, *eof = pe; const char *tok = nullptr; int cs; hb_glyph_info_t info = {0}; const hb_glyph_position_t pos = {0}; -#line 201 "hb-buffer-deserialize-text-unicode.hh" +#line 154 "hb-buffer-deserialize-text-unicode.hh" { cs = deserialize_text_unicode_start; } -#line 206 "hb-buffer-deserialize-text-unicode.hh" +#line 159 "hb-buffer-deserialize-text-unicode.hh" { int _slen; int _trans; @@ -227,38 +180,27 @@ goto _again; switch ( _deserialize_text_unicode_trans_actions[_trans] ) { - case 1: + case 4: #line 38 "hb-buffer-deserialize-text-unicode.rl" { hb_memset (&info, 0, sizeof (info)); } break; - case 2: + case 1: #line 51 "hb-buffer-deserialize-text-unicode.rl" { tok = p; } break; - case 4: + case 2: #line 55 "hb-buffer-deserialize-text-unicode.rl" {if (!parse_hex (tok, p, &info.codepoint )) return false; } break; case 3: -#line 55 "hb-buffer-deserialize-text-unicode.rl" - {if (!parse_hex (tok, p, &info.codepoint )) return false; } -#line 42 "hb-buffer-deserialize-text-unicode.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - if (buffer->have_positions) - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 5: #line 57 "hb-buffer-deserialize-text-unicode.rl" { if (!parse_uint (tok, p, &info.cluster )) return false; } + break; + case 6: #line 42 "hb-buffer-deserialize-text-unicode.rl" { buffer->add_info (info); @@ -268,8 +210,12 @@ buffer->pos[buffer->len - 1] = pos; *end_ptr = p; } +#line 38 "hb-buffer-deserialize-text-unicode.rl" + { + hb_memset (&info, 0, sizeof (info)); +} break; -#line 273 "hb-buffer-deserialize-text-unicode.hh" +#line 219 "hb-buffer-deserialize-text-unicode.hh" } _again: @@ -281,22 +227,7 @@ if ( p == eof ) { switch ( _deserialize_text_unicode_eof_actions[cs] ) { - case 3: -#line 55 "hb-buffer-deserialize-text-unicode.rl" - {if (!parse_hex (tok, p, &info.codepoint )) return false; } -#line 42 "hb-buffer-deserialize-text-unicode.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - if (buffer->have_positions) - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; case 5: -#line 57 "hb-buffer-deserialize-text-unicode.rl" - { if (!parse_uint (tok, p, &info.cluster )) return false; } #line 42 "hb-buffer-deserialize-text-unicode.rl" { buffer->add_info (info); @@ -307,22 +238,15 @@ *end_ptr = p; } break; -#line 311 "hb-buffer-deserialize-text-unicode.hh" +#line 242 "hb-buffer-deserialize-text-unicode.hh" } } _out: {} } -#line 115 "hb-buffer-deserialize-text-unicode.rl" - +#line 98 "hb-buffer-deserialize-text-unicode.rl" - if (pe < orig_pe && *pe == '>') - { - pe++; - if (p == pe) - p++; - } *end_ptr = p; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-buffer-serialize.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-serialize.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-buffer-serialize.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-serialize.cc 2025-10-13 07:49:24.000000000 +0000 @@ -169,11 +169,13 @@ if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS) { hb_glyph_extents_t extents; - hb_font_get_glyph_extents(font, info[i].codepoint, &extents); - p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d", - extents.x_bearing, extents.y_bearing)); - p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d", - extents.width, extents.height)); + if (hb_font_get_glyph_extents(font, info[i].codepoint, &extents)) + { + p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d", + extents.x_bearing, extents.y_bearing)); + p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d", + extents.width, extents.height)); + } } *p++ = '}'; @@ -318,8 +320,8 @@ if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS) { hb_glyph_extents_t extents; - hb_font_get_glyph_extents(font, info[i].codepoint, &extents); - p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height)); + if (hb_font_get_glyph_extents(font, info[i].codepoint, &extents)) + p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height)); } if (i == end-1) { @@ -737,8 +739,7 @@ * Deserializes glyphs @buffer from textual representation in the format * produced by hb_buffer_serialize_glyphs(). * - * Return value: `true` if parse was successful, `false` if an error - * occurred. + * Return value: `true` if the full string was parsed, `false` otherwise. * * Since: 0.9.7 **/ @@ -810,8 +811,7 @@ * Deserializes Unicode @buffer from textual representation in the format * produced by hb_buffer_serialize_unicode(). * - * Return value: `true` if parse was successful, `false` if an error - * occurred. + * Return value: `true` if the full string was parsed, `false` otherwise. * * Since: 2.7.3 **/ diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc 2025-10-13 07:49:24.000000000 +0000 @@ -63,23 +63,24 @@ buffer_verify_monotone (hb_buffer_t *buffer, hb_font_t *font) { - /* Check that clusters are monotone. */ - if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES || - buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS) + if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (buffer->cluster_level)) { - bool is_forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer)); + /* Cannot perform this check without monotone clusters. */ + return true; + } - unsigned int num_glyphs; - hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs); + bool is_forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer)); - for (unsigned int i = 1; i < num_glyphs; i++) - if (info[i-1].cluster != info[i].cluster && - (info[i-1].cluster < info[i].cluster) != is_forward) - { - buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "clusters are not monotone."); - return false; - } - } + unsigned int num_glyphs; + hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs); + + for (unsigned int i = 1; i < num_glyphs; i++) + if (info[i-1].cluster != info[i].cluster && + (info[i-1].cluster < info[i].cluster) != is_forward) + { + buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "clusters are not monotone."); + return false; + } return true; } @@ -92,8 +93,7 @@ unsigned int num_features, const char * const *shapers) { - if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES && - buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS) + if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (buffer->cluster_level)) { /* Cannot perform this check without monotone clusters. */ return true; @@ -207,8 +207,7 @@ unsigned int num_features, const char * const *shapers) { - if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES && - buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS) + if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (buffer->cluster_level)) { /* Cannot perform this check without monotone clusters. */ return true; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc 2025-10-13 07:49:24.000000000 +0000 @@ -370,6 +370,18 @@ len++; } +void +hb_buffer_t::add_info_and_pos (const hb_glyph_info_t &glyph_info, + const hb_glyph_position_t &glyph_pos) +{ + if (unlikely (!ensure (len + 1))) return; + + info[len] = glyph_info; + assert (have_positions); + pos[len] = glyph_pos; + + len++; +} void @@ -518,7 +530,7 @@ hb_buffer_t::merge_clusters_impl (unsigned int start, unsigned int end) { - if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS) + if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (cluster_level)) { unsafe_to_break (start, end); return; @@ -551,7 +563,7 @@ hb_buffer_t::merge_out_clusters (unsigned int start, unsigned int end) { - if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS) + if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (cluster_level)) return; if (unlikely (end - start < 2)) diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-buffer.h openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer.h --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-buffer.h 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer.h 2025-10-13 07:49:24.000000000 +0000 @@ -422,6 +422,7 @@ * @HB_BUFFER_CLUSTER_LEVEL_CHARACTERS: Don't group cluster values. * @HB_BUFFER_CLUSTER_LEVEL_DEFAULT: Default cluster level, * equal to @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES. + * @HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES: Only group clusters, but don't enforce monotone order. * * Data type for holding HarfBuzz's clustering behavior options. The cluster level * dictates one aspect of how HarfBuzz will treat non-base characters @@ -429,11 +430,26 @@ * * In @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES, non-base * characters are merged into the cluster of the base character that precedes them. + * There is also cluster merging every time the clusters will otherwise become non-monotone. * * In @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS, non-base characters are initially * assigned their own cluster values, which are not merged into preceding base * clusters. This allows HarfBuzz to perform additional operations like reorder - * sequences of adjacent marks. + * sequences of adjacent marks. The output is still monotone, but the cluster + * values are more granular. + * + * In @HB_BUFFER_CLUSTER_LEVEL_CHARACTERS, non-base characters are assigned their + * own cluster values, which are not merged into preceding base clusters. Moreover, + * the cluster values are not merged into monotone order. This is the most granular + * cluster level, and it is useful for clients that need to know the exact cluster + * values of each character, but is harder to use for clients, since clusters + * might appear in any order. + * + * In @HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES, non-base characters are merged into the + * cluster of the base character that precedes them. This is similar to the Unicode + * Grapheme Cluster algorithm, but it is not exactly the same. The output is + * not forced to be monotone. This is useful for clients that want to use HarfBuzz + * as a cheap implementation of the Unicode Grapheme Cluster algorithm. * * @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES is the default, because it maintains * backward compatibility with older versions of HarfBuzz. New client programs that @@ -446,9 +462,52 @@ HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES = 0, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS = 1, HB_BUFFER_CLUSTER_LEVEL_CHARACTERS = 2, + HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES = 3, HB_BUFFER_CLUSTER_LEVEL_DEFAULT = HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES } hb_buffer_cluster_level_t; +/** + * HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE: + * @level: #hb_buffer_cluster_level_t to test + * + * Tests whether a cluster level groups cluster values into monotone order. + * Requires that the level be valid. + * + * Since: 11.0.0 + */ +#define HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE(level) \ + ((bool) ((1u << (unsigned) (level)) & \ + ((1u << HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) | \ + (1u << HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)))) + +/** + * HB_BUFFER_CLUSTER_LEVEL_IS_GRAPHEMES: + * @level: #hb_buffer_cluster_level_t to test + * + * Tests whether a cluster level groups cluster values by graphemes. Requires + * that the level be valid. + * + * Since: 11.0.0 + */ +#define HB_BUFFER_CLUSTER_LEVEL_IS_GRAPHEMES(level) \ + ((bool) ((1u << (unsigned) (level)) & \ + ((1u << HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) | \ + (1u << HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES)))) + +/** + * HB_BUFFER_CLUSTER_LEVEL_IS_CHARACTERS + * @level: #hb_buffer_cluster_level_t to test + * + * Tests whether a cluster level does not group cluster values by graphemes. + * Requires that the level be valid. + * + * Since: 11.0.0 + */ +#define HB_BUFFER_CLUSTER_LEVEL_IS_CHARACTERS(level) \ + ((bool) ((1u << (unsigned) (level)) & \ + ((1u << HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARCATERS) | \ + (1u << HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)))) + HB_EXTERN void hb_buffer_set_cluster_level (hb_buffer_t *buffer, hb_buffer_cluster_level_t cluster_level); diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh 2025-10-13 07:49:24.000000000 +0000 @@ -229,6 +229,8 @@ HB_INTERNAL void add (hb_codepoint_t codepoint, unsigned int cluster); HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info); + HB_INTERNAL void add_info_and_pos (const hb_glyph_info_t &glyph_info, + const hb_glyph_position_t &glyph_pos); void reverse_range (unsigned start, unsigned end) { @@ -410,6 +412,9 @@ { end = hb_min (end, len); + if (unlikely (end - start > 255)) + return; + if (interior && !from_out_buffer && end - start < 2) return; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-cache.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-cache.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-cache.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-cache.hh 2025-10-13 07:49:24.000000000 +0000 @@ -30,18 +30,31 @@ #include "hb.hh" -/* Implements a lockfree cache for int->int functions. +/* Implements a lockfree and thread-safe cache for int->int functions, + * using (optionally) _relaxed_ atomic integer operations. * - * The cache is a fixed-size array of 16-bit or 32-bit integers. - * The key is split into two parts: the cache index and the rest. + * The cache is a fixed-size array of 16-bit or 32-bit integers, + * typically 256 elements. * - * The cache index is used to index into the array. The rest is used - * to store the key and the value. + * The key is split into two parts: the cache index (high bits) + * and the rest (low bits). + * + * The cache index is used to index into the array. The array + * member is a 16-bit or 32-bit integer that is used *both* + * to store the low bits of the key, and the value. * * The value is stored in the least significant bits of the integer. - * The key is stored in the most significant bits of the integer. - * The key is shifted by cache_bits to the left to make room for the - * value. + * The low bits of the key are stored in the most significant bits + * of the integer. + * + * A cache hit is detected by comparing the low bits of the key + * with the high bits of the integer at the array position indexed + * by the high bits of the key. If they match, the value is extracted + * from the least significant bits of the integer and returned. + * Otherwise, a cache miss is reported. + * + * Cache operations (storage and retrieval) involve just a few + * arithmetic operations and a single memory access. */ template ::type, + hb_atomic_t, + hb_atomic_t>::type, typename std::conditional::type + unsigned short, + unsigned int>::type >::type; static_assert ((key_bits >= cache_bits), ""); diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh 2025-10-13 07:49:24.000000000 +0000 @@ -71,7 +71,8 @@ template cff2_cs_interp_env_t (const hb_ubytes_t &str, ACC &acc, unsigned int fd, const int *coords_=nullptr, unsigned int num_coords_=0) - : SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs) + : SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs), + cached_scalars_vector (&acc.cached_scalars_vector) { coords = coords_; num_coords = num_coords_; @@ -80,9 +81,39 @@ set_ivs (acc.privateDicts[fd].ivs); } - void fini () + ~cff2_cs_interp_env_t () { - SUPER::fini (); + release_scalars_vector (scalars); + } + + hb_vector_t *acquire_scalars_vector () const + { + hb_vector_t *scalars = cached_scalars_vector->get_acquire (); + + if (!scalars || !cached_scalars_vector->cmpexch (scalars, nullptr)) + { + scalars = (hb_vector_t *) hb_calloc (1, sizeof (hb_vector_t)); + if (unlikely (!scalars)) + return nullptr; + scalars->init (); + } + + return scalars; + } + + void release_scalars_vector (hb_vector_t *scalars) const + { + if (!scalars) + return; + + scalars->clear (); + + if (!cached_scalars_vector->cmpexch (nullptr, scalars)) + { + scalars->fini (); + hb_free (scalars); + } + scalars = nullptr; } op_code_t fetch_op () @@ -111,14 +142,20 @@ { if (!seen_blend) { - region_count = varStore->varStore.get_region_index_count (get_ivs ()); - if (do_blend) + scalars = acquire_scalars_vector (); + if (unlikely (!scalars)) + SUPER::set_error (); + else { - if (unlikely (!scalars.resize_exact (region_count))) - SUPER::set_error (); - else - varStore->varStore.get_region_scalars (get_ivs (), coords, num_coords, - &scalars[0], region_count); + region_count = varStore->varStore.get_region_index_count (get_ivs ()); + if (do_blend) + { + if (unlikely (!scalars->resize_exact (region_count))) + SUPER::set_error (); + else + varStore->varStore.get_region_scalars (get_ivs (), coords, num_coords, + &(*scalars)[0], region_count); + } } seen_blend = true; } @@ -149,11 +186,11 @@ double v = 0; if (do_blend) { - if (likely (scalars.length == deltas.length)) + if (likely (scalars && scalars->length == deltas.length)) { - unsigned count = scalars.length; + unsigned count = scalars->length; for (unsigned i = 0; i < count; i++) - v += (double) scalars.arrayZ[i] * deltas.arrayZ[i].to_real (); + v += (double) scalars->arrayZ[i] * deltas.arrayZ[i].to_real (); } } return v; @@ -167,7 +204,8 @@ const CFF2ItemVariationStore *varStore; unsigned int region_count; unsigned int ivs; - hb_vector_t scalars; + hb_vector_t *scalars = nullptr; + hb_atomic_t *> *cached_scalars_vector = nullptr; bool do_blend; bool seen_vsindex_ = false; bool seen_blend = false; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-common.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-common.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-common.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-common.cc 2025-10-13 07:49:24.000000000 +0000 @@ -42,7 +42,7 @@ /* hb_options_t */ -hb_atomic_int_t _hb_options; +hb_atomic_t _hb_options; void _hb_options_init () @@ -273,7 +273,7 @@ /* Thread-safe lockfree language list */ -static hb_atomic_ptr_t langs; +static hb_atomic_t langs; static inline void free_langs () @@ -403,7 +403,7 @@ hb_language_t hb_language_get_default () { - static hb_atomic_ptr_t default_language; + static hb_atomic_t default_language; hb_language_t language = default_language; if (unlikely (language == HB_LANGUAGE_INVALID)) @@ -968,6 +968,9 @@ * understood by hb_feature_from_string(). The client in responsible for * allocating big enough size for @buf, 128 bytes is more than enough. * + * Note that the feature value will be omitted if it is '1', but the + * string won't include any whitespace. + * * Since: 0.9.5 **/ void @@ -1121,6 +1124,8 @@ * understood by hb_variation_from_string(). The client in responsible for * allocating big enough size for @buf, 128 bytes is more than enough. * + * Note that the string won't include any whitespace. + * * Since: 1.4.2 */ void @@ -1212,6 +1217,58 @@ return hb_color_get_blue (color); } +/** + * hb_malloc: + * @size: The size of the memory to allocate. + * + * Allocates @size bytes of memory, using the allocator set at + * compile-time. Typically just malloc(). + * + * Return value: A pointer to the allocated memory. + * + * Since: 11.0.0 + **/ +void* hb_malloc(size_t size) { return hb_malloc_impl (size); } + +/** + * hb_calloc: + * @nmemb: The number of elements to allocate. + * @size: The size of each element. + * + * Allocates @nmemb elements of @size bytes each, initialized to zero, + * using the allocator set at compile-time. Typically just calloc(). + * + * Return value: A pointer to the allocated memory. + * + * Since: 11.0.0 + **/ +void* hb_calloc(size_t nmemb, size_t size) { return hb_calloc_impl (nmemb, size); } + +/** + * hb_realloc: + * @ptr: The pointer to the memory to reallocate. + * @size: The new size of the memory. + * + * Reallocates the memory pointed to by @ptr to @size bytes, using the + * allocator set at compile-time. Typically just realloc(). + * + * Return value: A pointer to the reallocated memory. + * + * Since: 11.0.0 + **/ +void* hb_realloc(void *ptr, size_t size) { return hb_realloc_impl (ptr, size); } + +/** + * hb_free: + * @ptr: The pointer to the memory to free. + * + * Frees the memory pointed to by @ptr, using the allocator set at + * compile-time. Typically just free(). + * + * Since: 11.0.0 + **/ +void hb_free(void *ptr) { hb_free_impl (ptr); } + /* If there is no visibility control, then hb-static.cc will NOT * define anything. Instead, we get it to define one set in here diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-common.h openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-common.h --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-common.h 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-common.h 2025-10-13 07:49:24.000000000 +0000 @@ -65,6 +65,7 @@ #else # include #endif +#include #if defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) #define HB_DEPRECATED __attribute__((__deprecated__)) @@ -337,437 +338,7 @@ hb_language_matches (hb_language_t language, hb_language_t specific); -/** - * hb_script_t: - * @HB_SCRIPT_COMMON: `Zyyy` - * @HB_SCRIPT_INHERITED: `Zinh` - * @HB_SCRIPT_UNKNOWN: `Zzzz` - * @HB_SCRIPT_ARABIC: `Arab` - * @HB_SCRIPT_ARMENIAN: `Armn` - * @HB_SCRIPT_BENGALI: `Beng` - * @HB_SCRIPT_CYRILLIC: `Cyrl` - * @HB_SCRIPT_DEVANAGARI: `Deva` - * @HB_SCRIPT_GEORGIAN: `Geor` - * @HB_SCRIPT_GREEK: `Grek` - * @HB_SCRIPT_GUJARATI: `Gujr` - * @HB_SCRIPT_GURMUKHI: `Guru` - * @HB_SCRIPT_HANGUL: `Hang` - * @HB_SCRIPT_HAN: `Hani` - * @HB_SCRIPT_HEBREW: `Hebr` - * @HB_SCRIPT_HIRAGANA: `Hira` - * @HB_SCRIPT_KANNADA: `Knda` - * @HB_SCRIPT_KATAKANA: `Kana` - * @HB_SCRIPT_LAO: `Laoo` - * @HB_SCRIPT_LATIN: `Latn` - * @HB_SCRIPT_MALAYALAM: `Mlym` - * @HB_SCRIPT_ORIYA: `Orya` - * @HB_SCRIPT_TAMIL: `Taml` - * @HB_SCRIPT_TELUGU: `Telu` - * @HB_SCRIPT_THAI: `Thai` - * @HB_SCRIPT_TIBETAN: `Tibt` - * @HB_SCRIPT_BOPOMOFO: `Bopo` - * @HB_SCRIPT_BRAILLE: `Brai` - * @HB_SCRIPT_CANADIAN_SYLLABICS: `Cans` - * @HB_SCRIPT_CHEROKEE: `Cher` - * @HB_SCRIPT_ETHIOPIC: `Ethi` - * @HB_SCRIPT_KHMER: `Khmr` - * @HB_SCRIPT_MONGOLIAN: `Mong` - * @HB_SCRIPT_MYANMAR: `Mymr` - * @HB_SCRIPT_OGHAM: `Ogam` - * @HB_SCRIPT_RUNIC: `Runr` - * @HB_SCRIPT_SINHALA: `Sinh` - * @HB_SCRIPT_SYRIAC: `Syrc` - * @HB_SCRIPT_THAANA: `Thaa` - * @HB_SCRIPT_YI: `Yiii` - * @HB_SCRIPT_DESERET: `Dsrt` - * @HB_SCRIPT_GOTHIC: `Goth` - * @HB_SCRIPT_OLD_ITALIC: `Ital` - * @HB_SCRIPT_BUHID: `Buhd` - * @HB_SCRIPT_HANUNOO: `Hano` - * @HB_SCRIPT_TAGALOG: `Tglg` - * @HB_SCRIPT_TAGBANWA: `Tagb` - * @HB_SCRIPT_CYPRIOT: `Cprt` - * @HB_SCRIPT_LIMBU: `Limb` - * @HB_SCRIPT_LINEAR_B: `Linb` - * @HB_SCRIPT_OSMANYA: `Osma` - * @HB_SCRIPT_SHAVIAN: `Shaw` - * @HB_SCRIPT_TAI_LE: `Tale` - * @HB_SCRIPT_UGARITIC: `Ugar` - * @HB_SCRIPT_BUGINESE: `Bugi` - * @HB_SCRIPT_COPTIC: `Copt` - * @HB_SCRIPT_GLAGOLITIC: `Glag` - * @HB_SCRIPT_KHAROSHTHI: `Khar` - * @HB_SCRIPT_NEW_TAI_LUE: `Talu` - * @HB_SCRIPT_OLD_PERSIAN: `Xpeo` - * @HB_SCRIPT_SYLOTI_NAGRI: `Sylo` - * @HB_SCRIPT_TIFINAGH: `Tfng` - * @HB_SCRIPT_BALINESE: `Bali` - * @HB_SCRIPT_CUNEIFORM: `Xsux` - * @HB_SCRIPT_NKO: `Nkoo` - * @HB_SCRIPT_PHAGS_PA: `Phag` - * @HB_SCRIPT_PHOENICIAN: `Phnx` - * @HB_SCRIPT_CARIAN: `Cari` - * @HB_SCRIPT_CHAM: `Cham` - * @HB_SCRIPT_KAYAH_LI: `Kali` - * @HB_SCRIPT_LEPCHA: `Lepc` - * @HB_SCRIPT_LYCIAN: `Lyci` - * @HB_SCRIPT_LYDIAN: `Lydi` - * @HB_SCRIPT_OL_CHIKI: `Olck` - * @HB_SCRIPT_REJANG: `Rjng` - * @HB_SCRIPT_SAURASHTRA: `Saur` - * @HB_SCRIPT_SUNDANESE: `Sund` - * @HB_SCRIPT_VAI: `Vaii` - * @HB_SCRIPT_AVESTAN: `Avst` - * @HB_SCRIPT_BAMUM: `Bamu` - * @HB_SCRIPT_EGYPTIAN_HIEROGLYPHS: `Egyp` - * @HB_SCRIPT_IMPERIAL_ARAMAIC: `Armi` - * @HB_SCRIPT_INSCRIPTIONAL_PAHLAVI: `Phli` - * @HB_SCRIPT_INSCRIPTIONAL_PARTHIAN: `Prti` - * @HB_SCRIPT_JAVANESE: `Java` - * @HB_SCRIPT_KAITHI: `Kthi` - * @HB_SCRIPT_LISU: `Lisu` - * @HB_SCRIPT_MEETEI_MAYEK: `Mtei` - * @HB_SCRIPT_OLD_SOUTH_ARABIAN: `Sarb` - * @HB_SCRIPT_OLD_TURKIC: `Orkh` - * @HB_SCRIPT_SAMARITAN: `Samr` - * @HB_SCRIPT_TAI_THAM: `Lana` - * @HB_SCRIPT_TAI_VIET: `Tavt` - * @HB_SCRIPT_BATAK: `Batk` - * @HB_SCRIPT_BRAHMI: `Brah` - * @HB_SCRIPT_MANDAIC: `Mand` - * @HB_SCRIPT_CHAKMA: `Cakm` - * @HB_SCRIPT_MEROITIC_CURSIVE: `Merc` - * @HB_SCRIPT_MEROITIC_HIEROGLYPHS: `Mero` - * @HB_SCRIPT_MIAO: `Plrd` - * @HB_SCRIPT_SHARADA: `Shrd` - * @HB_SCRIPT_SORA_SOMPENG: `Sora` - * @HB_SCRIPT_TAKRI: `Takr` - * @HB_SCRIPT_BASSA_VAH: `Bass`, Since: 0.9.30 - * @HB_SCRIPT_CAUCASIAN_ALBANIAN: `Aghb`, Since: 0.9.30 - * @HB_SCRIPT_DUPLOYAN: `Dupl`, Since: 0.9.30 - * @HB_SCRIPT_ELBASAN: `Elba`, Since: 0.9.30 - * @HB_SCRIPT_GRANTHA: `Gran`, Since: 0.9.30 - * @HB_SCRIPT_KHOJKI: `Khoj`, Since: 0.9.30 - * @HB_SCRIPT_KHUDAWADI: `Sind`, Since: 0.9.30 - * @HB_SCRIPT_LINEAR_A: `Lina`, Since: 0.9.30 - * @HB_SCRIPT_MAHAJANI: `Mahj`, Since: 0.9.30 - * @HB_SCRIPT_MANICHAEAN: `Mani`, Since: 0.9.30 - * @HB_SCRIPT_MENDE_KIKAKUI: `Mend`, Since: 0.9.30 - * @HB_SCRIPT_MODI: `Modi`, Since: 0.9.30 - * @HB_SCRIPT_MRO: `Mroo`, Since: 0.9.30 - * @HB_SCRIPT_NABATAEAN: `Nbat`, Since: 0.9.30 - * @HB_SCRIPT_OLD_NORTH_ARABIAN: `Narb`, Since: 0.9.30 - * @HB_SCRIPT_OLD_PERMIC: `Perm`, Since: 0.9.30 - * @HB_SCRIPT_PAHAWH_HMONG: `Hmng`, Since: 0.9.30 - * @HB_SCRIPT_PALMYRENE: `Palm`, Since: 0.9.30 - * @HB_SCRIPT_PAU_CIN_HAU: `Pauc`, Since: 0.9.30 - * @HB_SCRIPT_PSALTER_PAHLAVI: `Phlp`, Since: 0.9.30 - * @HB_SCRIPT_SIDDHAM: `Sidd`, Since: 0.9.30 - * @HB_SCRIPT_TIRHUTA: `Tirh`, Since: 0.9.30 - * @HB_SCRIPT_WARANG_CITI: `Wara`, Since: 0.9.30 - * @HB_SCRIPT_AHOM: `Ahom`, Since: 0.9.30 - * @HB_SCRIPT_ANATOLIAN_HIEROGLYPHS: `Hluw`, Since: 0.9.30 - * @HB_SCRIPT_HATRAN: `Hatr`, Since: 0.9.30 - * @HB_SCRIPT_MULTANI: `Mult`, Since: 0.9.30 - * @HB_SCRIPT_OLD_HUNGARIAN: `Hung`, Since: 0.9.30 - * @HB_SCRIPT_SIGNWRITING: `Sgnw`, Since: 0.9.30 - * @HB_SCRIPT_ADLAM: `Adlm`, Since: 1.3.0 - * @HB_SCRIPT_BHAIKSUKI: `Bhks`, Since: 1.3.0 - * @HB_SCRIPT_MARCHEN: `Marc`, Since: 1.3.0 - * @HB_SCRIPT_OSAGE: `Osge`, Since: 1.3.0 - * @HB_SCRIPT_TANGUT: `Tang`, Since: 1.3.0 - * @HB_SCRIPT_NEWA: `Newa`, Since: 1.3.0 - * @HB_SCRIPT_MASARAM_GONDI: `Gonm`, Since: 1.6.0 - * @HB_SCRIPT_NUSHU: `Nshu`, Since: 1.6.0 - * @HB_SCRIPT_SOYOMBO: `Soyo`, Since: 1.6.0 - * @HB_SCRIPT_ZANABAZAR_SQUARE: `Zanb`, Since: 1.6.0 - * @HB_SCRIPT_DOGRA: `Dogr`, Since: 1.8.0 - * @HB_SCRIPT_GUNJALA_GONDI: `Gong`, Since: 1.8.0 - * @HB_SCRIPT_HANIFI_ROHINGYA: `Rohg`, Since: 1.8.0 - * @HB_SCRIPT_MAKASAR: `Maka`, Since: 1.8.0 - * @HB_SCRIPT_MEDEFAIDRIN: `Medf`, Since: 1.8.0 - * @HB_SCRIPT_OLD_SOGDIAN: `Sogo`, Since: 1.8.0 - * @HB_SCRIPT_SOGDIAN: `Sogd`, Since: 1.8.0 - * @HB_SCRIPT_ELYMAIC: `Elym`, Since: 2.4.0 - * @HB_SCRIPT_NANDINAGARI: `Nand`, Since: 2.4.0 - * @HB_SCRIPT_NYIAKENG_PUACHUE_HMONG: `Hmnp`, Since: 2.4.0 - * @HB_SCRIPT_WANCHO: `Wcho`, Since: 2.4.0 - * @HB_SCRIPT_CHORASMIAN: `Chrs`, Since: 2.6.7 - * @HB_SCRIPT_DIVES_AKURU: `Diak`, Since: 2.6.7 - * @HB_SCRIPT_KHITAN_SMALL_SCRIPT: `Kits`, Since: 2.6.7 - * @HB_SCRIPT_YEZIDI: `Yezi`, Since: 2.6.7 - * @HB_SCRIPT_CYPRO_MINOAN: `Cpmn`, Since: 3.0.0 - * @HB_SCRIPT_OLD_UYGHUR: `Ougr`, Since: 3.0.0 - * @HB_SCRIPT_TANGSA: `Tnsa`, Since: 3.0.0 - * @HB_SCRIPT_TOTO: `Toto`, Since: 3.0.0 - * @HB_SCRIPT_VITHKUQI: `Vith`, Since: 3.0.0 - * @HB_SCRIPT_MATH: `Zmth`, Since: 3.4.0 - * @HB_SCRIPT_KAWI: `Kawi`, Since: 5.2.0 - * @HB_SCRIPT_NAG_MUNDARI: `Nagm`, Since: 5.2.0 - * @HB_SCRIPT_GARAY: `Gara`, Since: 10.0.0 - * @HB_SCRIPT_GURUNG_KHEMA: `Gukh`, Since: 10.0.0 - * @HB_SCRIPT_KIRAT_RAI: `Krai`, Since: 10.0.0 - * @HB_SCRIPT_OL_ONAL: `Onao`, Since: 10.0.0 - * @HB_SCRIPT_SUNUWAR: `Sunu`, Since: 10.0.0 - * @HB_SCRIPT_TODHRI: `Todr`, Since: 10.0.0 - * @HB_SCRIPT_TULU_TIGALARI: `Tutg`, Since: 10.0.0 - * @HB_SCRIPT_INVALID: No script set - * - * Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding - * to the four-letter values defined by [ISO 15924](https://unicode.org/iso15924/). - * - * See also the Script (sc) property of the Unicode Character Database. - * - **/ - -/* https://docs.google.com/spreadsheets/d/1Y90M0Ie3MUJ6UVCRDOypOtijlMDLNNyyLk36T6iMu0o */ -typedef enum -{ - HB_SCRIPT_COMMON = HB_TAG ('Z','y','y','y'), /*1.1*/ - HB_SCRIPT_INHERITED = HB_TAG ('Z','i','n','h'), /*1.1*/ - HB_SCRIPT_UNKNOWN = HB_TAG ('Z','z','z','z'), /*5.0*/ - - HB_SCRIPT_ARABIC = HB_TAG ('A','r','a','b'), /*1.1*/ - HB_SCRIPT_ARMENIAN = HB_TAG ('A','r','m','n'), /*1.1*/ - HB_SCRIPT_BENGALI = HB_TAG ('B','e','n','g'), /*1.1*/ - HB_SCRIPT_CYRILLIC = HB_TAG ('C','y','r','l'), /*1.1*/ - HB_SCRIPT_DEVANAGARI = HB_TAG ('D','e','v','a'), /*1.1*/ - HB_SCRIPT_GEORGIAN = HB_TAG ('G','e','o','r'), /*1.1*/ - HB_SCRIPT_GREEK = HB_TAG ('G','r','e','k'), /*1.1*/ - HB_SCRIPT_GUJARATI = HB_TAG ('G','u','j','r'), /*1.1*/ - HB_SCRIPT_GURMUKHI = HB_TAG ('G','u','r','u'), /*1.1*/ - HB_SCRIPT_HANGUL = HB_TAG ('H','a','n','g'), /*1.1*/ - HB_SCRIPT_HAN = HB_TAG ('H','a','n','i'), /*1.1*/ - HB_SCRIPT_HEBREW = HB_TAG ('H','e','b','r'), /*1.1*/ - HB_SCRIPT_HIRAGANA = HB_TAG ('H','i','r','a'), /*1.1*/ - HB_SCRIPT_KANNADA = HB_TAG ('K','n','d','a'), /*1.1*/ - HB_SCRIPT_KATAKANA = HB_TAG ('K','a','n','a'), /*1.1*/ - HB_SCRIPT_LAO = HB_TAG ('L','a','o','o'), /*1.1*/ - HB_SCRIPT_LATIN = HB_TAG ('L','a','t','n'), /*1.1*/ - HB_SCRIPT_MALAYALAM = HB_TAG ('M','l','y','m'), /*1.1*/ - HB_SCRIPT_ORIYA = HB_TAG ('O','r','y','a'), /*1.1*/ - HB_SCRIPT_TAMIL = HB_TAG ('T','a','m','l'), /*1.1*/ - HB_SCRIPT_TELUGU = HB_TAG ('T','e','l','u'), /*1.1*/ - HB_SCRIPT_THAI = HB_TAG ('T','h','a','i'), /*1.1*/ - - HB_SCRIPT_TIBETAN = HB_TAG ('T','i','b','t'), /*2.0*/ - - HB_SCRIPT_BOPOMOFO = HB_TAG ('B','o','p','o'), /*3.0*/ - HB_SCRIPT_BRAILLE = HB_TAG ('B','r','a','i'), /*3.0*/ - HB_SCRIPT_CANADIAN_SYLLABICS = HB_TAG ('C','a','n','s'), /*3.0*/ - HB_SCRIPT_CHEROKEE = HB_TAG ('C','h','e','r'), /*3.0*/ - HB_SCRIPT_ETHIOPIC = HB_TAG ('E','t','h','i'), /*3.0*/ - HB_SCRIPT_KHMER = HB_TAG ('K','h','m','r'), /*3.0*/ - HB_SCRIPT_MONGOLIAN = HB_TAG ('M','o','n','g'), /*3.0*/ - HB_SCRIPT_MYANMAR = HB_TAG ('M','y','m','r'), /*3.0*/ - HB_SCRIPT_OGHAM = HB_TAG ('O','g','a','m'), /*3.0*/ - HB_SCRIPT_RUNIC = HB_TAG ('R','u','n','r'), /*3.0*/ - HB_SCRIPT_SINHALA = HB_TAG ('S','i','n','h'), /*3.0*/ - HB_SCRIPT_SYRIAC = HB_TAG ('S','y','r','c'), /*3.0*/ - HB_SCRIPT_THAANA = HB_TAG ('T','h','a','a'), /*3.0*/ - HB_SCRIPT_YI = HB_TAG ('Y','i','i','i'), /*3.0*/ - - HB_SCRIPT_DESERET = HB_TAG ('D','s','r','t'), /*3.1*/ - HB_SCRIPT_GOTHIC = HB_TAG ('G','o','t','h'), /*3.1*/ - HB_SCRIPT_OLD_ITALIC = HB_TAG ('I','t','a','l'), /*3.1*/ - - HB_SCRIPT_BUHID = HB_TAG ('B','u','h','d'), /*3.2*/ - HB_SCRIPT_HANUNOO = HB_TAG ('H','a','n','o'), /*3.2*/ - HB_SCRIPT_TAGALOG = HB_TAG ('T','g','l','g'), /*3.2*/ - HB_SCRIPT_TAGBANWA = HB_TAG ('T','a','g','b'), /*3.2*/ - - HB_SCRIPT_CYPRIOT = HB_TAG ('C','p','r','t'), /*4.0*/ - HB_SCRIPT_LIMBU = HB_TAG ('L','i','m','b'), /*4.0*/ - HB_SCRIPT_LINEAR_B = HB_TAG ('L','i','n','b'), /*4.0*/ - HB_SCRIPT_OSMANYA = HB_TAG ('O','s','m','a'), /*4.0*/ - HB_SCRIPT_SHAVIAN = HB_TAG ('S','h','a','w'), /*4.0*/ - HB_SCRIPT_TAI_LE = HB_TAG ('T','a','l','e'), /*4.0*/ - HB_SCRIPT_UGARITIC = HB_TAG ('U','g','a','r'), /*4.0*/ - - HB_SCRIPT_BUGINESE = HB_TAG ('B','u','g','i'), /*4.1*/ - HB_SCRIPT_COPTIC = HB_TAG ('C','o','p','t'), /*4.1*/ - HB_SCRIPT_GLAGOLITIC = HB_TAG ('G','l','a','g'), /*4.1*/ - HB_SCRIPT_KHAROSHTHI = HB_TAG ('K','h','a','r'), /*4.1*/ - HB_SCRIPT_NEW_TAI_LUE = HB_TAG ('T','a','l','u'), /*4.1*/ - HB_SCRIPT_OLD_PERSIAN = HB_TAG ('X','p','e','o'), /*4.1*/ - HB_SCRIPT_SYLOTI_NAGRI = HB_TAG ('S','y','l','o'), /*4.1*/ - HB_SCRIPT_TIFINAGH = HB_TAG ('T','f','n','g'), /*4.1*/ - - HB_SCRIPT_BALINESE = HB_TAG ('B','a','l','i'), /*5.0*/ - HB_SCRIPT_CUNEIFORM = HB_TAG ('X','s','u','x'), /*5.0*/ - HB_SCRIPT_NKO = HB_TAG ('N','k','o','o'), /*5.0*/ - HB_SCRIPT_PHAGS_PA = HB_TAG ('P','h','a','g'), /*5.0*/ - HB_SCRIPT_PHOENICIAN = HB_TAG ('P','h','n','x'), /*5.0*/ - - HB_SCRIPT_CARIAN = HB_TAG ('C','a','r','i'), /*5.1*/ - HB_SCRIPT_CHAM = HB_TAG ('C','h','a','m'), /*5.1*/ - HB_SCRIPT_KAYAH_LI = HB_TAG ('K','a','l','i'), /*5.1*/ - HB_SCRIPT_LEPCHA = HB_TAG ('L','e','p','c'), /*5.1*/ - HB_SCRIPT_LYCIAN = HB_TAG ('L','y','c','i'), /*5.1*/ - HB_SCRIPT_LYDIAN = HB_TAG ('L','y','d','i'), /*5.1*/ - HB_SCRIPT_OL_CHIKI = HB_TAG ('O','l','c','k'), /*5.1*/ - HB_SCRIPT_REJANG = HB_TAG ('R','j','n','g'), /*5.1*/ - HB_SCRIPT_SAURASHTRA = HB_TAG ('S','a','u','r'), /*5.1*/ - HB_SCRIPT_SUNDANESE = HB_TAG ('S','u','n','d'), /*5.1*/ - HB_SCRIPT_VAI = HB_TAG ('V','a','i','i'), /*5.1*/ - - HB_SCRIPT_AVESTAN = HB_TAG ('A','v','s','t'), /*5.2*/ - HB_SCRIPT_BAMUM = HB_TAG ('B','a','m','u'), /*5.2*/ - HB_SCRIPT_EGYPTIAN_HIEROGLYPHS = HB_TAG ('E','g','y','p'), /*5.2*/ - HB_SCRIPT_IMPERIAL_ARAMAIC = HB_TAG ('A','r','m','i'), /*5.2*/ - HB_SCRIPT_INSCRIPTIONAL_PAHLAVI = HB_TAG ('P','h','l','i'), /*5.2*/ - HB_SCRIPT_INSCRIPTIONAL_PARTHIAN = HB_TAG ('P','r','t','i'), /*5.2*/ - HB_SCRIPT_JAVANESE = HB_TAG ('J','a','v','a'), /*5.2*/ - HB_SCRIPT_KAITHI = HB_TAG ('K','t','h','i'), /*5.2*/ - HB_SCRIPT_LISU = HB_TAG ('L','i','s','u'), /*5.2*/ - HB_SCRIPT_MEETEI_MAYEK = HB_TAG ('M','t','e','i'), /*5.2*/ - HB_SCRIPT_OLD_SOUTH_ARABIAN = HB_TAG ('S','a','r','b'), /*5.2*/ - HB_SCRIPT_OLD_TURKIC = HB_TAG ('O','r','k','h'), /*5.2*/ - HB_SCRIPT_SAMARITAN = HB_TAG ('S','a','m','r'), /*5.2*/ - HB_SCRIPT_TAI_THAM = HB_TAG ('L','a','n','a'), /*5.2*/ - HB_SCRIPT_TAI_VIET = HB_TAG ('T','a','v','t'), /*5.2*/ - - HB_SCRIPT_BATAK = HB_TAG ('B','a','t','k'), /*6.0*/ - HB_SCRIPT_BRAHMI = HB_TAG ('B','r','a','h'), /*6.0*/ - HB_SCRIPT_MANDAIC = HB_TAG ('M','a','n','d'), /*6.0*/ - - HB_SCRIPT_CHAKMA = HB_TAG ('C','a','k','m'), /*6.1*/ - HB_SCRIPT_MEROITIC_CURSIVE = HB_TAG ('M','e','r','c'), /*6.1*/ - HB_SCRIPT_MEROITIC_HIEROGLYPHS = HB_TAG ('M','e','r','o'), /*6.1*/ - HB_SCRIPT_MIAO = HB_TAG ('P','l','r','d'), /*6.1*/ - HB_SCRIPT_SHARADA = HB_TAG ('S','h','r','d'), /*6.1*/ - HB_SCRIPT_SORA_SOMPENG = HB_TAG ('S','o','r','a'), /*6.1*/ - HB_SCRIPT_TAKRI = HB_TAG ('T','a','k','r'), /*6.1*/ - - /* - * Since: 0.9.30 - */ - HB_SCRIPT_BASSA_VAH = HB_TAG ('B','a','s','s'), /*7.0*/ - HB_SCRIPT_CAUCASIAN_ALBANIAN = HB_TAG ('A','g','h','b'), /*7.0*/ - HB_SCRIPT_DUPLOYAN = HB_TAG ('D','u','p','l'), /*7.0*/ - HB_SCRIPT_ELBASAN = HB_TAG ('E','l','b','a'), /*7.0*/ - HB_SCRIPT_GRANTHA = HB_TAG ('G','r','a','n'), /*7.0*/ - HB_SCRIPT_KHOJKI = HB_TAG ('K','h','o','j'), /*7.0*/ - HB_SCRIPT_KHUDAWADI = HB_TAG ('S','i','n','d'), /*7.0*/ - HB_SCRIPT_LINEAR_A = HB_TAG ('L','i','n','a'), /*7.0*/ - HB_SCRIPT_MAHAJANI = HB_TAG ('M','a','h','j'), /*7.0*/ - HB_SCRIPT_MANICHAEAN = HB_TAG ('M','a','n','i'), /*7.0*/ - HB_SCRIPT_MENDE_KIKAKUI = HB_TAG ('M','e','n','d'), /*7.0*/ - HB_SCRIPT_MODI = HB_TAG ('M','o','d','i'), /*7.0*/ - HB_SCRIPT_MRO = HB_TAG ('M','r','o','o'), /*7.0*/ - HB_SCRIPT_NABATAEAN = HB_TAG ('N','b','a','t'), /*7.0*/ - HB_SCRIPT_OLD_NORTH_ARABIAN = HB_TAG ('N','a','r','b'), /*7.0*/ - HB_SCRIPT_OLD_PERMIC = HB_TAG ('P','e','r','m'), /*7.0*/ - HB_SCRIPT_PAHAWH_HMONG = HB_TAG ('H','m','n','g'), /*7.0*/ - HB_SCRIPT_PALMYRENE = HB_TAG ('P','a','l','m'), /*7.0*/ - HB_SCRIPT_PAU_CIN_HAU = HB_TAG ('P','a','u','c'), /*7.0*/ - HB_SCRIPT_PSALTER_PAHLAVI = HB_TAG ('P','h','l','p'), /*7.0*/ - HB_SCRIPT_SIDDHAM = HB_TAG ('S','i','d','d'), /*7.0*/ - HB_SCRIPT_TIRHUTA = HB_TAG ('T','i','r','h'), /*7.0*/ - HB_SCRIPT_WARANG_CITI = HB_TAG ('W','a','r','a'), /*7.0*/ - - HB_SCRIPT_AHOM = HB_TAG ('A','h','o','m'), /*8.0*/ - HB_SCRIPT_ANATOLIAN_HIEROGLYPHS = HB_TAG ('H','l','u','w'), /*8.0*/ - HB_SCRIPT_HATRAN = HB_TAG ('H','a','t','r'), /*8.0*/ - HB_SCRIPT_MULTANI = HB_TAG ('M','u','l','t'), /*8.0*/ - HB_SCRIPT_OLD_HUNGARIAN = HB_TAG ('H','u','n','g'), /*8.0*/ - HB_SCRIPT_SIGNWRITING = HB_TAG ('S','g','n','w'), /*8.0*/ - - /* - * Since 1.3.0 - */ - HB_SCRIPT_ADLAM = HB_TAG ('A','d','l','m'), /*9.0*/ - HB_SCRIPT_BHAIKSUKI = HB_TAG ('B','h','k','s'), /*9.0*/ - HB_SCRIPT_MARCHEN = HB_TAG ('M','a','r','c'), /*9.0*/ - HB_SCRIPT_OSAGE = HB_TAG ('O','s','g','e'), /*9.0*/ - HB_SCRIPT_TANGUT = HB_TAG ('T','a','n','g'), /*9.0*/ - HB_SCRIPT_NEWA = HB_TAG ('N','e','w','a'), /*9.0*/ - - /* - * Since 1.6.0 - */ - HB_SCRIPT_MASARAM_GONDI = HB_TAG ('G','o','n','m'), /*10.0*/ - HB_SCRIPT_NUSHU = HB_TAG ('N','s','h','u'), /*10.0*/ - HB_SCRIPT_SOYOMBO = HB_TAG ('S','o','y','o'), /*10.0*/ - HB_SCRIPT_ZANABAZAR_SQUARE = HB_TAG ('Z','a','n','b'), /*10.0*/ - - /* - * Since 1.8.0 - */ - HB_SCRIPT_DOGRA = HB_TAG ('D','o','g','r'), /*11.0*/ - HB_SCRIPT_GUNJALA_GONDI = HB_TAG ('G','o','n','g'), /*11.0*/ - HB_SCRIPT_HANIFI_ROHINGYA = HB_TAG ('R','o','h','g'), /*11.0*/ - HB_SCRIPT_MAKASAR = HB_TAG ('M','a','k','a'), /*11.0*/ - HB_SCRIPT_MEDEFAIDRIN = HB_TAG ('M','e','d','f'), /*11.0*/ - HB_SCRIPT_OLD_SOGDIAN = HB_TAG ('S','o','g','o'), /*11.0*/ - HB_SCRIPT_SOGDIAN = HB_TAG ('S','o','g','d'), /*11.0*/ - - /* - * Since 2.4.0 - */ - HB_SCRIPT_ELYMAIC = HB_TAG ('E','l','y','m'), /*12.0*/ - HB_SCRIPT_NANDINAGARI = HB_TAG ('N','a','n','d'), /*12.0*/ - HB_SCRIPT_NYIAKENG_PUACHUE_HMONG = HB_TAG ('H','m','n','p'), /*12.0*/ - HB_SCRIPT_WANCHO = HB_TAG ('W','c','h','o'), /*12.0*/ - - /* - * Since 2.6.7 - */ - HB_SCRIPT_CHORASMIAN = HB_TAG ('C','h','r','s'), /*13.0*/ - HB_SCRIPT_DIVES_AKURU = HB_TAG ('D','i','a','k'), /*13.0*/ - HB_SCRIPT_KHITAN_SMALL_SCRIPT = HB_TAG ('K','i','t','s'), /*13.0*/ - HB_SCRIPT_YEZIDI = HB_TAG ('Y','e','z','i'), /*13.0*/ - - /* - * Since 3.0.0 - */ - HB_SCRIPT_CYPRO_MINOAN = HB_TAG ('C','p','m','n'), /*14.0*/ - HB_SCRIPT_OLD_UYGHUR = HB_TAG ('O','u','g','r'), /*14.0*/ - HB_SCRIPT_TANGSA = HB_TAG ('T','n','s','a'), /*14.0*/ - HB_SCRIPT_TOTO = HB_TAG ('T','o','t','o'), /*14.0*/ - HB_SCRIPT_VITHKUQI = HB_TAG ('V','i','t','h'), /*14.0*/ - - /* - * Since 3.4.0 - */ - HB_SCRIPT_MATH = HB_TAG ('Z','m','t','h'), - - /* - * Since 5.2.0 - */ - HB_SCRIPT_KAWI = HB_TAG ('K','a','w','i'), /*15.0*/ - HB_SCRIPT_NAG_MUNDARI = HB_TAG ('N','a','g','m'), /*15.0*/ - - /* - * Since 10.0.0 - */ - HB_SCRIPT_GARAY = HB_TAG ('G','a','r','a'), /*16.0*/ - HB_SCRIPT_GURUNG_KHEMA = HB_TAG ('G','u','k','h'), /*16.0*/ - HB_SCRIPT_KIRAT_RAI = HB_TAG ('K','r','a','i'), /*16.0*/ - HB_SCRIPT_OL_ONAL = HB_TAG ('O','n','a','o'), /*16.0*/ - HB_SCRIPT_SUNUWAR = HB_TAG ('S','u','n','u'), /*16.0*/ - HB_SCRIPT_TODHRI = HB_TAG ('T','o','d','r'), /*16.0*/ - HB_SCRIPT_TULU_TIGALARI = HB_TAG ('T','u','t','g'), /*16.0*/ - - /* No script set. */ - HB_SCRIPT_INVALID = HB_TAG_NONE, - - /*< private >*/ - - /* Dummy values to ensure any hb_tag_t value can be passed/stored as hb_script_t - * without risking undefined behavior. We have two, for historical reasons. - * HB_TAG_MAX used to be unsigned, but that was invalid Ansi C, so was changed - * to _HB_SCRIPT_MAX_VALUE to be equal to HB_TAG_MAX_SIGNED as well. - * - * See this thread for technicalities: - * - * https://lists.freedesktop.org/archives/harfbuzz/2014-March/004150.html - */ - _HB_SCRIPT_MAX_VALUE = HB_TAG_MAX_SIGNED, /*< skip >*/ - _HB_SCRIPT_MAX_VALUE_SIGNED = HB_TAG_MAX_SIGNED /*< skip >*/ - -} hb_script_t; - +#include "hb-script-list.h" /* Script functions */ @@ -948,6 +519,16 @@ */ typedef struct hb_font_t hb_font_t; +/* Not of much use to clients. */ +HB_EXTERN void* +hb_malloc (size_t size); +HB_EXTERN void* +hb_calloc (size_t nmemb, size_t size); +HB_EXTERN void* +hb_realloc (void *ptr, size_t size); +HB_EXTERN void +hb_free (void *ptr); + HB_END_DECLS #endif /* HB_COMMON_H */ diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-config.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-config.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-config.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-config.hh 2025-10-13 07:49:24.000000000 +0000 @@ -146,6 +146,7 @@ #ifdef HB_NO_DRAW #define HB_NO_OUTLINE +#define HB_NO_PAINT #endif #ifdef HB_NO_GETENV @@ -191,7 +192,6 @@ #ifdef HB_MINIMIZE_MEMORY_USAGE #define HB_NO_GDEF_CACHE #define HB_NO_OT_LAYOUT_LOOKUP_CACHE -#define HB_NO_OT_FONT_ADVANCE_CACHE #define HB_NO_OT_FONT_CMAP_CACHE #endif diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-debug.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-debug.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-debug.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-debug.hh 2025-10-13 07:49:24.000000000 +0000 @@ -49,15 +49,15 @@ }; union hb_options_union_t { - int i; + unsigned i; hb_options_t opts; }; -static_assert ((sizeof (hb_atomic_int_t) >= sizeof (hb_options_union_t)), ""); +static_assert ((sizeof (hb_atomic_t) >= sizeof (hb_options_union_t)), ""); HB_INTERNAL void _hb_options_init (); -extern HB_INTERNAL hb_atomic_int_t _hb_options; +extern HB_INTERNAL hb_atomic_t _hb_options; static inline hb_options_t hb_options () diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h 2025-10-13 07:49:24.000000000 +0000 @@ -276,6 +276,48 @@ void *user_data); /** + * hb_font_draw_glyph_func_t: + * @font: #hb_font_t to work upon + * @font_data: @font user data pointer + * @glyph: The glyph ID to query + * @draw_funcs: The draw functions to send the shape data to + * @draw_data: The data accompanying the draw functions + * @user_data: User data pointer passed by the caller + * + * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. + * + * Since: 7.0.0 + * XDeprecated: REPLACEME: Use hb_font_draw_glyph_func_or_fail_t instead. + **/ +typedef void (*hb_font_draw_glyph_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, void *draw_data, + void *user_data); + +/** + * hb_font_paint_glyph_func_t: + * @font: #hb_font_t to work upon + * @font_data: @font user data pointer + * @glyph: The glyph ID to query + * @paint_funcs: The paint functions to use + * @paint_data: The data accompanying the paint functions + * @palette_index: The color palette to use + * @foreground: The foreground color + * @user_data: User data pointer passed by the caller + * + * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. + * + * Since: 7.0.0 + * XDeprecated: REPLACEME: Use hb_font_paint_glyph_or_fail_func_t instead. + */ +typedef hb_bool_t (*hb_font_paint_glyph_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t glyph, + hb_paint_funcs_t *paint_funcs, void *paint_data, + unsigned int palette_index, + hb_color_t foreground, + void *user_data); + +/** * hb_font_funcs_set_glyph_shape_func: * @ffuncs: A font-function structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign @@ -288,13 +330,49 @@ * Since: 4.0.0 * Deprecated: 7.0.0: Use hb_font_funcs_set_draw_glyph_func() instead **/ -HB_DEPRECATED_FOR (hb_font_funcs_set_draw_glyph_func) +HB_DEPRECATED_FOR (hb_font_funcs_set_draw_glyph_or_fail_func) HB_EXTERN void hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_shape_func_t func, void *user_data, hb_destroy_func_t destroy); -HB_DEPRECATED_FOR (hb_font_draw_glyph) +/** + * hb_font_funcs_set_draw_glyph_func: + * @ffuncs: A font-function structure + * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign + * @user_data: Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is not needed anymore + * + * Sets the implementation function for #hb_font_draw_glyph_func_t. + * + * Since: 7.0.0 + * XDeprecated: REPLACEME: Use hb_font_funcs_set_draw_glyph_or_fail_func instead. + **/ +HB_DEPRECATED_FOR (hb_font_funcs_set_draw_glyph_or_fail_func) +HB_EXTERN void +hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs, + hb_font_draw_glyph_func_t func, + void *user_data, hb_destroy_func_t destroy); + +/** + * hb_font_funcs_set_paint_glyph_func: + * @ffuncs: A font-function structure + * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign + * @user_data: Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is no longer needed + * + * Sets the implementation function for #hb_font_paint_glyph_func_t. + * + * Since: 7.0.0 + * XDeprecated: REPLACEME: Use hb_font_funcs_set_paint_glyph_or_fail_func() instead. + */ +HB_DEPRECATED_FOR (hb_font_funcs_set_paint_glyph_or_fail_func) +HB_EXTERN void +hb_font_funcs_set_paint_glyph_func (hb_font_funcs_t *ffuncs, + hb_font_paint_glyph_func_t func, + void *user_data, hb_destroy_func_t destroy); + +HB_DEPRECATED_FOR (hb_font_draw_glyph_or_fail) HB_EXTERN void hb_font_get_glyph_shape (hb_font_t *font, hb_codepoint_t glyph, diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-draw.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-draw.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-draw.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-draw.cc 2025-10-13 07:49:24.000000000 +0000 @@ -28,6 +28,11 @@ #include "hb-draw.hh" +#include "hb-geometry.hh" + +#include "hb-machinery.hh" + + /** * SECTION:hb-draw * @title: hb-draw @@ -455,4 +460,92 @@ } +static void +hb_draw_extents_move_to (hb_draw_funcs_t *dfuncs HB_UNUSED, + void *data, + hb_draw_state_t *st, + float to_x, float to_y, + void *user_data HB_UNUSED) +{ + hb_extents_t *extents = (hb_extents_t *) data; + + extents->add_point (to_x, to_y); +} + +static void +hb_draw_extents_line_to (hb_draw_funcs_t *dfuncs HB_UNUSED, + void *data, + hb_draw_state_t *st, + float to_x, float to_y, + void *user_data HB_UNUSED) +{ + hb_extents_t *extents = (hb_extents_t *) data; + + extents->add_point (to_x, to_y); +} + +static void +hb_draw_extents_quadratic_to (hb_draw_funcs_t *dfuncs HB_UNUSED, + void *data, + hb_draw_state_t *st, + float control_x, float control_y, + float to_x, float to_y, + void *user_data HB_UNUSED) +{ + hb_extents_t *extents = (hb_extents_t *) data; + + extents->add_point (control_x, control_y); + extents->add_point (to_x, to_y); +} + +static void +hb_draw_extents_cubic_to (hb_draw_funcs_t *dfuncs HB_UNUSED, + void *data, + hb_draw_state_t *st, + float control1_x, float control1_y, + float control2_x, float control2_y, + float to_x, float to_y, + void *user_data HB_UNUSED) +{ + hb_extents_t *extents = (hb_extents_t *) data; + + extents->add_point (control1_x, control1_y); + extents->add_point (control2_x, control2_y); + extents->add_point (to_x, to_y); +} + +static inline void free_static_draw_extents_funcs (); + +static struct hb_draw_extents_funcs_lazy_loader_t : hb_draw_funcs_lazy_loader_t +{ + static hb_draw_funcs_t *create () + { + hb_draw_funcs_t *funcs = hb_draw_funcs_create (); + + hb_draw_funcs_set_move_to_func (funcs, hb_draw_extents_move_to, nullptr, nullptr); + hb_draw_funcs_set_line_to_func (funcs, hb_draw_extents_line_to, nullptr, nullptr); + hb_draw_funcs_set_quadratic_to_func (funcs, hb_draw_extents_quadratic_to, nullptr, nullptr); + hb_draw_funcs_set_cubic_to_func (funcs, hb_draw_extents_cubic_to, nullptr, nullptr); + + hb_draw_funcs_make_immutable (funcs); + + hb_atexit (free_static_draw_extents_funcs); + + return funcs; + } +} static_draw_extents_funcs; + +static inline +void free_static_draw_extents_funcs () +{ + static_draw_extents_funcs.free_instance (); +} + +hb_draw_funcs_t * +hb_draw_extents_get_funcs () +{ + return static_draw_extents_funcs.get_unconst (); +} + + #endif diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-draw.h openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-draw.h --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-draw.h 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-draw.h 2025-10-13 07:49:24.000000000 +0000 @@ -70,7 +70,7 @@ * * The default #hb_draw_state_t at the start of glyph drawing. */ -#define HB_DRAW_STATE_DEFAULT {0, 0.f, 0.f, 0.f, 0.f, {0.}, {0.}, {0.}, {0.}, {0.}, {0.}, {0.}} +#define HB_DRAW_STATE_DEFAULT {0, 0.f, 0.f, 0.f, 0.f, {0}, {0}, {0}, {0}, {0}, {0}, {0}} /** diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-draw.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-draw.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-draw.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-draw.hh 2025-10-13 07:49:24.000000000 +0000 @@ -99,6 +99,7 @@ float to_x, float to_y) { if (unlikely (st.path_open)) close_path (draw_data, st); + st.current_x = to_x; st.current_y = to_y; } @@ -109,7 +110,9 @@ float to_x, float to_y) { if (unlikely (!st.path_open)) start_path (draw_data, st); + emit_line_to (draw_data, st, to_x, to_y); + st.current_x = to_x; st.current_y = to_y; } @@ -121,7 +124,9 @@ float to_x, float to_y) { if (unlikely (!st.path_open)) start_path (draw_data, st); + emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y); + st.current_x = to_x; st.current_y = to_y; } @@ -134,7 +139,9 @@ float to_x, float to_y) { if (unlikely (!st.path_open)) start_path (draw_data, st); + emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y); + st.current_x = to_x; st.current_y = to_y; } @@ -168,9 +175,8 @@ struct hb_draw_session_t { - hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_, float slant_ = 0.f) - : slant {slant_}, not_slanted {slant == 0.f}, - funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT + hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_) + : funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT {} ~hb_draw_session_t () { close_path (); } @@ -178,36 +184,23 @@ HB_ALWAYS_INLINE void move_to (float to_x, float to_y) { - if (likely (not_slanted)) - funcs->move_to (draw_data, st, - to_x, to_y); - else - funcs->move_to (draw_data, st, - to_x + to_y * slant, to_y); + funcs->move_to (draw_data, st, + to_x, to_y); } HB_ALWAYS_INLINE void line_to (float to_x, float to_y) { - if (likely (not_slanted)) - funcs->line_to (draw_data, st, - to_x, to_y); - else - funcs->line_to (draw_data, st, - to_x + to_y * slant, to_y); + funcs->line_to (draw_data, st, + to_x, to_y); } void HB_ALWAYS_INLINE quadratic_to (float control_x, float control_y, float to_x, float to_y) { - if (likely (not_slanted)) - funcs->quadratic_to (draw_data, st, - control_x, control_y, - to_x, to_y); - else - funcs->quadratic_to (draw_data, st, - control_x + control_y * slant, control_y, - to_x + to_y * slant, to_y); + funcs->quadratic_to (draw_data, st, + control_x, control_y, + to_x, to_y); } void HB_ALWAYS_INLINE @@ -215,16 +208,10 @@ float control2_x, float control2_y, float to_x, float to_y) { - if (likely (not_slanted)) - funcs->cubic_to (draw_data, st, - control1_x, control1_y, - control2_x, control2_y, - to_x, to_y); - else - funcs->cubic_to (draw_data, st, - control1_x + control1_y * slant, control1_y, - control2_x + control2_y * slant, control2_y, - to_x + to_y * slant, to_y); + funcs->cubic_to (draw_data, st, + control1_x, control1_y, + control2_x, control2_y, + to_x, to_y); } HB_ALWAYS_INLINE void close_path () @@ -233,11 +220,14 @@ } public: - float slant; - bool not_slanted; hb_draw_funcs_t *funcs; void *draw_data; hb_draw_state_t st; }; + +HB_INTERNAL hb_draw_funcs_t * +hb_draw_extents_get_funcs (); + + #endif /* HB_DRAW_HH */ diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-face.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-face.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-face.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-face.cc 2025-10-13 07:49:24.000000000 +0000 @@ -34,6 +34,16 @@ #include "hb-ot-face.hh" #include "hb-ot-cmap-table.hh" +#ifdef HAVE_FREETYPE +#include "hb-ft.h" +#endif +#ifdef HAVE_CORETEXT +#include "hb-coretext.h" +#endif +#ifdef HAVE_DIRECTWRITE +#include "hb-directwrite.h" +#endif + /** * SECTION:hb-face @@ -72,14 +82,14 @@ if (unlikely (!blob)) return 0; - /* TODO We shouldn't be sanitizing blob. Port to run sanitizer and return if not sane. */ - /* Make API signature const after. */ - hb_blob_t *sanitized = hb_sanitize_context_t ().sanitize_blob (hb_blob_reference (blob)); - const OT::OpenTypeFontFile& ot = *sanitized->as (); - unsigned int ret = ot.get_face_count (); - hb_blob_destroy (sanitized); + hb_sanitize_context_t c (blob); + + const char *start = hb_blob_get_data (blob, nullptr); + auto *ot = reinterpret_cast (const_cast (start)); + if (unlikely (!ot->sanitize (&c))) + return 0; - return ret; + return ot->get_face_count (); } /* @@ -318,7 +328,209 @@ return face; } + +static struct supported_face_loaders_t { + char name[16]; + hb_face_t * (*from_file) (const char *font_file, unsigned face_index); + hb_face_t * (*from_blob) (hb_blob_t *blob, unsigned face_index); +} supported_face_loaders[] = +{ + {"ot", +#ifndef HB_NO_OPEN + hb_face_create_from_file_or_fail, +#else + nullptr, +#endif + hb_face_create_or_fail + }, +#ifdef HAVE_FREETYPE + {"ft", + hb_ft_face_create_from_file_or_fail, + hb_ft_face_create_from_blob_or_fail + }, #endif +#ifdef HAVE_CORETEXT + {"coretext", + hb_coretext_face_create_from_file_or_fail, + hb_coretext_face_create_from_blob_or_fail + }, +#endif +#ifdef HAVE_DIRECTWRITE + {"directwrite", + hb_directwrite_face_create_from_file_or_fail, + hb_directwrite_face_create_from_blob_or_fail + }, +#endif +}; + +static const char *get_default_loader_name () +{ + static hb_atomic_t static_loader_name; + const char *loader_name = static_loader_name.get_acquire (); + if (!loader_name) + { + loader_name = getenv ("HB_FACE_LOADER"); + if (!loader_name) + loader_name = ""; + if (!static_loader_name.cmpexch (nullptr, loader_name)) + loader_name = static_loader_name.get_acquire (); + } + return loader_name; +} + +/** + * hb_face_create_from_file_or_fail_using: + * @file_name: A font filename + * @index: The index of the face within the file + * @loader_name: (nullable): The name of the loader to use, or `NULL` + * + * A thin wrapper around the face loader functions registered with HarfBuzz. + * If @loader_name is `NULL` or the empty string, the first available loader + * is used. + * + * For example, the FreeType ("ft") loader might be able to load + * WOFF and WOFF2 files if FreeType is built with those features, + * whereas the OpenType ("ot") loader will not. + * + * Return value: (transfer full): The new face object, or `NULL` if + * the file cannot be read or the loader fails to load the face. + * + * Since: 11.0.0 + **/ +hb_face_t * +hb_face_create_from_file_or_fail_using (const char *file_name, + unsigned int index, + const char *loader_name) +{ + // Duplicated in hb_face_create_or_fail_using + bool retry = false; + if (!loader_name || !*loader_name) + { + loader_name = get_default_loader_name (); + retry = true; + } + if (loader_name && !*loader_name) loader_name = nullptr; + +retry: + for (unsigned i = 0; i < ARRAY_LENGTH (supported_face_loaders); i++) + { + if (!loader_name || (supported_face_loaders[i].from_file && !strcmp (supported_face_loaders[i].name, loader_name))) + return supported_face_loaders[i].from_file (file_name, index); + } + + if (retry) + { + retry = false; + loader_name = nullptr; + goto retry; + } + + return nullptr; +} + +/** + * hb_face_create_or_fail_using: + * @blob: #hb_blob_t to work upon + * @index: The index of the face within @blob + * @loader_name: (nullable): The name of the loader to use, or `NULL` + * + * A thin wrapper around the face loader functions registered with HarfBuzz. + * If @loader_name is `NULL` or the empty string, the first available loader + * is used. + * + * For example, the FreeType ("ft") loader might be able to load + * WOFF and WOFF2 files if FreeType is built with those features, + * whereas the OpenType ("ot") loader will not. + * + * Return value: (transfer full): The new face object, or `NULL` if + * the loader fails to load the face. + * + * Since: 11.0.0 + **/ +hb_face_t * +hb_face_create_or_fail_using (hb_blob_t *blob, + unsigned int index, + const char *loader_name) +{ + // Duplicated in hb_face_create_from_file_or_fail_using + bool retry = false; + if (!loader_name || !*loader_name) + { + loader_name = get_default_loader_name (); + retry = true; + } + if (loader_name && !*loader_name) loader_name = nullptr; + +retry: + for (unsigned i = 0; i < ARRAY_LENGTH (supported_face_loaders); i++) + { + if (!loader_name || (supported_face_loaders[i].from_blob && !strcmp (supported_face_loaders[i].name, loader_name))) + return supported_face_loaders[i].from_blob (blob, index); + } + + if (retry) + { + retry = false; + loader_name = nullptr; + goto retry; + } + + return nullptr; +} + +static inline void free_static_face_loader_list (); + +static const char * const nil_face_loader_list[] = {nullptr}; + +static struct hb_face_loader_list_lazy_loader_t : hb_lazy_loader_t +{ + static const char ** create () + { + const char **face_loader_list = (const char **) hb_calloc (1 + ARRAY_LENGTH (supported_face_loaders), sizeof (const char *)); + if (unlikely (!face_loader_list)) + return nullptr; + + unsigned i; + for (i = 0; i < ARRAY_LENGTH (supported_face_loaders); i++) + face_loader_list[i] = supported_face_loaders[i].name; + face_loader_list[i] = nullptr; + + hb_atexit (free_static_face_loader_list); + + return face_loader_list; + } + static void destroy (const char **l) + { hb_free (l); } + static const char * const * get_null () + { return nil_face_loader_list; } +} static_face_loader_list; + +static inline +void free_static_face_loader_list () +{ + static_face_loader_list.free_instance (); +} + +/** + * hb_face_list_loaders: + * + * Retrieves the list of face loaders supported by HarfBuzz. + * + * Return value: (transfer none) (array zero-terminated=1): a + * `NULL`-terminated array of supported face loaders + * constant strings. The returned array is owned by HarfBuzz + * and should not be modified or freed. + * + * Since: 11.0.0 + **/ +const char ** +hb_face_list_loaders () +{ + return static_face_loader_list.get_unconst (); +} +#endif + /** * hb_face_get_empty: @@ -460,7 +672,7 @@ * Since: 0.9.2 **/ hb_bool_t -hb_face_is_immutable (const hb_face_t *face) +hb_face_is_immutable (hb_face_t *face) { return hb_object_is_immutable (face); } diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-face.h openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-face.h --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-face.h 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-face.h 2025-10-13 07:49:24.000000000 +0000 @@ -64,9 +64,23 @@ unsigned int index); HB_EXTERN hb_face_t * +hb_face_create_or_fail_using (hb_blob_t *blob, + unsigned int index, + const char *loader_name); + +HB_EXTERN hb_face_t * hb_face_create_from_file_or_fail (const char *file_name, unsigned int index); +HB_EXTERN hb_face_t * +hb_face_create_from_file_or_fail_using (const char *file_name, + unsigned int index, + const char *loader_name); + +HB_EXTERN const char ** +hb_face_list_loaders (void); + + /** * hb_reference_table_func_t: * @face: an #hb_face_t to reference table for @@ -117,7 +131,7 @@ hb_face_make_immutable (hb_face_t *face); HB_EXTERN hb_bool_t -hb_face_is_immutable (const hb_face_t *face); +hb_face_is_immutable (hb_face_t *face); HB_EXTERN hb_blob_t * diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-face.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-face.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-face.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-face.hh 2025-10-13 07:49:24.000000000 +0000 @@ -49,8 +49,8 @@ hb_object_header_t header; unsigned int index; /* Face index in a collection, zero-based. */ - mutable hb_atomic_int_t upem; /* Units-per-EM. */ - mutable hb_atomic_int_t num_glyphs; /* Number of glyphs. */ + mutable hb_atomic_t upem; /* Units-per-EM. */ + mutable hb_atomic_t num_glyphs;/* Number of glyphs. */ hb_reference_table_func_t reference_table_func; void *user_data; @@ -70,7 +70,7 @@ plan_node_t *next; }; #ifndef HB_NO_SHAPER - hb_atomic_ptr_t shape_plans; + hb_atomic_t shape_plans; #endif hb_blob_t *reference_table (hb_tag_t tag) const diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-font.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-font.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-font.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-font.cc 2025-10-13 07:49:24.000000000 +0000 @@ -38,6 +38,22 @@ #include "hb-ot-var-avar-table.hh" #include "hb-ot-var-fvar-table.hh" +#ifndef HB_NO_OT_FONT +#include "hb-ot.h" +#endif +#ifdef HAVE_FREETYPE +#include "hb-ft.h" +#endif +#ifdef HAVE_FONTATIONS +#include "hb-fontations.h" +#endif +#ifdef HAVE_CORETEXT +#include "hb-coretext.h" +#endif +#ifdef HAVE_DIRECTWRITE +#include "hb-directwrite.h" +#endif + /** * SECTION:hb-font @@ -87,7 +103,7 @@ hb_font_extents_t *extents, void *user_data HB_UNUSED) { - hb_bool_t ret = font->parent->get_font_h_extents (extents); + hb_bool_t ret = font->parent->get_font_h_extents (extents, false); if (ret) { extents->ascender = font->parent_scale_y_distance (extents->ascender); extents->descender = font->parent_scale_y_distance (extents->descender); @@ -112,7 +128,7 @@ hb_font_extents_t *extents, void *user_data HB_UNUSED) { - hb_bool_t ret = font->parent->get_font_v_extents (extents); + hb_bool_t ret = font->parent->get_font_v_extents (extents, false); if (ret) { extents->ascender = font->parent_scale_x_distance (extents->ascender); extents->descender = font->parent_scale_x_distance (extents->descender); @@ -218,10 +234,10 @@ if (font->has_glyph_h_advances_func_set ()) { hb_position_t ret; - font->get_glyph_h_advances (1, &glyph, 0, &ret, 0); + font->get_glyph_h_advances (1, &glyph, 0, &ret, 0, false); return ret; } - return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph)); + return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph, false)); } static hb_position_t @@ -243,10 +259,10 @@ if (font->has_glyph_v_advances_func_set ()) { hb_position_t ret; - font->get_glyph_v_advances (1, &glyph, 0, &ret, 0); + font->get_glyph_v_advances (1, &glyph, 0, &ret, 0, false); return ret; } - return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph)); + return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph, false)); } #define hb_font_get_glyph_h_advances_nil hb_font_get_glyph_h_advances_default @@ -265,7 +281,7 @@ { for (unsigned int i = 0; i < count; i++) { - *first_advance = font->get_glyph_h_advance (*first_glyph); + *first_advance = font->get_glyph_h_advance (*first_glyph, false); first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); } @@ -274,7 +290,8 @@ font->parent->get_glyph_h_advances (count, first_glyph, glyph_stride, - first_advance, advance_stride); + first_advance, advance_stride, + false); for (unsigned int i = 0; i < count; i++) { *first_advance = font->parent_scale_x_distance (*first_advance); @@ -297,7 +314,7 @@ { for (unsigned int i = 0; i < count; i++) { - *first_advance = font->get_glyph_v_advance (*first_glyph); + *first_advance = font->get_glyph_v_advance (*first_glyph, false); first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); } @@ -306,7 +323,8 @@ font->parent->get_glyph_v_advances (count, first_glyph, glyph_stride, - first_advance, advance_stride); + first_advance, advance_stride, + false); for (unsigned int i = 0; i < count; i++) { *first_advance = font->parent_scale_y_distance (*first_advance); @@ -426,7 +444,7 @@ hb_glyph_extents_t *extents, void *user_data HB_UNUSED) { - hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents); + hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents, false); if (ret) { font->parent_scale_position (&extents->x_bearing, &extents->y_bearing); font->parent_scale_distance (&extents->width, &extents->height); @@ -456,7 +474,7 @@ hb_position_t *y, void *user_data HB_UNUSED) { - hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y); + hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y, false); if (ret) font->parent_scale_position (x, y); return ret; @@ -508,26 +526,28 @@ return font->parent->get_glyph_from_name (name, len, glyph); } -static void -hb_font_draw_glyph_nil (hb_font_t *font HB_UNUSED, - void *font_data HB_UNUSED, - hb_codepoint_t glyph, - hb_draw_funcs_t *draw_funcs, - void *draw_data, - void *user_data HB_UNUSED) +static hb_bool_t +hb_font_draw_glyph_or_fail_nil (hb_font_t *font HB_UNUSED, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, + void *draw_data, + void *user_data HB_UNUSED) { + return false; } -static void -hb_font_paint_glyph_nil (hb_font_t *font HB_UNUSED, - void *font_data HB_UNUSED, - hb_codepoint_t glyph HB_UNUSED, - hb_paint_funcs_t *paint_funcs HB_UNUSED, - void *paint_data HB_UNUSED, - unsigned int palette HB_UNUSED, - hb_color_t foreground HB_UNUSED, - void *user_data HB_UNUSED) +static hb_bool_t +hb_font_paint_glyph_or_fail_nil (hb_font_t *font HB_UNUSED, + void *font_data HB_UNUSED, + hb_codepoint_t glyph HB_UNUSED, + hb_paint_funcs_t *paint_funcs HB_UNUSED, + void *paint_data HB_UNUSED, + unsigned int palette HB_UNUSED, + hb_color_t foreground HB_UNUSED, + void *user_data HB_UNUSED) { + return false; } typedef struct hb_font_draw_glyph_default_adaptor_t { @@ -535,7 +555,6 @@ void *draw_data; float x_scale; float y_scale; - float slant; } hb_font_draw_glyph_default_adaptor_t; static void @@ -548,10 +567,9 @@ hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data; float x_scale = adaptor->x_scale; float y_scale = adaptor->y_scale; - float slant = adaptor->slant; adaptor->draw_funcs->emit_move_to (adaptor->draw_data, *st, - x_scale * to_x + slant * to_y, y_scale * to_y); + x_scale * to_x, y_scale * to_y); } static void @@ -563,13 +581,12 @@ hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data; float x_scale = adaptor->x_scale; float y_scale = adaptor->y_scale; - float slant = adaptor->slant; - st->current_x = st->current_x * x_scale + st->current_y * slant; + st->current_x = st->current_x * x_scale; st->current_y = st->current_y * y_scale; adaptor->draw_funcs->emit_line_to (adaptor->draw_data, *st, - x_scale * to_x + slant * to_y, y_scale * to_y); + x_scale * to_x, y_scale * to_y); } static void @@ -582,14 +599,13 @@ hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data; float x_scale = adaptor->x_scale; float y_scale = adaptor->y_scale; - float slant = adaptor->slant; - st->current_x = st->current_x * x_scale + st->current_y * slant; + st->current_x = st->current_x * x_scale; st->current_y = st->current_y * y_scale; adaptor->draw_funcs->emit_quadratic_to (adaptor->draw_data, *st, - x_scale * control_x + slant * control_y, y_scale * control_y, - x_scale * to_x + slant * to_y, y_scale * to_y); + x_scale * control_x, y_scale * control_y, + x_scale * to_x, y_scale * to_y); } static void @@ -603,15 +619,14 @@ hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data; float x_scale = adaptor->x_scale; float y_scale = adaptor->y_scale; - float slant = adaptor->slant; - st->current_x = st->current_x * x_scale + st->current_y * slant; + st->current_x = st->current_x * x_scale; st->current_y = st->current_y * y_scale; adaptor->draw_funcs->emit_cubic_to (adaptor->draw_data, *st, - x_scale * control1_x + slant * control1_y, y_scale * control1_y, - x_scale * control2_x + slant * control2_y, y_scale * control2_y, - x_scale * to_x + slant * to_y, y_scale * to_y); + x_scale * control1_x, y_scale * control1_y, + x_scale * control2_x, y_scale * control2_y, + x_scale * to_x, y_scale * to_y); } static void @@ -634,49 +649,47 @@ } }; -static void -hb_font_draw_glyph_default (hb_font_t *font, - void *font_data HB_UNUSED, - hb_codepoint_t glyph, - hb_draw_funcs_t *draw_funcs, - void *draw_data, - void *user_data HB_UNUSED) +static hb_bool_t +hb_font_draw_glyph_or_fail_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, + void *draw_data, + void *user_data HB_UNUSED) { hb_font_draw_glyph_default_adaptor_t adaptor = { draw_funcs, draw_data, font->parent->x_scale ? (float) font->x_scale / (float) font->parent->x_scale : 0.f, - font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0.f, - font->parent->y_scale ? (font->slant - font->parent->slant) * - (float) font->x_scale / (float) font->parent->y_scale : 0.f + font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0.f }; - font->parent->draw_glyph (glyph, - const_cast (&_hb_draw_funcs_default), - &adaptor); + return font->parent->draw_glyph_or_fail (glyph, + const_cast (&_hb_draw_funcs_default), + &adaptor, + false); } -static void -hb_font_paint_glyph_default (hb_font_t *font, - void *font_data, - hb_codepoint_t glyph, - hb_paint_funcs_t *paint_funcs, - void *paint_data, - unsigned int palette, - hb_color_t foreground, - void *user_data) +static hb_bool_t +hb_font_paint_glyph_or_fail_default (hb_font_t *font, + void *font_data, + hb_codepoint_t glyph, + hb_paint_funcs_t *paint_funcs, + void *paint_data, + unsigned int palette, + hb_color_t foreground, + void *user_data) { paint_funcs->push_transform (paint_data, - font->parent->x_scale ? (float) font->x_scale / (float) font->parent->x_scale : 0.f, - font->parent->y_scale ? (font->slant - font->parent->slant) * - (float) font->x_scale / (float) font->parent->y_scale : 0.f, - 0.f, - font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0.f, - 0.f, 0.f); + font->parent->x_scale ? (float) font->x_scale / (float) font->parent->x_scale : 0, 0, + 0, font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0, + 0, 0); - font->parent->paint_glyph (glyph, paint_funcs, paint_data, palette, foreground); + bool ret = font->parent->paint_glyph_or_fail (glyph, paint_funcs, paint_data, palette, foreground); paint_funcs->pop_transform (paint_data); + + return ret; } DEFINE_NULL_INSTANCE (hb_font_funcs_t) = @@ -1414,6 +1427,92 @@ #endif /** + * hb_font_draw_glyph_or_fail: + * @font: #hb_font_t to work upon + * @glyph: The glyph ID + * @dfuncs: #hb_draw_funcs_t to draw to + * @draw_data: User data to pass to draw callbacks + * + * Draws the outline that corresponds to a glyph in the specified @font. + * + * This is a newer name for hb_font_draw_glyph(), that returns `false` + * if the font has no outlines for the glyph. + * + * The outline is returned by way of calls to the callbacks of the @dfuncs + * objects, with @draw_data passed to them. + * + * Return value: `true` if glyph was drawn, `false` otherwise + * + * XSince: REPLACEME + **/ +hb_bool_t +hb_font_draw_glyph_or_fail (hb_font_t *font, + hb_codepoint_t glyph, + hb_draw_funcs_t *dfuncs, void *draw_data) +{ + return font->draw_glyph_or_fail (glyph, dfuncs, draw_data); +} + +/** + * hb_font_paint_glyph_or_fail: + * @font: #hb_font_t to work upon + * @glyph: The glyph ID + * @pfuncs: #hb_paint_funcs_t to paint with + * @paint_data: User data to pass to paint callbacks + * @palette_index: The index of the font's color palette to use + * @foreground: The foreground color, unpremultipled + * + * Paints a color glyph. + * + * This function is similar to, but lower-level than, + * hb_font_paint_glyph(). It is suitable for clients that + * need more control. If there are no color glyphs available, + * it will return `false`. The client can then fall back to + * hb_font_draw_glyph_or_fail() for the monochrome outline glyph. + * + * The painting instructions are returned by way of calls to + * the callbacks of the @funcs object, with @paint_data passed + * to them. + * + * If the font has color palettes (see hb_ot_color_has_palettes()), + * then @palette_index selects the palette to use. If the font only + * has one palette, this will be 0. + * + * Return value: `true` if glyph was painted, `false` otherwise + * + * XSince: REPLACEME + */ +hb_bool_t +hb_font_paint_glyph_or_fail (hb_font_t *font, + hb_codepoint_t glyph, + hb_paint_funcs_t *pfuncs, void *paint_data, + unsigned int palette_index, + hb_color_t foreground) +{ + return font->paint_glyph_or_fail (glyph, pfuncs, paint_data, palette_index, foreground); +} + +/* A bit higher-level, and with fallback */ + +void +hb_font_t::paint_glyph (hb_codepoint_t glyph, + hb_paint_funcs_t *paint_funcs, void *paint_data, + unsigned int palette, + hb_color_t foreground) +{ + if (paint_glyph_or_fail (glyph, + paint_funcs, paint_data, + palette, foreground)) + return; + + /* Fallback for outline glyph. */ + paint_funcs->push_clip_glyph (paint_data, glyph, this); + paint_funcs->color (paint_data, true, foreground); + paint_funcs->pop_clip (paint_data); +} + + +/** * hb_font_draw_glyph: * @font: #hb_font_t to work upon * @glyph: The glyph ID @@ -1422,6 +1521,9 @@ * * Draws the outline that corresponds to a glyph in the specified @font. * + * This is an older name for hb_font_draw_glyph_or_fail(), with no + * return value. + * * The outline is returned by way of calls to the callbacks of the @dfuncs * objects, with @draw_data passed to them. * @@ -1429,10 +1531,10 @@ **/ void hb_font_draw_glyph (hb_font_t *font, - hb_codepoint_t glyph, - hb_draw_funcs_t *dfuncs, void *draw_data) + hb_codepoint_t glyph, + hb_draw_funcs_t *dfuncs, void *draw_data) { - font->draw_glyph (glyph, dfuncs, draw_data); + (void) hb_font_draw_glyph_or_fail (font, glyph, dfuncs, draw_data); } /** @@ -1444,7 +1546,10 @@ * @palette_index: The index of the font's color palette to use * @foreground: The foreground color, unpremultipled * - * Paints the glyph. + * Paints the glyph. This function is similar to + * hb_font_paint_glyph_or_fail(), but if painting a color glyph + * failed, it will fall back to painting an outline monochrome + * glyph. * * The painting instructions are returned by way of calls to * the callbacks of the @funcs object, with @paint_data passed @@ -1466,8 +1571,6 @@ font->paint_glyph (glyph, pfuncs, paint_data, palette_index, foreground); } -/* A bit higher-level, and with fallback */ - /** * hb_font_get_extents_for_direction: * @font: #hb_font_t to work upon @@ -1854,10 +1957,7 @@ { hb_font_t *font = _hb_font_create (face); -#ifndef HB_NO_OT_FONT - /* Install our in-house, very lightweight, funcs. */ - hb_ot_font_set_funcs (font); -#endif + hb_font_set_funcs_using (font, nullptr); #ifndef HB_NO_VAR if (face && face->index >> 16) @@ -1880,7 +1980,8 @@ font->design_coords = design_coords; font->num_coords = coords_length; - font->mults_changed (); // Easiest to call this to drop cached data + font->changed (); + font->serial_coords = font->serial; } /** @@ -1935,7 +2036,8 @@ } } - font->mults_changed (); + font->changed (); + font->serial_coords = font->serial; return font; } @@ -2023,7 +2125,7 @@ hb_bool_t replace) { if (!hb_object_is_immutable (font)) - font->serial++; + font->changed (); return hb_object_set_user_data (font, key, data, destroy, replace); } @@ -2098,7 +2200,7 @@ unsigned int hb_font_get_serial (hb_font_t *font) { - return font->serial; + return font->serial.get_acquire (); } /** @@ -2117,9 +2219,7 @@ if (hb_object_is_immutable (font)) return; - font->serial++; - - font->mults_changed (); + font->changed (); } /** @@ -2141,8 +2241,6 @@ if (parent == font->parent) return; - font->serial++; - if (!parent) parent = hb_font_get_empty (); @@ -2151,6 +2249,8 @@ font->parent = hb_font_reference (parent); hb_font_destroy (old); + + font->changed (); } /** @@ -2188,8 +2288,6 @@ if (face == font->face) return; - font->serial++; - if (unlikely (!face)) face = hb_face_get_empty (); @@ -2197,9 +2295,12 @@ hb_face_make_immutable (face); font->face = hb_face_reference (face); - font->mults_changed (); + font->changed (); hb_face_destroy (old); + + font->changed (); + font->serial_coords = font->serial; } /** @@ -2244,8 +2345,6 @@ return; } - font->serial++; - if (font->destroy) font->destroy (font->user_data); @@ -2257,6 +2356,8 @@ font->klass = klass; font->user_data = font_data; font->destroy = destroy; + + font->changed (); } /** @@ -2283,15 +2384,151 @@ return; } - font->serial++; - if (font->destroy) font->destroy (font->user_data); font->user_data = font_data; font->destroy = destroy; + + font->changed (); +} + +static struct supported_font_funcs_t { + char name[16]; + void (*func) (hb_font_t *); +} supported_font_funcs[] = +{ +#ifndef HB_NO_OT_FONT + {"ot", hb_ot_font_set_funcs}, +#endif +#ifdef HAVE_FREETYPE + {"ft", hb_ft_font_set_funcs}, +#endif +#ifdef HAVE_FONTATIONS + {"fontations",hb_fontations_font_set_funcs}, +#endif +#ifdef HAVE_CORETEXT + {"coretext", hb_coretext_font_set_funcs}, +#endif +#ifdef HAVE_DIRECTWRITE + {"directwrite",hb_directwrite_font_set_funcs}, +#endif +}; + +static const char *get_default_funcs_name () +{ + static hb_atomic_t static_funcs_name; + const char *name = static_funcs_name.get_acquire (); + if (!name) + { + name = getenv ("HB_FONT_FUNCS"); + if (!name) + name = ""; + if (!static_funcs_name.cmpexch (nullptr, name)) + name = static_funcs_name.get_acquire (); + } + return name; +} + +/** + * hb_font_set_funcs_using: + * @font: #hb_font_t to work upon + * @name: The name of the font-functions structure to use, or `NULL` + * + * Sets the font-functions structure to use for a font, based on the + * specified name. + * + * If @name is `NULL` or the empty string, the default (first) functioning font-functions + * are used. This default can be changed by setting the `HB_FONT_FUNCS` environment + * variable to the name of the desired font-functions. + * + * Return value: `true` if the font-functions was found and set, `false` otherwise + * + * Since: 11.0.0 + **/ +hb_bool_t +hb_font_set_funcs_using (hb_font_t *font, + const char *name) +{ + bool retry = false; + + if (!name || !*name) + { + name = get_default_funcs_name (); + retry = true; + } + if (name && !*name) name = nullptr; + +retry: + for (unsigned i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++) + if (!name || strcmp (supported_font_funcs[i].name, name) == 0) + { + supported_font_funcs[i].func (font); + if (name || font->klass != hb_font_funcs_get_empty ()) + return true; + } + + if (retry) + { + retry = false; + name = nullptr; + goto retry; + } + + return false; } +static inline void free_static_font_funcs_list (); + +static const char * const nil_font_funcs_list[] = {nullptr}; + +static struct hb_font_funcs_list_lazy_loader_t : hb_lazy_loader_t +{ + static const char ** create () + { + const char **font_funcs_list = (const char **) hb_calloc (1 + ARRAY_LENGTH (supported_font_funcs), sizeof (const char *)); + if (unlikely (!font_funcs_list)) + return nullptr; + + unsigned i; + for (i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++) + font_funcs_list[i] = supported_font_funcs[i].name; + font_funcs_list[i] = nullptr; + + hb_atexit (free_static_font_funcs_list); + + return font_funcs_list; + } + static void destroy (const char **l) + { hb_free (l); } + static const char * const * get_null () + { return nil_font_funcs_list; } +} static_font_funcs_list; + +static inline +void free_static_font_funcs_list () +{ + static_font_funcs_list.free_instance (); +} + +/** + * hb_font_list_funcs: + * + * Retrieves the list of font functions supported by HarfBuzz. + * + * Return value: (transfer none) (array zero-terminated=1): a + * `NULL`-terminated array of supported font functions + * constant strings. The returned array is owned by HarfBuzz + * and should not be modified or freed. + * + * Since: 11.0.0 + **/ +const char ** +hb_font_list_funcs () +{ + return static_font_funcs_list.get_unconst (); +} /** * hb_font_set_scale: @@ -2339,11 +2576,10 @@ if (font->x_scale == x_scale && font->y_scale == y_scale) return; - font->serial++; - font->x_scale = x_scale; font->y_scale = y_scale; - font->mults_changed (); + + font->changed (); } /** @@ -2390,10 +2626,10 @@ if (font->x_ppem == x_ppem && font->y_ppem == y_ppem) return; - font->serial++; - font->x_ppem = x_ppem; font->y_ppem = y_ppem; + + font->changed (); } /** @@ -2437,9 +2673,9 @@ if (font->ptem == ptem) return; - font->serial++; - font->ptem = ptem; + + font->changed (); } /** @@ -2460,6 +2696,23 @@ } /** + * hb_font_is_synthetic: + * @font: #hb_font_t to work upon + * + * Tests whether a font is synthetic. A synthetic font is one + * that has either synthetic slant or synthetic bold set on it. + * + * Return value: `true` if the font is synthetic, `false` otherwise. + * + * XSince: REPLACEME + */ +hb_bool_t +hb_font_is_synthetic (hb_font_t *font) +{ + return font->is_synthetic (); +} + +/** * hb_font_set_synthetic_bold: * @font: #hb_font_t to work upon * @x_embolden: the amount to embolden horizontally @@ -2476,7 +2729,7 @@ * points of the glyph shape. * * Synthetic boldness is applied when rendering a glyph via - * hb_font_draw_glyph(). + * hb_font_draw_glyph_or_fail(). * * If @in_place is `false`, then glyph advance-widths are also * adjusted, otherwise they are not. The in-place mode is @@ -2499,12 +2752,11 @@ font->embolden_in_place == (bool) in_place) return; - font->serial++; - font->x_embolden = x_embolden; font->y_embolden = y_embolden; font->embolden_in_place = in_place; - font->mults_changed (); + + font->changed (); } /** @@ -2541,7 +2793,7 @@ * HarfBuzz needs to know this value to adjust shaping results, * metrics, and style values to match the slanted rendering. * - * Note: The glyph shape fetched via the hb_font_draw_glyph() + * Note: The glyph shape fetched via the hb_font_draw_glyph_or_fail() * function is slanted to reflect this value as well. * * Note: The slant value is a ratio. For example, a @@ -2558,10 +2810,9 @@ if (font->slant == slant) return; - font->serial++; - font->slant = slant; - font->mults_changed (); + + font->changed (); } /** @@ -2607,8 +2858,6 @@ if (hb_object_is_immutable (font)) return; - font->serial_coords = ++font->serial; - if (!variations_length && font->instance_index == HB_FONT_NO_VAR_NAMED_INSTANCE) { hb_font_set_var_coords_normalized (font, nullptr, 0); @@ -2677,8 +2926,6 @@ if (hb_object_is_immutable (font)) return; - font->serial_coords = ++font->serial; - // TODO Share some of this code with set_variations() const OT::fvar &fvar = *font->face->table.fvar; @@ -2749,8 +2996,6 @@ if (hb_object_is_immutable (font)) return; - font->serial_coords = ++font->serial; - int *normalized = coords_length ? (int *) hb_calloc (coords_length, sizeof (int)) : nullptr; float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr; @@ -2787,8 +3032,6 @@ if (font->instance_index == instance_index) return; - font->serial_coords = ++font->serial; - font->instance_index = instance_index; hb_font_set_variations (font, nullptr, 0); } @@ -2834,8 +3077,6 @@ if (hb_object_is_immutable (font)) return; - font->serial_coords = ++font->serial; - int *copy = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr; int *unmapped = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr; float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (design_coords[0])) : nullptr; @@ -3058,12 +3299,134 @@ #ifndef HB_DISABLE_DEPRECATED + +struct hb_draw_glyph_closure_t +{ + hb_font_draw_glyph_func_t func; + void *user_data; + hb_destroy_func_t destroy; +}; +static hb_bool_t +hb_font_draw_glyph_trampoline (hb_font_t *font, + void *font_data, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, + void *draw_data, + void *user_data) +{ + hb_draw_glyph_closure_t *closure = (hb_draw_glyph_closure_t *) user_data; + closure->func (font, font_data, glyph, draw_funcs, draw_data, closure->user_data); + return true; +} +static void +hb_font_draw_glyph_closure_destroy (void *user_data) +{ + hb_draw_glyph_closure_t *closure = (hb_draw_glyph_closure_t *) user_data; + + if (closure->destroy) + closure->destroy (closure->user_data); + hb_free (closure); +} +static void +_hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs, + hb_font_draw_glyph_func_t func, + void *user_data, + hb_destroy_func_t destroy /* May be NULL. */) +{ + if (hb_object_is_immutable (ffuncs)) + { + if (destroy) + destroy (user_data); + return; + } + hb_draw_glyph_closure_t *closure = (hb_draw_glyph_closure_t *) hb_calloc (1, sizeof (hb_draw_glyph_closure_t)); + if (unlikely (!closure)) + { + if (destroy) + destroy (user_data); + return; + } + closure->func = func; + closure->user_data = user_data; + closure->destroy = destroy; + + hb_font_funcs_set_draw_glyph_or_fail_func (ffuncs, + hb_font_draw_glyph_trampoline, + closure, + hb_font_draw_glyph_closure_destroy); +} +void +hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs, + hb_font_draw_glyph_func_t func, + void *user_data, + hb_destroy_func_t destroy /* May be NULL. */) +{ + _hb_font_funcs_set_draw_glyph_func (ffuncs, func, user_data, destroy); +} void hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_shape_func_t func, void *user_data, hb_destroy_func_t destroy /* May be NULL. */) { - hb_font_funcs_set_draw_glyph_func (ffuncs, func, user_data, destroy); + _hb_font_funcs_set_draw_glyph_func (ffuncs, func, user_data, destroy); +} + +struct hb_paint_glyph_closure_t +{ + hb_font_paint_glyph_func_t func; + void *user_data; + hb_destroy_func_t destroy; +}; +static hb_bool_t +hb_font_paint_glyph_trampoline (hb_font_t *font, + void *font_data, + hb_codepoint_t glyph, + hb_paint_funcs_t *paint_funcs, + void *paint_data, + unsigned int palette, + hb_color_t foreground, + void *user_data) +{ + hb_paint_glyph_closure_t *closure = (hb_paint_glyph_closure_t *) user_data; + closure->func (font, font_data, glyph, paint_funcs, paint_data, palette, foreground, closure->user_data); + return true; +} +static void +hb_font_paint_glyph_closure_destroy (void *user_data) +{ + hb_paint_glyph_closure_t *closure = (hb_paint_glyph_closure_t *) user_data; + + if (closure->destroy) + closure->destroy (closure->user_data); + hb_free (closure); +} +void +hb_font_funcs_set_paint_glyph_func (hb_font_funcs_t *ffuncs, + hb_font_paint_glyph_func_t func, + void *user_data, + hb_destroy_func_t destroy /* May be NULL. */) +{ + if (hb_object_is_immutable (ffuncs)) + { + if (destroy) + destroy (user_data); + return; + } + hb_paint_glyph_closure_t *closure = (hb_paint_glyph_closure_t *) hb_calloc (1, sizeof (hb_paint_glyph_closure_t)); + if (unlikely (!closure)) + { + if (destroy) + destroy (user_data); + return; + } + closure->func = func; + closure->user_data = user_data; + closure->destroy = destroy; + + hb_font_funcs_set_paint_glyph_or_fail_func (ffuncs, + hb_font_paint_glyph_trampoline, + closure, + hb_font_paint_glyph_closure_destroy); } #endif diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-font.h openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-font.h --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-font.h 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-font.h 2025-10-13 07:49:24.000000000 +0000 @@ -486,7 +486,7 @@ void *user_data); /** - * hb_font_draw_glyph_func_t: + * hb_font_draw_glyph_or_fail_func_t: * @font: #hb_font_t to work upon * @font_data: @font user data pointer * @glyph: The glyph ID to query @@ -496,16 +496,17 @@ * * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * - * Since: 7.0.0 + * Return value: `true` if glyph was drawn, `false` otherwise * + * XSince: REPLACEME **/ -typedef void (*hb_font_draw_glyph_func_t) (hb_font_t *font, void *font_data, - hb_codepoint_t glyph, - hb_draw_funcs_t *draw_funcs, void *draw_data, - void *user_data); +typedef hb_bool_t (*hb_font_draw_glyph_or_fail_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, void *draw_data, + void *user_data); /** - * hb_font_paint_glyph_func_t: + * hb_font_paint_glyph_or_fail_func_t: * @font: #hb_font_t to work upon * @font_data: @font user data pointer * @glyph: The glyph ID to query @@ -517,14 +518,16 @@ * * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * - * Since: 7.0.0 + * Return value: `true` if glyph was painted, `false` otherwise + * + * XSince: REPLACEME */ -typedef void (*hb_font_paint_glyph_func_t) (hb_font_t *font, void *font_data, - hb_codepoint_t glyph, - hb_paint_funcs_t *paint_funcs, void *paint_data, - unsigned int palette_index, - hb_color_t foreground, - void *user_data); +typedef hb_bool_t (*hb_font_paint_glyph_or_fail_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t glyph, + hb_paint_funcs_t *paint_funcs, void *paint_data, + unsigned int palette_index, + hb_color_t foreground, + void *user_data); /* func setters */ @@ -785,36 +788,36 @@ void *user_data, hb_destroy_func_t destroy); /** - * hb_font_funcs_set_draw_glyph_func: + * hb_font_funcs_set_draw_glyph_or_fail_func: * @ffuncs: A font-function structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func * @destroy: (nullable): The function to call when @user_data is not needed anymore * - * Sets the implementation function for #hb_font_draw_glyph_func_t. + * Sets the implementation function for #hb_font_draw_glyph_or_fail_func_t. * - * Since: 7.0.0 + * XSince: REPLACEME **/ HB_EXTERN void -hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs, - hb_font_draw_glyph_func_t func, - void *user_data, hb_destroy_func_t destroy); +hb_font_funcs_set_draw_glyph_or_fail_func (hb_font_funcs_t *ffuncs, + hb_font_draw_glyph_or_fail_func_t func, + void *user_data, hb_destroy_func_t destroy); /** - * hb_font_funcs_set_paint_glyph_func: + * hb_font_funcs_set_paint_glyph_or_fail_func: * @ffuncs: A font-function structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func * @destroy: (nullable): The function to call when @user_data is no longer needed * - * Sets the implementation function for #hb_font_paint_glyph_func_t. + * Sets the implementation function for #hb_font_paint_glyph_or_fail_func_t. * - * Since: 7.0.0 + * XSince: REPLACEME */ HB_EXTERN void -hb_font_funcs_set_paint_glyph_func (hb_font_funcs_t *ffuncs, - hb_font_paint_glyph_func_t func, - void *user_data, hb_destroy_func_t destroy); +hb_font_funcs_set_paint_glyph_or_fail_func (hb_font_funcs_t *ffuncs, + hb_font_paint_glyph_or_fail_func_t func, + void *user_data, hb_destroy_func_t destroy); /* func dispatch */ @@ -896,17 +899,17 @@ const char *name, int len, /* -1 means nul-terminated */ hb_codepoint_t *glyph); -HB_EXTERN void -hb_font_draw_glyph (hb_font_t *font, - hb_codepoint_t glyph, - hb_draw_funcs_t *dfuncs, void *draw_data); +HB_EXTERN hb_bool_t +hb_font_draw_glyph_or_fail (hb_font_t *font, + hb_codepoint_t glyph, + hb_draw_funcs_t *dfuncs, void *draw_data); -HB_EXTERN void -hb_font_paint_glyph (hb_font_t *font, - hb_codepoint_t glyph, - hb_paint_funcs_t *pfuncs, void *paint_data, - unsigned int palette_index, - hb_color_t foreground); +HB_EXTERN hb_bool_t +hb_font_paint_glyph_or_fail (hb_font_t *font, + hb_codepoint_t glyph, + hb_paint_funcs_t *pfuncs, void *paint_data, + unsigned int palette_index, + hb_color_t foreground); /* high-level funcs, with fallback */ @@ -979,6 +982,19 @@ const char *s, int len, /* -1 means nul-terminated */ hb_codepoint_t *glyph); +/* Older alias for hb_font_draw_glyph_or_fail() with no return value. */ +HB_EXTERN void +hb_font_draw_glyph (hb_font_t *font, + hb_codepoint_t glyph, + hb_draw_funcs_t *dfuncs, void *draw_data); + +/* Paints color glyph; if failed, draws outline glyph. */ +HB_EXTERN void +hb_font_paint_glyph (hb_font_t *font, + hb_codepoint_t glyph, + hb_paint_funcs_t *pfuncs, void *paint_data, + unsigned int palette_index, + hb_color_t foreground); /* * hb_font_t @@ -1052,6 +1068,12 @@ void *font_data, hb_destroy_func_t destroy); +HB_EXTERN hb_bool_t +hb_font_set_funcs_using (hb_font_t *font, + const char *name); + +HB_EXTERN const char ** +hb_font_list_funcs (void); HB_EXTERN void hb_font_set_scale (hb_font_t *font, @@ -1086,6 +1108,9 @@ HB_EXTERN float hb_font_get_ptem (hb_font_t *font); +HB_EXTERN hb_bool_t +hb_font_is_synthetic (hb_font_t *font); + HB_EXTERN void hb_font_set_synthetic_bold (hb_font_t *font, float x_embolden, float y_embolden, diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-font.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-font.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-font.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-font.hh 2025-10-13 07:49:24.000000000 +0000 @@ -32,7 +32,11 @@ #include "hb.hh" #include "hb-face.hh" +#include "hb-atomic.hh" +#include "hb-draw.hh" +#include "hb-paint-extents.hh" #include "hb-shaper.hh" +#include "hb-outline.hh" /* @@ -57,8 +61,8 @@ HB_FONT_FUNC_IMPLEMENT (get_,glyph_contour_point) \ HB_FONT_FUNC_IMPLEMENT (get_,glyph_name) \ HB_FONT_FUNC_IMPLEMENT (get_,glyph_from_name) \ - HB_FONT_FUNC_IMPLEMENT (,draw_glyph) \ - HB_FONT_FUNC_IMPLEMENT (,paint_glyph) \ + HB_FONT_FUNC_IMPLEMENT (,draw_glyph_or_fail) \ + HB_FONT_FUNC_IMPLEMENT (,paint_glyph_or_fail) \ /* ^--- Add new callbacks here */ struct hb_font_funcs_t @@ -105,8 +109,8 @@ struct hb_font_t { hb_object_header_t header; - unsigned int serial; - unsigned int serial_coords; + hb_atomic_t serial; + hb_atomic_t serial_coords; hb_font_t *parent; hb_face_t *face; @@ -191,23 +195,35 @@ void scale_glyph_extents (hb_glyph_extents_t *extents) { - float x1 = em_fscale_x (extents->x_bearing); - float y1 = em_fscale_y (extents->y_bearing); - float x2 = em_fscale_x (extents->x_bearing + extents->width); - float y2 = em_fscale_y (extents->y_bearing + extents->height); + float x1 = em_scale_x (extents->x_bearing); + float y1 = em_scale_y (extents->y_bearing); + float x2 = em_scale_x (extents->x_bearing + extents->width); + float y2 = em_scale_y (extents->y_bearing + extents->height); - /* Apply slant. */ + extents->x_bearing = roundf (x1); + extents->y_bearing = roundf (y1); + extents->width = roundf (x2) - extents->x_bearing; + extents->height = roundf (y2) - extents->y_bearing; + } + + void synthetic_glyph_extents (hb_glyph_extents_t *extents) + { + /* Slant. */ if (slant_xy) { - x1 += hb_min (y1 * slant_xy, y2 * slant_xy); - x2 += hb_max (y1 * slant_xy, y2 * slant_xy); - } + hb_position_t x1 = extents->x_bearing; + hb_position_t y1 = extents->y_bearing; + hb_position_t x2 = extents->x_bearing + extents->width; + hb_position_t y2 = extents->y_bearing + extents->height; + + x1 += floorf (hb_min (y1 * slant_xy, y2 * slant_xy)); + x2 += ceilf (hb_max (y1 * slant_xy, y2 * slant_xy)); - extents->x_bearing = floorf (x1); - extents->y_bearing = floorf (y1); - extents->width = ceilf (x2) - extents->x_bearing; - extents->height = ceilf (y2) - extents->y_bearing; + extents->x_bearing = x1; + extents->width = x2 - extents->x_bearing; + } + /* Embolden. */ if (x_strength || y_strength) { /* Y */ @@ -250,19 +266,45 @@ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS #undef HB_FONT_FUNC_IMPLEMENT - hb_bool_t get_font_h_extents (hb_font_extents_t *extents) + hb_bool_t get_font_h_extents (hb_font_extents_t *extents, + bool synthetic = true) { hb_memset (extents, 0, sizeof (*extents)); - return klass->get.f.font_h_extents (this, user_data, - extents, - !klass->user_data ? nullptr : klass->user_data->font_h_extents); + bool ret = klass->get.f.font_h_extents (this, user_data, + extents, + !klass->user_data ? nullptr : klass->user_data->font_h_extents); + + if (synthetic && ret) + { + /* Embolden */ + int y_shift = y_scale < 0 ? -y_strength : y_strength; + extents->ascender += y_shift; + } + + return ret; } - hb_bool_t get_font_v_extents (hb_font_extents_t *extents) + hb_bool_t get_font_v_extents (hb_font_extents_t *extents, + bool synthetic = true) { hb_memset (extents, 0, sizeof (*extents)); - return klass->get.f.font_v_extents (this, user_data, - extents, - !klass->user_data ? nullptr : klass->user_data->font_v_extents); + bool ret = klass->get.f.font_v_extents (this, user_data, + extents, + !klass->user_data ? nullptr : klass->user_data->font_v_extents); + + if (synthetic && ret) + { + /* Embolden */ + int x_shift = x_scale < 0 ? -x_strength : x_strength; + if (embolden_in_place) + { + extents->ascender += x_shift / 2; + extents->descender -= x_shift - x_shift / 2; + } + else + extents->ascender += x_shift; + } + + return ret; } bool has_glyph (hb_codepoint_t unicode) @@ -303,44 +345,88 @@ !klass->user_data ? nullptr : klass->user_data->variation_glyph); } - hb_position_t get_glyph_h_advance (hb_codepoint_t glyph) + hb_position_t get_glyph_h_advance (hb_codepoint_t glyph, + bool synthetic = true) { - return klass->get.f.glyph_h_advance (this, user_data, - glyph, - !klass->user_data ? nullptr : klass->user_data->glyph_h_advance); + hb_position_t advance = klass->get.f.glyph_h_advance (this, user_data, + glyph, + !klass->user_data ? nullptr : klass->user_data->glyph_h_advance); + + if (synthetic && x_strength && !embolden_in_place) + { + /* Embolden */ + hb_position_t strength = x_scale >= 0 ? x_strength : -x_strength; + advance += advance ? strength : 0; + } + + return advance; } - hb_position_t get_glyph_v_advance (hb_codepoint_t glyph) + hb_position_t get_glyph_v_advance (hb_codepoint_t glyph, + bool synthetic = true) { - return klass->get.f.glyph_v_advance (this, user_data, - glyph, - !klass->user_data ? nullptr : klass->user_data->glyph_v_advance); + hb_position_t advance = klass->get.f.glyph_v_advance (this, user_data, + glyph, + !klass->user_data ? nullptr : klass->user_data->glyph_v_advance); + + if (synthetic && y_strength && !embolden_in_place) + { + /* Embolden */ + hb_position_t strength = y_scale >= 0 ? y_strength : -y_strength; + advance += advance ? strength : 0; + } + + return advance; } void get_glyph_h_advances (unsigned int count, const hb_codepoint_t *first_glyph, unsigned int glyph_stride, hb_position_t *first_advance, - unsigned int advance_stride) + unsigned int advance_stride, + bool synthetic = true) { - return klass->get.f.glyph_h_advances (this, user_data, - count, - first_glyph, glyph_stride, - first_advance, advance_stride, - !klass->user_data ? nullptr : klass->user_data->glyph_h_advances); + klass->get.f.glyph_h_advances (this, user_data, + count, + first_glyph, glyph_stride, + first_advance, advance_stride, + !klass->user_data ? nullptr : klass->user_data->glyph_h_advances); + + if (synthetic && x_strength && !embolden_in_place) + { + /* Embolden */ + hb_position_t strength = x_scale >= 0 ? x_strength : -x_strength; + for (unsigned int i = 0; i < count; i++) + { + *first_advance += *first_advance ? strength : 0; + first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); + } + } } void get_glyph_v_advances (unsigned int count, const hb_codepoint_t *first_glyph, unsigned int glyph_stride, hb_position_t *first_advance, - unsigned int advance_stride) + unsigned int advance_stride, + bool synthetic = true) { - return klass->get.f.glyph_v_advances (this, user_data, - count, - first_glyph, glyph_stride, - first_advance, advance_stride, - !klass->user_data ? nullptr : klass->user_data->glyph_v_advances); + klass->get.f.glyph_v_advances (this, user_data, + count, + first_glyph, glyph_stride, + first_advance, advance_stride, + !klass->user_data ? nullptr : klass->user_data->glyph_v_advances); + + if (synthetic && y_strength && !embolden_in_place) + { + /* Embolden */ + hb_position_t strength = y_scale >= 0 ? y_strength : -y_strength; + for (unsigned int i = 0; i < count; i++) + { + *first_advance += *first_advance ? strength : 0; + first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); + } + } } hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph, @@ -386,23 +472,82 @@ } hb_bool_t get_glyph_extents (hb_codepoint_t glyph, - hb_glyph_extents_t *extents) + hb_glyph_extents_t *extents, + bool synthetic = true) { hb_memset (extents, 0, sizeof (*extents)); - return klass->get.f.glyph_extents (this, user_data, - glyph, - extents, - !klass->user_data ? nullptr : klass->user_data->glyph_extents); + + /* This is rather messy, but necessary. */ + + if (!synthetic) + { + return klass->get.f.glyph_extents (this, user_data, + glyph, + extents, + !klass->user_data ? nullptr : klass->user_data->glyph_extents); + } + if (!is_synthetic () && + klass->get.f.glyph_extents (this, user_data, + glyph, + extents, + !klass->user_data ? nullptr : klass->user_data->glyph_extents)) + return true; + + /* Try getting extents from paint(), then draw(), *then* get_extents() + * and apply synthetic settings in the last case. */ + + hb_paint_extents_context_t paint_extents; + if (paint_glyph_or_fail (glyph, + hb_paint_extents_get_funcs (), &paint_extents, + 0, 0)) + { + *extents = paint_extents.get_extents ().to_glyph_extents (); + return true; + } + + hb_extents_t draw_extents; + if (draw_glyph_or_fail (glyph, + hb_draw_extents_get_funcs (), &draw_extents)) + { + *extents = draw_extents.to_glyph_extents (); + return true; + } + + bool ret = klass->get.f.glyph_extents (this, user_data, + glyph, + extents, + !klass->user_data ? nullptr : klass->user_data->glyph_extents); + if (ret) + synthetic_glyph_extents (extents); + + return ret; } hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index, - hb_position_t *x, hb_position_t *y) + hb_position_t *x, hb_position_t *y, + bool synthetic = true) { *x = *y = 0; - return klass->get.f.glyph_contour_point (this, user_data, - glyph, point_index, - x, y, - !klass->user_data ? nullptr : klass->user_data->glyph_contour_point); + bool ret = klass->get.f.glyph_contour_point (this, user_data, + glyph, point_index, + x, y, + !klass->user_data ? nullptr : klass->user_data->glyph_contour_point); + + if (synthetic && ret) + { + /* Slant */ + if (slant_xy) + *x += roundf (*y * slant_xy); + + /* Embolden */ + if (!embolden_in_place) + { + int x_shift = x_scale < 0 ? -x_strength : x_strength; + *x += x_shift; + } + } + + return ret; } hb_bool_t get_glyph_name (hb_codepoint_t glyph, @@ -426,29 +571,88 @@ !klass->user_data ? nullptr : klass->user_data->glyph_from_name); } - void draw_glyph (hb_codepoint_t glyph, - hb_draw_funcs_t *draw_funcs, void *draw_data) - { - klass->get.f.draw_glyph (this, user_data, - glyph, - draw_funcs, draw_data, - !klass->user_data ? nullptr : klass->user_data->draw_glyph); + bool draw_glyph_or_fail (hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, void *draw_data, + bool synthetic = true) + { +#ifndef HB_NO_OUTLINE + bool embolden = x_strength || y_strength; + bool slanted = slant_xy; + synthetic = synthetic && (embolden || slanted); +#else + synthetic = false; +#endif + + if (!synthetic) + { + return klass->get.f.draw_glyph_or_fail (this, user_data, + glyph, + draw_funcs, draw_data, + !klass->user_data ? nullptr : klass->user_data->draw_glyph_or_fail); + } + +#ifndef HB_NO_OUTLINE + + hb_outline_t outline; + if (!klass->get.f.draw_glyph_or_fail (this, user_data, + glyph, + hb_outline_recording_pen_get_funcs (), &outline, + !klass->user_data ? nullptr : klass->user_data->draw_glyph_or_fail)) + return false; + + // Slant before embolden; produces nicer results. + + if (slanted) + outline.slant (slant_xy); + + if (embolden) + { + float x_shift = embolden_in_place ? 0 : (float) x_strength / 2; + float y_shift = (float) y_strength / 2; + if (x_scale < 0) x_shift = -x_shift; + if (y_scale < 0) y_shift = -y_shift; + outline.embolden (x_strength, y_strength, x_shift, y_shift); + } + + outline.replay (draw_funcs, draw_data); + + return true; +#endif } - void paint_glyph (hb_codepoint_t glyph, - hb_paint_funcs_t *paint_funcs, void *paint_data, - unsigned int palette, - hb_color_t foreground) - { - klass->get.f.paint_glyph (this, user_data, - glyph, - paint_funcs, paint_data, - palette, foreground, - !klass->user_data ? nullptr : klass->user_data->paint_glyph); + bool paint_glyph_or_fail (hb_codepoint_t glyph, + hb_paint_funcs_t *paint_funcs, void *paint_data, + unsigned int palette, + hb_color_t foreground, + bool synthetic = true) + { + /* Slant */ + if (synthetic && slant_xy) + hb_paint_push_transform (paint_funcs, paint_data, + 1.f, 0.f, + slant_xy, 1.f, + 0.f, 0.f); + + bool ret = klass->get.f.paint_glyph_or_fail (this, user_data, + glyph, + paint_funcs, paint_data, + palette, foreground, + !klass->user_data ? nullptr : klass->user_data->paint_glyph_or_fail); + + if (synthetic && slant_xy) + hb_paint_pop_transform (paint_funcs, paint_data); + + return ret; } /* A bit higher-level, and with fallback */ + HB_INTERNAL + void paint_glyph (hb_codepoint_t glyph, + hb_paint_funcs_t *paint_funcs, void *paint_data, + unsigned int palette, + hb_color_t foreground); + void get_h_extents_with_fallback (hb_font_extents_t *extents) { if (!get_font_h_extents (extents)) @@ -686,7 +890,12 @@ return false; } - void mults_changed () + bool is_synthetic () const + { + return x_embolden || y_embolden || slant; + } + + void changed () { float upem = face->get_upem (); @@ -697,12 +906,14 @@ bool y_neg = y_scale < 0; y_mult = (y_neg ? -((int64_t) -y_scale << 16) : ((int64_t) y_scale << 16)) / upem; - x_strength = fabsf (roundf (x_scale * x_embolden)); - y_strength = fabsf (roundf (y_scale * y_embolden)); + x_strength = roundf (abs (x_scale) * x_embolden); + y_strength = roundf (abs (y_scale) * y_embolden); slant_xy = y_scale ? slant * x_scale / y_scale : 0.f; data.fini (); + + serial++; } hb_position_t em_mult (int16_t v, int64_t mult) diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ft.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ft.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ft.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ft.cc 2025-10-13 07:49:24.000000000 +0000 @@ -37,11 +37,7 @@ #include "hb-draw.hh" #include "hb-font.hh" #include "hb-machinery.hh" -#ifndef HB_NO_AAT -#include "hb-aat-layout-trak-table.hh" -#endif #include "hb-ot-os2-table.hh" -#include "hb-ot-stat-table.hh" #include "hb-ot-shaper-arabic-pua.hh" #include "hb-paint.hh" @@ -101,7 +97,7 @@ mutable hb_mutex_t lock; /* Protects members below. */ FT_Face ft_face; - mutable unsigned cached_serial; + mutable hb_atomic_t cached_serial; mutable hb_ft_advance_cache_t advance_cache; }; @@ -118,7 +114,7 @@ ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; - ft_font->cached_serial = (unsigned) -1; + ft_font->cached_serial = UINT_MAX; new (&ft_font->advance_cache) hb_ft_advance_cache_t; return ft_font; @@ -213,9 +209,10 @@ { if (font->serial != ft_font->cached_serial) { + hb_lock_t lock (ft_font->lock); _hb_ft_hb_font_changed (font, ft_font->ft_face); ft_font->advance_cache.clear (); - ft_font->cached_serial = font->serial; + ft_font->cached_serial.set_release (font->serial.get_acquire ()); return true; } return false; @@ -478,7 +475,8 @@ void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; - hb_position_t *orig_first_advance = first_advance; + _hb_ft_hb_font_check_changed (font, ft_font); + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; int load_flags = ft_font->load_flags; @@ -519,38 +517,6 @@ first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); } - - if (font->x_strength && !font->embolden_in_place) - { - /* Emboldening. */ - hb_position_t x_strength = font->x_scale >= 0 ? font->x_strength : -font->x_strength; - first_advance = orig_first_advance; - for (unsigned int i = 0; i < count; i++) - { - *first_advance += *first_advance ? x_strength : 0; - first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); - } - } - -#ifndef HB_NO_AAT - /* According to Ned, trak is applied by default for "modern fonts", as detected by presence of STAT table. */ -#ifndef HB_NO_STYLE - bool apply_trak = font->face->table.STAT->has_data () && font->face->table.trak->has_data (); -#else - bool apply_trak = false; -#endif - if (apply_trak) - { - hb_position_t tracking = font->face->table.trak->get_h_tracking (font); - first_advance = orig_first_advance; - for (unsigned int i = 0; i < count; i++) - { - *first_advance += tracking; - first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); - first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); - } - } -#endif } #ifndef HB_NO_VERTICAL @@ -561,6 +527,8 @@ void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + _hb_ft_hb_font_check_changed (font, ft_font); + hb_lock_t lock (ft_font->lock); FT_Fixed v; float y_mult; @@ -581,26 +549,11 @@ if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | FT_LOAD_VERTICAL_LAYOUT, &v))) return 0; - v = (int) (y_mult * v); - /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates * have a Y growing upward. Hence the extra negation. */ + v = ((-v + (1<<9)) >> 10); - hb_position_t y_strength = font->y_scale >= 0 ? font->y_strength : -font->y_strength; - v = ((-v + (1<<9)) >> 10) + (font->embolden_in_place ? 0 : y_strength); - -#ifndef HB_NO_AAT - /* According to Ned, trak is applied by default for "modern fonts", as detected by presence of STAT table. */ -#ifndef HB_NO_STYLE - bool apply_trak = font->face->table.STAT->has_data () && font->face->table.trak->has_data (); -#else - bool apply_trak = false; -#endif - if (apply_trak) - v += font->face->table.trak->get_v_tracking (font); -#endif - - return v; + return (hb_position_t) (y_mult * v); } #endif @@ -614,6 +567,8 @@ void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + _hb_ft_hb_font_check_changed (font, ft_font); + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; float x_mult, y_mult; @@ -658,6 +613,8 @@ void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + _hb_ft_hb_font_check_changed (font, ft_font); + hb_lock_t lock (ft_font->lock); FT_Vector kerningv; @@ -669,6 +626,41 @@ } #endif +static bool +hb_ft_is_colr_glyph (hb_font_t *font, + void *font_data, + hb_codepoint_t gid) +{ +#ifndef HB_NO_PAINT +#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21300 + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + FT_Face ft_face = ft_font->ft_face; + + + /* COLRv1 */ + FT_OpaquePaint paint = {0}; + if (FT_Get_Color_Glyph_Paint (ft_face, gid, + FT_COLOR_NO_ROOT_TRANSFORM, + &paint)) + return true; + + /* COLRv0 */ + FT_LayerIterator iterator; + FT_UInt layer_glyph_index; + FT_UInt layer_color_index; + iterator.p = NULL; + if (FT_Get_Color_Glyph_Layer (ft_face, + gid, + &layer_glyph_index, + &layer_color_index, + &iterator)) + return true; +#endif +#endif + + return false; +} + static hb_bool_t hb_ft_get_glyph_extents (hb_font_t *font, void *font_data, @@ -676,11 +668,17 @@ hb_glyph_extents_t *extents, void *user_data HB_UNUSED) { + // FreeType doesn't return COLR glyph extents. + if (hb_ft_is_colr_glyph (font, font_data, glyph)) + return false; + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + _hb_ft_hb_font_check_changed (font, ft_font); + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; float x_mult, y_mult; - float slant_xy = font->slant_xy; + #ifdef HAVE_FT_GET_TRANSFORM if (ft_font->transform) { @@ -708,33 +706,10 @@ float x2 = x1 + x_mult * ft_face->glyph->metrics.width; float y2 = y1 + y_mult * -ft_face->glyph->metrics.height; - /* Apply slant. */ - if (slant_xy) - { - x1 += hb_min (y1 * slant_xy, y2 * slant_xy); - x2 += hb_max (y1 * slant_xy, y2 * slant_xy); - } - - extents->x_bearing = floorf (x1); - extents->y_bearing = floorf (y1); - extents->width = ceilf (x2) - extents->x_bearing; - extents->height = ceilf (y2) - extents->y_bearing; - - if (font->x_strength || font->y_strength) - { - /* Y */ - int y_shift = font->y_strength; - if (font->y_scale < 0) y_shift = -y_shift; - extents->y_bearing += y_shift; - extents->height -= y_shift; - - /* X */ - int x_shift = font->x_strength; - if (font->x_scale < 0) x_shift = -x_shift; - if (font->embolden_in_place) - extents->x_bearing -= x_shift / 2; - extents->width += x_shift; - } + extents->x_bearing = roundf (x1); + extents->y_bearing = roundf (y1); + extents->width = roundf (x2) - extents->x_bearing; + extents->height = roundf (y2) - extents->y_bearing; return true; } @@ -749,6 +724,8 @@ void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + _hb_ft_hb_font_check_changed (font, ft_font); + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; @@ -826,6 +803,8 @@ void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + _hb_ft_hb_font_check_changed (font, ft_font); + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; float y_mult; @@ -857,7 +836,7 @@ metrics->line_gap = ft_face->size->metrics.height - (metrics->ascender - metrics->descender); } - metrics->ascender = (hb_position_t) (y_mult * (metrics->ascender + font->y_strength)); + metrics->ascender = (hb_position_t) (y_mult * metrics->ascender); metrics->descender = (hb_position_t) (y_mult * metrics->descender); metrics->line_gap = (hb_position_t) (y_mult * metrics->line_gap); @@ -908,23 +887,25 @@ return FT_Err_Ok; } -static void -hb_ft_draw_glyph (hb_font_t *font, - void *font_data, - hb_codepoint_t glyph, - hb_draw_funcs_t *draw_funcs, void *draw_data, - void *user_data HB_UNUSED) +static hb_bool_t +hb_ft_draw_glyph_or_fail (hb_font_t *font, + void *font_data, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, void *draw_data, + void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + _hb_ft_hb_font_check_changed (font, ft_font); + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; if (unlikely (FT_Load_Glyph (ft_face, glyph, FT_LOAD_NO_BITMAP | ft_font->load_flags))) - return; + return false; if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE) - return; + return false; const FT_Outline_Funcs outline_funcs = { _hb_ft_move_to, @@ -935,43 +916,13 @@ 0, /* delta */ }; - hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy); - - /* Embolden */ - if (font->x_strength || font->y_strength) - { - FT_Outline_EmboldenXY (&ft_face->glyph->outline, font->x_strength, font->y_strength); - - int x_shift = 0; - int y_shift = 0; - if (font->embolden_in_place) - { - /* Undo the FreeType shift. */ - x_shift = -font->x_strength / 2; - y_shift = 0; - if (font->y_scale < 0) y_shift = -font->y_strength; - } - else - { - /* FreeType applied things in the wrong direction for negative scale; fix up. */ - if (font->x_scale < 0) x_shift = -font->x_strength; - if (font->y_scale < 0) y_shift = -font->y_strength; - } - if (x_shift || y_shift) - { - auto &outline = ft_face->glyph->outline; - for (auto &point : hb_iter (outline.points, outline.contours[outline.n_contours - 1] + 1)) - { - point.x += x_shift; - point.y += y_shift; - } - } - } - + hb_draw_session_t draw_session {draw_funcs, draw_data}; FT_Outline_Decompose (&ft_face->glyph->outline, &outline_funcs, &draw_session); + + return true; } #endif @@ -980,20 +931,22 @@ #include "hb-ft-colr.hh" -static void -hb_ft_paint_glyph (hb_font_t *font, - void *font_data, - hb_codepoint_t gid, - hb_paint_funcs_t *paint_funcs, void *paint_data, - unsigned int palette_index, - hb_color_t foreground, - void *user_data) +static hb_bool_t +hb_ft_paint_glyph_or_fail (hb_font_t *font, + void *font_data, + hb_codepoint_t gid, + hb_paint_funcs_t *paint_funcs, void *paint_data, + unsigned int palette_index, + hb_color_t foreground, + void *user_data) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + _hb_ft_hb_font_check_changed (font, ft_font); + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; - FT_Long load_flags = ft_font->load_flags | FT_LOAD_NO_BITMAP | FT_LOAD_COLOR; + FT_Long load_flags = ft_font->load_flags | FT_LOAD_COLOR; #if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21301 load_flags |= FT_LOAD_NO_SVG; #endif @@ -1002,7 +955,7 @@ * eg. draw API can call back into the face.*/ if (unlikely (FT_Load_Glyph (ft_face, gid, load_flags))) - return; + return false; if (ft_face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) { @@ -1010,26 +963,21 @@ paint_funcs, paint_data, palette_index, foreground, user_data)) - return; - - /* Simple outline. */ - ft_font->lock.unlock (); - paint_funcs->push_clip_glyph (paint_data, gid, font); - ft_font->lock.lock (); - paint_funcs->color (paint_data, true, foreground); - paint_funcs->pop_clip (paint_data); + return true; - return; + // Outline glyph + return false; } auto *glyph = ft_face->glyph; if (glyph->format == FT_GLYPH_FORMAT_BITMAP) { + bool ret = false; auto &bitmap = glyph->bitmap; if (bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) { if (bitmap.pitch != (signed) bitmap.width * 4) - return; + return ret; ft_font->lock.unlock (); @@ -1039,27 +987,26 @@ nullptr, nullptr); hb_glyph_extents_t extents; - if (!hb_font_get_glyph_extents (font, gid, &extents)) + if (!font->get_glyph_extents (gid, &extents, false)) goto out; - if (!paint_funcs->image (paint_data, - blob, - bitmap.width, - bitmap.rows, - HB_PAINT_IMAGE_FORMAT_BGRA, - font->slant_xy, - &extents)) - { - /* TODO Try a forced outline load and paint? */ - } + if (paint_funcs->image (paint_data, + blob, + bitmap.width, + bitmap.rows, + HB_PAINT_IMAGE_FORMAT_BGRA, + 0.f, + &extents)) + ret = true; out: hb_blob_destroy (blob); ft_font->lock.lock (); } - return; + return ret; } + return false; } #endif #endif @@ -1079,10 +1026,8 @@ hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, nullptr, nullptr); hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ft_get_glyph_h_advances, nullptr, nullptr); - //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, nullptr, nullptr); #ifndef HB_NO_VERTICAL - //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr); hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr); hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, nullptr, nullptr); #endif @@ -1090,19 +1035,18 @@ #ifndef HB_NO_OT_SHAPE_FALLBACK hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, nullptr, nullptr); #endif - //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, nullptr, nullptr); hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, nullptr, nullptr); hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, nullptr, nullptr); hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr); hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, nullptr, nullptr); #ifndef HB_NO_DRAW - hb_font_funcs_set_draw_glyph_func (funcs, hb_ft_draw_glyph, nullptr, nullptr); + hb_font_funcs_set_draw_glyph_or_fail_func (funcs, hb_ft_draw_glyph_or_fail, nullptr, nullptr); #endif #ifndef HB_NO_PAINT #if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21300 - hb_font_funcs_set_paint_glyph_func (funcs, hb_ft_paint_glyph, nullptr, nullptr); + hb_font_funcs_set_paint_glyph_or_fail_func (funcs, hb_ft_paint_glyph_or_fail, nullptr, nullptr); #endif #endif @@ -1456,6 +1400,10 @@ * variation-axis settings on the @font. * This call is fast if nothing has changed on @font. * + * Note that as of version 11.0.0, calling this function is not necessary, + * as HarfBuzz will automatically detect changes to the font and update + * the underlying FT_Face as needed. + * * Return value: true if changed, false otherwise * * Since: 4.4.0 @@ -1587,7 +1535,8 @@ * font file and face index. * * This is similar in functionality to hb_face_create_from_file_or_fail(), - * but uses the FreeType library for loading the font file. + * but uses the FreeType library for loading the font file. This can + * be useful, for example, to load WOFF and WOFF2 font data. * * Return value: (transfer full): The new face object, or `NULL` if * no face is found at the specified index or the file cannot be read. @@ -1623,6 +1572,75 @@ return face; } + +static hb_user_data_key_t ft_blob_key = {0}; + +static void +_destroy_blob (void *p) +{ + hb_blob_destroy ((hb_blob_t *) p); +} + +/** + * hb_ft_face_create_from_blob_or_fail: + * @blob: A blob + * @index: The index of the face within the blob + * + * Creates an #hb_face_t face object from the specified + * font blob and face index. + * + * This is similar in functionality to hb_face_create_from_blob_or_fail(), + * but uses the FreeType library for loading the font blob. This can + * be useful, for example, to load WOFF and WOFF2 font data. + * + * Return value: (transfer full): The new face object, or `NULL` if + * loading fails (eg. blob does not contain valid font data). + * + * Since: 11.0.0 + */ +hb_face_t * +hb_ft_face_create_from_blob_or_fail (hb_blob_t *blob, + unsigned int index) +{ + FT_Library ft_library = reference_ft_library (); + if (unlikely (!ft_library)) + { + DEBUG_MSG (FT, ft_library, "reference_ft_library failed"); + return nullptr; + } + + hb_blob_make_immutable (blob); + unsigned blob_size; + const char *blob_data = hb_blob_get_data (blob, &blob_size); + + FT_Face ft_face; + if (unlikely (FT_New_Memory_Face (ft_library, + (const FT_Byte *) blob_data, + blob_size, + index, + &ft_face))) + return nullptr; + + hb_face_t *face = hb_ft_face_create_referenced (ft_face); + FT_Done_Face (ft_face); + + ft_face->generic.data = ft_library; + ft_face->generic.finalizer = finalize_ft_library; + + if (hb_face_is_immutable (face)) + return nullptr; + + // Hook the blob to the hb_face_t, since FT_Face still needs it. + hb_blob_reference (blob); + if (!hb_face_set_user_data (face, &ft_blob_key, blob, _destroy_blob, true)) + { + hb_blob_destroy (blob); + hb_face_destroy (face); + return nullptr; + } + + return face; +} static void _release_blob (void *arg) diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ft.h openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ft.h --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ft.h 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ft.h 2025-10-13 07:49:24.000000000 +0000 @@ -88,6 +88,10 @@ hb_ft_face_create_from_file_or_fail (const char *file_name, unsigned int index); +HB_EXTERN hb_face_t * +hb_ft_face_create_from_blob_or_fail (hb_blob_t *blob, + unsigned int index); + /* * hb-font from ft-face. */ diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-geometry.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-geometry.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-geometry.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-geometry.hh 2025-10-13 07:49:24.000000000 +0000 @@ -30,6 +30,11 @@ struct hb_extents_t { hb_extents_t () {} + hb_extents_t (const hb_glyph_extents_t &extents) : + xmin (hb_min (extents.x_bearing, extents.x_bearing + extents.width)), + ymin (hb_min (extents.y_bearing, extents.y_bearing + extents.height)), + xmax (hb_max (extents.x_bearing, extents.x_bearing + extents.width)), + ymax (hb_max (extents.y_bearing, extents.y_bearing + extents.height)) {} hb_extents_t (float xmin, float ymin, float xmax, float ymax) : xmin (xmin), ymin (ymin), xmax (xmax), ymax (ymax) {} @@ -38,6 +43,12 @@ void union_ (const hb_extents_t &o) { + if (o.is_empty ()) return; + if (is_empty ()) + { + *this = o; + return; + } xmin = hb_min (xmin, o.xmin); ymin = hb_min (ymin, o.ymin); xmax = hb_max (xmax, o.xmax); @@ -46,6 +57,11 @@ void intersect (const hb_extents_t &o) { + if (o.is_empty () || is_empty ()) + { + *this = hb_extents_t {}; + return; + } xmin = hb_max (xmin, o.xmin); ymin = hb_max (ymin, o.ymin); xmax = hb_min (xmax, o.xmax); @@ -69,6 +85,18 @@ } } + hb_glyph_extents_t to_glyph_extents (bool xneg = false, bool yneg = false) const + { + hb_position_t x0 = (hb_position_t) roundf (xmin); + hb_position_t y0 = (hb_position_t) roundf (ymin); + hb_position_t x1 = (hb_position_t) roundf (xmax); + hb_position_t y1 = (hb_position_t) roundf (ymax); + return hb_glyph_extents_t {xneg ? x1 : x0, + yneg ? y0 : y1, + xneg ? x0 - x1 : x1 - x0, + yneg ? y1 - y0 : y0 - y1}; + } + float xmin = 0.f; float ymin = 0.f; float xmax = -1.f; @@ -218,7 +246,7 @@ EMPTY, }; - hb_bounds_t (status_t status) : status (status) {} + hb_bounds_t (status_t status = UNBOUNDED) : status (status) {} hb_bounds_t (const hb_extents_t &extents) : status (extents.is_empty () ? EMPTY : BOUNDED), extents (extents) {} diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-machinery.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-machinery.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-machinery.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-machinery.hh 2025-10-13 07:49:24.000000000 +0000 @@ -273,7 +273,7 @@ private: /* Must only have one pointer. */ - hb_atomic_ptr_t instance; + mutable hb_atomic_t instance; }; /* Specializations. */ diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-mutex.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-mutex.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-mutex.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-mutex.hh 2025-10-13 07:49:24.000000000 +0000 @@ -99,6 +99,8 @@ hb_mutex_t () { init (); } ~hb_mutex_t () { fini (); } + hb_mutex_t (const hb_mutex_t &) = delete; + hb_mutex_t &operator= (const hb_mutex_t &) = delete; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-align" @@ -114,6 +116,10 @@ hb_lock_t (hb_mutex_t &mutex_) : mutex (&mutex_) { mutex->lock (); } hb_lock_t (hb_mutex_t *mutex_) : mutex (mutex_) { if (mutex) mutex->lock (); } ~hb_lock_t () { if (mutex) mutex->unlock (); } + + hb_lock_t (const hb_lock_t &) = delete; + hb_lock_t &operator= (const hb_lock_t &) = delete; + private: hb_mutex_t *mutex; }; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-object.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-object.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-object.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-object.hh 2025-10-13 07:49:24.000000000 +0000 @@ -142,7 +142,7 @@ struct hb_reference_count_t { - mutable hb_atomic_int_t ref_count; + mutable hb_atomic_t ref_count; void init (int v = 1) { ref_count = v; } int get_relaxed () const { return ref_count; } @@ -213,8 +213,8 @@ struct hb_object_header_t { hb_reference_count_t ref_count; - mutable hb_atomic_int_t writable = 0; - hb_atomic_ptr_t user_data; + mutable hb_atomic_t writable = false; + hb_atomic_t user_data; bool is_inert () const { return !ref_count.get_relaxed (); } }; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh 2025-10-13 07:49:24.000000000 +0000 @@ -1888,7 +1888,7 @@ bool ensure_run () { - if (likely (run_count > 0)) return true; + if (run_count > 0) return true; if (unlikely (p >= end)) { @@ -1943,6 +1943,11 @@ unsigned count = hb_min (n - i, (unsigned) run_count); switch (width) { + case 0: + { + arrayZ += count; + break; + } case 1: { const auto *pp = (const HBINT8 *) p; @@ -1958,6 +1963,8 @@ #endif for (; j < count; j++) *arrayZ++ += scaled ? *pp++ * scale : *pp++; + + p = (const unsigned char *) pp; } break; case 2: @@ -1975,6 +1982,8 @@ #endif for (; j < count; j++) *arrayZ++ += scaled ? *pp++ * scale : *pp++; + + p = (const unsigned char *) pp; } break; case 4: @@ -1982,10 +1991,11 @@ const auto *pp = (const HBINT32 *) p; for (unsigned j = 0; j < count; j++) *arrayZ++ += scaled ? *pp++ * scale : *pp++; + + p = (const unsigned char *) pp; } break; } - p += count * width; run_count -= count; i += count; } diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh 2025-10-13 07:49:24.000000000 +0000 @@ -1073,7 +1073,7 @@ this->blob = sc.reference_table (face); - /* setup for run-time santization */ + /* setup for run-time sanitization */ sc.init (this->blob); sc.start_processing (); @@ -1176,7 +1176,8 @@ if (unlikely (!font_interp.interpret (*font))) goto fail; PRIVDICTVAL *priv = &privateDicts[i]; const hb_ubytes_t privDictStr = StructAtOffsetOrNull (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size); - if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail; + if (unlikely (font->privateDictInfo.size && + privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail; num_interp_env_t env2 (privDictStr); dict_interpreter_t priv_interp (env2); priv->init (); @@ -1191,7 +1192,8 @@ PRIVDICTVAL *priv = &privateDicts[0]; const hb_ubytes_t privDictStr = StructAtOffsetOrNull (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size); - if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail; + if (font->privateDictInfo.size && + unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail; num_interp_env_t env (privDictStr); dict_interpreter_t priv_interp (env); priv->init (); @@ -1483,7 +1485,7 @@ int cmp (const gname_t &a) const { return cmp (&a, this); } }; - mutable hb_atomic_ptr_t> glyph_names; + mutable hb_atomic_t *> glyph_names; typedef accelerator_templ_t SUPER; }; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc 2025-10-13 07:49:24.000000000 +0000 @@ -103,6 +103,14 @@ hb_codepoint_t glyph, hb_glyph_extents_t *extents) const { + return get_extents_at (font, glyph, extents, hb_array (font->coords, font->num_coords)); +} + +bool OT::cff2::accelerator_t::get_extents_at (hb_font_t *font, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents, + hb_array_t coords) const +{ #ifdef HB_NO_OT_FONT_CFF /* XXX Remove check when this code moves to .hh file. */ return true; @@ -112,7 +120,7 @@ unsigned int fd = fdSelect->get_fd (glyph); const hb_ubytes_t str = (*charStrings)[glyph]; - cff2_cs_interp_env_t env (str, *this, fd, font->coords, font->num_coords); + cff2_cs_interp_env_t env (str, *this, fd, coords.arrayZ, coords.length); cff2_cs_interpreter_t interp (env); cff2_extents_param_t param; if (unlikely (!interp.interpret (param))) return false; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh 2025-10-13 07:49:24.000000000 +0000 @@ -405,7 +405,7 @@ this->blob = sc.reference_table (face); - /* setup for run-time santization */ + /* setup for run-time sanitization */ sc.init (this->blob); sc.start_processing (); @@ -458,7 +458,8 @@ if (unlikely (!font_interp.interpret (*font))) goto fail; const hb_ubytes_t privDictStr = StructAtOffsetOrNull (cff2, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size); - if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail; + if (unlikely (font->privateDictInfo.size && + privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail; cff2_priv_dict_interp_env_t env2 (privDictStr); dict_interpreter_t priv_interp (env2); privateDicts[i].init (); @@ -481,6 +482,13 @@ privateDicts.fini (); hb_blob_destroy (blob); blob = nullptr; + + auto *scalars = cached_scalars_vector.get_acquire (); + if (scalars && cached_scalars_vector.cmpexch (scalars, nullptr)) + { + scalars->fini (); + hb_free (scalars); + } } hb_vector_t *create_glyph_to_sid_map () const @@ -508,6 +516,8 @@ hb_vector_t fontDicts; hb_vector_t privateDicts; + mutable hb_atomic_t *> cached_scalars_vector; + unsigned int num_glyphs = 0; }; @@ -518,6 +528,10 @@ HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const; + HB_INTERNAL bool get_extents_at (hb_font_t *font, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents, + hb_array_t coords) const; HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const; HB_INTERNAL bool get_path_at (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session, hb_array_t coords) const; }; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh 2025-10-13 07:49:24.000000000 +0000 @@ -2014,7 +2014,8 @@ struct accelerator_t { - using cache_t = hb_cache_t<21, 16, 8, true>; + using cache_t = hb_cache_t<21, 19>; + static_assert (sizeof (cache_t) == 1024, ""); accelerator_t (hb_face_t *face) { @@ -2028,6 +2029,14 @@ subtable_uvs = &st->u.format14; } +#ifndef HB_NO_OT_FONT_CMAP_CACHE + cache = (cache_t *) hb_malloc (sizeof (cache_t)); + if (cache) + new (cache) cache_t (); + else + return; // Such that get_glyph_funcZ remains null. +#endif + this->get_glyph_data = subtable; #ifndef HB_NO_CMAP_LEGACY_SUBTABLES if (unlikely (symbol)) @@ -2061,62 +2070,71 @@ #endif { switch (subtable->u.format) { - /* Accelerate format 4 and format 12. */ - default: - this->get_glyph_funcZ = get_glyph_from; - break; - case 12: - this->get_glyph_funcZ = get_glyph_from; - break; - case 4: - { - this->format4_accel.init (&subtable->u.format4); - this->get_glyph_data = &this->format4_accel; - this->get_glyph_funcZ = this->format4_accel.get_glyph_func; - break; - } + /* Accelerate format 4 and format 12. */ + default: + this->get_glyph_funcZ = get_glyph_from; + break; + case 12: + this->get_glyph_funcZ = get_glyph_from; + break; + case 4: + { + this->format4_accel.init (&subtable->u.format4); + this->get_glyph_data = &this->format4_accel; + this->get_glyph_funcZ = this->format4_accel.get_glyph_func; + break; + } } } } - ~accelerator_t () { this->table.destroy (); } + ~accelerator_t () + { +#ifndef HB_NO_OT_FONT_CMAP_CACHE + hb_free (cache); +#endif + table.destroy (); + } inline bool _cached_get (hb_codepoint_t unicode, - hb_codepoint_t *glyph, - cache_t *cache) const + hb_codepoint_t *glyph) const { +#ifndef HB_NO_OT_FONT_CMAP_CACHE + // cache is always non-null if we have a get_glyph_funcZ unsigned v; - if (cache && cache->get (unicode, &v)) + if (cache->get (unicode, &v)) { *glyph = v; return true; } +#endif bool ret = this->get_glyph_funcZ (this->get_glyph_data, unicode, glyph); - if (cache && ret) +#ifndef HB_NO_OT_FONT_CMAP_CACHE + if (ret) cache->set (unicode, *glyph); +#endif + return ret; } bool get_nominal_glyph (hb_codepoint_t unicode, - hb_codepoint_t *glyph, - cache_t *cache = nullptr) const + hb_codepoint_t *glyph) const { if (unlikely (!this->get_glyph_funcZ)) return false; - return _cached_get (unicode, glyph, cache); + return _cached_get (unicode, glyph); } unsigned int get_nominal_glyphs (unsigned int count, const hb_codepoint_t *first_unicode, unsigned int unicode_stride, hb_codepoint_t *first_glyph, - unsigned int glyph_stride, - cache_t *cache = nullptr) const + unsigned int glyph_stride) const { if (unlikely (!this->get_glyph_funcZ)) return 0; unsigned int done; for (done = 0; - done < count && _cached_get (*first_unicode, first_glyph, cache); + done < count && _cached_get (*first_unicode, first_glyph); done++) { first_unicode = &StructAtOffsetUnaligned (first_unicode, unicode_stride); @@ -2127,8 +2145,7 @@ bool get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector, - hb_codepoint_t *glyph, - cache_t *cache = nullptr) const + hb_codepoint_t *glyph) const { switch (this->subtable_uvs->get_glyph_variant (unicode, variation_selector, @@ -2139,7 +2156,7 @@ case GLYPH_VARIANT_USE_DEFAULT: break; } - return get_nominal_glyph (unicode, glyph, cache); + return get_nominal_glyph (unicode, glyph); } void collect_unicodes (hb_set_t *out, unsigned int num_glyphs) const @@ -2209,11 +2226,15 @@ hb_nonnull_ptr_t subtable; hb_nonnull_ptr_t subtable_uvs; - hb_cmap_get_glyph_func_t get_glyph_funcZ; - const void *get_glyph_data; + hb_cmap_get_glyph_func_t get_glyph_funcZ = nullptr; + const void *get_glyph_data = nullptr; CmapSubtableFormat4::accelerator_t format4_accel; +#ifndef HB_NO_OT_FONT_CMAP_CACHE + cache_t *cache = nullptr; +#endif + public: hb_blob_ptr_t table; }; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-color.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-color.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-color.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-color.cc 2025-10-13 07:49:24.000000000 +0000 @@ -204,7 +204,7 @@ hb_bool_t hb_ot_color_has_layers (hb_face_t *face) { - return face->table.COLR->has_v0_data (); + return face->table.COLR->colr->has_v0_data (); } /** @@ -221,7 +221,7 @@ hb_bool_t hb_ot_color_has_paint (hb_face_t *face) { - return face->table.COLR->has_v1_data (); + return face->table.COLR->colr->has_v1_data (); } /** @@ -240,7 +240,7 @@ hb_ot_color_glyph_has_paint (hb_face_t *face, hb_codepoint_t glyph) { - return face->table.COLR->has_paint_for_glyph (glyph); + return face->table.COLR->colr->has_paint_for_glyph (glyph); } /** @@ -266,7 +266,7 @@ unsigned int *layer_count, /* IN/OUT. May be NULL. */ hb_ot_color_layer_t *layers /* OUT. May be NULL. */) { - return face->table.COLR->get_glyph_layers (glyph, start_offset, layer_count, layers); + return face->table.COLR->colr->get_glyph_layers (glyph, start_offset, layer_count, layers); } diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh 2025-10-13 07:49:24.000000000 +0000 @@ -136,7 +136,7 @@ /* OpenType color fonts. */ #ifndef HB_NO_COLOR -HB_OT_CORE_TABLE (OT, COLR) +HB_OT_ACCELERATOR (OT, COLR) HB_OT_CORE_TABLE (OT, CPAL) HB_OT_ACCELERATOR (OT, CBDT) HB_OT_ACCELERATOR (OT, sbix) diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-face.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-face.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-face.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-face.cc 2025-10-13 07:49:24.000000000 +0000 @@ -36,6 +36,7 @@ #include "hb-ot-name-table.hh" #include "hb-ot-post-table.hh" #include "OT/Color/CBDT/CBDT.hh" +#include "OT/Color/COLR/COLR.hh" #include "OT/Color/sbix/sbix.hh" #include "OT/Color/svg/svg.hh" #include "hb-ot-layout-gdef-table.hh" diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc 2025-10-13 07:49:24.000000000 +0000 @@ -34,11 +34,7 @@ #include "hb-font.hh" #include "hb-machinery.hh" #include "hb-ot-face.hh" -#include "hb-outline.hh" -#ifndef HB_NO_AAT -#include "hb-aat-layout-trak-table.hh" -#endif #include "hb-ot-cmap-table.hh" #include "hb-ot-glyf-table.hh" #include "hb-ot-cff2-table.hh" @@ -65,28 +61,111 @@ * never need to call these functions directly. **/ -using hb_ot_font_cmap_cache_t = hb_cache_t<21, 16, 8, true>; -using hb_ot_font_advance_cache_t = hb_cache_t<24, 16, 8, true>; - -#ifndef HB_NO_OT_FONT_CMAP_CACHE -static hb_user_data_key_t hb_ot_font_cmap_cache_user_data_key; -#endif +using hb_ot_font_advance_cache_t = hb_cache_t<24, 16>; +static_assert (sizeof (hb_ot_font_advance_cache_t) == 1024, ""); struct hb_ot_font_t { const hb_ot_face_t *ot_face; -#ifndef HB_NO_AAT - bool apply_trak; -#endif + /* h_advance caching */ + mutable hb_atomic_t cached_coords_serial; + struct advance_cache_t + { + mutable hb_atomic_t advance_cache; + mutable hb_atomic_t varStore_cache; -#ifndef HB_NO_OT_FONT_CMAP_CACHE - hb_ot_font_cmap_cache_t *cmap_cache; -#endif + ~advance_cache_t () + { + clear (); + } - /* h_advance caching */ - mutable hb_atomic_int_t cached_coords_serial; - mutable hb_atomic_ptr_t advance_cache; + hb_ot_font_advance_cache_t *acquire_advance_cache () const + { + retry: + auto *cache = advance_cache.get_acquire (); + if (!cache) + { + cache = (hb_ot_font_advance_cache_t *) hb_malloc (sizeof (hb_ot_font_advance_cache_t)); + if (!cache) + return nullptr; + new (cache) hb_ot_font_advance_cache_t; + return cache; + } + if (advance_cache.cmpexch (cache, nullptr)) + return cache; + else + goto retry; + } + void release_advance_cache (hb_ot_font_advance_cache_t *cache) const + { + if (!cache) + return; + if (!advance_cache.cmpexch (nullptr, cache)) + hb_free (cache); + } + void clear_advance_cache () const + { + retry: + auto *cache = advance_cache.get_acquire (); + if (!cache) + return; + if (advance_cache.cmpexch (cache, nullptr)) + hb_free (cache); + else + goto retry; + } + + OT::ItemVariationStore::cache_t *acquire_varStore_cache (const OT::ItemVariationStore &varStore) const + { + retry: + auto *cache = varStore_cache.get_acquire (); + if (!cache) + return varStore.create_cache (); + if (varStore_cache.cmpexch (cache, nullptr)) + return cache; + else + goto retry; + } + void release_varStore_cache (OT::ItemVariationStore::cache_t *cache) const + { + if (!cache) + return; + if (!varStore_cache.cmpexch (nullptr, cache)) + OT::ItemVariationStore::destroy_cache (cache); + } + void clear_varStore_cache () const + { + retry: + auto *cache = varStore_cache.get_acquire (); + if (!cache) + return; + if (varStore_cache.cmpexch (cache, nullptr)) + OT::ItemVariationStore::destroy_cache (cache); + else + goto retry; + } + + void clear () const + { + clear_advance_cache (); + clear_varStore_cache (); + } + + } h, v; + + void check_serial (hb_font_t *font) const + { + int font_serial = font->serial_coords.get_acquire (); + + if (cached_coords_serial.get_acquire () == font_serial) + return; + + h.clear (); + v.clear (); + + cached_coords_serial.set_release (font_serial); + } }; static hb_ot_font_t * @@ -98,44 +177,6 @@ ot_font->ot_face = &font->face->table; -#ifndef HB_NO_AAT - /* According to Ned, trak is applied by default for "modern fonts", as detected by presence of STAT table. */ -#ifndef HB_NO_STYLE - ot_font->apply_trak = font->face->table.STAT->has_data () && font->face->table.trak->has_data (); -#else - ot_font->apply_trak = false; -#endif -#endif - -#ifndef HB_NO_OT_FONT_CMAP_CACHE - // retry: - auto *cmap_cache = (hb_ot_font_cmap_cache_t *) hb_face_get_user_data (font->face, - &hb_ot_font_cmap_cache_user_data_key); - if (!cmap_cache) - { - cmap_cache = (hb_ot_font_cmap_cache_t *) hb_malloc (sizeof (hb_ot_font_cmap_cache_t)); - if (unlikely (!cmap_cache)) goto out; - new (cmap_cache) hb_ot_font_cmap_cache_t (); - if (unlikely (!hb_face_set_user_data (font->face, - &hb_ot_font_cmap_cache_user_data_key, - cmap_cache, - hb_free, - false))) - { - hb_free (cmap_cache); - cmap_cache = nullptr; - /* Normally we would retry here, but that would - * infinite-loop if the face is the empty-face. - * Just let it go and this font will be uncached if it - * happened to collide with another thread creating the - * cache at the same time. */ - // goto retry; - } - } - out: - ot_font->cmap_cache = cmap_cache; -#endif - return ot_font; } @@ -144,8 +185,7 @@ { hb_ot_font_t *ot_font = (hb_ot_font_t *) font_data; - auto *cache = ot_font->advance_cache.get_relaxed (); - hb_free (cache); + ot_font->~hb_ot_font_t (); hb_free (ot_font); } @@ -159,11 +199,7 @@ { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; const hb_ot_face_t *ot_face = ot_font->ot_face; - hb_ot_font_cmap_cache_t *cmap_cache = nullptr; -#ifndef HB_NO_OT_FONT_CMAP_CACHE - cmap_cache = ot_font->cmap_cache; -#endif - return ot_face->cmap->get_nominal_glyph (unicode, glyph, cmap_cache); + return ot_face->cmap->get_nominal_glyph (unicode, glyph); } static unsigned int @@ -178,14 +214,9 @@ { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; const hb_ot_face_t *ot_face = ot_font->ot_face; - hb_ot_font_cmap_cache_t *cmap_cache = nullptr; -#ifndef HB_NO_OT_FONT_CMAP_CACHE - cmap_cache = ot_font->cmap_cache; -#endif return ot_face->cmap->get_nominal_glyphs (count, first_unicode, unicode_stride, - first_glyph, glyph_stride, - cmap_cache); + first_glyph, glyph_stride); } static hb_bool_t @@ -198,13 +229,8 @@ { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; const hb_ot_face_t *ot_face = ot_font->ot_face; - hb_ot_font_cmap_cache_t *cmap_cache = nullptr; -#ifndef HB_NO_OT_FONT_CMAP_CACHE - cmap_cache = ot_font->cmap_cache; -#endif return ot_face->cmap->get_variation_glyph (unicode, - variation_selector, glyph, - cmap_cache); + variation_selector, glyph); } static void @@ -216,47 +242,25 @@ unsigned advance_stride, void *user_data HB_UNUSED) { + const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; const hb_ot_face_t *ot_face = ot_font->ot_face; const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx; - hb_position_t *orig_first_advance = first_advance; - -#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) + ot_font->check_serial (font); const OT::HVAR &HVAR = *hmtx.var_table; const OT::ItemVariationStore &varStore = &HVAR + HVAR.varStore; - OT::ItemVariationStore::cache_t *varStore_cache = font->num_coords * count >= 128 ? varStore.create_cache () : nullptr; + OT::ItemVariationStore::cache_t *varStore_cache = ot_font->h.acquire_varStore_cache (varStore); - bool use_cache = font->num_coords; -#else - OT::ItemVariationStore::cache_t *varStore_cache = nullptr; - bool use_cache = false; -#endif + hb_ot_font_advance_cache_t *advance_cache = nullptr; - hb_ot_font_advance_cache_t *cache = nullptr; + bool use_cache = font->num_coords; if (use_cache) { - retry: - cache = ot_font->advance_cache.get_acquire (); - if (unlikely (!cache)) - { - cache = (hb_ot_font_advance_cache_t *) hb_malloc (sizeof (hb_ot_font_advance_cache_t)); - if (unlikely (!cache)) - { - use_cache = false; - goto out; - } - new (cache) hb_ot_font_advance_cache_t; - - if (unlikely (!ot_font->advance_cache.cmpexch (nullptr, cache))) - { - hb_free (cache); - goto retry; - } - ot_font->cached_coords_serial.set_release (font->serial_coords); - } + advance_cache = ot_font->h.acquire_advance_cache (); + if (!advance_cache) + use_cache = false; } - out: if (!use_cache) { @@ -269,58 +273,26 @@ } else { /* Use cache. */ - if (ot_font->cached_coords_serial.get_acquire () != (int) font->serial_coords) - { - ot_font->advance_cache->clear (); - ot_font->cached_coords_serial.set_release (font->serial_coords); - } - for (unsigned int i = 0; i < count; i++) { hb_position_t v; unsigned cv; - if (ot_font->advance_cache->get (*first_glyph, &cv)) + if (advance_cache->get (*first_glyph, &cv)) v = cv; else { v = hmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache); - ot_font->advance_cache->set (*first_glyph, v); + advance_cache->set (*first_glyph, v); } *first_advance = font->em_scale_x (v); first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); } - } - -#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) - OT::ItemVariationStore::destroy_cache (varStore_cache); -#endif - if (font->x_strength && !font->embolden_in_place) - { - /* Emboldening. */ - hb_position_t x_strength = font->x_scale >= 0 ? font->x_strength : -font->x_strength; - first_advance = orig_first_advance; - for (unsigned int i = 0; i < count; i++) - { - *first_advance += *first_advance ? x_strength : 0; - first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); - } + ot_font->h.release_advance_cache (advance_cache); } -#ifndef HB_NO_AAT - if (ot_font->apply_trak) - { - hb_position_t tracking = font->face->table.trak->get_h_tracking (font); - first_advance = orig_first_advance; - for (unsigned int i = 0; i < count; i++) - { - *first_advance += tracking; - first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); - first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); - } - } -#endif + ot_font->h.release_varStore_cache (varStore_cache); } #ifndef HB_NO_VERTICAL @@ -337,17 +309,13 @@ const hb_ot_face_t *ot_face = ot_font->ot_face; const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx; - hb_position_t *orig_first_advance = first_advance; - if (vmtx.has_data ()) { -#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) + ot_font->check_serial (font); const OT::VVAR &VVAR = *vmtx.var_table; const OT::ItemVariationStore &varStore = &VVAR + VVAR.varStore; - OT::ItemVariationStore::cache_t *varStore_cache = font->num_coords ? varStore.create_cache () : nullptr; -#else - OT::ItemVariationStore::cache_t *varStore_cache = nullptr; -#endif + OT::ItemVariationStore::cache_t *varStore_cache = ot_font->v.acquire_varStore_cache (varStore); + // TODO Use advance_cache. for (unsigned int i = 0; i < count; i++) { @@ -356,9 +324,7 @@ first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); } -#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) - OT::ItemVariationStore::destroy_cache (varStore_cache); -#endif + ot_font->v.release_varStore_cache (varStore_cache); } else { @@ -373,32 +339,6 @@ first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); } } - - if (font->y_strength && !font->embolden_in_place) - { - /* Emboldening. */ - hb_position_t y_strength = font->y_scale >= 0 ? font->y_strength : -font->y_strength; - first_advance = orig_first_advance; - for (unsigned int i = 0; i < count; i++) - { - *first_advance += *first_advance ? y_strength : 0; - first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); - } - } - -#ifndef HB_NO_AAT - if (ot_font->apply_trak) - { - hb_position_t tracking = font->face->table.trak->get_v_tracking (font); - first_advance = orig_first_advance; - for (unsigned int i = 0; i < count; i++) - { - *first_advance += tracking; - first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); - first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); - } - } -#endif } #endif @@ -435,7 +375,8 @@ } hb_glyph_extents_t extents = {0}; - if (ot_face->glyf->get_extents (font, glyph, &extents)) + + if (hb_font_get_glyph_extents (font, glyph, &extents)) { const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx; int tsb = 0; @@ -448,7 +389,7 @@ hb_font_extents_t font_extents; font->get_h_extents_with_fallback (&font_extents); hb_position_t advance = font_extents.ascender - font_extents.descender; - int diff = advance - -extents.height; + hb_position_t diff = advance - -extents.height; *y = extents.y_bearing + (diff >> 1); return true; } @@ -478,6 +419,9 @@ #if !defined(HB_NO_COLOR) && !defined(HB_NO_PAINT) if (ot_face->COLR->get_extents (font, glyph, extents)) return true; #endif +#ifndef HB_NO_VAR_COMPOSITES + if (ot_face->VARC->get_extents (font, glyph, extents)) return true; +#endif if (ot_face->glyf->get_extents (font, glyph, extents)) return true; #ifndef HB_NO_OT_FONT_CFF if (ot_face->cff2->get_extents (font, glyph, extents)) return true; @@ -528,16 +472,9 @@ hb_font_extents_t *metrics, void *user_data HB_UNUSED) { - bool ret = _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, &metrics->ascender) && - _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &metrics->descender) && - _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap); - - /* Embolden */ - int y_shift = font->y_strength; - if (font->y_scale < 0) y_shift = -y_shift; - metrics->ascender += y_shift; - - return ret; + return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, &metrics->ascender) && + _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &metrics->descender) && + _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap); } #ifndef HB_NO_VERTICAL @@ -554,68 +491,46 @@ #endif #ifndef HB_NO_DRAW -static void -hb_ot_draw_glyph (hb_font_t *font, - void *font_data HB_UNUSED, - hb_codepoint_t glyph, - hb_draw_funcs_t *draw_funcs, void *draw_data, - void *user_data) -{ - bool embolden = font->x_strength || font->y_strength; - hb_outline_t outline; - - { // Need draw_session to be destructed before emboldening. - hb_draw_session_t draw_session (embolden ? hb_outline_recording_pen_get_funcs () : draw_funcs, - embolden ? &outline : draw_data, font->slant_xy); +static hb_bool_t +hb_ot_draw_glyph_or_fail (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, void *draw_data, + void *user_data) +{ + hb_draw_session_t draw_session {draw_funcs, draw_data}; #ifndef HB_NO_VAR_COMPOSITES - if (!font->face->table.VARC->get_path (font, glyph, draw_session)) + if (font->face->table.VARC->get_path (font, glyph, draw_session)) return true; #endif - // Keep the following in synch with VARC::get_path_at() - if (!font->face->table.glyf->get_path (font, glyph, draw_session)) + // Keep the following in synch with VARC::get_path_at() + if (font->face->table.glyf->get_path (font, glyph, draw_session)) return true; #ifndef HB_NO_CFF - if (!font->face->table.cff2->get_path (font, glyph, draw_session)) - if (!font->face->table.cff1->get_path (font, glyph, draw_session)) + if (font->face->table.cff2->get_path (font, glyph, draw_session)) return true; + if (font->face->table.cff1->get_path (font, glyph, draw_session)) return true; #endif - {} - } - - if (embolden) - { - float x_shift = font->embolden_in_place ? 0 : (float) font->x_strength / 2; - float y_shift = (float) font->y_strength / 2; - if (font->x_scale < 0) x_shift = -x_shift; - if (font->y_scale < 0) y_shift = -y_shift; - outline.embolden (font->x_strength, font->y_strength, - x_shift, y_shift); - - outline.replay (draw_funcs, draw_data); - } + return false; } #endif #ifndef HB_NO_PAINT -static void -hb_ot_paint_glyph (hb_font_t *font, - void *font_data, - hb_codepoint_t glyph, - hb_paint_funcs_t *paint_funcs, void *paint_data, - unsigned int palette, - hb_color_t foreground, - void *user_data) +static hb_bool_t +hb_ot_paint_glyph_or_fail (hb_font_t *font, + void *font_data, + hb_codepoint_t glyph, + hb_paint_funcs_t *paint_funcs, void *paint_data, + unsigned int palette, + hb_color_t foreground, + void *user_data) { #ifndef HB_NO_COLOR - if (font->face->table.COLR->paint_glyph (font, glyph, paint_funcs, paint_data, palette, foreground)) return; - if (font->face->table.SVG->paint_glyph (font, glyph, paint_funcs, paint_data)) return; + if (font->face->table.COLR->paint_glyph (font, glyph, paint_funcs, paint_data, palette, foreground)) return true; + if (font->face->table.SVG->paint_glyph (font, glyph, paint_funcs, paint_data)) return true; #ifndef HB_NO_OT_FONT_BITMAP - if (font->face->table.CBDT->paint_glyph (font, glyph, paint_funcs, paint_data)) return; - if (font->face->table.sbix->paint_glyph (font, glyph, paint_funcs, paint_data)) return; + if (font->face->table.CBDT->paint_glyph (font, glyph, paint_funcs, paint_data)) return true; + if (font->face->table.sbix->paint_glyph (font, glyph, paint_funcs, paint_data)) return true; #endif #endif - - // Outline glyph - paint_funcs->push_clip_glyph (paint_data, glyph, font); - paint_funcs->color (paint_data, true, foreground); - paint_funcs->pop_clip (paint_data); + return false; } #endif @@ -642,11 +557,11 @@ #endif #ifndef HB_NO_DRAW - hb_font_funcs_set_draw_glyph_func (funcs, hb_ot_draw_glyph, nullptr, nullptr); + hb_font_funcs_set_draw_glyph_or_fail_func (funcs, hb_ot_draw_glyph_or_fail, nullptr, nullptr); #endif #ifndef HB_NO_PAINT - hb_font_funcs_set_paint_glyph_func (funcs, hb_ot_paint_glyph, nullptr, nullptr); + hb_font_funcs_set_paint_glyph_or_fail_func (funcs, hb_ot_paint_glyph_or_fail, nullptr, nullptr); #endif hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr); diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh 2025-10-13 07:49:24.000000000 +0000 @@ -359,7 +359,13 @@ return true; } - return _glyf_get_leading_bearing_with_var_unscaled (font, glyph, T::tableTag == HB_OT_TAG_vmtx, lsb); + // If there's no vmtx data, the phantom points from glyf table are not accurate, + // so we cannot take the next path. + bool is_vertical = T::tableTag == HB_OT_TAG_vmtx; + if (is_vertical && !has_data ()) + return false; + + return _glyf_get_leading_bearing_with_var_unscaled (font, glyph, is_vertical, lsb); #else return false; #endif diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-kern-table.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-kern-table.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-kern-table.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-kern-table.hh 2025-10-13 07:49:24.000000000 +0000 @@ -27,6 +27,7 @@ #ifndef HB_OT_KERN_TABLE_HH #define HB_OT_KERN_TABLE_HH +#include "hb-aat-layout-common.hh" #include "hb-aat-layout-kerx-table.hh" @@ -400,6 +401,7 @@ hb_blob_ptr_t table; AAT::kern_accelerator_data_t accel_data; + AAT::hb_aat_scratch_t scratch; }; protected: diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh 2025-10-13 07:49:24.000000000 +0000 @@ -182,7 +182,7 @@ void collect_variation_indices (hb_set_t& varidx_set /* OUT */) const { switch (u.format) { - case 3: hb_barrier (); u.format3.collect_variation_indices (varidx_set); + case 3: hb_barrier (); u.format3.collect_variation_indices (varidx_set); return; default:return; } } diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh 2025-10-13 07:49:24.000000000 +0000 @@ -1850,7 +1850,7 @@ hb_sorted_vector_t glyph_and_klass; hb_set_t orig_klasses; - if (glyph_set.get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2 + if (glyph_set.get_population () * hb_bit_storage ((unsigned) rangeRecord.len) < get_population ()) { for (hb_codepoint_t g : glyph_set) @@ -1931,7 +1931,7 @@ bool intersects (const hb_set_t *glyphs) const { - if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2) + if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len)) { for (auto g : *glyphs) if (get_class (g)) @@ -2000,7 +2000,7 @@ } unsigned count = rangeRecord.len; - if (count > glyphs->get_population () * hb_bit_storage (count) * 8) + if (count > glyphs->get_population () * hb_bit_storage (count)) { for (auto g : *glyphs) { @@ -2548,11 +2548,13 @@ DEFINE_SIZE_STATIC (8); }; -#define REGION_CACHE_ITEM_CACHE_INVALID 2.f +#define REGION_CACHE_ITEM_CACHE_INVALID INT_MIN +#define REGION_CACHE_ITEM_MULTIPLIER (float (1 << ((sizeof (int) * 8) - 2))) +#define REGION_CACHE_ITEM_DIVISOR (1.f / float (1 << ((sizeof (int) * 8) - 2))) struct VarRegionList { - using cache_t = float; + using cache_t = hb_atomic_t; float evaluate (unsigned int region_index, const int *coords, unsigned int coord_len, @@ -2561,12 +2563,12 @@ if (unlikely (region_index >= regionCount)) return 0.; - float *cached_value = nullptr; + cache_t *cached_value = nullptr; if (cache) { cached_value = &(cache[region_index]); - if (likely (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID)) - return *cached_value; + if (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID) + return *cached_value * REGION_CACHE_ITEM_DIVISOR; } const VarRegionAxis *axes = axesZ.arrayZ + (region_index * axisCount); @@ -2587,7 +2589,7 @@ } if (cache) - *cached_value = v; + *cached_value = v * REGION_CACHE_ITEM_MULTIPLIER; return v; } @@ -2730,7 +2732,7 @@ struct SparseVarRegionList { - using cache_t = float; + using cache_t = hb_atomic_t; float evaluate (unsigned int region_index, const int *coords, unsigned int coord_len, @@ -2739,12 +2741,12 @@ if (unlikely (region_index >= regions.len)) return 0.; - float *cached_value = nullptr; + cache_t *cached_value = nullptr; if (cache) { cached_value = &(cache[region_index]); - if (likely (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID)) - return *cached_value; + if (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID) + return *cached_value * REGION_CACHE_ITEM_DIVISOR; } const SparseVariationRegion ®ion = this+regions[region_index]; @@ -2752,7 +2754,7 @@ float v = region.evaluate (coords, coord_len); if (cache) - *cached_value = v; + *cached_value = v * REGION_CACHE_ITEM_MULTIPLIER; return v; } @@ -2861,8 +2863,13 @@ const hb_vector_t*>& rows) { TRACE_SERIALIZE (this); - if (unlikely (!c->extend_min (this))) return_trace (false); unsigned row_count = rows.length; + if (!row_count) { + // Nothing to serialize, will be empty. + return false; + } + + if (unlikely (!c->extend_min (this))) return_trace (false); itemCount = row_count; int min_threshold = has_long ? -65536 : -128; @@ -3187,10 +3194,10 @@ #ifdef HB_NO_VAR return nullptr; #endif - auto &r = this+regions; - unsigned count = r.regionCount; + unsigned count = (this+regions).regionCount; + if (!count) return nullptr; - float *cache = (float *) hb_malloc (sizeof (float) * count); + cache_t *cache = (cache_t *) hb_malloc (sizeof (float) * count); if (unlikely (!cache)) return nullptr; for (unsigned i = 0; i < count; i++) @@ -3440,7 +3447,7 @@ { using cache_t = SparseVarRegionList::cache_t; - cache_t *create_cache (hb_array_t static_cache = hb_array_t ()) const + cache_t *create_cache (hb_array_t static_cache = hb_array_t ()) const { #ifdef HB_NO_VAR return nullptr; @@ -3448,12 +3455,12 @@ auto &r = this+regions; unsigned count = r.regions.len; - float *cache; + cache_t *cache; if (count <= static_cache.length) cache = static_cache.arrayZ; else { - cache = (float *) hb_malloc (sizeof (float) * count); + cache = (cache_t *) hb_malloc (sizeof (float) * count); if (unlikely (!cache)) return nullptr; } @@ -3464,7 +3471,7 @@ } static void destroy_cache (cache_t *cache, - hb_array_t static_cache = hb_array_t ()) + hb_array_t static_cache = hb_array_t ()) { if (cache != static_cache.arrayZ) hb_free (cache); @@ -4777,12 +4784,12 @@ hb_position_t get_x_delta (hb_font_t *font, const ItemVariationStore &store, ItemVariationStore::cache_t *store_cache = nullptr) const - { return font->em_scalef_x (get_delta (font, store, store_cache)); } + { return !font->num_coords ? 0 : font->em_scalef_x (get_delta (font, store, store_cache)); } hb_position_t get_y_delta (hb_font_t *font, const ItemVariationStore &store, ItemVariationStore::cache_t *store_cache = nullptr) const - { return font->em_scalef_y (get_delta (font, store, store_cache)); } + { return !font->num_coords ? 0 : font->em_scalef_y (get_delta (font, store, store_cache)); } VariationDevice* copy (hb_serialize_context_t *c, const hb_hashmap_t> *layout_variation_idx_delta_map) const diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-gsubgpos.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-gsubgpos.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-gsubgpos.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-gsubgpos.hh 2025-10-13 07:49:24.000000000 +0000 @@ -737,7 +737,8 @@ hb_ot_apply_context_t (unsigned int table_index_, hb_font_t *font_, hb_buffer_t *buffer_, - hb_blob_t *table_blob_) : + hb_blob_t *table_blob_, + ItemVariationStore::cache_t *var_store_cache_ = nullptr) : table_index (table_index_), font (font_), face (font->face), buffer (buffer_), sanitizer (table_blob_), @@ -756,13 +757,7 @@ #endif ), var_store (gdef.get_var_store ()), - var_store_cache ( -#ifndef HB_NO_VAR - table_index == 1 && font->num_coords ? var_store.create_cache () : nullptr -#else - nullptr -#endif - ), + var_store_cache (var_store_cache_), direction (buffer_->props.direction), has_glyph_classes (gdef.has_glyph_classes ()) { @@ -770,13 +765,6 @@ buffer->collect_codepoints (digest); } - ~hb_ot_apply_context_t () - { -#ifndef HB_NO_VAR - ItemVariationStore::destroy_cache (var_store_cache); -#endif - } - void init_iters () { iter_input.init (this, false); @@ -4900,7 +4888,7 @@ this->lookup_count = table->get_lookup_count (); - this->accels = (hb_atomic_ptr_t *) hb_calloc (this->lookup_count, sizeof (*accels)); + this->accels = (hb_atomic_t *) hb_calloc (this->lookup_count, sizeof (*accels)); if (unlikely (!this->accels)) { this->lookup_count = 0; @@ -4948,7 +4936,7 @@ hb_blob_ptr_t table; unsigned int lookup_count; - hb_atomic_ptr_t *accels; + hb_atomic_t *accels; }; protected: diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc 2025-10-13 07:49:24.000000000 +0000 @@ -131,13 +131,15 @@ hb_font_t *font, hb_buffer_t *buffer) { - hb_blob_t *blob = font->face->table.kern.get_blob (); - const auto& kern = *font->face->table.kern; + auto &accel = *font->face->table.kern; + hb_blob_t *blob = accel.get_blob (); AAT::hb_aat_apply_context_t c (plan, font, buffer, blob); if (!buffer->message (font, "start table kern")) return; - kern.apply (&c); + c.buffer_glyph_set = accel.scratch.create_buffer_glyph_set (); + accel.apply (&c); + accel.scratch.destroy_buffer_glyph_set (c.buffer_glyph_set); (void) buffer->message (font, "end table kern"); } #endif @@ -2013,7 +2015,11 @@ { const unsigned int table_index = proxy.table_index; unsigned int i = 0; - OT::hb_ot_apply_context_t c (table_index, font, buffer, proxy.accel.get_blob ()); + + auto *font_data = font->data.ot.get (); + auto *var_store_cache = font_data == HB_SHAPER_DATA_SUCCEEDED ? nullptr : (OT::ItemVariationStore::cache_t *) font_data; + + OT::hb_ot_apply_context_t c (table_index, font, buffer, proxy.accel.get_blob (), var_store_cache); c.set_recurse_func (Proxy::Lookup::template dispatch_recurse_func); for (unsigned int stage_index = 0; stage_index < stages[table_index].length; stage_index++) @@ -2626,7 +2632,8 @@ * @alternate_glyphs: (out caller-allocates) (array length=alternate_count): A glyphs buffer. * Alternate glyphs associated with the glyph id. * - * Fetches alternates of a glyph from a given GSUB lookup index. + * Fetches alternates of a glyph from a given GSUB lookup index. Note that for one-to-one GSUB + * glyph substitutions, this function fetches the substituted glyph. * * Return value: Total number of alternates found in the specific lookup index for the given glyph id. * diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.hh 2025-10-13 07:49:24.000000000 +0000 @@ -202,7 +202,8 @@ /* If GEN_CAT=FORMAT, top byte masks: */ UPROPS_MASK_Cf_ZWJ = 0x0100u, UPROPS_MASK_Cf_ZWNJ = 0x0200u, - UPROPS_MASK_Cf_VS = 0x0400u + UPROPS_MASK_Cf_VS = 0x0400u, + UPROPS_MASK_Cf_AAT_DELETED = 0x0800u }; HB_MARK_AS_FLAG_T (hb_unicode_props_flags_t); @@ -386,6 +387,8 @@ static inline void _hb_ot_layout_reverse_graphemes (hb_buffer_t *buffer) { + // MONOTONE_GRAPHEMES was already applied and is taken care of by _hb_grapheme_group_func. + // So we just check for MONOTONE_CHARACTERS here. buffer->reverse_groups (_hb_grapheme_group_func, buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS); } @@ -418,6 +421,18 @@ return; info->unicode_props() ^= UPROPS_MASK_Cf_ZWNJ | UPROPS_MASK_Cf_ZWJ; } +static inline bool +_hb_glyph_info_is_aat_deleted (const hb_glyph_info_t *info) +{ + return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_AAT_DELETED); +} +static inline void +_hb_glyph_info_set_aat_deleted (hb_glyph_info_t *info) +{ + _hb_glyph_info_set_general_category (info, HB_UNICODE_GENERAL_CATEGORY_FORMAT); + info->unicode_props() |= UPROPS_MASK_Cf_AAT_DELETED; + info->unicode_props() |= UPROPS_MASK_HIDDEN; +} /* lig_props: aka lig_id / lig_comp * diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-math-table.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-math-table.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-math-table.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-math-table.hh 2025-10-13 07:49:24.000000000 +0000 @@ -1104,6 +1104,24 @@ mathVariants.sanitize (c, this)); } + // https://github.com/harfbuzz/harfbuzz/issues/4653 + HB_INTERNAL bool is_bad_cambria (hb_font_t *font) const + { +#ifndef HB_NO_MATH + switch HB_CODEPOINT_ENCODE3 (font->face->table.MATH.get_blob ()->length, + get_constant (HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT, font), + get_constant (HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT, font)) + { + /* sha1sum:ab4a4fe054d23061f3c039493d6f665cfda2ecf5 cambria.ttc + * sha1sum:086855301bff644f9d8827b88491fcf73a6d4cb9 cambria.ttc + * sha1sum:b1e5a3feaca2ea3dfcf79ccb377de749ecf60343 cambria.ttc */ + case HB_CODEPOINT_ENCODE3 (25722, 2500, 3000): + return true; + } +#endif + return false; + } + hb_position_t get_constant (hb_ot_math_constant_t constant, hb_font_t *font) const { return (this+mathConstants).get_value (constant, font); } diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-math.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-math.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-math.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-math.cc 2025-10-13 07:49:24.000000000 +0000 @@ -87,6 +87,20 @@ hb_ot_math_get_constant (hb_font_t *font, hb_ot_math_constant_t constant) { + /* https://github.com/harfbuzz/harfbuzz/issues/4653 + * Cambria Math has incorrect value for displayOperatorMinHeight, and + * apparently Microsoft implementation swaps displayOperatorMinHeight and + * delimitedSubFormulaMinHeight, so we do the same if we detect Cambria Math + * with the swapped values. */ + if ((constant == HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT || + constant == HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT) && + font->face->table.MATH->is_bad_cambria (font)) + { + if (constant == HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT) + constant = HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT; + else + constant = HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT; + } return font->face->table.MATH->get_constant(constant, font); } diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table.hh 2025-10-13 07:49:24.000000000 +0000 @@ -290,7 +290,7 @@ const Array16Of *glyphNameIndex = nullptr; hb_vector_t index_to_offset; const uint8_t *pool = nullptr; - hb_atomic_ptr_t gids_sorted_by_name; + mutable hb_atomic_t gids_sorted_by_name; }; bool has_data () const { return version.to_int (); } diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-fallback.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-fallback.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-fallback.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-fallback.cc 2025-10-13 07:49:24.000000000 +0000 @@ -427,8 +427,13 @@ /* Find mark glyphs */ unsigned int j; for (j = i + 1; j < end; j++) + { + if (_hb_glyph_info_is_hidden (&info[j]) || + _hb_glyph_info_is_default_ignorable (&info[j])) + continue; if (!_hb_glyph_info_is_unicode_mark (&info[j])) break; + } position_around_base (plan, font, buffer, i, j, adjust_offsets_when_zeroing); @@ -455,7 +460,9 @@ unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; for (unsigned int i = 1; i < count; i++) - if (likely (!_hb_glyph_info_is_unicode_mark (&info[i]))) { + if (likely (!_hb_glyph_info_is_unicode_mark (&info[i]) && + !_hb_glyph_info_is_hidden (&info[i]) && + !_hb_glyph_info_is_default_ignorable (&info[i]))) { position_cluster (plan, font, buffer, start, i, adjust_offsets_when_zeroing); start = i; } diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.cc 2025-10-13 07:49:24.000000000 +0000 @@ -46,6 +46,7 @@ #include "hb-set.hh" #include "hb-aat-layout.hh" +#include "hb-ot-layout-gdef-table.hh" #include "hb-ot-stat-table.hh" @@ -84,6 +85,7 @@ props (props), map (face, props) #ifndef HB_NO_AAT_SHAPE + , aat_map (face, props) , apply_morx (_hb_apply_morx (face, props)) #endif { @@ -106,6 +108,10 @@ plan.props = props; plan.shaper = shaper; map.compile (plan.map, key); +#ifndef HB_NO_AAT_SHAPE + if (apply_morx) + aat_map.compile (plan.aat_map); +#endif #ifndef HB_NO_OT_SHAPE_FRACTIONS plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c')); @@ -205,6 +211,14 @@ https://github.com/harfbuzz/harfbuzz/issues/2967. */ if (plan.apply_morx) plan.adjust_mark_positioning_when_zeroing = false; + + /* According to Ned, trak is applied by default for "modern fonts", as detected by presence of STAT table. */ +#ifndef HB_NO_STYLE + plan.apply_trak = hb_aat_layout_has_tracking (face) && face->table.STAT->has_data (); +#else + plan.apply_trak = false; +#endif + #endif } @@ -269,6 +283,11 @@ #endif else if (this->apply_fallback_kern) _hb_ot_shape_fallback_kern (this, font, buffer); + +#ifndef HB_NO_AAT_SHAPE + if (this->apply_trak) + hb_aat_layout_track (this, font, buffer); +#endif } @@ -405,17 +424,26 @@ * shaper font data */ -struct hb_ot_font_data_t {}; +struct hb_ot_font_data_t { + OT::ItemVariationStore::cache_t unused; // Just for alignment +}; hb_ot_font_data_t * -_hb_ot_shaper_font_data_create (hb_font_t *font HB_UNUSED) +_hb_ot_shaper_font_data_create (hb_font_t *font) { - return (hb_ot_font_data_t *) HB_SHAPER_DATA_SUCCEEDED; + if (!font->num_coords) + return (hb_ot_font_data_t *) HB_SHAPER_DATA_SUCCEEDED; + + const OT::ItemVariationStore &var_store = font->face->table.GDEF->table->get_var_store (); + auto *cache = (hb_ot_font_data_t *) var_store.create_cache (); + return cache ? cache : (hb_ot_font_data_t *) HB_SHAPER_DATA_SUCCEEDED; } void -_hb_ot_shaper_font_data_destroy (hb_ot_font_data_t *data HB_UNUSED) +_hb_ot_shaper_font_data_destroy (hb_ot_font_data_t *data) { + if (data == HB_SHAPER_DATA_SUCCEEDED) return; + OT::ItemVariationStore::destroy_cache ((OT::ItemVariationStore::cache_t *) data); } @@ -551,7 +579,7 @@ if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII)) return; - if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) + if (HB_BUFFER_CLUSTER_LEVEL_IS_GRAPHEMES (buffer->cluster_level)) foreach_grapheme (buffer, start, end) buffer->merge_clusters (start, end); else @@ -609,7 +637,7 @@ * Ogham fonts are supposed to be implemented BTT or not. Need to research that * first. */ if ((HB_DIRECTION_IS_HORIZONTAL (direction) && - direction != horiz_dir && horiz_dir != HB_DIRECTION_INVALID) || + direction != horiz_dir && HB_DIRECTION_IS_VALID (horiz_dir)) || (HB_DIRECTION_IS_VERTICAL (direction) && direction != HB_DIRECTION_TTB)) { @@ -1109,10 +1137,6 @@ /* Finish off. Has to follow a certain order. */ hb_ot_layout_position_finish_advances (c->font, c->buffer); hb_ot_zero_width_default_ignorables (c->buffer); -#ifndef HB_NO_AAT_SHAPE - if (c->plan->apply_morx) - hb_aat_layout_zero_width_deleted_glyphs (c->buffer); -#endif hb_ot_layout_position_finish_offsets (c->font, c->buffer); /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.hh 2025-10-13 07:49:24.000000000 +0000 @@ -66,6 +66,7 @@ hb_segment_properties_t props; const struct hb_ot_shaper_t *shaper; hb_ot_map_t map; + hb_aat_map_t aat_map; const void *data; #ifndef HB_NO_OT_SHAPE_FRACTIONS hb_mask_t frac_mask, numr_mask, dnom_mask; @@ -108,9 +109,11 @@ #ifndef HB_NO_AAT_SHAPE bool apply_kerx : 1; bool apply_morx : 1; + bool apply_trak : 1; #else static constexpr bool apply_kerx = false; static constexpr bool apply_morx = false; + static constexpr bool apply_trak = false; #endif void collect_lookups (hb_tag_t table_tag, hb_set_t *lookups) const @@ -141,6 +144,7 @@ hb_segment_properties_t props; hb_ot_map_builder_t map; #ifndef HB_NO_AAT_SHAPE + hb_aat_map_builder_t aat_map; bool apply_morx : 1; #else static constexpr bool apply_morx = false; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic.cc 2025-10-13 07:49:24.000000000 +0000 @@ -260,7 +260,7 @@ * mask_array[NONE] == 0. */ hb_mask_t mask_array[ARABIC_NUM_FEATURES + 1]; - hb_atomic_ptr_t fallback_plan; + mutable hb_atomic_t fallback_plan; unsigned int do_fallback : 1; unsigned int has_stch : 1; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-hangul.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-hangul.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-hangul.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-hangul.cc 2025-10-13 07:49:24.000000000 +0000 @@ -298,8 +298,7 @@ end = start + 2; if (unlikely (!buffer->successful)) break; - if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) - buffer->merge_out_clusters (start, end); + buffer->merge_out_clusters (start, end); continue; } } @@ -372,8 +371,7 @@ if (i < end) info[i++].hangul_shaping_feature() = TJMO; - if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) - buffer->merge_out_clusters (start, end); + buffer->merge_out_clusters (start, end); continue; } else if ((!tindex && buffer->idx + 1 < count && isT (buffer->cur(+1).codepoint))) diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic.cc 2025-10-13 07:49:24.000000000 +0000 @@ -301,7 +301,7 @@ #else static constexpr bool uniscribe_bug_compatible = false; #endif - mutable hb_atomic_int_t virama_glyph; + mutable hb_atomic_t virama_glyph; hb_indic_would_substitute_feature_t rphf; hb_indic_would_substitute_feature_t pref; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-thai.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-thai.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-thai.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-thai.cc 2025-10-13 07:49:24.000000000 +0000 @@ -360,7 +360,7 @@ { /* Since we decomposed, and NIKHAHIT is combining, merge clusters with the * previous cluster. */ - if (start && buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) + if (start) buffer->merge_out_clusters (start - 1, end); } } diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-tag.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-tag.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-tag.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-tag.cc 2025-10-13 07:49:24.000000000 +0000 @@ -326,7 +326,7 @@ hb_tag_t lang_tag = hb_tag_from_string (lang_str, first_len); - static hb_atomic_int_t last_tag_idx; /* Poor man's cache. */ + static hb_atomic_t last_tag_idx = 0; /* Poor man's cache. */ unsigned tag_idx = last_tag_idx; if (likely (tag_idx < ot_languages_len && ot_languages[tag_idx].language == lang_tag) || diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-var-gvar-table.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-var-gvar-table.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-var-gvar-table.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-var-gvar-table.hh 2025-10-13 07:49:24.000000000 +0000 @@ -53,10 +53,6 @@ contour_point_vector_t deltas; hb_vector_t shared_indices; hb_vector_t private_indices; - - // VARC - hb_vector_t axisIndices; - hb_vector_t axisValues; }; namespace OT { @@ -594,9 +590,9 @@ /* If sanitize failed, set glyphCount to 0. */ glyphCount = table->version.to_int () ? face->get_num_glyphs () : 0; - /* For shared tuples that only have one axis active, shared the index of - * that axis as a cache. This will speed up caclulate_scalar() a lot - * for fonts with lots of axes and many "monovar" tuples. */ + /* For shared tuples that only have one or two axes active, shared the index + * of that axis as a cache. This will speed up caclulate_scalar() a lot + * for fonts with lots of axes and many "monovar" or "duovar" tuples. */ hb_array_t shared_tuples = (table+table->sharedTuples).as_array (table->sharedTupleCount * table->axisCount); unsigned count = table->sharedTupleCount; if (unlikely (!shared_tuple_active_idx.resize (count, false))) return; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-var.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-var.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-ot-var.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-ot-var.cc 2025-10-13 07:49:24.000000000 +0000 @@ -117,7 +117,7 @@ * in the specified face. * * Since: 1.4.2 - * Deprecated: 2.2.0 - use hb_ot_var_find_axis_info() instead + * Deprecated: 2.2.0: use hb_ot_var_find_axis_info() instead **/ hb_bool_t hb_ot_var_find_axis (hb_face_t *face, diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-outline.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-outline.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-outline.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-outline.cc 2025-10-13 07:49:24.000000000 +0000 @@ -84,6 +84,12 @@ } } +void hb_outline_t::slant (float slant_xy) +{ + for (auto &p : points) + p.x += slant_xy * p.y; +} + float hb_outline_t::control_area () const { float a = 0; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-outline.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-outline.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-outline.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-outline.hh 2025-10-13 07:49:24.000000000 +0000 @@ -69,6 +69,7 @@ HB_INTERNAL void replay (hb_draw_funcs_t *pen, void *pen_data) const; HB_INTERNAL float control_area () const; + HB_INTERNAL void slant (float slant_xy); HB_INTERNAL void embolden (float x_strength, float y_strength, float x_shift, float y_shift); diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.cc 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.cc 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,207 @@ +/* + * Copyright © 2022 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#include "hb.hh" + +#ifndef HB_NO_PAINT + +#include "hb-paint-bounded.hh" + +#include "hb-machinery.hh" + + +/* + * This file implements boundedness computation of COLRv1 fonts as described in: + * + * https://learn.microsoft.com/en-us/typography/opentype/spec/colr#glyph-metrics-and-boundedness + */ + +static void +hb_paint_bounded_push_clip_glyph (hb_paint_funcs_t *funcs HB_UNUSED, + void *paint_data, + hb_codepoint_t glyph, + hb_font_t *font, + void *user_data HB_UNUSED) +{ + hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data; + + c->push_clip (); +} + +static void +hb_paint_bounded_push_clip_rectangle (hb_paint_funcs_t *funcs HB_UNUSED, + void *paint_data, + float xmin, float ymin, float xmax, float ymax, + void *user_data) +{ + hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data; + + c->push_clip (); +} + +static void +hb_paint_bounded_pop_clip (hb_paint_funcs_t *funcs HB_UNUSED, + void *paint_data, + void *user_data HB_UNUSED) +{ + hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data; + + c->pop_clip (); +} + +static void +hb_paint_bounded_push_group (hb_paint_funcs_t *funcs HB_UNUSED, + void *paint_data, + void *user_data HB_UNUSED) +{ + hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data; + + c->push_group (); +} + +static void +hb_paint_bounded_pop_group (hb_paint_funcs_t *funcs HB_UNUSED, + void *paint_data, + hb_paint_composite_mode_t mode, + void *user_data HB_UNUSED) +{ + hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data; + + c->pop_group (mode); +} + +static hb_bool_t +hb_paint_bounded_paint_image (hb_paint_funcs_t *funcs HB_UNUSED, + void *paint_data, + hb_blob_t *blob HB_UNUSED, + unsigned int width HB_UNUSED, + unsigned int height HB_UNUSED, + hb_tag_t format HB_UNUSED, + float slant HB_UNUSED, + hb_glyph_extents_t *glyph_extents, + void *user_data HB_UNUSED) +{ + hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data; + + c->push_clip (); + c->paint (); + c->pop_clip (); + + return true; +} + +static void +hb_paint_bounded_paint_color (hb_paint_funcs_t *funcs HB_UNUSED, + void *paint_data, + hb_bool_t use_foreground HB_UNUSED, + hb_color_t color HB_UNUSED, + void *user_data HB_UNUSED) +{ + hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data; + + c->paint (); +} + +static void +hb_paint_bounded_paint_linear_gradient (hb_paint_funcs_t *funcs HB_UNUSED, + void *paint_data, + hb_color_line_t *color_line HB_UNUSED, + float x0 HB_UNUSED, float y0 HB_UNUSED, + float x1 HB_UNUSED, float y1 HB_UNUSED, + float x2 HB_UNUSED, float y2 HB_UNUSED, + void *user_data HB_UNUSED) +{ + hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data; + + c->paint (); +} + +static void +hb_paint_bounded_paint_radial_gradient (hb_paint_funcs_t *funcs HB_UNUSED, + void *paint_data, + hb_color_line_t *color_line HB_UNUSED, + float x0 HB_UNUSED, float y0 HB_UNUSED, float r0 HB_UNUSED, + float x1 HB_UNUSED, float y1 HB_UNUSED, float r1 HB_UNUSED, + void *user_data HB_UNUSED) +{ + hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data; + + c->paint (); +} + +static void +hb_paint_bounded_paint_sweep_gradient (hb_paint_funcs_t *funcs HB_UNUSED, + void *paint_data, + hb_color_line_t *color_line HB_UNUSED, + float cx HB_UNUSED, float cy HB_UNUSED, + float start_angle HB_UNUSED, + float end_angle HB_UNUSED, + void *user_data HB_UNUSED) +{ + hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data; + + c->paint (); +} + +static inline void free_static_paint_bounded_funcs (); + +static struct hb_paint_bounded_funcs_lazy_loader_t : hb_paint_funcs_lazy_loader_t +{ + static hb_paint_funcs_t *create () + { + hb_paint_funcs_t *funcs = hb_paint_funcs_create (); + + hb_paint_funcs_set_push_clip_glyph_func (funcs, hb_paint_bounded_push_clip_glyph, nullptr, nullptr); + hb_paint_funcs_set_push_clip_rectangle_func (funcs, hb_paint_bounded_push_clip_rectangle, nullptr, nullptr); + hb_paint_funcs_set_pop_clip_func (funcs, hb_paint_bounded_pop_clip, nullptr, nullptr); + hb_paint_funcs_set_push_group_func (funcs, hb_paint_bounded_push_group, nullptr, nullptr); + hb_paint_funcs_set_pop_group_func (funcs, hb_paint_bounded_pop_group, nullptr, nullptr); + hb_paint_funcs_set_color_func (funcs, hb_paint_bounded_paint_color, nullptr, nullptr); + hb_paint_funcs_set_image_func (funcs, hb_paint_bounded_paint_image, nullptr, nullptr); + hb_paint_funcs_set_linear_gradient_func (funcs, hb_paint_bounded_paint_linear_gradient, nullptr, nullptr); + hb_paint_funcs_set_radial_gradient_func (funcs, hb_paint_bounded_paint_radial_gradient, nullptr, nullptr); + hb_paint_funcs_set_sweep_gradient_func (funcs, hb_paint_bounded_paint_sweep_gradient, nullptr, nullptr); + + hb_paint_funcs_make_immutable (funcs); + + hb_atexit (free_static_paint_bounded_funcs); + + return funcs; + } +} static_paint_bounded_funcs; + +static inline +void free_static_paint_bounded_funcs () +{ + static_paint_bounded_funcs.free_instance (); +} + +hb_paint_funcs_t * +hb_paint_bounded_get_funcs () +{ + return static_paint_bounded_funcs.get_unconst (); +} + + +#endif diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.hh 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.hh 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,117 @@ +/* + * Copyright © 2022 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef HB_PAINT_BOUNDED_HH +#define HB_PAINT_BOUNDED_HH + +#include "hb.hh" +#include "hb-paint.h" + +#include "hb-geometry.hh" + + +typedef struct hb_paint_bounded_context_t hb_paint_bounded_context_t; + +struct hb_paint_bounded_context_t +{ + void clear () + { + clips = 0; + bounded = true; + groups.clear (); + } + + hb_paint_bounded_context_t () + { + clear (); + } + + bool is_bounded () + { + return bounded; + } + + void push_clip () + { + clips++; + } + + void pop_clip () + { + if (clips == 0) return; + clips--; + } + + void push_group () + { + groups.push (bounded); + bounded = true; + } + + void pop_group (hb_paint_composite_mode_t mode) + { + const bool src_bounded = bounded; + bounded = groups.pop (); + bool &backdrop_bounded = bounded; + + // https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-32-paintcomposite + switch ((int) mode) + { + case HB_PAINT_COMPOSITE_MODE_CLEAR: + backdrop_bounded = true; + break; + case HB_PAINT_COMPOSITE_MODE_SRC: + case HB_PAINT_COMPOSITE_MODE_SRC_OUT: + backdrop_bounded = src_bounded; + break; + case HB_PAINT_COMPOSITE_MODE_DEST: + case HB_PAINT_COMPOSITE_MODE_DEST_OUT: + break; + case HB_PAINT_COMPOSITE_MODE_SRC_IN: + case HB_PAINT_COMPOSITE_MODE_DEST_IN: + backdrop_bounded = backdrop_bounded && src_bounded; + break; + default: + backdrop_bounded = backdrop_bounded || src_bounded; + break; + } + } + + void paint () + { + if (!clips) + bounded = false; + } + + protected: + bool bounded; // true if current drawing bounded + unsigned clips; // number of active clips + hb_vector_t groups; // true if group bounded +}; + +HB_INTERNAL hb_paint_funcs_t * +hb_paint_bounded_get_funcs (); + + +#endif /* HB_PAINT_BOUNDED_HH */ diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.cc 2025-10-13 07:49:24.000000000 +0000 @@ -28,14 +28,13 @@ #include "hb-paint-extents.hh" -#include "hb-draw.h" +#include "hb-draw.hh" #include "hb-machinery.hh" /* - * This file implements bounds-extraction as well as boundedness - * computation of COLRv1 fonts as described in: + * This file implements bounds-extraction computation of COLRv1 fonts as described in: * * https://learn.microsoft.com/en-us/typography/opentype/spec/colr#glyph-metrics-and-boundedness */ @@ -64,93 +63,6 @@ } static void -hb_draw_extents_move_to (hb_draw_funcs_t *dfuncs HB_UNUSED, - void *data, - hb_draw_state_t *st, - float to_x, float to_y, - void *user_data HB_UNUSED) -{ - hb_extents_t *extents = (hb_extents_t *) data; - - extents->add_point (to_x, to_y); -} - -static void -hb_draw_extents_line_to (hb_draw_funcs_t *dfuncs HB_UNUSED, - void *data, - hb_draw_state_t *st, - float to_x, float to_y, - void *user_data HB_UNUSED) -{ - hb_extents_t *extents = (hb_extents_t *) data; - - extents->add_point (to_x, to_y); -} - -static void -hb_draw_extents_quadratic_to (hb_draw_funcs_t *dfuncs HB_UNUSED, - void *data, - hb_draw_state_t *st, - float control_x, float control_y, - float to_x, float to_y, - void *user_data HB_UNUSED) -{ - hb_extents_t *extents = (hb_extents_t *) data; - - extents->add_point (control_x, control_y); - extents->add_point (to_x, to_y); -} - -static void -hb_draw_extents_cubic_to (hb_draw_funcs_t *dfuncs HB_UNUSED, - void *data, - hb_draw_state_t *st, - float control1_x, float control1_y, - float control2_x, float control2_y, - float to_x, float to_y, - void *user_data HB_UNUSED) -{ - hb_extents_t *extents = (hb_extents_t *) data; - - extents->add_point (control1_x, control1_y); - extents->add_point (control2_x, control2_y); - extents->add_point (to_x, to_y); -} - -static inline void free_static_draw_extents_funcs (); - -static struct hb_draw_extents_funcs_lazy_loader_t : hb_draw_funcs_lazy_loader_t -{ - static hb_draw_funcs_t *create () - { - hb_draw_funcs_t *funcs = hb_draw_funcs_create (); - - hb_draw_funcs_set_move_to_func (funcs, hb_draw_extents_move_to, nullptr, nullptr); - hb_draw_funcs_set_line_to_func (funcs, hb_draw_extents_line_to, nullptr, nullptr); - hb_draw_funcs_set_quadratic_to_func (funcs, hb_draw_extents_quadratic_to, nullptr, nullptr); - hb_draw_funcs_set_cubic_to_func (funcs, hb_draw_extents_cubic_to, nullptr, nullptr); - - hb_draw_funcs_make_immutable (funcs); - - hb_atexit (free_static_draw_extents_funcs); - - return funcs; - } -} static_draw_extents_funcs; - -static inline -void free_static_draw_extents_funcs () -{ - static_draw_extents_funcs.free_instance (); -} - -static hb_draw_funcs_t * -hb_draw_extents_get_funcs () -{ - return static_draw_extents_funcs.get_unconst (); -} - -static void hb_paint_extents_push_clip_glyph (hb_paint_funcs_t *funcs HB_UNUSED, void *paint_data, hb_codepoint_t glyph, @@ -221,6 +133,9 @@ { hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data; + if (!glyph_extents) + return false; // Happens with SVG images. + hb_extents_t extents = {(float) glyph_extents->x_bearing, (float) glyph_extents->y_bearing + glyph_extents->height, (float) glyph_extents->x_bearing + glyph_extents->width, diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.hh 2025-10-13 07:49:24.000000000 +0000 @@ -35,13 +35,22 @@ struct hb_paint_extents_context_t { - hb_paint_extents_context_t () + void clear () { + transforms.clear (); + clips.clear (); + groups.clear (); + transforms.push (hb_transform_t{}); clips.push (hb_bounds_t{hb_bounds_t::UNBOUNDED}); groups.push (hb_bounds_t{hb_bounds_t::EMPTY}); } + hb_paint_extents_context_t () + { + clear (); + } + hb_extents_t get_extents () { return groups.tail().extents; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-paint.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-paint.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-paint.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-paint.cc 2025-10-13 07:49:24.000000000 +0000 @@ -87,7 +87,7 @@ unsigned int width, unsigned int height, hb_tag_t format, - float slant_xy, + float slant_xy_deprecated, hb_glyph_extents_t *extents, void *user_data) { return false; } @@ -465,6 +465,42 @@ } /** + * hb_paint_push_font_transform: + * @funcs: paint functions + * @paint_data: associated data passed by the caller + * @font: a font + * + * Push the transform reflecting the font's scale and slant + * settings onto the paint functions. + * + * Since: 11.0.0 + */ +void +hb_paint_push_font_transform (hb_paint_funcs_t *funcs, void *paint_data, + const hb_font_t *font) +{ + funcs->push_font_transform (paint_data, font); +} + +/** + * hb_paint_push_inverse_font_transform: + * @funcs: paint functions + * @paint_data: associated data passed by the caller + * @font: a font + * + * Push the inverse of the transform reflecting the font's + * scale and slant settings onto the paint functions. + * + * Since: 11.0.0 + */ +void +hb_paint_push_inverse_font_transform (hb_paint_funcs_t *funcs, void *paint_data, + const hb_font_t *font) +{ + funcs->push_inverse_font_transform (paint_data, font); +} + +/** * hb_paint_pop_transform: * @funcs: paint functions * @paint_data: associated data passed by the caller @@ -579,7 +615,7 @@ * @width: width of the raster image in pixels, or 0 * @height: height of the raster image in pixels, or 0 * @format: the image format as a tag - * @slant: the synthetic slant ratio to be applied to the image during rendering + * @slant: Deprecated. set to 0.0 * @extents: (nullable): the extents of the glyph * * Perform a "image" paint operation. @@ -592,10 +628,10 @@ unsigned int width, unsigned int height, hb_tag_t format, - float slant, + HB_UNUSED float slant, hb_glyph_extents_t *extents) { - funcs->image (paint_data, image, width, height, format, slant, extents); + funcs->image (paint_data, image, width, height, format, 0.f, extents); } /** @@ -646,7 +682,7 @@ float x0, float y0, float r0, float x1, float y1, float r1) { - funcs->radial_gradient (paint_data, color_line, x0, y0, r0, y1, x1, r1); + funcs->radial_gradient (paint_data, color_line, x0, y0, r0, x1, y1, r1); } /** diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-paint.h openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-paint.h --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-paint.h 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-paint.h 2025-10-13 07:49:24.000000000 +0000 @@ -167,8 +167,10 @@ * A virtual method for the #hb_paint_funcs_t to clip * subsequent paint calls to the outline of a glyph. * - * The coordinates of the glyph outline are interpreted according - * to the current transform. + * The coordinates of the glyph outline are expected in the + * current @font scale (ie. the results of calling + * hb_font_draw_glyph() with @font). The outline is + * transformed by the current transform. * * This clip is applied in addition to the current clip, * and remains in effect until a matching call to @@ -281,7 +283,7 @@ * @width: width of the raster image in pixels, or 0 * @height: height of the raster image in pixels, or 0 * @format: the image format as a tag - * @slant: the synthetic slant ratio to be applied to the image during rendering + * @slant: Deprecated. Always set to 0.0. * @extents: (nullable): glyph extents for desired rendering * @user_data: User data pointer passed to hb_paint_funcs_set_image_func() * @@ -957,6 +959,14 @@ float dx, float dy); HB_EXTERN void +hb_paint_push_font_transform (hb_paint_funcs_t *funcs, void *paint_data, + const hb_font_t *font); + +HB_EXTERN void +hb_paint_push_inverse_font_transform (hb_paint_funcs_t *funcs, void *paint_data, + const hb_font_t *font); + +HB_EXTERN void hb_paint_pop_transform (hb_paint_funcs_t *funcs, void *paint_data); HB_EXTERN hb_bool_t diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-paint.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-paint.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-paint.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-paint.hh 2025-10-13 07:49:24.000000000 +0000 @@ -157,27 +157,29 @@ /* Internal specializations. */ - void push_root_transform (void *paint_data, + void push_font_transform (void *paint_data, const hb_font_t *font) { float upem = font->face->get_upem (); int xscale = font->x_scale, yscale = font->y_scale; - float slant = font->slant_xy; push_transform (paint_data, - xscale/upem, 0, slant * yscale/upem, yscale/upem, 0, 0); + xscale/upem, 0, + 0, yscale/upem, + 0, 0); } - void push_inverse_root_transform (void *paint_data, - hb_font_t *font) + void push_inverse_font_transform (void *paint_data, + const hb_font_t *font) { float upem = font->face->get_upem (); int xscale = font->x_scale ? font->x_scale : upem; int yscale = font->y_scale ? font->y_scale : upem; - float slant = font->slant_xy; push_transform (paint_data, - upem/xscale, 0, -slant * upem/xscale, upem/yscale, 0, 0); + upem/xscale, 0, + 0, upem/yscale, + 0, 0); } HB_NODISCARD diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-script-list.h openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-script-list.h --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-script-list.h 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-script-list.h 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,484 @@ +/* + * Copyright © 2007,2008,2009 Red Hat, Inc. + * Copyright © 2011,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod + */ + +#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) +#error "Include instead." +#endif + +#ifndef HB_SCRIPT_LIST_H +#define HB_SCRIPT_LIST_H + +/* This file belongs to the middle of hb-common.h. + * The reason it has been surgically extracted is because + * FreeType imports types and enums from hb-common.h, + * and since this enum is large and growing, we want to + * make it easy to just copy the file over to FreeType. + * https://github.com/harfbuzz/harfbuzz/issues/5271 + */ + +/* Dummy lines to make our checks happy. */ +#if 0 +#include "hb-common.h" +HB_BEGIN_DECLS +HB_END_DECLS +#endif + + +/** + * hb_script_t: + * @HB_SCRIPT_COMMON: `Zyyy` + * @HB_SCRIPT_INHERITED: `Zinh` + * @HB_SCRIPT_UNKNOWN: `Zzzz` + * @HB_SCRIPT_ARABIC: `Arab` + * @HB_SCRIPT_ARMENIAN: `Armn` + * @HB_SCRIPT_BENGALI: `Beng` + * @HB_SCRIPT_CYRILLIC: `Cyrl` + * @HB_SCRIPT_DEVANAGARI: `Deva` + * @HB_SCRIPT_GEORGIAN: `Geor` + * @HB_SCRIPT_GREEK: `Grek` + * @HB_SCRIPT_GUJARATI: `Gujr` + * @HB_SCRIPT_GURMUKHI: `Guru` + * @HB_SCRIPT_HANGUL: `Hang` + * @HB_SCRIPT_HAN: `Hani` + * @HB_SCRIPT_HEBREW: `Hebr` + * @HB_SCRIPT_HIRAGANA: `Hira` + * @HB_SCRIPT_KANNADA: `Knda` + * @HB_SCRIPT_KATAKANA: `Kana` + * @HB_SCRIPT_LAO: `Laoo` + * @HB_SCRIPT_LATIN: `Latn` + * @HB_SCRIPT_MALAYALAM: `Mlym` + * @HB_SCRIPT_ORIYA: `Orya` + * @HB_SCRIPT_TAMIL: `Taml` + * @HB_SCRIPT_TELUGU: `Telu` + * @HB_SCRIPT_THAI: `Thai` + * @HB_SCRIPT_TIBETAN: `Tibt` + * @HB_SCRIPT_BOPOMOFO: `Bopo` + * @HB_SCRIPT_BRAILLE: `Brai` + * @HB_SCRIPT_CANADIAN_SYLLABICS: `Cans` + * @HB_SCRIPT_CHEROKEE: `Cher` + * @HB_SCRIPT_ETHIOPIC: `Ethi` + * @HB_SCRIPT_KHMER: `Khmr` + * @HB_SCRIPT_MONGOLIAN: `Mong` + * @HB_SCRIPT_MYANMAR: `Mymr` + * @HB_SCRIPT_OGHAM: `Ogam` + * @HB_SCRIPT_RUNIC: `Runr` + * @HB_SCRIPT_SINHALA: `Sinh` + * @HB_SCRIPT_SYRIAC: `Syrc` + * @HB_SCRIPT_THAANA: `Thaa` + * @HB_SCRIPT_YI: `Yiii` + * @HB_SCRIPT_DESERET: `Dsrt` + * @HB_SCRIPT_GOTHIC: `Goth` + * @HB_SCRIPT_OLD_ITALIC: `Ital` + * @HB_SCRIPT_BUHID: `Buhd` + * @HB_SCRIPT_HANUNOO: `Hano` + * @HB_SCRIPT_TAGALOG: `Tglg` + * @HB_SCRIPT_TAGBANWA: `Tagb` + * @HB_SCRIPT_CYPRIOT: `Cprt` + * @HB_SCRIPT_LIMBU: `Limb` + * @HB_SCRIPT_LINEAR_B: `Linb` + * @HB_SCRIPT_OSMANYA: `Osma` + * @HB_SCRIPT_SHAVIAN: `Shaw` + * @HB_SCRIPT_TAI_LE: `Tale` + * @HB_SCRIPT_UGARITIC: `Ugar` + * @HB_SCRIPT_BUGINESE: `Bugi` + * @HB_SCRIPT_COPTIC: `Copt` + * @HB_SCRIPT_GLAGOLITIC: `Glag` + * @HB_SCRIPT_KHAROSHTHI: `Khar` + * @HB_SCRIPT_NEW_TAI_LUE: `Talu` + * @HB_SCRIPT_OLD_PERSIAN: `Xpeo` + * @HB_SCRIPT_SYLOTI_NAGRI: `Sylo` + * @HB_SCRIPT_TIFINAGH: `Tfng` + * @HB_SCRIPT_BALINESE: `Bali` + * @HB_SCRIPT_CUNEIFORM: `Xsux` + * @HB_SCRIPT_NKO: `Nkoo` + * @HB_SCRIPT_PHAGS_PA: `Phag` + * @HB_SCRIPT_PHOENICIAN: `Phnx` + * @HB_SCRIPT_CARIAN: `Cari` + * @HB_SCRIPT_CHAM: `Cham` + * @HB_SCRIPT_KAYAH_LI: `Kali` + * @HB_SCRIPT_LEPCHA: `Lepc` + * @HB_SCRIPT_LYCIAN: `Lyci` + * @HB_SCRIPT_LYDIAN: `Lydi` + * @HB_SCRIPT_OL_CHIKI: `Olck` + * @HB_SCRIPT_REJANG: `Rjng` + * @HB_SCRIPT_SAURASHTRA: `Saur` + * @HB_SCRIPT_SUNDANESE: `Sund` + * @HB_SCRIPT_VAI: `Vaii` + * @HB_SCRIPT_AVESTAN: `Avst` + * @HB_SCRIPT_BAMUM: `Bamu` + * @HB_SCRIPT_EGYPTIAN_HIEROGLYPHS: `Egyp` + * @HB_SCRIPT_IMPERIAL_ARAMAIC: `Armi` + * @HB_SCRIPT_INSCRIPTIONAL_PAHLAVI: `Phli` + * @HB_SCRIPT_INSCRIPTIONAL_PARTHIAN: `Prti` + * @HB_SCRIPT_JAVANESE: `Java` + * @HB_SCRIPT_KAITHI: `Kthi` + * @HB_SCRIPT_LISU: `Lisu` + * @HB_SCRIPT_MEETEI_MAYEK: `Mtei` + * @HB_SCRIPT_OLD_SOUTH_ARABIAN: `Sarb` + * @HB_SCRIPT_OLD_TURKIC: `Orkh` + * @HB_SCRIPT_SAMARITAN: `Samr` + * @HB_SCRIPT_TAI_THAM: `Lana` + * @HB_SCRIPT_TAI_VIET: `Tavt` + * @HB_SCRIPT_BATAK: `Batk` + * @HB_SCRIPT_BRAHMI: `Brah` + * @HB_SCRIPT_MANDAIC: `Mand` + * @HB_SCRIPT_CHAKMA: `Cakm` + * @HB_SCRIPT_MEROITIC_CURSIVE: `Merc` + * @HB_SCRIPT_MEROITIC_HIEROGLYPHS: `Mero` + * @HB_SCRIPT_MIAO: `Plrd` + * @HB_SCRIPT_SHARADA: `Shrd` + * @HB_SCRIPT_SORA_SOMPENG: `Sora` + * @HB_SCRIPT_TAKRI: `Takr` + * @HB_SCRIPT_BASSA_VAH: `Bass`, Since: 0.9.30 + * @HB_SCRIPT_CAUCASIAN_ALBANIAN: `Aghb`, Since: 0.9.30 + * @HB_SCRIPT_DUPLOYAN: `Dupl`, Since: 0.9.30 + * @HB_SCRIPT_ELBASAN: `Elba`, Since: 0.9.30 + * @HB_SCRIPT_GRANTHA: `Gran`, Since: 0.9.30 + * @HB_SCRIPT_KHOJKI: `Khoj`, Since: 0.9.30 + * @HB_SCRIPT_KHUDAWADI: `Sind`, Since: 0.9.30 + * @HB_SCRIPT_LINEAR_A: `Lina`, Since: 0.9.30 + * @HB_SCRIPT_MAHAJANI: `Mahj`, Since: 0.9.30 + * @HB_SCRIPT_MANICHAEAN: `Mani`, Since: 0.9.30 + * @HB_SCRIPT_MENDE_KIKAKUI: `Mend`, Since: 0.9.30 + * @HB_SCRIPT_MODI: `Modi`, Since: 0.9.30 + * @HB_SCRIPT_MRO: `Mroo`, Since: 0.9.30 + * @HB_SCRIPT_NABATAEAN: `Nbat`, Since: 0.9.30 + * @HB_SCRIPT_OLD_NORTH_ARABIAN: `Narb`, Since: 0.9.30 + * @HB_SCRIPT_OLD_PERMIC: `Perm`, Since: 0.9.30 + * @HB_SCRIPT_PAHAWH_HMONG: `Hmng`, Since: 0.9.30 + * @HB_SCRIPT_PALMYRENE: `Palm`, Since: 0.9.30 + * @HB_SCRIPT_PAU_CIN_HAU: `Pauc`, Since: 0.9.30 + * @HB_SCRIPT_PSALTER_PAHLAVI: `Phlp`, Since: 0.9.30 + * @HB_SCRIPT_SIDDHAM: `Sidd`, Since: 0.9.30 + * @HB_SCRIPT_TIRHUTA: `Tirh`, Since: 0.9.30 + * @HB_SCRIPT_WARANG_CITI: `Wara`, Since: 0.9.30 + * @HB_SCRIPT_AHOM: `Ahom`, Since: 0.9.30 + * @HB_SCRIPT_ANATOLIAN_HIEROGLYPHS: `Hluw`, Since: 0.9.30 + * @HB_SCRIPT_HATRAN: `Hatr`, Since: 0.9.30 + * @HB_SCRIPT_MULTANI: `Mult`, Since: 0.9.30 + * @HB_SCRIPT_OLD_HUNGARIAN: `Hung`, Since: 0.9.30 + * @HB_SCRIPT_SIGNWRITING: `Sgnw`, Since: 0.9.30 + * @HB_SCRIPT_ADLAM: `Adlm`, Since: 1.3.0 + * @HB_SCRIPT_BHAIKSUKI: `Bhks`, Since: 1.3.0 + * @HB_SCRIPT_MARCHEN: `Marc`, Since: 1.3.0 + * @HB_SCRIPT_OSAGE: `Osge`, Since: 1.3.0 + * @HB_SCRIPT_TANGUT: `Tang`, Since: 1.3.0 + * @HB_SCRIPT_NEWA: `Newa`, Since: 1.3.0 + * @HB_SCRIPT_MASARAM_GONDI: `Gonm`, Since: 1.6.0 + * @HB_SCRIPT_NUSHU: `Nshu`, Since: 1.6.0 + * @HB_SCRIPT_SOYOMBO: `Soyo`, Since: 1.6.0 + * @HB_SCRIPT_ZANABAZAR_SQUARE: `Zanb`, Since: 1.6.0 + * @HB_SCRIPT_DOGRA: `Dogr`, Since: 1.8.0 + * @HB_SCRIPT_GUNJALA_GONDI: `Gong`, Since: 1.8.0 + * @HB_SCRIPT_HANIFI_ROHINGYA: `Rohg`, Since: 1.8.0 + * @HB_SCRIPT_MAKASAR: `Maka`, Since: 1.8.0 + * @HB_SCRIPT_MEDEFAIDRIN: `Medf`, Since: 1.8.0 + * @HB_SCRIPT_OLD_SOGDIAN: `Sogo`, Since: 1.8.0 + * @HB_SCRIPT_SOGDIAN: `Sogd`, Since: 1.8.0 + * @HB_SCRIPT_ELYMAIC: `Elym`, Since: 2.4.0 + * @HB_SCRIPT_NANDINAGARI: `Nand`, Since: 2.4.0 + * @HB_SCRIPT_NYIAKENG_PUACHUE_HMONG: `Hmnp`, Since: 2.4.0 + * @HB_SCRIPT_WANCHO: `Wcho`, Since: 2.4.0 + * @HB_SCRIPT_CHORASMIAN: `Chrs`, Since: 2.6.7 + * @HB_SCRIPT_DIVES_AKURU: `Diak`, Since: 2.6.7 + * @HB_SCRIPT_KHITAN_SMALL_SCRIPT: `Kits`, Since: 2.6.7 + * @HB_SCRIPT_YEZIDI: `Yezi`, Since: 2.6.7 + * @HB_SCRIPT_CYPRO_MINOAN: `Cpmn`, Since: 3.0.0 + * @HB_SCRIPT_OLD_UYGHUR: `Ougr`, Since: 3.0.0 + * @HB_SCRIPT_TANGSA: `Tnsa`, Since: 3.0.0 + * @HB_SCRIPT_TOTO: `Toto`, Since: 3.0.0 + * @HB_SCRIPT_VITHKUQI: `Vith`, Since: 3.0.0 + * @HB_SCRIPT_MATH: `Zmth`, Since: 3.4.0 + * @HB_SCRIPT_KAWI: `Kawi`, Since: 5.2.0 + * @HB_SCRIPT_NAG_MUNDARI: `Nagm`, Since: 5.2.0 + * @HB_SCRIPT_GARAY: `Gara`, Since: 10.0.0 + * @HB_SCRIPT_GURUNG_KHEMA: `Gukh`, Since: 10.0.0 + * @HB_SCRIPT_KIRAT_RAI: `Krai`, Since: 10.0.0 + * @HB_SCRIPT_OL_ONAL: `Onao`, Since: 10.0.0 + * @HB_SCRIPT_SUNUWAR: `Sunu`, Since: 10.0.0 + * @HB_SCRIPT_TODHRI: `Todr`, Since: 10.0.0 + * @HB_SCRIPT_TULU_TIGALARI: `Tutg`, Since: 10.0.0 + * @HB_SCRIPT_INVALID: No script set + * + * Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding + * to the four-letter values defined by [ISO 15924](https://unicode.org/iso15924/). + * + * See also the Script (sc) property of the Unicode Character Database. + * + **/ + +/* https://docs.google.com/spreadsheets/d/1Y90M0Ie3MUJ6UVCRDOypOtijlMDLNNyyLk36T6iMu0o */ +typedef enum +{ + HB_SCRIPT_COMMON = HB_TAG ('Z','y','y','y'), /*1.1*/ + HB_SCRIPT_INHERITED = HB_TAG ('Z','i','n','h'), /*1.1*/ + HB_SCRIPT_UNKNOWN = HB_TAG ('Z','z','z','z'), /*5.0*/ + + HB_SCRIPT_ARABIC = HB_TAG ('A','r','a','b'), /*1.1*/ + HB_SCRIPT_ARMENIAN = HB_TAG ('A','r','m','n'), /*1.1*/ + HB_SCRIPT_BENGALI = HB_TAG ('B','e','n','g'), /*1.1*/ + HB_SCRIPT_CYRILLIC = HB_TAG ('C','y','r','l'), /*1.1*/ + HB_SCRIPT_DEVANAGARI = HB_TAG ('D','e','v','a'), /*1.1*/ + HB_SCRIPT_GEORGIAN = HB_TAG ('G','e','o','r'), /*1.1*/ + HB_SCRIPT_GREEK = HB_TAG ('G','r','e','k'), /*1.1*/ + HB_SCRIPT_GUJARATI = HB_TAG ('G','u','j','r'), /*1.1*/ + HB_SCRIPT_GURMUKHI = HB_TAG ('G','u','r','u'), /*1.1*/ + HB_SCRIPT_HANGUL = HB_TAG ('H','a','n','g'), /*1.1*/ + HB_SCRIPT_HAN = HB_TAG ('H','a','n','i'), /*1.1*/ + HB_SCRIPT_HEBREW = HB_TAG ('H','e','b','r'), /*1.1*/ + HB_SCRIPT_HIRAGANA = HB_TAG ('H','i','r','a'), /*1.1*/ + HB_SCRIPT_KANNADA = HB_TAG ('K','n','d','a'), /*1.1*/ + HB_SCRIPT_KATAKANA = HB_TAG ('K','a','n','a'), /*1.1*/ + HB_SCRIPT_LAO = HB_TAG ('L','a','o','o'), /*1.1*/ + HB_SCRIPT_LATIN = HB_TAG ('L','a','t','n'), /*1.1*/ + HB_SCRIPT_MALAYALAM = HB_TAG ('M','l','y','m'), /*1.1*/ + HB_SCRIPT_ORIYA = HB_TAG ('O','r','y','a'), /*1.1*/ + HB_SCRIPT_TAMIL = HB_TAG ('T','a','m','l'), /*1.1*/ + HB_SCRIPT_TELUGU = HB_TAG ('T','e','l','u'), /*1.1*/ + HB_SCRIPT_THAI = HB_TAG ('T','h','a','i'), /*1.1*/ + + HB_SCRIPT_TIBETAN = HB_TAG ('T','i','b','t'), /*2.0*/ + + HB_SCRIPT_BOPOMOFO = HB_TAG ('B','o','p','o'), /*3.0*/ + HB_SCRIPT_BRAILLE = HB_TAG ('B','r','a','i'), /*3.0*/ + HB_SCRIPT_CANADIAN_SYLLABICS = HB_TAG ('C','a','n','s'), /*3.0*/ + HB_SCRIPT_CHEROKEE = HB_TAG ('C','h','e','r'), /*3.0*/ + HB_SCRIPT_ETHIOPIC = HB_TAG ('E','t','h','i'), /*3.0*/ + HB_SCRIPT_KHMER = HB_TAG ('K','h','m','r'), /*3.0*/ + HB_SCRIPT_MONGOLIAN = HB_TAG ('M','o','n','g'), /*3.0*/ + HB_SCRIPT_MYANMAR = HB_TAG ('M','y','m','r'), /*3.0*/ + HB_SCRIPT_OGHAM = HB_TAG ('O','g','a','m'), /*3.0*/ + HB_SCRIPT_RUNIC = HB_TAG ('R','u','n','r'), /*3.0*/ + HB_SCRIPT_SINHALA = HB_TAG ('S','i','n','h'), /*3.0*/ + HB_SCRIPT_SYRIAC = HB_TAG ('S','y','r','c'), /*3.0*/ + HB_SCRIPT_THAANA = HB_TAG ('T','h','a','a'), /*3.0*/ + HB_SCRIPT_YI = HB_TAG ('Y','i','i','i'), /*3.0*/ + + HB_SCRIPT_DESERET = HB_TAG ('D','s','r','t'), /*3.1*/ + HB_SCRIPT_GOTHIC = HB_TAG ('G','o','t','h'), /*3.1*/ + HB_SCRIPT_OLD_ITALIC = HB_TAG ('I','t','a','l'), /*3.1*/ + + HB_SCRIPT_BUHID = HB_TAG ('B','u','h','d'), /*3.2*/ + HB_SCRIPT_HANUNOO = HB_TAG ('H','a','n','o'), /*3.2*/ + HB_SCRIPT_TAGALOG = HB_TAG ('T','g','l','g'), /*3.2*/ + HB_SCRIPT_TAGBANWA = HB_TAG ('T','a','g','b'), /*3.2*/ + + HB_SCRIPT_CYPRIOT = HB_TAG ('C','p','r','t'), /*4.0*/ + HB_SCRIPT_LIMBU = HB_TAG ('L','i','m','b'), /*4.0*/ + HB_SCRIPT_LINEAR_B = HB_TAG ('L','i','n','b'), /*4.0*/ + HB_SCRIPT_OSMANYA = HB_TAG ('O','s','m','a'), /*4.0*/ + HB_SCRIPT_SHAVIAN = HB_TAG ('S','h','a','w'), /*4.0*/ + HB_SCRIPT_TAI_LE = HB_TAG ('T','a','l','e'), /*4.0*/ + HB_SCRIPT_UGARITIC = HB_TAG ('U','g','a','r'), /*4.0*/ + + HB_SCRIPT_BUGINESE = HB_TAG ('B','u','g','i'), /*4.1*/ + HB_SCRIPT_COPTIC = HB_TAG ('C','o','p','t'), /*4.1*/ + HB_SCRIPT_GLAGOLITIC = HB_TAG ('G','l','a','g'), /*4.1*/ + HB_SCRIPT_KHAROSHTHI = HB_TAG ('K','h','a','r'), /*4.1*/ + HB_SCRIPT_NEW_TAI_LUE = HB_TAG ('T','a','l','u'), /*4.1*/ + HB_SCRIPT_OLD_PERSIAN = HB_TAG ('X','p','e','o'), /*4.1*/ + HB_SCRIPT_SYLOTI_NAGRI = HB_TAG ('S','y','l','o'), /*4.1*/ + HB_SCRIPT_TIFINAGH = HB_TAG ('T','f','n','g'), /*4.1*/ + + HB_SCRIPT_BALINESE = HB_TAG ('B','a','l','i'), /*5.0*/ + HB_SCRIPT_CUNEIFORM = HB_TAG ('X','s','u','x'), /*5.0*/ + HB_SCRIPT_NKO = HB_TAG ('N','k','o','o'), /*5.0*/ + HB_SCRIPT_PHAGS_PA = HB_TAG ('P','h','a','g'), /*5.0*/ + HB_SCRIPT_PHOENICIAN = HB_TAG ('P','h','n','x'), /*5.0*/ + + HB_SCRIPT_CARIAN = HB_TAG ('C','a','r','i'), /*5.1*/ + HB_SCRIPT_CHAM = HB_TAG ('C','h','a','m'), /*5.1*/ + HB_SCRIPT_KAYAH_LI = HB_TAG ('K','a','l','i'), /*5.1*/ + HB_SCRIPT_LEPCHA = HB_TAG ('L','e','p','c'), /*5.1*/ + HB_SCRIPT_LYCIAN = HB_TAG ('L','y','c','i'), /*5.1*/ + HB_SCRIPT_LYDIAN = HB_TAG ('L','y','d','i'), /*5.1*/ + HB_SCRIPT_OL_CHIKI = HB_TAG ('O','l','c','k'), /*5.1*/ + HB_SCRIPT_REJANG = HB_TAG ('R','j','n','g'), /*5.1*/ + HB_SCRIPT_SAURASHTRA = HB_TAG ('S','a','u','r'), /*5.1*/ + HB_SCRIPT_SUNDANESE = HB_TAG ('S','u','n','d'), /*5.1*/ + HB_SCRIPT_VAI = HB_TAG ('V','a','i','i'), /*5.1*/ + + HB_SCRIPT_AVESTAN = HB_TAG ('A','v','s','t'), /*5.2*/ + HB_SCRIPT_BAMUM = HB_TAG ('B','a','m','u'), /*5.2*/ + HB_SCRIPT_EGYPTIAN_HIEROGLYPHS = HB_TAG ('E','g','y','p'), /*5.2*/ + HB_SCRIPT_IMPERIAL_ARAMAIC = HB_TAG ('A','r','m','i'), /*5.2*/ + HB_SCRIPT_INSCRIPTIONAL_PAHLAVI = HB_TAG ('P','h','l','i'), /*5.2*/ + HB_SCRIPT_INSCRIPTIONAL_PARTHIAN = HB_TAG ('P','r','t','i'), /*5.2*/ + HB_SCRIPT_JAVANESE = HB_TAG ('J','a','v','a'), /*5.2*/ + HB_SCRIPT_KAITHI = HB_TAG ('K','t','h','i'), /*5.2*/ + HB_SCRIPT_LISU = HB_TAG ('L','i','s','u'), /*5.2*/ + HB_SCRIPT_MEETEI_MAYEK = HB_TAG ('M','t','e','i'), /*5.2*/ + HB_SCRIPT_OLD_SOUTH_ARABIAN = HB_TAG ('S','a','r','b'), /*5.2*/ + HB_SCRIPT_OLD_TURKIC = HB_TAG ('O','r','k','h'), /*5.2*/ + HB_SCRIPT_SAMARITAN = HB_TAG ('S','a','m','r'), /*5.2*/ + HB_SCRIPT_TAI_THAM = HB_TAG ('L','a','n','a'), /*5.2*/ + HB_SCRIPT_TAI_VIET = HB_TAG ('T','a','v','t'), /*5.2*/ + + HB_SCRIPT_BATAK = HB_TAG ('B','a','t','k'), /*6.0*/ + HB_SCRIPT_BRAHMI = HB_TAG ('B','r','a','h'), /*6.0*/ + HB_SCRIPT_MANDAIC = HB_TAG ('M','a','n','d'), /*6.0*/ + + HB_SCRIPT_CHAKMA = HB_TAG ('C','a','k','m'), /*6.1*/ + HB_SCRIPT_MEROITIC_CURSIVE = HB_TAG ('M','e','r','c'), /*6.1*/ + HB_SCRIPT_MEROITIC_HIEROGLYPHS = HB_TAG ('M','e','r','o'), /*6.1*/ + HB_SCRIPT_MIAO = HB_TAG ('P','l','r','d'), /*6.1*/ + HB_SCRIPT_SHARADA = HB_TAG ('S','h','r','d'), /*6.1*/ + HB_SCRIPT_SORA_SOMPENG = HB_TAG ('S','o','r','a'), /*6.1*/ + HB_SCRIPT_TAKRI = HB_TAG ('T','a','k','r'), /*6.1*/ + + /* + * Since: 0.9.30 + */ + HB_SCRIPT_BASSA_VAH = HB_TAG ('B','a','s','s'), /*7.0*/ + HB_SCRIPT_CAUCASIAN_ALBANIAN = HB_TAG ('A','g','h','b'), /*7.0*/ + HB_SCRIPT_DUPLOYAN = HB_TAG ('D','u','p','l'), /*7.0*/ + HB_SCRIPT_ELBASAN = HB_TAG ('E','l','b','a'), /*7.0*/ + HB_SCRIPT_GRANTHA = HB_TAG ('G','r','a','n'), /*7.0*/ + HB_SCRIPT_KHOJKI = HB_TAG ('K','h','o','j'), /*7.0*/ + HB_SCRIPT_KHUDAWADI = HB_TAG ('S','i','n','d'), /*7.0*/ + HB_SCRIPT_LINEAR_A = HB_TAG ('L','i','n','a'), /*7.0*/ + HB_SCRIPT_MAHAJANI = HB_TAG ('M','a','h','j'), /*7.0*/ + HB_SCRIPT_MANICHAEAN = HB_TAG ('M','a','n','i'), /*7.0*/ + HB_SCRIPT_MENDE_KIKAKUI = HB_TAG ('M','e','n','d'), /*7.0*/ + HB_SCRIPT_MODI = HB_TAG ('M','o','d','i'), /*7.0*/ + HB_SCRIPT_MRO = HB_TAG ('M','r','o','o'), /*7.0*/ + HB_SCRIPT_NABATAEAN = HB_TAG ('N','b','a','t'), /*7.0*/ + HB_SCRIPT_OLD_NORTH_ARABIAN = HB_TAG ('N','a','r','b'), /*7.0*/ + HB_SCRIPT_OLD_PERMIC = HB_TAG ('P','e','r','m'), /*7.0*/ + HB_SCRIPT_PAHAWH_HMONG = HB_TAG ('H','m','n','g'), /*7.0*/ + HB_SCRIPT_PALMYRENE = HB_TAG ('P','a','l','m'), /*7.0*/ + HB_SCRIPT_PAU_CIN_HAU = HB_TAG ('P','a','u','c'), /*7.0*/ + HB_SCRIPT_PSALTER_PAHLAVI = HB_TAG ('P','h','l','p'), /*7.0*/ + HB_SCRIPT_SIDDHAM = HB_TAG ('S','i','d','d'), /*7.0*/ + HB_SCRIPT_TIRHUTA = HB_TAG ('T','i','r','h'), /*7.0*/ + HB_SCRIPT_WARANG_CITI = HB_TAG ('W','a','r','a'), /*7.0*/ + + HB_SCRIPT_AHOM = HB_TAG ('A','h','o','m'), /*8.0*/ + HB_SCRIPT_ANATOLIAN_HIEROGLYPHS = HB_TAG ('H','l','u','w'), /*8.0*/ + HB_SCRIPT_HATRAN = HB_TAG ('H','a','t','r'), /*8.0*/ + HB_SCRIPT_MULTANI = HB_TAG ('M','u','l','t'), /*8.0*/ + HB_SCRIPT_OLD_HUNGARIAN = HB_TAG ('H','u','n','g'), /*8.0*/ + HB_SCRIPT_SIGNWRITING = HB_TAG ('S','g','n','w'), /*8.0*/ + + /* + * Since 1.3.0 + */ + HB_SCRIPT_ADLAM = HB_TAG ('A','d','l','m'), /*9.0*/ + HB_SCRIPT_BHAIKSUKI = HB_TAG ('B','h','k','s'), /*9.0*/ + HB_SCRIPT_MARCHEN = HB_TAG ('M','a','r','c'), /*9.0*/ + HB_SCRIPT_OSAGE = HB_TAG ('O','s','g','e'), /*9.0*/ + HB_SCRIPT_TANGUT = HB_TAG ('T','a','n','g'), /*9.0*/ + HB_SCRIPT_NEWA = HB_TAG ('N','e','w','a'), /*9.0*/ + + /* + * Since 1.6.0 + */ + HB_SCRIPT_MASARAM_GONDI = HB_TAG ('G','o','n','m'), /*10.0*/ + HB_SCRIPT_NUSHU = HB_TAG ('N','s','h','u'), /*10.0*/ + HB_SCRIPT_SOYOMBO = HB_TAG ('S','o','y','o'), /*10.0*/ + HB_SCRIPT_ZANABAZAR_SQUARE = HB_TAG ('Z','a','n','b'), /*10.0*/ + + /* + * Since 1.8.0 + */ + HB_SCRIPT_DOGRA = HB_TAG ('D','o','g','r'), /*11.0*/ + HB_SCRIPT_GUNJALA_GONDI = HB_TAG ('G','o','n','g'), /*11.0*/ + HB_SCRIPT_HANIFI_ROHINGYA = HB_TAG ('R','o','h','g'), /*11.0*/ + HB_SCRIPT_MAKASAR = HB_TAG ('M','a','k','a'), /*11.0*/ + HB_SCRIPT_MEDEFAIDRIN = HB_TAG ('M','e','d','f'), /*11.0*/ + HB_SCRIPT_OLD_SOGDIAN = HB_TAG ('S','o','g','o'), /*11.0*/ + HB_SCRIPT_SOGDIAN = HB_TAG ('S','o','g','d'), /*11.0*/ + + /* + * Since 2.4.0 + */ + HB_SCRIPT_ELYMAIC = HB_TAG ('E','l','y','m'), /*12.0*/ + HB_SCRIPT_NANDINAGARI = HB_TAG ('N','a','n','d'), /*12.0*/ + HB_SCRIPT_NYIAKENG_PUACHUE_HMONG = HB_TAG ('H','m','n','p'), /*12.0*/ + HB_SCRIPT_WANCHO = HB_TAG ('W','c','h','o'), /*12.0*/ + + /* + * Since 2.6.7 + */ + HB_SCRIPT_CHORASMIAN = HB_TAG ('C','h','r','s'), /*13.0*/ + HB_SCRIPT_DIVES_AKURU = HB_TAG ('D','i','a','k'), /*13.0*/ + HB_SCRIPT_KHITAN_SMALL_SCRIPT = HB_TAG ('K','i','t','s'), /*13.0*/ + HB_SCRIPT_YEZIDI = HB_TAG ('Y','e','z','i'), /*13.0*/ + + /* + * Since 3.0.0 + */ + HB_SCRIPT_CYPRO_MINOAN = HB_TAG ('C','p','m','n'), /*14.0*/ + HB_SCRIPT_OLD_UYGHUR = HB_TAG ('O','u','g','r'), /*14.0*/ + HB_SCRIPT_TANGSA = HB_TAG ('T','n','s','a'), /*14.0*/ + HB_SCRIPT_TOTO = HB_TAG ('T','o','t','o'), /*14.0*/ + HB_SCRIPT_VITHKUQI = HB_TAG ('V','i','t','h'), /*14.0*/ + + /* + * Since 3.4.0 + */ + HB_SCRIPT_MATH = HB_TAG ('Z','m','t','h'), + + /* + * Since 5.2.0 + */ + HB_SCRIPT_KAWI = HB_TAG ('K','a','w','i'), /*15.0*/ + HB_SCRIPT_NAG_MUNDARI = HB_TAG ('N','a','g','m'), /*15.0*/ + + /* + * Since 10.0.0 + */ + HB_SCRIPT_GARAY = HB_TAG ('G','a','r','a'), /*16.0*/ + HB_SCRIPT_GURUNG_KHEMA = HB_TAG ('G','u','k','h'), /*16.0*/ + HB_SCRIPT_KIRAT_RAI = HB_TAG ('K','r','a','i'), /*16.0*/ + HB_SCRIPT_OL_ONAL = HB_TAG ('O','n','a','o'), /*16.0*/ + HB_SCRIPT_SUNUWAR = HB_TAG ('S','u','n','u'), /*16.0*/ + HB_SCRIPT_TODHRI = HB_TAG ('T','o','d','r'), /*16.0*/ + HB_SCRIPT_TULU_TIGALARI = HB_TAG ('T','u','t','g'), /*16.0*/ + + /* No script set. */ + HB_SCRIPT_INVALID = HB_TAG_NONE, + + /*< private >*/ + + /* Dummy values to ensure any hb_tag_t value can be passed/stored as hb_script_t + * without risking undefined behavior. We have two, for historical reasons. + * HB_TAG_MAX used to be unsigned, but that was invalid Ansi C, so was changed + * to _HB_SCRIPT_MAX_VALUE to be equal to HB_TAG_MAX_SIGNED as well. + * + * See this thread for technicalities: + * + * https://lists.freedesktop.org/archives/harfbuzz/2014-March/004150.html + */ + _HB_SCRIPT_MAX_VALUE = HB_TAG_MAX_SIGNED, /*< skip >*/ + _HB_SCRIPT_MAX_VALUE_SIGNED = HB_TAG_MAX_SIGNED /*< skip >*/ + +} hb_script_t; + + +#endif /* HB_SCRIPT_LIST_H */ diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-set-digest.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-set-digest.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-set-digest.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-set-digest.hh 2025-10-13 07:49:24.000000000 +0000 @@ -31,11 +31,10 @@ #include "hb-machinery.hh" /* - * The set-digests here implement various "filters" that support - * "approximate member query". Conceptually these are like Bloom - * Filter and Quotient Filter, however, much smaller, faster, and - * designed to fit the requirements of our uses for glyph coverage - * queries. + * The set-digests implement "filters" that support "approximate + * member query". Conceptually these are like Bloom Filter and + * Quotient Filter, however, much smaller, faster, and designed + * to fit the requirements of our uses for glyph coverage queries. * * Our filters are highly accurate if the lookup covers fairly local * set of glyphs, but fully flooded and ineffective if coverage is diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-set.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-set.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-set.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-set.hh 2025-10-13 07:49:24.000000000 +0000 @@ -30,6 +30,7 @@ #include "hb.hh" #include "hb-bit-set-invertible.hh" +#include "hb-bit-vector.hh" // Just to include template diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-shape.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-shape.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-shape.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-shape.cc 2025-10-13 07:49:24.000000000 +0000 @@ -91,8 +91,10 @@ * * Retrieves the list of shapers supported by HarfBuzz. * - * Return value: (transfer none) (array zero-terminated=1): an array of - * constant strings + * Return value: (transfer none) (array zero-terminated=1): a + * `NULL`-terminated array of supported shapers constant string. + * The returned array is owned by HarfBuzz and should not be + * modified or freed. * * Since: 0.9.2 **/ diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-static.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-static.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-static.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-static.cc 2025-10-13 07:49:24.000000000 +0000 @@ -41,6 +41,7 @@ #include "hb-ot-maxp-table.hh" #ifndef HB_NO_VISIBILITY + #include "hb-ot-name-language-static.hh" uint64_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {}; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-subset-cff-common.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-subset-cff-common.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-subset-cff-common.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-subset-cff-common.hh 2025-10-13 07:49:24.000000000 +0000 @@ -570,7 +570,7 @@ parsed_cs_str_vec_t parsed_charstrings; parsed_cs_str_vec_t parsed_global_subrs; hb_vector_t parsed_local_subrs; - mutable hb_atomic_ptr_t glyph_to_sid_map; + mutable hb_atomic_t glyph_to_sid_map; private: hb_blob_t* original_blob; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-subset-input.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-subset-input.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-subset-input.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-subset-input.cc 2025-10-13 07:49:24.000000000 +0000 @@ -868,7 +868,7 @@ src = hb_utf8_t::next (src, src_end, &unicode, replacement); if (unicode >= 0x0080u) { - printf ("Non-ascii character detected, ignored...This API supports ascii characters only for mac platform\n"); + // Non-ascii character detected, ignored... return false; } } diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.cc 2025-10-13 07:49:24.000000000 +0000 @@ -29,27 +29,21 @@ #include "hb-map.hh" #include "hb-multimap.hh" #include "hb-set.hh" +#include "hb-subset.h" +#include "hb-unicode.h" #include "hb-ot-cmap-table.hh" #include "hb-ot-glyf-table.hh" #include "hb-ot-layout-base-table.hh" -#include "hb-ot-layout-gdef-table.hh" -#include "hb-ot-layout-gpos-table.hh" -#include "hb-ot-layout-gsub-table.hh" #include "hb-ot-cff1-table.hh" #include "hb-ot-cff2-table.hh" #include "OT/Color/COLR/COLR.hh" #include "OT/Color/COLR/colrv1-closure.hh" #include "OT/Color/CPAL/CPAL.hh" #include "hb-ot-var-fvar-table.hh" -#include "hb-ot-var-avar-table.hh" #include "hb-ot-stat-table.hh" #include "hb-ot-math-table.hh" -using OT::Layout::GSUB; -using OT::Layout::GPOS; - - hb_subset_accelerator_t::~hb_subset_accelerator_t () { if (cmap_cache && destroy_cmap_cache) @@ -63,7 +57,6 @@ } -typedef hb_hashmap_t> script_langsys_map; #ifndef HB_NO_SUBSET_CFF static inline bool _add_cff_seac_components (const OT::cff1::accelerator_subset_t &cff, @@ -98,414 +91,14 @@ } } -static void -_remap_indexes (const hb_set_t *indexes, - hb_map_t *mapping /* OUT */) +void +remap_indexes (const hb_set_t *indexes, + hb_map_t *mapping /* OUT */) { for (auto _ : + hb_enumerate (indexes->iter ())) mapping->set (_.second, _.first); - } -#ifndef HB_NO_SUBSET_LAYOUT - -/* - * Removes all tags from 'tags' that are not in filter. Additionally eliminates any duplicates. - * Returns true if anything was removed (not including duplicates). - */ -static bool _filter_tag_list(hb_vector_t* tags, /* IN/OUT */ - const hb_set_t* filter) -{ - hb_vector_t out; - out.alloc (tags->get_size() + 1); // +1 is to allocate room for the null terminator. - - bool removed = false; - hb_set_t visited; - - for (hb_tag_t tag : *tags) - { - if (!tag) continue; - if (visited.has (tag)) continue; - - if (!filter->has (tag)) - { - removed = true; - continue; - } - - visited.add (tag); - out.push (tag); - } - - // The collect function needs a null element to signal end of the array. - out.push (HB_TAG_NONE); - - hb_swap (out, *tags); - return removed; -} - -template -static void _collect_layout_indices (hb_subset_plan_t *plan, - const T& table, - hb_set_t *lookup_indices, /* OUT */ - hb_set_t *feature_indices, /* OUT */ - hb_hashmap_t> *feature_record_cond_idx_map, /* OUT */ - hb_hashmap_t *feature_substitutes_map, /* OUT */ - hb_set_t& catch_all_record_feature_idxes, /* OUT */ - hb_hashmap_t>& catch_all_record_idx_feature_map /* OUT */) -{ - unsigned num_features = table.get_feature_count (); - hb_vector_t features; - if (!plan->check_success (features.resize (num_features))) return; - table.get_feature_tags (0, &num_features, features.arrayZ); - bool retain_all_features = !_filter_tag_list (&features, &plan->layout_features); - - unsigned num_scripts = table.get_script_count (); - hb_vector_t scripts; - if (!plan->check_success (scripts.resize (num_scripts))) return; - table.get_script_tags (0, &num_scripts, scripts.arrayZ); - bool retain_all_scripts = !_filter_tag_list (&scripts, &plan->layout_scripts); - - if (!plan->check_success (!features.in_error ()) || !features - || !plan->check_success (!scripts.in_error ()) || !scripts) - return; - - hb_ot_layout_collect_features (plan->source, - T::tableTag, - retain_all_scripts ? nullptr : scripts.arrayZ, - nullptr, - retain_all_features ? nullptr : features.arrayZ, - feature_indices); - -#ifndef HB_NO_VAR - // collect feature substitutes with variations - if (!plan->user_axes_location.is_empty ()) - { - hb_hashmap_t, unsigned> conditionset_map; - OT::hb_collect_feature_substitutes_with_var_context_t c = - { - &plan->axes_old_index_tag_map, - &plan->axes_location, - feature_record_cond_idx_map, - feature_substitutes_map, - catch_all_record_feature_idxes, - feature_indices, - false, - false, - false, - 0, - &conditionset_map - }; - table.collect_feature_substitutes_with_variations (&c); - } -#endif - - for (unsigned feature_index : *feature_indices) - { - const OT::Feature* f = &(table.get_feature (feature_index)); - const OT::Feature **p = nullptr; - if (feature_substitutes_map->has (feature_index, &p)) - f = *p; - - f->add_lookup_indexes_to (lookup_indices); - } - -#ifndef HB_NO_VAR - if (catch_all_record_feature_idxes) - { - for (unsigned feature_index : catch_all_record_feature_idxes) - { - const OT::Feature& f = table.get_feature (feature_index); - f.add_lookup_indexes_to (lookup_indices); - const void *tag = reinterpret_cast (&(table.get_feature_list ().get_tag (feature_index))); - catch_all_record_idx_feature_map.set (feature_index, hb_pair (&f, tag)); - } - } - - // If all axes are pinned then all feature variations will be dropped so there's no need - // to collect lookups from them. - if (!plan->all_axes_pinned) - table.feature_variation_collect_lookups (feature_indices, - plan->user_axes_location.is_empty () ? nullptr: feature_record_cond_idx_map, - lookup_indices); -#endif -} - - -static inline void -_GSUBGPOS_find_duplicate_features (const OT::GSUBGPOS &g, - const hb_map_t *lookup_indices, - const hb_set_t *feature_indices, - const hb_hashmap_t *feature_substitutes_map, - hb_map_t *duplicate_feature_map /* OUT */) -{ - if (feature_indices->is_empty ()) return; - hb_hashmap_t> unique_features; - //find out duplicate features after subset - for (unsigned i : feature_indices->iter ()) - { - hb_tag_t t = g.get_feature_tag (i); - if (t == HB_MAP_VALUE_INVALID) continue; - if (!unique_features.has (t)) - { - if (unlikely (!unique_features.set (t, hb::unique_ptr {hb_set_create ()}))) - return; - if (unique_features.has (t)) - unique_features.get (t)->add (i); - duplicate_feature_map->set (i, i); - continue; - } - - bool found = false; - - hb_set_t* same_tag_features = unique_features.get (t); - for (unsigned other_f_index : same_tag_features->iter ()) - { - const OT::Feature* f = &(g.get_feature (i)); - const OT::Feature **p = nullptr; - if (feature_substitutes_map->has (i, &p)) - f = *p; - - const OT::Feature* other_f = &(g.get_feature (other_f_index)); - if (feature_substitutes_map->has (other_f_index, &p)) - other_f = *p; - - auto f_iter = - + hb_iter (f->lookupIndex) - | hb_filter (lookup_indices) - ; - - auto other_f_iter = - + hb_iter (other_f->lookupIndex) - | hb_filter (lookup_indices) - ; - - bool is_equal = true; - for (; f_iter && other_f_iter; f_iter++, other_f_iter++) - { - unsigned a = *f_iter; - unsigned b = *other_f_iter; - if (a != b) { is_equal = false; break; } - } - - if (is_equal == false || f_iter || other_f_iter) continue; - - found = true; - duplicate_feature_map->set (i, other_f_index); - break; - } - - if (found == false) - { - same_tag_features->add (i); - duplicate_feature_map->set (i, i); - } - } -} - -template -static inline void -_closure_glyphs_lookups_features (hb_subset_plan_t *plan, - hb_set_t *gids_to_retain, - hb_map_t *lookups, - hb_map_t *features, - script_langsys_map *langsys_map, - hb_hashmap_t> *feature_record_cond_idx_map, - hb_hashmap_t *feature_substitutes_map, - hb_set_t &catch_all_record_feature_idxes, - hb_hashmap_t>& catch_all_record_idx_feature_map) -{ - hb_blob_ptr_t table = plan->source_table (); - hb_tag_t table_tag = table->tableTag; - hb_set_t lookup_indices, feature_indices; - _collect_layout_indices (plan, - *table, - &lookup_indices, - &feature_indices, - feature_record_cond_idx_map, - feature_substitutes_map, - catch_all_record_feature_idxes, - catch_all_record_idx_feature_map); - - if (table_tag == HB_OT_TAG_GSUB && !(plan->flags & HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE)) - hb_ot_layout_lookups_substitute_closure (plan->source, - &lookup_indices, - gids_to_retain); - table->closure_lookups (plan->source, - gids_to_retain, - &lookup_indices); - _remap_indexes (&lookup_indices, lookups); - - // prune features - table->prune_features (lookups, - plan->user_axes_location.is_empty () ? nullptr : feature_record_cond_idx_map, - feature_substitutes_map, - &feature_indices); - hb_map_t duplicate_feature_map; - _GSUBGPOS_find_duplicate_features (*table, lookups, &feature_indices, feature_substitutes_map, &duplicate_feature_map); - - feature_indices.clear (); - table->prune_langsys (&duplicate_feature_map, &plan->layout_scripts, langsys_map, &feature_indices); - _remap_indexes (&feature_indices, features); - - table.destroy (); -} - -#endif - -#ifndef HB_NO_VAR -static inline void -_generate_varstore_inner_maps (const hb_set_t& varidx_set, - unsigned subtable_count, - hb_vector_t &inner_maps /* OUT */) -{ - if (varidx_set.is_empty () || subtable_count == 0) return; - - if (unlikely (!inner_maps.resize (subtable_count))) return; - for (unsigned idx : varidx_set) - { - uint16_t major = idx >> 16; - uint16_t minor = idx & 0xFFFF; - - if (major >= subtable_count) - continue; - inner_maps[major].add (minor); - } -} - -static inline hb_font_t* -_get_hb_font_with_variations (const hb_subset_plan_t *plan) -{ - hb_font_t *font = hb_font_create (plan->source); - - hb_vector_t vars; - if (!vars.alloc (plan->user_axes_location.get_population ())) { - hb_font_destroy (font); - return nullptr; - } - - for (auto _ : plan->user_axes_location) - { - hb_variation_t var; - var.tag = _.first; - var.value = _.second.middle; - vars.push (var); - } - -#ifndef HB_NO_VAR - hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location.get_population ()); -#endif - return font; -} - -static inline void -_remap_variation_indices (const OT::ItemVariationStore &var_store, - const hb_set_t &variation_indices, - const hb_vector_t& normalized_coords, - bool calculate_delta, /* not pinned at default */ - bool no_variations, /* all axes pinned */ - hb_hashmap_t> &variation_idx_delta_map /* OUT */) -{ - if (&var_store == &Null (OT::ItemVariationStore)) return; - unsigned subtable_count = var_store.get_sub_table_count (); - float *store_cache = var_store.create_cache (); - - unsigned new_major = 0, new_minor = 0; - unsigned last_major = (variation_indices.get_min ()) >> 16; - for (unsigned idx : variation_indices) - { - int delta = 0; - if (calculate_delta) - delta = roundf (var_store.get_delta (idx, normalized_coords.arrayZ, - normalized_coords.length, store_cache)); - - if (no_variations) - { - variation_idx_delta_map.set (idx, hb_pair_t (HB_OT_LAYOUT_NO_VARIATIONS_INDEX, delta)); - continue; - } - - uint16_t major = idx >> 16; - if (major >= subtable_count) break; - if (major != last_major) - { - new_minor = 0; - ++new_major; - } - - unsigned new_idx = (new_major << 16) + new_minor; - variation_idx_delta_map.set (idx, hb_pair_t (new_idx, delta)); - ++new_minor; - last_major = major; - } - var_store.destroy_cache (store_cache); -} - -static inline void -_collect_layout_variation_indices (hb_subset_plan_t* plan) -{ - hb_blob_ptr_t gdef = plan->source_table (); - hb_blob_ptr_t gpos = plan->source_table (); - - if (!gdef->has_data () || !gdef->has_var_store ()) - { - gdef.destroy (); - gpos.destroy (); - return; - } - - hb_set_t varidx_set; - OT::hb_collect_variation_indices_context_t c (&varidx_set, - &plan->_glyphset_gsub, - &plan->gpos_lookups); - gdef->collect_variation_indices (&c); - - if (hb_ot_layout_has_positioning (plan->source)) - gpos->collect_variation_indices (&c); - - _remap_variation_indices (gdef->get_var_store (), - varidx_set, plan->normalized_coords, - !plan->pinned_at_default, - plan->all_axes_pinned, - plan->layout_variation_idx_delta_map); - - unsigned subtable_count = gdef->get_var_store ().get_sub_table_count (); - _generate_varstore_inner_maps (varidx_set, subtable_count, plan->gdef_varstore_inner_maps); - - gdef.destroy (); - gpos.destroy (); -} - -#ifndef HB_NO_BASE -static inline void -_collect_base_variation_indices (hb_subset_plan_t* plan) -{ - hb_blob_ptr_t base = plan->source_table (); - if (!base->has_var_store ()) - { - base.destroy (); - return; - } - - hb_set_t varidx_set; - base->collect_variation_indices (plan, varidx_set); - const OT::ItemVariationStore &var_store = base->get_var_store (); - unsigned subtable_count = var_store.get_sub_table_count (); - - - _remap_variation_indices (var_store, varidx_set, - plan->normalized_coords, - !plan->pinned_at_default, - plan->all_axes_pinned, - plan->base_variation_idx_map); - _generate_varstore_inner_maps (varidx_set, subtable_count, plan->base_varstore_inner_maps); - - base.destroy (); -} - -#endif -#endif - static inline void _cmap_closure (hb_face_t *face, const hb_set_t *unicodes, @@ -515,41 +108,6 @@ cmap.table->closure_glyphs (unicodes, glyphset); } -#ifndef HB_NO_VAR -static void -_remap_colrv1_delta_set_index_indices (const OT::DeltaSetIndexMap &index_map, - const hb_set_t &delta_set_idxes, - hb_hashmap_t> &variation_idx_delta_map, /* IN/OUT */ - hb_map_t &new_deltaset_idx_varidx_map /* OUT */) -{ - if (!index_map.get_map_count ()) - return; - - hb_hashmap_t> delta_set_idx_delta_map; - unsigned new_delta_set_idx = 0; - for (unsigned delta_set_idx : delta_set_idxes) - { - unsigned var_idx = index_map.map (delta_set_idx); - unsigned new_varidx = HB_OT_LAYOUT_NO_VARIATIONS_INDEX; - int delta = 0; - - if (var_idx != HB_OT_LAYOUT_NO_VARIATIONS_INDEX) - { - hb_pair_t *new_varidx_delta; - if (!variation_idx_delta_map.has (var_idx, &new_varidx_delta)) continue; - - new_varidx = hb_first (*new_varidx_delta); - delta = hb_second (*new_varidx_delta); - } - - new_deltaset_idx_varidx_map.set (new_delta_set_idx, new_varidx); - delta_set_idx_delta_map.set (delta_set_idx, hb_pair_t (new_delta_set_idx, delta)); - new_delta_set_idx++; - } - variation_idx_delta_map = std::move (delta_set_idx_delta_map); -} -#endif - static void _colr_closure (hb_subset_plan_t* plan, hb_set_t *glyphs_colred) { @@ -569,7 +127,7 @@ colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices, &variation_indices, &delta_set_indices); colr.closure_V0palette_indices (glyphs_colred, &palette_indices); - _remap_indexes (&layer_indices, &plan->colrv1_layers); + remap_indexes (&layer_indices, &plan->colrv1_layers); _remap_palette_indexes (&palette_indices, &plan->colr_palettes); #ifndef HB_NO_VAR @@ -578,7 +136,7 @@ const OT::ItemVariationStore &var_store = colr.get_var_store (); // generated inner_maps is used by ItemVariationStore serialize(), which is subset only unsigned subtable_count = var_store.get_sub_table_count (); - _generate_varstore_inner_maps (variation_indices, subtable_count, plan->colrv1_varstore_inner_maps); + generate_varstore_inner_maps (variation_indices, subtable_count, plan->colrv1_varstore_inner_maps); /* colr variation indices mapping during planning phase: * generate colrv1_variation_idx_delta_map. When delta set index map is not @@ -590,7 +148,7 @@ * instancing. */ if (!plan->all_axes_pinned) { - _remap_variation_indices (var_store, + remap_variation_indices (var_store, variation_indices, plan->normalized_coords, false, /* no need to calculate delta for COLR during planning */ @@ -598,7 +156,7 @@ plan->colrv1_variation_idx_delta_map); if (colr.has_delta_set_index_map ()) - _remap_colrv1_delta_set_index_indices (colr.get_delta_set_index_map (), + remap_colrv1_delta_set_index_indices (colr.get_delta_set_index_map (), delta_set_indices, plan->colrv1_variation_idx_delta_map, plan->colrv1_new_deltaset_idx_varidx_map); @@ -617,25 +175,6 @@ } static inline void -_remap_used_mark_sets (hb_subset_plan_t *plan, - hb_map_t& used_mark_sets_map) -{ - hb_blob_ptr_t gdef = plan->source_table (); - - if (!gdef->has_data () || !gdef->has_mark_glyph_sets ()) - { - gdef.destroy (); - return; - } - - hb_set_t used_mark_sets; - gdef->get_mark_glyph_sets ().collect_used_mark_sets (plan->_glyphset_gsub, used_mark_sets); - gdef.destroy (); - - _remap_indexes (&used_mark_sets, &used_mark_sets_map); -} - -static inline void _remove_invalid_gids (hb_set_t *glyphs, unsigned int num_glyphs) { @@ -672,15 +211,46 @@ _fill_unicode_and_glyph_map(plan, unicode_iterator, unicode_to_gid_for_iterator, unicode_to_gid_for_iterator); } +/* + * Finds additional unicode codepoints which are reachable from the input unicode set. + * Currently this adds in mirrored variants (needed for bidi) of any input unicodes. + */ +static hb_set_t +_unicode_closure (const hb_set_t* unicodes, bool bidi_closure) { + // TODO: we may want to also consider pulling in reachable unicode composition and decompositions. + // see: https://github.com/harfbuzz/harfbuzz/issues/2283 + hb_set_t out = *unicodes; + if (!bidi_closure) return out; + + if (out.is_inverted()) { + // don't closure inverted sets, they are asking to specifically exclude certain codepoints. + // otherwise everything is already included. + return out; + } + + auto unicode_funcs = hb_unicode_funcs_get_default (); + for (hb_codepoint_t cp : *unicodes) { + hb_codepoint_t mirror = hb_unicode_mirroring(unicode_funcs, cp); + if (unlikely (mirror != cp)) { + out.add(mirror); + } + } + + return out; +} + static void -_populate_unicodes_to_retain (const hb_set_t *unicodes, +_populate_unicodes_to_retain (const hb_set_t *unicodes_in, const hb_set_t *glyphs, hb_subset_plan_t *plan) { + hb_set_t unicodes = _unicode_closure(unicodes_in, + !(plan->flags & HB_SUBSET_FLAGS_NO_BIDI_CLOSURE)); + OT::cmap::accelerator_t cmap (plan->source); unsigned size_threshold = plan->source->get_num_glyphs (); - if (glyphs->is_empty () && unicodes->get_population () < size_threshold) + if (glyphs->is_empty () && unicodes.get_population () < size_threshold) { const hb_map_t* unicode_to_gid = nullptr; @@ -690,9 +260,9 @@ // This is approach to collection is faster, but can only be used if glyphs // are not being explicitly added to the subset and the input unicodes set is // not excessively large (eg. an inverted set). - plan->unicode_to_new_gid_list.alloc (unicodes->get_population ()); + plan->unicode_to_new_gid_list.alloc (unicodes.get_population ()); if (!unicode_to_gid) { - _fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) { + _fill_unicode_and_glyph_map(plan, unicodes.iter(), [&] (hb_codepoint_t cp) { hb_codepoint_t gid; if (!cmap.get_nominal_glyph (cp, &gid)) { return HB_MAP_VALUE_INVALID; @@ -704,7 +274,7 @@ // the map. This code is mostly duplicated from above to avoid doing // conditionals on the presence of the unicode_to_gid map each // iteration. - _fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) { + _fill_unicode_and_glyph_map(plan, unicodes.iter(), [&] (hb_codepoint_t cp) { return unicode_to_gid->get (cp); }); } @@ -721,7 +291,7 @@ if (!plan->accelerator) { cmap.collect_mapping (&cmap_unicodes_storage, &unicode_glyphid_map_storage); - plan->unicode_to_new_gid_list.alloc (hb_min(unicodes->get_population () + plan->unicode_to_new_gid_list.alloc (hb_min(unicodes.get_population () + glyphs->get_population (), cmap_unicodes->get_population ())); } else { @@ -730,10 +300,10 @@ } if (plan->accelerator && - unicodes->get_population () < cmap_unicodes->get_population () && + unicodes.get_population () < cmap_unicodes->get_population () && glyphs->get_population () < cmap_unicodes->get_population ()) { - plan->codepoint_to_glyph->alloc (unicodes->get_population () + glyphs->get_population ()); + plan->codepoint_to_glyph->alloc (unicodes.get_population () + glyphs->get_population ()); auto &gid_to_unicodes = plan->accelerator->gid_to_unicodes; @@ -748,7 +318,7 @@ }); } - _fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) { + _fill_unicode_and_glyph_map(plan, unicodes.iter(), [&] (hb_codepoint_t cp) { /* Don't double-add entry. */ if (plan->codepoint_to_glyph->has (cp)) return HB_MAP_VALUE_INVALID; @@ -769,7 +339,7 @@ { _fill_unicode_and_glyph_map(plan, hb_range(first, last + 1), [&] (hb_codepoint_t cp) { hb_codepoint_t gid = (*unicode_glyphid_map)[cp]; - if (!unicodes->has (cp) && !glyphs->has (gid)) + if (!unicodes.has (cp) && !glyphs->has (gid)) return HB_MAP_VALUE_INVALID; return gid; }, @@ -860,18 +430,7 @@ #endif #ifndef HB_NO_SUBSET_LAYOUT - if (!drop_tables->has (HB_OT_TAG_GPOS)) - { - hb_blob_ptr_t gpos = plan->source_table (); - gpos->collect_name_ids (&plan->gpos_features, &plan->name_ids); - gpos.destroy (); - } - if (!drop_tables->has (HB_OT_TAG_GSUB)) - { - hb_blob_ptr_t gsub = plan->source_table (); - gsub->collect_name_ids (&plan->gsub_features, &plan->name_ids); - gsub.destroy (); - } + layout_nameid_closure(plan, drop_tables); #endif } @@ -893,31 +452,9 @@ _cmap_closure (plan->source, &plan->unicodes, &plan->_glyphset_gsub); #ifndef HB_NO_SUBSET_LAYOUT - if (!drop_tables->has (HB_OT_TAG_GSUB)) - // closure all glyphs/lookups/features needed for GSUB substitutions. - _closure_glyphs_lookups_features ( - plan, - &plan->_glyphset_gsub, - &plan->gsub_lookups, - &plan->gsub_features, - &plan->gsub_langsys, - &plan->gsub_feature_record_cond_idx_map, - &plan->gsub_feature_substitutes_map, - plan->gsub_old_features, - plan->gsub_old_feature_idx_tag_map); - - if (!drop_tables->has (HB_OT_TAG_GPOS)) - _closure_glyphs_lookups_features ( - plan, - &plan->_glyphset_gsub, - &plan->gpos_lookups, - &plan->gpos_features, - &plan->gpos_langsys, - &plan->gpos_feature_record_cond_idx_map, - &plan->gpos_feature_substitutes_map, - plan->gpos_old_features, - plan->gpos_old_feature_idx_tag_map); + layout_populate_gids_to_retain(plan, drop_tables); #endif + _remove_invalid_gids (&plan->_glyphset_gsub, plan->source->get_num_glyphs ()); plan->_glyphset_mathed = plan->_glyphset_gsub; @@ -962,8 +499,10 @@ _remove_invalid_gids (&plan->_glyphset, plan->source->get_num_glyphs ()); #ifndef HB_NO_VAR +#ifndef HB_NO_SUBSET_LAYOUT if (!drop_tables->has (HB_OT_TAG_GDEF)) - _collect_layout_variation_indices (plan); + collect_layout_variation_indices (plan); +#endif #endif } @@ -1077,193 +616,6 @@ return true; } -#ifndef HB_NO_VAR -static void -_normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan) -{ - if (plan->user_axes_location.is_empty ()) - return; - - hb_array_t axes = face->table.fvar->get_axes (); - plan->normalized_coords.resize (axes.length); - - bool has_avar = face->table.avar->has_data (); - const OT::SegmentMaps *seg_maps = nullptr; - unsigned avar_axis_count = 0; - if (has_avar) - { - seg_maps = face->table.avar->get_segment_maps (); - avar_axis_count = face->table.avar->get_axis_count(); - } - - bool axis_not_pinned = false; - unsigned old_axis_idx = 0, new_axis_idx = 0; - for (const auto& axis : axes) - { - hb_tag_t axis_tag = axis.get_axis_tag (); - plan->axes_old_index_tag_map.set (old_axis_idx, axis_tag); - - if (!plan->user_axes_location.has (axis_tag) || - !plan->user_axes_location.get (axis_tag).is_point ()) - { - axis_not_pinned = true; - plan->axes_index_map.set (old_axis_idx, new_axis_idx); - plan->axis_tags.push (axis_tag); - new_axis_idx++; - } - - Triple *axis_range; - if (plan->user_axes_location.has (axis_tag, &axis_range)) - { - plan->axes_triple_distances.set (axis_tag, axis.get_triple_distances ()); - - int normalized_min = axis.normalize_axis_value (axis_range->minimum); - int normalized_default = axis.normalize_axis_value (axis_range->middle); - int normalized_max = axis.normalize_axis_value (axis_range->maximum); - - if (has_avar && old_axis_idx < avar_axis_count) - { - normalized_min = seg_maps->map (normalized_min); - normalized_default = seg_maps->map (normalized_default); - normalized_max = seg_maps->map (normalized_max); - } - plan->axes_location.set (axis_tag, Triple (static_cast (normalized_min / 16384.0), - static_cast (normalized_default / 16384.0), - static_cast (normalized_max / 16384.0))); - - if (normalized_default != 0) - plan->pinned_at_default = false; - - plan->normalized_coords[old_axis_idx] = normalized_default; - } - - old_axis_idx++; - - if (has_avar && old_axis_idx < avar_axis_count) - seg_maps = &StructAfter (*seg_maps); - } - plan->all_axes_pinned = !axis_not_pinned; -} - -static void -_update_instance_metrics_map_from_cff2 (hb_subset_plan_t *plan) -{ - if (!plan->normalized_coords) return; - OT::cff2::accelerator_t cff2 (plan->source); - if (!cff2.is_valid ()) return; - - hb_font_t *font = _get_hb_font_with_variations (plan); - if (unlikely (!plan->check_success (font != nullptr))) - { - hb_font_destroy (font); - return; - } - - hb_glyph_extents_t extents = {0x7FFF, -0x7FFF}; - OT::hmtx_accelerator_t _hmtx (plan->source); - float *hvar_store_cache = nullptr; - if (_hmtx.has_data () && _hmtx.var_table.get_length ()) - hvar_store_cache = _hmtx.var_table->get_var_store ().create_cache (); - - OT::vmtx_accelerator_t _vmtx (plan->source); - float *vvar_store_cache = nullptr; - if (_vmtx.has_data () && _vmtx.var_table.get_length ()) - vvar_store_cache = _vmtx.var_table->get_var_store ().create_cache (); - - for (auto p : *plan->glyph_map) - { - hb_codepoint_t old_gid = p.first; - hb_codepoint_t new_gid = p.second; - if (!cff2.get_extents (font, old_gid, &extents)) continue; - bool has_bounds_info = true; - if (extents.x_bearing == 0 && extents.width == 0 && - extents.height == 0 && extents.y_bearing == 0) - has_bounds_info = false; - - if (has_bounds_info) - { - plan->head_maxp_info.xMin = hb_min (plan->head_maxp_info.xMin, extents.x_bearing); - plan->head_maxp_info.xMax = hb_max (plan->head_maxp_info.xMax, extents.x_bearing + extents.width); - plan->head_maxp_info.yMax = hb_max (plan->head_maxp_info.yMax, extents.y_bearing); - plan->head_maxp_info.yMin = hb_min (plan->head_maxp_info.yMin, extents.y_bearing + extents.height); - } - - if (_hmtx.has_data ()) - { - int hori_aw = _hmtx.get_advance_without_var_unscaled (old_gid); - if (_hmtx.var_table.get_length ()) - hori_aw += (int) roundf (_hmtx.var_table->get_advance_delta_unscaled (old_gid, font->coords, font->num_coords, - hvar_store_cache)); - int lsb = extents.x_bearing; - if (!has_bounds_info) - { - if (!_hmtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb)) - continue; - } - plan->hmtx_map.set (new_gid, hb_pair ((unsigned) hori_aw, lsb)); - plan->bounds_width_vec[new_gid] = extents.width; - } - - if (_vmtx.has_data ()) - { - int vert_aw = _vmtx.get_advance_without_var_unscaled (old_gid); - if (_vmtx.var_table.get_length ()) - vert_aw += (int) roundf (_vmtx.var_table->get_advance_delta_unscaled (old_gid, font->coords, font->num_coords, - vvar_store_cache)); - - int tsb = extents.y_bearing; - if (!has_bounds_info) - { - if (!_vmtx.get_leading_bearing_without_var_unscaled (old_gid, &tsb)) - continue; - } - plan->vmtx_map.set (new_gid, hb_pair ((unsigned) vert_aw, tsb)); - plan->bounds_height_vec[new_gid] = extents.height; - } - } - hb_font_destroy (font); - if (hvar_store_cache) - _hmtx.var_table->get_var_store ().destroy_cache (hvar_store_cache); - if (vvar_store_cache) - _vmtx.var_table->get_var_store ().destroy_cache (vvar_store_cache); -} - -static bool -_get_instance_glyphs_contour_points (hb_subset_plan_t *plan) -{ - /* contour_points vector only needed for updating gvar table (infer delta and - * iup delta optimization) during partial instancing */ - if (plan->user_axes_location.is_empty () || plan->all_axes_pinned) - return true; - - OT::glyf_accelerator_t glyf (plan->source); - - for (auto &_ : plan->new_to_old_gid_list) - { - hb_codepoint_t new_gid = _.first; - contour_point_vector_t all_points; - if (new_gid == 0 && !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)) - { - if (unlikely (!plan->new_gid_contour_points_map.set (new_gid, all_points))) - return false; - continue; - } - - hb_codepoint_t old_gid = _.second; - auto glyph = glyf.glyph_for_gid (old_gid); - if (unlikely (!glyph.get_all_points_without_var (plan->source, all_points))) - return false; - if (unlikely (!plan->new_gid_contour_points_map.set (new_gid, all_points))) - return false; - - /* composite new gids are only needed by iup delta optimization */ - if ((plan->flags & HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS) && glyph.is_composite ()) - plan->composite_new_gids.add (new_gid); - } - return true; -} -#endif - hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face, const hb_subset_input_t *input) { @@ -1324,7 +676,7 @@ return; #ifndef HB_NO_VAR - _normalize_axes_location (face, this); + normalize_axes_location (face, this); #endif _populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, this); @@ -1365,13 +717,15 @@ for (auto &v : bounds_height_vec) v = 0xFFFFFFFF; +#ifndef HB_NO_SUBSET_LAYOUT if (!drop_tables.has (HB_OT_TAG_GDEF)) - _remap_used_mark_sets (this, used_mark_sets_map); + remap_used_mark_sets (this, used_mark_sets_map); +#endif #ifndef HB_NO_VAR #ifndef HB_NO_BASE if (!drop_tables.has (HB_OT_TAG_BASE)) - _collect_base_variation_indices (this); + collect_base_variation_indices (this); #endif #endif @@ -1379,8 +733,8 @@ return; #ifndef HB_NO_VAR - _update_instance_metrics_map_from_cff2 (this); - if (!check_success (_get_instance_glyphs_contour_points (this))) + update_instance_metrics_map_from_cff2 (this); + if (!check_success (get_instance_glyphs_contour_points (this))) return; #endif diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.hh 2025-10-13 07:49:24.000000000 +0000 @@ -296,5 +296,75 @@ } }; +// hb-subset-plan implementation is split into multiple files to keep +// compile times more reasonable: +// - hb-subset-plan.cc +// - hb-subset-plan-layout.cc +// +// The functions below are those needed to connect the split files +// above together. +HB_INTERNAL void +remap_indexes (const hb_set_t *indexes, + hb_map_t *mapping /* OUT */); + + +#ifndef HB_NO_VAR +template +HB_INTERNAL void +remap_variation_indices (const ItemVarStore &var_store, + const hb_set_t &variation_indices, + const hb_vector_t& normalized_coords, + bool calculate_delta, /* not pinned at default */ + bool no_variations, /* all axes pinned */ + hb_hashmap_t> &variation_idx_delta_map /* OUT */); + + +template +HB_INTERNAL void +remap_colrv1_delta_set_index_indices (const DeltaSetIndexMap &index_map, + const hb_set_t &delta_set_idxes, + hb_hashmap_t> &variation_idx_delta_map, /* IN/OUT */ + hb_map_t &new_deltaset_idx_varidx_map /* OUT */); + + +HB_INTERNAL void +generate_varstore_inner_maps (const hb_set_t& varidx_set, + unsigned subtable_count, + hb_vector_t &inner_maps /* OUT */); + +HB_INTERNAL void +normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan); + +HB_INTERNAL void +update_instance_metrics_map_from_cff2 (hb_subset_plan_t *plan); + +HB_INTERNAL bool +get_instance_glyphs_contour_points (hb_subset_plan_t *plan); + +#ifndef HB_NO_BASE +HB_INTERNAL void +collect_base_variation_indices (hb_subset_plan_t* plan); +#endif +#endif + +#ifndef HB_NO_SUBSET_LAYOUT +typedef hb_hashmap_t> script_langsys_map; + +HB_INTERNAL void +remap_used_mark_sets (hb_subset_plan_t *plan, + hb_map_t& used_mark_sets_map); + +HB_INTERNAL void +layout_nameid_closure (hb_subset_plan_t* plan, + hb_set_t* drop_tables); + +HB_INTERNAL void +layout_populate_gids_to_retain (hb_subset_plan_t* plan, + hb_set_t* drop_tables); + +HB_INTERNAL void +collect_layout_variation_indices (hb_subset_plan_t* plan); +#endif + #endif /* HB_SUBSET_PLAN_HH */ diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-subset.cc openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-subset.cc --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-subset.cc 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-subset.cc 2025-10-13 07:49:24.000000000 +0000 @@ -708,3 +708,107 @@ end: return success ? hb_face_reference (plan->dest) : nullptr; } + + +#ifdef HB_EXPERIMENTAL_API + +#include "hb-ot-cff1-table.hh" + +template +static hb_blob_t* get_charstrings_data(accel_t& accel, hb_codepoint_t glyph_index) { + if (!accel.is_valid()) { + return hb_blob_get_empty (); + } + + hb_ubytes_t bytes = (*accel.charStrings)[glyph_index]; + if (!bytes) { + return hb_blob_get_empty (); + } + + hb_blob_t* cff_blob = accel.get_blob(); + uint32_t length; + const char* cff_data = hb_blob_get_data(cff_blob, &length) ; + + long int offset = (const char*) bytes.arrayZ - cff_data; + if (offset < 0 || offset > INT32_MAX) { + return hb_blob_get_empty (); + } + + return hb_blob_create_sub_blob(cff_blob, (uint32_t) offset, bytes.length); +} + +template +static hb_blob_t* get_charstrings_index(accel_t& accel) { + if (!accel.is_valid()) { + return hb_blob_get_empty (); + } + + const char* charstrings_start = (const char*) accel.charStrings; + unsigned charstrings_length = accel.charStrings->get_size(); + + hb_blob_t* cff_blob = accel.get_blob(); + uint32_t length; + const char* cff_data = hb_blob_get_data(cff_blob, &length) ; + + long int offset = charstrings_start - cff_data; + if (offset < 0 || offset > INT32_MAX) { + return hb_blob_get_empty (); + } + + return hb_blob_create_sub_blob(cff_blob, (uint32_t) offset, charstrings_length); +} + +/** + * hb_subset_cff_get_charstring_data: + * @face: A face object + * @glyph_index: Glyph index to get data for. + * + * Returns the raw outline data from the CFF/CFF2 table associated with the given glyph index. + * + * XSince: EXPERIMENTAL + **/ +HB_EXTERN hb_blob_t* +hb_subset_cff_get_charstring_data(hb_face_t* face, hb_codepoint_t glyph_index) { + return get_charstrings_data(*face->table.cff1, glyph_index); +} + +/** + * hb_subset_cff_get_charstrings_index: + * @face: A face object + * + * Returns the raw CFF CharStrings INDEX from the CFF table. + * + * XSince: EXPERIMENTAL + **/ +HB_EXTERN hb_blob_t* +hb_subset_cff_get_charstrings_index (hb_face_t* face) { + return get_charstrings_index (*face->table.cff1); +} + +/** + * hb_subset_cff2_get_charstring_data: + * @face: A face object + * @glyph_index: Glyph index to get data for. + * + * Returns the raw outline data from the CFF/CFF2 table associated with the given glyph index. + * + * XSince: EXPERIMENTAL + **/ +HB_EXTERN hb_blob_t* +hb_subset_cff2_get_charstring_data(hb_face_t* face, hb_codepoint_t glyph_index) { + return get_charstrings_data(*face->table.cff2, glyph_index); +} + +/** + * hb_subset_cff2_get_charstrings_index: + * @face: A face object + * + * Returns the raw CFF2 CharStrings INDEX from the CFF2 table. + * + * XSince: EXPERIMENTAL + **/ +HB_EXTERN hb_blob_t* +hb_subset_cff2_get_charstrings_index (hb_face_t* face) { + return get_charstrings_index (*face->table.cff2); +} +#endif \ No newline at end of file diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-subset.h openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-subset.h --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-subset.h 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-subset.h 2025-10-13 07:49:24.000000000 +0000 @@ -71,10 +71,12 @@ * in the final subset. * @HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES: If set then the unicode ranges in * OS/2 will not be recalculated. - * @HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE: If set don't perform glyph closure on layout + * @HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE: If set do not perform glyph closure on layout * substitution rules (GSUB). Since: 7.2.0. * @HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS: If set perform IUP delta optimization on the * remaining gvar table's deltas. Since: 8.5.0 + * @HB_SUBSET_FLAGS_NO_BIDI_CLOSURE: If set do not pull mirrored versions of input + * codepoints into the subset. Since: 11.1.0 * @HB_SUBSET_FLAGS_IFTB_REQUIREMENTS: If set enforce requirements on the output subset * to allow it to be used with incremental font transfer IFTB patches. Primarily, * this forces all outline data to use long (32 bit) offsets. Since: EXPERIMENTAL @@ -96,8 +98,9 @@ HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES = 0x00000100u, HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE = 0x00000200u, HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS = 0x00000400u, + HB_SUBSET_FLAGS_NO_BIDI_CLOSURE = 0x00000800u, #ifdef HB_EXPERIMENTAL_API - HB_SUBSET_FLAGS_IFTB_REQUIREMENTS = 0x00000800u, + HB_SUBSET_FLAGS_IFTB_REQUIREMENTS = 0x00001000u, #endif } hb_subset_flags_t; @@ -224,6 +227,23 @@ unsigned language_id, const char *name_str, int str_len); + + +/* +* Raw outline data access +*/ + +HB_EXTERN hb_blob_t* +hb_subset_cff_get_charstring_data (hb_face_t* face, hb_codepoint_t glyph_index); + +HB_EXTERN hb_blob_t* +hb_subset_cff_get_charstrings_index (hb_face_t* face); + +HB_EXTERN hb_blob_t* +hb_subset_cff2_get_charstring_data (hb_face_t* face, hb_codepoint_t glyph_index); + +HB_EXTERN hb_blob_t* +hb_subset_cff2_get_charstrings_index (hb_face_t* face); #endif HB_EXTERN hb_face_t * diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-vector.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-vector.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-vector.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-vector.hh 2025-10-13 07:49:24.000000000 +0000 @@ -90,7 +90,13 @@ { auto iter = hb_iter (o); if (iter.is_random_access_iterator || iter.has_fast_len) - alloc (hb_len (iter), true); + { + if (unlikely (!alloc (hb_len (iter), true))) + return; + unsigned count = hb_len (iter); + for (unsigned i = 0; i < count; i++) + push_has_room (*iter++); + } while (iter) { if (unlikely (!alloc (length + 1))) @@ -436,7 +442,6 @@ new_allocated += (new_allocated >> 1) + 8; } - /* Reallocate */ bool overflows = diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-version.h openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-version.h --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb-version.h 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb-version.h 2025-10-13 07:49:24.000000000 +0000 @@ -41,13 +41,13 @@ * * The major component of the library version available at compile-time. */ -#define HB_VERSION_MAJOR 10 +#define HB_VERSION_MAJOR 11 /** * HB_VERSION_MINOR: * * The minor component of the library version available at compile-time. */ -#define HB_VERSION_MINOR 4 +#define HB_VERSION_MINOR 2 /** * HB_VERSION_MICRO: * @@ -60,7 +60,7 @@ * * A string literal containing the library version available at compile-time. */ -#define HB_VERSION_STRING "10.4.0" +#define HB_VERSION_STRING "11.2.0" /** * HB_VERSION_ATLEAST: diff -Nru openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb.hh openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb.hh --- openjdk-21-21.0.8+9/src/java.desktop/share/native/libharfbuzz/hb.hh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/share/native/libharfbuzz/hb.hh 2025-10-13 07:49:24.000000000 +0000 @@ -89,6 +89,7 @@ #pragma GCC diagnostic error "-Wstring-conversion" #pragma GCC diagnostic error "-Wswitch-enum" #pragma GCC diagnostic error "-Wtautological-overlap-compare" +#pragma GCC diagnostic error "-Wuninitialized" #pragma GCC diagnostic error "-Wunneeded-internal-declaration" #pragma GCC diagnostic error "-Wunused" #pragma GCC diagnostic error "-Wunused-local-typedefs" @@ -230,33 +231,6 @@ #define HB_PASTE(a,b) HB_PASTE1(a,b) -/* Compile-time custom allocator support. */ - -#if !defined(HB_CUSTOM_MALLOC) \ - && defined(hb_malloc_impl) \ - && defined(hb_calloc_impl) \ - && defined(hb_realloc_impl) \ - && defined(hb_free_impl) -#define HB_CUSTOM_MALLOC -#endif - -#ifdef HB_CUSTOM_MALLOC -extern "C" void* hb_malloc_impl(size_t size); -extern "C" void* hb_calloc_impl(size_t nmemb, size_t size); -extern "C" void* hb_realloc_impl(void *ptr, size_t size); -extern "C" void hb_free_impl(void *ptr); -#define hb_malloc hb_malloc_impl -#define hb_calloc hb_calloc_impl -#define hb_realloc hb_realloc_impl -#define hb_free hb_free_impl -#else -#define hb_malloc malloc -#define hb_calloc calloc -#define hb_realloc realloc -#define hb_free free -#endif - - /* * Compiler attributes */ @@ -282,7 +256,7 @@ #define __attribute__(x) #endif -#if defined(__MINGW32__) && (__GNUC__ >= 3) +#if defined(__MINGW32__) && (__GNUC__ >= 3) && !defined(__clang__) #define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (gnu_printf, format_idx, arg_idx))) #elif defined(__GNUC__) && (__GNUC__ >= 3) #define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx))) @@ -491,7 +465,7 @@ # define hb_atexit atexit # else template struct hb_atexit_t { ~hb_atexit_t () { function (); } }; -# define hb_atexit(f) static hb_atexit_t _hb_atexit_##__LINE__; +# define hb_atexit(f) static hb_atexit_t _hb_atexit_##__LINE__ # endif #endif #endif @@ -539,6 +513,29 @@ #define HB_PI 3.14159265358979f #define HB_2_PI (2.f * HB_PI) +/* Compile-time custom allocator support. */ + +#if !defined(HB_CUSTOM_MALLOC) \ + && defined(hb_malloc_impl) \ + && defined(hb_calloc_impl) \ + && defined(hb_realloc_impl) \ + && defined(hb_free_impl) +#define HB_CUSTOM_MALLOC +#endif + +#ifdef HB_CUSTOM_MALLOC +extern "C" void* hb_malloc_impl(size_t size); +extern "C" void* hb_calloc_impl(size_t nmemb, size_t size); +extern "C" void* hb_realloc_impl(void *ptr, size_t size); +extern "C" void hb_free_impl(void *ptr); +#else +#define hb_malloc_impl malloc +#define hb_calloc_impl calloc +#define hb_realloc_impl realloc +#define hb_free_impl free +#endif + + /* Headers we include for everyone. Keep topologically sorted by dependency. * They express dependency amongst themselves, but no other file should include diff -Nru openjdk-21-21.0.8+9/src/java.desktop/unix/classes/sun/awt/PlatformGraphicsInfo.java openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/PlatformGraphicsInfo.java --- openjdk-21-21.0.8+9/src/java.desktop/unix/classes/sun/awt/PlatformGraphicsInfo.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/PlatformGraphicsInfo.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,7 +93,6 @@ No X11 DISPLAY variable was set, or no headful library support was found, - but this program performed an operation which requires it, - """; + but this program performed an operation which requires it."""; } } diff -Nru openjdk-21-21.0.8+9/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java --- openjdk-21-21.0.8+9/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java 2025-10-13 07:49:24.000000000 +0000 @@ -50,7 +50,6 @@ import java.awt.image.WritableRaster; import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStreamReader; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Arrays; @@ -280,14 +279,12 @@ return result; } - private Integer getGnomeShellMajorVersion() { + public Integer getGnomeShellMajorVersion() { try { Process process = new ProcessBuilder("/usr/bin/gnome-shell", "--version") .start(); - try (InputStreamReader isr = new InputStreamReader(process.getInputStream()); - BufferedReader reader = new BufferedReader(isr)) { - + try (BufferedReader reader = process.inputReader()) { if (process.waitFor(2, SECONDS) && process.exitValue() == 0) { String line = reader.readLine(); if (line != null) { diff -Nru openjdk-21-21.0.8+9/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java --- openjdk-21-21.0.8+9/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,15 +36,13 @@ import sun.awt.X11GraphicsConfig; import sun.awt.X11GraphicsDevice; import sun.awt.screencast.ScreencastHelper; +import sun.awt.screencast.XdgDesktopPortal; import sun.security.action.GetPropertyAction; @SuppressWarnings("removal") final class XRobotPeer implements RobotPeer { private static final boolean tryGtk; - private static final String screenshotMethod; - private static final String METHOD_X11 = "x11"; - private static final String METHOD_SCREENCAST = "dbusScreencast"; static { loadNativeLibraries(); @@ -54,20 +52,6 @@ new GetPropertyAction("awt.robot.gtk", "true") )); - - boolean isOnWayland = false; - - if (Toolkit.getDefaultToolkit() instanceof SunToolkit sunToolkit) { - isOnWayland = sunToolkit.isRunningOnWayland(); - } - - screenshotMethod = AccessController.doPrivileged( - new GetPropertyAction( - "awt.robot.screenshotMethod", - isOnWayland - ? METHOD_SCREENCAST - : METHOD_X11 - )); } private static volatile boolean useGtk; @@ -92,39 +76,63 @@ @Override public void mouseMove(int x, int y) { mouseMoveImpl(xgc, xgc.scaleUp(x), xgc.scaleUp(y)); + if (XdgDesktopPortal.isRemoteDesktop() && ScreencastHelper.isAvailable()) { + // We still call mouseMoveImpl on purpose to change the mouse position + // within the XWayland server so that we can retrieve it later. + ScreencastHelper.remoteDesktopMouseMove(xgc.scaleUp(x), xgc.scaleUp(y)); + } } @Override public void mousePress(int buttons) { - mousePressImpl(buttons); + if (XdgDesktopPortal.isRemoteDesktop() && ScreencastHelper.isAvailable()) { + ScreencastHelper.remoteDesktopMouseButton(true, buttons); + } else { + mousePressImpl(buttons); + } } @Override public void mouseRelease(int buttons) { - mouseReleaseImpl(buttons); + if (XdgDesktopPortal.isRemoteDesktop() && ScreencastHelper.isAvailable()) { + ScreencastHelper.remoteDesktopMouseButton(false, buttons); + } else { + mouseReleaseImpl(buttons); + } } @Override public void mouseWheel(int wheelAmt) { - mouseWheelImpl(wheelAmt); + if (XdgDesktopPortal.isRemoteDesktop() && ScreencastHelper.isAvailable()) { + ScreencastHelper.remoteDesktopMouseWheel(wheelAmt); + } else { + mouseWheelImpl(wheelAmt); + } } @Override public void keyPress(int keycode) { - keyPressImpl(keycode); + if (XdgDesktopPortal.isRemoteDesktop() && ScreencastHelper.isAvailable()) { + ScreencastHelper.remoteDesktopKey(true, keycode); + } else { + keyPressImpl(keycode); + } } @Override public void keyRelease(int keycode) { - keyReleaseImpl(keycode); + if (XdgDesktopPortal.isRemoteDesktop() && ScreencastHelper.isAvailable()) { + ScreencastHelper.remoteDesktopKey(false, keycode); + } else { + keyReleaseImpl(keycode); + } } @Override public int getRGBPixel(int x, int y) { int[] pixelArray = new int[1]; - if (screenshotMethod.equals(METHOD_SCREENCAST) - && ScreencastHelper.isAvailable()) { - + if ((XdgDesktopPortal.isScreencast() + || XdgDesktopPortal.isRemoteDesktop()) && ScreencastHelper.isAvailable()) { ScreencastHelper.getRGBPixels(x, y, 1, 1, pixelArray); } else { getRGBPixelsImpl(xgc, x, y, 1, 1, pixelArray, useGtk); @@ -135,8 +143,8 @@ @Override public int[] getRGBPixels(Rectangle bounds) { int[] pixelArray = new int[bounds.width * bounds.height]; - if (screenshotMethod.equals(METHOD_SCREENCAST) - && ScreencastHelper.isAvailable()) { + if ((XdgDesktopPortal.isScreencast() + || XdgDesktopPortal.isRemoteDesktop()) && ScreencastHelper.isAvailable()) { ScreencastHelper.getRGBPixels(bounds.x, bounds.y, bounds.width, bounds.height, diff -Nru openjdk-21-21.0.8+9/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java --- openjdk-21-21.0.8+9/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -142,6 +142,8 @@ import sun.awt.X11GraphicsEnvironment; import sun.awt.XSettings; import sun.awt.datatransfer.DataTransferer; +import sun.awt.screencast.ScreencastHelper; +import sun.awt.screencast.XdgDesktopPortal; import sun.awt.util.PerformanceLogger; import sun.awt.util.ThreadGroupUtils; import sun.font.FontConfigManager; @@ -1565,16 +1567,21 @@ awtLock(); try { if (numberOfButtons == 0) { - numberOfButtons = getNumberOfButtonsImpl(); - numberOfButtons = (numberOfButtons > MAX_BUTTONS_SUPPORTED)? MAX_BUTTONS_SUPPORTED : numberOfButtons; - //4th and 5th buttons are for wheel and shouldn't be reported as buttons. - //If we have more than 3 physical buttons and a wheel, we report N-2 buttons. - //If we have 3 physical buttons and a wheel, we report 3 buttons. - //If we have 1,2,3 physical buttons, we report it as is i.e. 1,2 or 3 respectively. - if (numberOfButtons >=5) { - numberOfButtons -= 2; - } else if (numberOfButtons == 4 || numberOfButtons ==5){ + if (XdgDesktopPortal.isRemoteDesktop() + && ScreencastHelper.isAvailable()) { numberOfButtons = 3; + } else { + numberOfButtons = getNumberOfButtonsImpl(); + numberOfButtons = (numberOfButtons > MAX_BUTTONS_SUPPORTED) ? MAX_BUTTONS_SUPPORTED : numberOfButtons; + //4th and 5th buttons are for wheel and shouldn't be reported as buttons. + //If we have more than 3 physical buttons and a wheel, we report N-2 buttons. + //If we have 3 physical buttons and a wheel, we report 3 buttons. + //If we have 1,2,3 physical buttons, we report it as is i.e. 1,2 or 3 respectively. + if (numberOfButtons >= 5) { + numberOfButtons -= 2; + } else if (numberOfButtons == 4 || numberOfButtons == 5) { + numberOfButtons = 3; + } } } //Assume don't have to re-query the number again and again. diff -Nru openjdk-21-21.0.8+9/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java --- openjdk-21-21.0.8+9/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java 2025-10-13 07:49:24.000000000 +0000 @@ -339,7 +339,7 @@ private static native void enterFullScreenExclusive(long window); private static native void exitFullScreenExclusive(long window); - private static native boolean initXrandrExtension(); + private static native boolean initXrandrExtension(boolean useOldConfigDisplayMode); private static native DisplayMode getCurrentDisplayMode(int screen); private static native void enumDisplayModes(int screen, ArrayList modes); @@ -356,10 +356,11 @@ */ private static synchronized boolean isXrandrExtensionSupported() { if (xrandrExtSupported == null) { - xrandrExtSupported = - Boolean.valueOf(initXrandrExtension()); + boolean useOldConfigDisplayMode = + Boolean.getBoolean("awt.x11useOldConfigDisplayMode"); + xrandrExtSupported = initXrandrExtension(useOldConfigDisplayMode); } - return xrandrExtSupported.booleanValue(); + return xrandrExtSupported; } @Override diff -Nru openjdk-21-21.0.8+9/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java --- openjdk-21-21.0.8+9/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,7 @@ import java.util.Set; import java.util.Timer; import java.util.TimerTask; +import java.util.function.Function; import java.util.stream.IntStream; /** @@ -54,10 +55,13 @@ static final boolean SCREENCAST_DEBUG; private static final boolean IS_NATIVE_LOADED; - private static final int ERROR = -1; private static final int DENIED = -11; private static final int OUT_OF_BOUNDS = -12; + private static final int NO_STREAMS = -13; + + private static final int XDG_METHOD_SCREENCAST = 0; + private static final int XDG_METHOD_REMOTE_DESKTOP = 1; private static final int DELAY_BEFORE_SESSION_CLOSE = 2000; @@ -66,8 +70,7 @@ = new Timer("auto-close screencast session", true); - private ScreencastHelper() { - } + private ScreencastHelper() {} static { SCREENCAST_DEBUG = Boolean.parseBoolean( @@ -80,9 +83,16 @@ boolean loadFailed = false; + boolean shouldLoadNative = XdgDesktopPortal.isRemoteDesktop() + || XdgDesktopPortal.isScreencast(); + + int methodId = XdgDesktopPortal.isScreencast() + ? XDG_METHOD_SCREENCAST + : XDG_METHOD_REMOTE_DESKTOP; + if (!(Toolkit.getDefaultToolkit() instanceof UNIXToolkit tk && tk.loadGTK()) - || !loadPipewire(SCREENCAST_DEBUG)) { + || !(shouldLoadNative && loadPipewire(methodId, SCREENCAST_DEBUG))) { System.err.println( "Could not load native libraries for ScreencastHelper" @@ -98,7 +108,7 @@ return IS_NATIVE_LOADED; } - private static native boolean loadPipewire(boolean screencastDebug); + private static native boolean loadPipewire(int method, boolean isDebug); private static native int getRGBPixelsImpl( int x, int y, int width, int height, @@ -195,7 +205,7 @@ if (retVal >= 0) { // we have received a screen data return; - } else if (!checkReturnValue(retVal)) { + } else if (!checkReturnValue(retVal, true)) { return; } // else, try other tokens } @@ -209,25 +219,72 @@ null ); - checkReturnValue(retVal); + checkReturnValue(retVal, true); } - private static boolean checkReturnValue(int retVal) { + private static boolean checkReturnValue(int retVal, + boolean throwException) { if (retVal == DENIED) { - // user explicitly denied the capture, no more tries. - throw new SecurityException( - "Screen Capture in the selected area was not allowed" - ); + if (SCREENCAST_DEBUG) { + System.err.println("robot action: access denied by user."); + } + if (throwException) { + // user explicitly denied the capture, no more tries. + throw new SecurityException( + "Screen Capture in the selected area was not allowed" + ); + } } else if (retVal == ERROR) { if (SCREENCAST_DEBUG) { - System.err.println("Screen capture failed."); + System.err.println("robot action: failed."); } } else if (retVal == OUT_OF_BOUNDS) { if (SCREENCAST_DEBUG) { System.err.println( "Token does not provide access to requested area."); } + } else if (retVal == NO_STREAMS) { + if (SCREENCAST_DEBUG) { + System.err.println("robot action: no streams available"); + } } return retVal != ERROR; } + + private static void performWithToken(Function func) { + if (!XdgDesktopPortal.isRemoteDesktop() || !IS_NATIVE_LOADED) return; + + timerCloseSessionRestart(); + + for (TokenItem tokenItem : TokenStorage.getTokens(getSystemScreensBounds())) { + int retVal = func.apply(tokenItem.token); + + if (retVal >= 0 || !checkReturnValue(retVal, false)) { + return; + } + } + + checkReturnValue(func.apply(null), false); + } + + public static synchronized void remoteDesktopMouseMove(int x, int y) { + performWithToken((token) -> remoteDesktopMouseMoveImpl(x, y, token)); + } + + public static synchronized void remoteDesktopMouseButton(boolean isPress, int buttons) { + performWithToken((token) -> remoteDesktopMouseButtonImpl(isPress, buttons, token)); + } + + public static synchronized void remoteDesktopMouseWheel(int wheel) { + performWithToken((token) -> remoteDesktopMouseWheelImpl(wheel, token)); + } + + public static synchronized void remoteDesktopKey(boolean isPress, int key) { + performWithToken((token) -> remoteDesktopKeyImpl(isPress, key, token)); + } + + private static synchronized native int remoteDesktopMouseMoveImpl(int x, int y, String token); + private static synchronized native int remoteDesktopMouseButtonImpl(boolean isPress, int buttons, String token); + private static synchronized native int remoteDesktopMouseWheelImpl(int wheelAmt, String token); + private static synchronized native int remoteDesktopKeyImpl(boolean isPress, int key, String token); } diff -Nru openjdk-21-21.0.8+9/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java --- openjdk-21-21.0.8+9/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,6 +69,9 @@ private static final String REL_NAME_SECONDARY = ".awt/robot/screencast-tokens.properties"; + private static final String REL_RD_NAME = + ".java/robot/remote-desktop-tokens.properties"; + private static final Properties PROPS = new Properties(); private static final Path PROPS_PATH; private static final Path PROP_FILENAME; @@ -107,11 +110,18 @@ return null; } - Path path = Path.of(userHome, REL_NAME); - Path secondaryPath = Path.of(userHome, REL_NAME_SECONDARY); + Path path; + Path secondaryPath = null; + + if (XdgDesktopPortal.isRemoteDesktop()) { + path = Path.of(userHome, REL_RD_NAME); + } else { + path = Path.of(userHome, REL_NAME); + secondaryPath = Path.of(userHome, REL_NAME_SECONDARY); + } boolean copyFromSecondary = !Files.isWritable(path) - && Files.isWritable(secondaryPath); + && secondaryPath != null && Files.isWritable(secondaryPath); Path workdir = path.getParent(); diff -Nru openjdk-21-21.0.8+9/src/java.desktop/unix/classes/sun/awt/screencast/XdgDesktopPortal.java openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/screencast/XdgDesktopPortal.java --- openjdk-21-21.0.8+9/src/java.desktop/unix/classes/sun/awt/screencast/XdgDesktopPortal.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/unix/classes/sun/awt/screencast/XdgDesktopPortal.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.awt.screencast; + +import sun.awt.SunToolkit; +import sun.awt.UNIXToolkit; + +import java.awt.Toolkit; +import java.security.AccessController; +import sun.security.action.GetPropertyAction; + +public class XdgDesktopPortal { + private static final String METHOD_X11 = "x11"; + private static final String METHOD_SCREENCAST = "dbusScreencast"; + private static final String METHOD_REMOTE_DESKTOP = "dbusRemoteDesktop"; + + private static final String method; + private static final boolean isRemoteDesktop; + private static final boolean isScreencast; + + private XdgDesktopPortal() {} + + static { + boolean isOnWayland = false; + + if (Toolkit.getDefaultToolkit() instanceof SunToolkit sunToolkit) { + isOnWayland = sunToolkit.isRunningOnWayland(); + } + + String defaultMethod = METHOD_X11; + if (isOnWayland) { + Integer gnomeShellVersion = null; + + UNIXToolkit toolkit = (UNIXToolkit) Toolkit.getDefaultToolkit(); + if ("gnome".equals(toolkit.getDesktop())) { + gnomeShellVersion = toolkit.getGnomeShellMajorVersion(); + } + + defaultMethod = (gnomeShellVersion != null && gnomeShellVersion >= 47) + ? METHOD_REMOTE_DESKTOP + : METHOD_SCREENCAST; + } + + @SuppressWarnings("removal") + String m = AccessController.doPrivileged( + new GetPropertyAction( + "awt.robot.screenshotMethod", defaultMethod + )); + + if (!METHOD_REMOTE_DESKTOP.equals(m) + && !METHOD_SCREENCAST.equals(m) + && !METHOD_X11.equals(m)) { + m = defaultMethod; + } + + isRemoteDesktop = METHOD_REMOTE_DESKTOP.equals(m); + isScreencast = METHOD_SCREENCAST.equals(m); + method = m; + + } + + public static String getMethod() { + return method; + } + + public static boolean isRemoteDesktop() { + return isRemoteDesktop; + } + + public static boolean isScreencast() { + return isScreencast; + } +} diff -Nru openjdk-21-21.0.8+9/src/java.desktop/unix/native/common/awt/awt_GraphicsEnv.h openjdk-21-21.0.9+10/src/java.desktop/unix/native/common/awt/awt_GraphicsEnv.h --- openjdk-21-21.0.8+9/src/java.desktop/unix/native/common/awt/awt_GraphicsEnv.h 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/unix/native/common/awt/awt_GraphicsEnv.h 2025-10-13 07:49:24.000000000 +0000 @@ -62,4 +62,11 @@ jfieldID bitsPerPixel; }; +#define MAX_DISPLAY_MODES 256 +typedef struct { + unsigned int width; + unsigned int height; + jint refresh; +} DisplayMode; + #endif /* _AWT_GRAPHICSENV_H_ */ diff -Nru openjdk-21-21.0.8+9/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c --- openjdk-21-21.0.8+9/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c 2025-10-13 07:49:24.000000000 +0000 @@ -55,6 +55,7 @@ #include "gdefs.h" #include #include "Trace.h" +#include int awt_numScreens; /* Xinerama-aware number of screens */ @@ -76,6 +77,8 @@ jmethodID awtNotifyAllMID = NULL; jboolean awtLockInited = JNI_FALSE; +static Bool useNewConfigDisplayMode = True; + /** Convenience macro for loading the lock-related method IDs. */ #define GET_STATIC_METHOD(klass, method_id, method_name, method_sig) \ do { \ @@ -1508,6 +1511,20 @@ typedef void (*XRRFreeCrtcInfoType)(XRRCrtcInfo *crtcInfo); +typedef void (*XRRSetScreenSizeType)(Display *dpy, Window window, + int width, int height, + int mmWidth, int mmHeight); + +typedef Status (*XRRSetCrtcConfigType)(Display *dpy, + XRRScreenResources *resources, + RRCrtc crtc, + Time timestamp, + int x, int y, + RRMode mode, + Rotation rotation, + RROutput *outputs, + int noutputs); + static XRRQueryVersionType awt_XRRQueryVersion; static XRRGetScreenInfoType awt_XRRGetScreenInfo; static XRRFreeScreenConfigInfoType awt_XRRFreeScreenConfigInfo; @@ -1523,6 +1540,8 @@ static XRRFreeOutputInfoType awt_XRRFreeOutputInfo; static XRRGetCrtcInfoType awt_XRRGetCrtcInfo; static XRRFreeCrtcInfoType awt_XRRFreeCrtcInfo; +static XRRSetScreenSizeType awt_XRRSetScreenSize; +static XRRSetCrtcConfigType awt_XRRSetCrtcConfig; #define LOAD_XRANDR_FUNC(f) \ do { \ @@ -1600,6 +1619,8 @@ LOAD_XRANDR_FUNC(XRRFreeOutputInfo); LOAD_XRANDR_FUNC(XRRGetCrtcInfo); LOAD_XRANDR_FUNC(XRRFreeCrtcInfo); + LOAD_XRANDR_FUNC(XRRSetScreenSize); + LOAD_XRANDR_FUNC(XRRSetCrtcConfig); return JNI_TRUE; } @@ -1700,11 +1721,11 @@ /* * Class: sun_awt_X11GraphicsDevice * Method: initXrandrExtension - * Signature: ()Z + * Signature: (Z)Z */ JNIEXPORT jboolean JNICALL Java_sun_awt_X11GraphicsDevice_initXrandrExtension - (JNIEnv *env, jclass x11gd) + (JNIEnv *env, jclass x11gd, jboolean useOldConfigDisplayMode) { #if defined(NO_XRANDR) return JNI_FALSE; @@ -1720,10 +1741,305 @@ } AWT_FLUSH_UNLOCK(); + useNewConfigDisplayMode = !useOldConfigDisplayMode; + return ret; #endif /* NO_XRANDR */ } +// --------------------------------------------------- +// display mode change via XRRSetCrtcConfig +// --------------------------------------------------- +#if !defined(NO_XRANDR) +static jint refreshRateFromModeInfo(const XRRModeInfo *modeInfo) { + if (!modeInfo->hTotal || !modeInfo->vTotal) { + return 0; + } + + double vTotal = modeInfo->vTotal; + + if (modeInfo->modeFlags & RR_Interlace) { + vTotal /= 2; + } + + if (modeInfo->modeFlags & RR_DoubleScan) { + vTotal *= 2; + } + + return (jint) round((double) modeInfo->dotClock / (vTotal * (double) modeInfo->hTotal)); +} + +static inline Bool isLandscapeOrientation(XRRCrtcInfo* info) { + if (!info) { + return True; + } + return info->rotation == RR_Rotate_0 || info->rotation == RR_Rotate_180; +} + +static Bool xrrGetInfoForScreen(XRRScreenResources *res, + int screen, + XRRCrtcInfo **outCrtcInfo, + XRROutputInfo **outOutputInfo) { + if (!res) { + return False; + } + + int screenX = 0; + int screenY = 0; + + if (usingXinerama) { + int nscreens = 0; + XineramaScreenInfo *screens = XineramaQueryScreens(awt_display, &nscreens); + + if (!screens) { + return False; + } + + if (screen >= nscreens) { + XFree(screens); + return False; + } + + XineramaScreenInfo xScreenInfo = screens[screen]; + + screenX = xScreenInfo.x_org; + screenY= xScreenInfo.y_org; + + XFree(screens); + } + + for (int i = 0; i < res->noutput; ++i) { + XRROutputInfo *output = awt_XRRGetOutputInfo(awt_display, res, res->outputs[i]); + if (!output) { + continue; + } + if (output->connection == RR_Connected && output->crtc) { + // output is connected and has an active mode + XRRCrtcInfo *crtcInfo = awt_XRRGetCrtcInfo(awt_display, res, output->crtc); + if (crtcInfo) { + if (crtcInfo->mode != None + && crtcInfo->x == screenX + && crtcInfo->y == screenY) { + if (outCrtcInfo) { + *outCrtcInfo = crtcInfo; + } else { + awt_XRRFreeCrtcInfo(crtcInfo); + } + if (outOutputInfo) { + *outOutputInfo = output; + } else { + awt_XRRFreeOutputInfo(output); + } + return True; + } + awt_XRRFreeCrtcInfo(crtcInfo); + } + } + awt_XRRFreeOutputInfo(output); + } + + return False; +} + +static jobject xrrGetCurrentDisplayMode(JNIEnv* env, int screen) { + XRRScreenResources *res = awt_XRRGetScreenResources(awt_display, DefaultRootWindow(awt_display)); + if (!res) { + return NULL; + } + + XRRCrtcInfo* currentCrtcInfo = NULL; + if (!xrrGetInfoForScreen(res, screen, ¤tCrtcInfo, NULL)) { + goto cleanup; + } + + if (!currentCrtcInfo || currentCrtcInfo->mode == None) { + goto cleanup; + } + + for (int i = 0; i < res->nmode; ++i) { + if (res->modes[i].id == currentCrtcInfo->mode) { + XRRModeInfo mode = res->modes[i]; + DisplayMode dm = { + mode.width, + mode.height, + refreshRateFromModeInfo(&mode) + }; + + Bool isLandscape = isLandscapeOrientation(currentCrtcInfo); + + jint resultWidth = isLandscape ? (jint) dm.width : (jint) dm.height; + jint resultHeight = isLandscape ? (jint) dm.height : (jint) dm.width; + + jobject displayMode = X11GD_CreateDisplayMode(env, + resultWidth, + resultHeight, + BIT_DEPTH_MULTI, + dm.refresh); + + awt_XRRFreeCrtcInfo(currentCrtcInfo); + awt_XRRFreeScreenResources(res); + + return displayMode; + } + } + + cleanup: + if (currentCrtcInfo) { + awt_XRRFreeCrtcInfo(currentCrtcInfo); + } + awt_XRRFreeScreenResources(res); + return NULL; +} + +static Bool isUniqueDisplayMode(DisplayMode seen[], int count, unsigned int width, unsigned int height, int refresh) { + for (int i = 0; i < count; ++i) { + if (seen[i].width == width && + seen[i].height == height && + seen[i].refresh == refresh) { + return False; + } + } + return True; +} + +static void xrrEnumDisplayModes(JNIEnv *env, jobject arrayList, jint screen) { + XRRScreenResources *res = awt_XRRGetScreenResources(awt_display, DefaultRootWindow(awt_display)); + if (!res) { + return; + } + + XRRCrtcInfo *crtcInfo = NULL; + XRROutputInfo *outputInfo = NULL; + if (!xrrGetInfoForScreen(res, screen, &crtcInfo, &outputInfo)) { + goto cleanup; + } + + DisplayMode seenModes[MAX_DISPLAY_MODES]; + int seenCount = 0; + + Bool isLandscape = isLandscapeOrientation(crtcInfo); + + for (int i = 0; i < outputInfo->nmode; ++i) { + RRMode mode_id = outputInfo->modes[i]; + + for (int j = 0; j < res->nmode; ++j) { + if (res->modes[j].id == mode_id) { + XRRModeInfo mode = res->modes[j]; + jint rr = refreshRateFromModeInfo(&mode); + + // The refresh rate is stored as an integer in Java, so we need to round the double value. + // Because of this rounding, duplicate modes may appear. We only keep the first one encountered. + if (isUniqueDisplayMode(seenModes, seenCount, mode.width, mode.height, rr)) { + seenModes[seenCount++] = (DisplayMode) { + mode.width, + mode.height, + rr + }; + X11GD_AddDisplayMode(env, arrayList, + isLandscape ? (jint) mode.width : (jint) mode.height, + isLandscape ? (jint) mode.height : (jint) mode.width, + BIT_DEPTH_MULTI, + rr); + if ((*env)->ExceptionCheck(env)) { + goto cleanup; + } + } + break; + } + } + } + + cleanup: + if (outputInfo) { + awt_XRRFreeOutputInfo(outputInfo); + } + if (crtcInfo) { + awt_XRRFreeCrtcInfo(crtcInfo); + } + awt_XRRFreeScreenResources(res); +} + +static void xrrChangeDisplayMode(jint screen, jint width, jint height, jint refreshRate) { + Drawable root = DefaultRootWindow(awt_display); + + + XRRScreenResources *res = awt_XRRGetScreenResources(awt_display, root); + if (!res) { + return; + } + + XRRCrtcInfo *crtcInfo = NULL; + XRROutputInfo *outputInfo = NULL; + + if (!xrrGetInfoForScreen(res, screen, &crtcInfo, &outputInfo)) { + goto cleanup; + } + + RRMode new_mode = None; + + Bool isLandscape = isLandscapeOrientation(crtcInfo); + + for (int i = 0; i < res->nmode; ++i) { + XRRModeInfo mode = res->modes[i]; + jint rr = refreshRateFromModeInfo(&mode); + + Bool matchW = (isLandscape ? mode.width : mode.height) == (unsigned int) width; + Bool matchH = (isLandscape ? mode.height : mode.width) == (unsigned int) height; + + if (matchW && matchH && rr == refreshRate) { + for (int j = 0; j < outputInfo->nmode; ++j) { + if (mode.id == outputInfo->modes[j]) { + // belongs to our output + new_mode = mode.id; + break; + } + } + if (new_mode != None) { + break; + } + } + } + + if (new_mode == None) { + goto cleanup; + } + + awt_XRRSetCrtcConfig (awt_display, res, outputInfo->crtc, CurrentTime, + 0, 0, None, RR_Rotate_0, NULL, 0); + + int resultMmWidth = outputInfo->mm_width + ? (int) outputInfo->mm_width + : DisplayWidthMM(awt_display, DefaultScreen(awt_display)); + + int resultMmHeight = outputInfo->mm_height + ? (int) outputInfo->mm_height + : XDisplayHeightMM(awt_display, DefaultScreen(awt_display)); + + awt_XRRSetScreenSize(awt_display, root, + width, height, + resultMmWidth, resultMmHeight); + + Status s = awt_XRRSetCrtcConfig(awt_display, res, outputInfo->crtc, + CurrentTime, + crtcInfo->x, crtcInfo->y, + new_mode, crtcInfo->rotation, + crtcInfo->outputs, crtcInfo->noutput); + + cleanup: + if (crtcInfo) { + awt_XRRFreeCrtcInfo(crtcInfo); + } + if (outputInfo) { + awt_XRRFreeOutputInfo(outputInfo); + } + awt_XRRFreeScreenResources(res); +} +#endif + +// --------------------------------------------------- +// display mode change via XRRSetCrtcConfig +// --------------------------------------------------- + /* * Class: sun_awt_X11GraphicsDevice * Method: getCurrentDisplayMode @@ -1736,9 +2052,17 @@ #if defined(NO_XRANDR) return NULL; #else - XRRScreenConfiguration *config; jobject displayMode = NULL; + if (useNewConfigDisplayMode) { + AWT_LOCK(); + displayMode = xrrGetCurrentDisplayMode(env, screen); + AWT_FLUSH_UNLOCK(); + return displayMode; + } + + XRRScreenConfiguration *config; + AWT_LOCK(); if (screen < ScreenCount(awt_display)) { @@ -1789,7 +2113,12 @@ { #if !defined(NO_XRANDR) - AWT_LOCK(); + if (useNewConfigDisplayMode) { + AWT_LOCK(); + xrrEnumDisplayModes(env, arrayList, screen); + AWT_FLUSH_UNLOCK(); + return; + } if (XScreenCount(awt_display) > 0) { @@ -1839,6 +2168,15 @@ jint screen, jint width, jint height, jint refreshRate) { #if !defined(NO_XRANDR) + if (useNewConfigDisplayMode) { + AWT_LOCK(); + XGrabServer(awt_display); + xrrChangeDisplayMode(screen, width, height, refreshRate); + XUngrabServer(awt_display); + AWT_FLUSH_UNLOCK(); + return; + } + jboolean success = JNI_FALSE; XRRScreenConfiguration *config; Drawable root; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c --- openjdk-21-21.0.8+9/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c 2025-10-13 07:49:24.000000000 +0000 @@ -1618,14 +1618,14 @@ if (NULL != pX11IMData->statusWindow) { Window focus = 0; int revert_to; -#if defined(_LP64) && !defined(_LITTLE_ENDIAN) - // The Window value which is used for XGetICValues must be 32bit on BigEndian XOrg's xlib - unsigned int w = 0; -#else Window w = 0; -#endif XGetInputFocus(awt_display, &focus, &revert_to); XGetICValues(pX11IMData->current_ic, XNFocusWindow, &w, NULL); +#if defined(_LP64) && !defined(_LITTLE_ENDIAN) + // On 64bit BigEndian, + // Window value may be stored on high 32bit by XGetICValues via XIM + if (w > 0xffffffffUL) w = w >> 32; +#endif if (RevertToPointerRoot == revert_to && pX11IMData->ic_active != pX11IMData->ic_passive) { if (pX11IMData->current_ic == pX11IMData->ic_active) { @@ -1674,12 +1674,7 @@ { X11InputMethodData *pX11IMData = NULL; char * ret = NULL; -#if defined(__linux__) && defined(_LP64) && !defined(_LITTLE_ENDIAN) - // XIMPreeditState value which is used for XGetICValues must be 32bit on BigEndian XOrg's xlib - unsigned int state = XIMPreeditUnKnown; -#else XIMPreeditState state = XIMPreeditUnKnown; -#endif XVaNestedList pr_atrb; @@ -1695,6 +1690,11 @@ ret = XGetICValues(pX11IMData->current_ic, XNPreeditAttributes, pr_atrb, NULL); XFree((void *)pr_atrb); AWT_UNLOCK(); +#if defined(__linux__) && defined(_LP64) && !defined(_LITTLE_ENDIAN) + // On 64bit BigEndian, + // XIMPreeditState value may be stored on high 32bit by XGetICValues via XIM + if (state > 0xffffffffUL) state = state >> 32; +#endif if ((ret != 0) && ((strcmp(ret, XNPreeditAttributes) == 0) diff -Nru openjdk-21-21.0.8+9/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c --- openjdk-21-21.0.8+9/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -617,11 +617,14 @@ glib_version_2_68 = !fp_glib_check_version(2, 68, 0); if (glib_version_2_68) { + // those function are called only by Screencast / Remote desktop fp_g_string_replace = dl_symbol("g_string_replace"); //since: 2.68 fp_g_uuid_string_is_valid = //since: 2.52 dl_symbol("g_uuid_string_is_valid"); + fp_g_variant_print = dl_symbol("g_variant_print"); // since 2.24 } fp_g_string_printf = dl_symbol("g_string_printf"); + fp_g_strconcat = dl_symbol("g_strconcat"); fp_g_error_free = dl_symbol("g_error_free"); fp_g_unix_fd_list_get = dl_symbol("g_unix_fd_list_get"); @@ -3099,6 +3102,7 @@ gtk->g_variant_new_string = fp_g_variant_new_string; gtk->g_variant_new_boolean = fp_g_variant_new_boolean; gtk->g_variant_new_uint32 = fp_g_variant_new_uint32; + gtk->g_variant_print = fp_g_variant_print; gtk->g_variant_get = fp_g_variant_get; gtk->g_variant_get_string = fp_g_variant_get_string; @@ -3123,6 +3127,7 @@ gtk->g_string_free = fp_g_string_free; gtk->g_string_replace = fp_g_string_replace; gtk->g_string_printf = fp_g_string_printf; + gtk->g_strconcat = fp_g_strconcat; gtk->g_uuid_string_is_valid = fp_g_uuid_string_is_valid; gtk->g_main_context_iteration = fp_g_main_context_iteration; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h --- openjdk-21-21.0.8+9/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -399,6 +399,7 @@ static gchar** (*fp_g_strsplit)(const gchar *string, const gchar *delimiter, gint max_tokens); static void (*fp_g_strfreev)(gchar **str_array); +static gchar* (*fp_g_strconcat)(const gchar* string1, ...); static cairo_surface_t* (*fp_cairo_image_surface_create)(cairo_format_t format, @@ -738,6 +739,8 @@ static GVariant *(*fp_g_variant_new_uint32)(guint32 value); +static gchar *(*fp_g_variant_print) (GVariant* value, gboolean type_annotate); + static void (*fp_g_variant_get)(GVariant *value, const gchar *format_string, ...); diff -Nru openjdk-21-21.0.8+9/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h --- openjdk-21-21.0.8+9/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -678,6 +678,7 @@ GVariant *(*g_variant_new_boolean)(gboolean value); GVariant *(*g_variant_new_uint32)(guint32 value); + gchar *(*g_variant_print)(GVariant* value, gboolean type_annotate); void (*g_variant_get)(GVariant *value, const gchar *format_string, @@ -734,6 +735,8 @@ const gchar *format, ...); + gchar* (*g_strconcat)(const gchar* string1, ...); + gboolean (*g_uuid_string_is_valid)(const gchar *str); diff -Nru openjdk-21-21.0.8+9/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c --- openjdk-21-21.0.8+9/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,12 +30,17 @@ #include #include "jni_util.h" #include "awt.h" + +#ifndef _AIX #include "screencast_pipewire.h" #include "fp_pipewire.h" +#include "java_awt_event_KeyEvent.h" + #include #include "gtk_interface.h" #include "gtk3_interface.h" +#include "canvas.h" int DEBUG_SCREENCAST_ENABLED = FALSE; @@ -50,6 +55,7 @@ struct ScreenSpace screenSpace = {0}; static struct PwLoopData pw = {0}; volatile bool isGtkMainThread = FALSE; +gboolean isRemoteDesktop = FALSE; jclass tokenStorageClass = NULL; jmethodID storeTokenMethodID = NULL; @@ -140,7 +146,7 @@ /** * @return TRUE on success */ -static gboolean initScreencast(const gchar *token, +static gboolean initPortal(const gchar *token, GdkRectangle *affectedBounds, gint affectedBoundsLength) { gboolean isSameToken = !token @@ -167,8 +173,8 @@ if (!initScreenSpace() || !initXdgDesktopPortal() - || (pw.pwFd = getPipewireFd(token, - affectedBounds, + || !initAndStartSession(token, &pw.pwFd) + || (pw.pwFd = getPipewireFd(affectedBounds, affectedBoundsLength)) < 0) { doCleanup(); return FALSE; @@ -801,10 +807,19 @@ * Signature: (IZ)Z */ JNIEXPORT jboolean JNICALL Java_sun_awt_screencast_ScreencastHelper_loadPipewire( - JNIEnv *env, jclass cls, jboolean screencastDebug + JNIEnv *env, jclass cls, jint method, jboolean screencastDebug ) { DEBUG_SCREENCAST_ENABLED = screencastDebug; + if (method != XDG_METHOD_SCREENCAST + && method != XDG_METHOD_REMOTE_DESKTOP) { + return JNI_FALSE; + } + + isRemoteDesktop = method == XDG_METHOD_REMOTE_DESKTOP; + + DEBUG_SCREENCAST("method %d\n", method) + if (!loadSymbols()) { return JNI_FALSE; } @@ -877,7 +892,7 @@ GdkRectangle *affectedScreenBounds, gint affectedBoundsLength ) { - if (!initScreencast(token, affectedScreenBounds, affectedBoundsLength)) { + if (!initPortal(token, affectedScreenBounds, affectedBoundsLength)) { return pw.pwFd; } @@ -948,6 +963,7 @@ const gchar *token = jtoken ? (*env)->GetStringUTFChars(env, jtoken, NULL) : NULL; + JNU_CHECK_EXCEPTION_RETURN(env, RESULT_ERROR); isGtkMainThread = gtk->g_main_context_is_owner(gtk->g_main_context_default()); DEBUG_SCREENCAST( @@ -1040,3 +1056,192 @@ releaseToken(env, jtoken, token); return 0; } + +/* + * Class: sun_awt_screencast_ScreencastHelper + * Method: remoteDesktopMouseMove + * Signature: (IILjava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMouseMoveImpl + (JNIEnv *env, jclass cls, jint jx, jint jy, jstring jtoken) { + + + const gchar *token = jtoken + ? (*env)->GetStringUTFChars(env, jtoken, NULL) + : NULL; + JNU_CHECK_EXCEPTION_RETURN(env, RESULT_ERROR); + + DEBUG_SCREENCAST("moving mouse to\n\t%d %d\n\twith token |%s|\n", jx, jy, token); + + gboolean result = initPortal(token, NULL, 0); + DEBUG_SCREENCAST("init result %b, moving to %d %d\n", result, jx, jy) + + if (result) { + if (!remoteDesktopMouseMove(jx, jy)) { + releaseToken(env, jtoken, token); + return RESULT_DENIED; + } + } + + releaseToken(env, jtoken, token); + + return result ? RESULT_OK : pw.pwFd; +} + +/* + * Class: sun_awt_screencast_ScreencastHelper + * Method: remoteDesktopMouseButtonImpl + * Signature: (ZILjava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMouseButtonImpl + (JNIEnv *env, jclass cls, jboolean isPress, jint buttons, jstring jtoken) { + + const gchar *token = jtoken + ? (*env)->GetStringUTFChars(env, jtoken, NULL) + : NULL; + JNU_CHECK_EXCEPTION_RETURN(env, RESULT_ERROR); + + gboolean result = initPortal(token, NULL, 0); + DEBUG_SCREENCAST("init result %b, mouse pressing %d\n", result, buttons) + + if (result) { + if (!remoteDesktopMouse(isPress, buttons)) { + releaseToken(env, jtoken, token); + return RESULT_DENIED; + } + } + + releaseToken(env, jtoken, token); + + return result ? RESULT_OK : pw.pwFd; +} + +/* + * Class: sun_awt_screencast_ScreencastHelper + * Method: remoteDesktopMouseWheelImpl + * Signature: (ILjava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMouseWheelImpl + (JNIEnv *env, jclass cls, jint jWheelAmt, jstring jtoken) { + + const gchar *token = jtoken + ? (*env)->GetStringUTFChars(env, jtoken, NULL) + : NULL; + JNU_CHECK_EXCEPTION_RETURN(env, RESULT_ERROR); + + gboolean result = initPortal(token, NULL, 0); + DEBUG_SCREENCAST("init result %b, mouse wheel %d\n", result, jWheelAmt) + + if (result) { + if (!remoteDesktopMouseWheel(jWheelAmt)) { + releaseToken(env, jtoken, token); + return RESULT_DENIED; + } + } + + releaseToken(env, jtoken, token); + + return result ? RESULT_OK : pw.pwFd; +} + +static int getNumpadKey(jint jkey) { + switch (jkey) { + case java_awt_event_KeyEvent_VK_NUMPAD0: return XK_KP_Insert; + case java_awt_event_KeyEvent_VK_NUMPAD1: return XK_KP_End; + case java_awt_event_KeyEvent_VK_NUMPAD2: return XK_KP_Down; + case java_awt_event_KeyEvent_VK_NUMPAD3: return XK_KP_Page_Down; + case java_awt_event_KeyEvent_VK_NUMPAD4: return XK_KP_Left; + case java_awt_event_KeyEvent_VK_NUMPAD5: return XK_KP_Begin; + case java_awt_event_KeyEvent_VK_NUMPAD6: return XK_KP_Right; + case java_awt_event_KeyEvent_VK_NUMPAD7: return XK_KP_Home; + case java_awt_event_KeyEvent_VK_NUMPAD8: return XK_KP_Up; + case java_awt_event_KeyEvent_VK_NUMPAD9: return XK_KP_Prior; + case java_awt_event_KeyEvent_VK_DECIMAL: + case java_awt_event_KeyEvent_VK_SEPARATOR: return XK_KP_Delete; + default: return 0; + } +} + +/* + * Class: sun_awt_screencast_ScreencastHelper + * Method: remoteDesktopKeyImpl + * Signature: (ZILjava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopKeyImpl + (JNIEnv *env, jclass cls, jboolean isPress, jint jkey, jstring jtoken) { + + int key = getNumpadKey(jkey); + if (!key) { + AWT_LOCK(); + key = awt_getX11KeySym(jkey); + AWT_UNLOCK(); + } + + if (key == NoSymbol || (*env)->ExceptionCheck(env)) { + return RESULT_ERROR; + } + + const gchar *token = jtoken + ? (*env)->GetStringUTFChars(env, jtoken, NULL) + : NULL; + JNU_CHECK_EXCEPTION_RETURN(env, RESULT_ERROR); + + gboolean result = initPortal(token, NULL, 0); + DEBUG_SCREENCAST("init result %b, key %d -> %d isPress %b\n", result, jkey, key, isPress) + + if (result) { + if (!remoteDesktopKey(isPress, key)) { + releaseToken(env, jtoken, token); + return RESULT_DENIED; + } + } + + releaseToken(env, jtoken, token); + + return result ? RESULT_OK : pw.pwFd; +} + +#else +JNIEXPORT void JNICALL +Java_sun_awt_screencast_ScreencastHelper_closeSession(JNIEnv *env, jclass cls) {} + +JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_getRGBPixelsImpl( + JNIEnv *env, + jclass cls, + jint jx, + jint jy, + jint jwidth, + jint jheight, + jintArray pixelArray, + jintArray affectedScreensBoundsArray, + jstring jtoken +) { + return -1; /* RESULT_ERROR */ +} + +JNIEXPORT jboolean JNICALL Java_sun_awt_screencast_ScreencastHelper_loadPipewire( + JNIEnv *env, jclass cls, jint method, jboolean screencastDebug +) { + return JNI_FALSE; +} + +JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMouseMoveImpl + (JNIEnv *env, jclass cls, jint jx, jint jy, jstring token) { + return -1; +} + +JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMouseButtonImpl + (JNIEnv *env, jclass cls, jboolean isPress, jint buttons, jstring jtoken) { + return -1; +} + +JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMouseWheelImpl + (JNIEnv *env, jclass cls, jint jWheelAmt, jstring jtoken) { + return -1; +} + +JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopKeyImpl + (JNIEnv *env, jclass cls, jboolean isPress, jint jkey, jstring jtoken) { + return -1; +} +#endif diff -Nru openjdk-21-21.0.8+9/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.h openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.h --- openjdk-21-21.0.8+9/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.h 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.h 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,8 @@ void storeRestoreToken(const gchar* oldToken, const gchar* newToken); +void print_gvariant_content(gchar *caption, GVariant *response); + struct ScreenProps { guint32 id; GdkRectangle bounds; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.c openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.c --- openjdk-21-21.0.8+9/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.c 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.c 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,19 +24,26 @@ */ #include "stdlib.h" -#include -#include #include -#include -#include + +#include "java_awt_event_InputEvent.h" + +#ifndef _AIX #include "screencast_pipewire.h" + #include "screencast_portal.h" extern volatile bool isGtkMainThread; +extern gboolean isRemoteDesktop; extern struct ScreenSpace screenSpace; struct XdgDesktopPortalApi *portal = NULL; +extern int DEBUG_SCREENCAST_ENABLED; + +GDBusProxy *getProxy() { + return isRemoteDesktop ? portal->remoteDesktopProxy : portal->screenCastProxy; +} void errHandle( GError *error, @@ -167,26 +174,38 @@ } /** - * Checks screencast protocol version - * @return FALSE if version < 4, or could not be determined + * Checks the version of the Screencast/Remote Desktop protocol + * to determine whether it supports the restore_token. + * @return FALSE if version is below required, or could not be determined */ gboolean checkVersion() { static guint32 version = 0; + + const gchar *interface = isRemoteDesktop + ? PORTAL_IFACE_REMOTE_DESKTOP + : PORTAL_IFACE_SCREENCAST; + if (version == 0) { GError *error = NULL; + GVariant *retVersion = gtk->g_dbus_proxy_call_sync( - portal->screenCastProxy, + getProxy(), "org.freedesktop.DBus.Properties.Get", gtk->g_variant_new("(ss)", - "org.freedesktop.portal.ScreenCast", + interface, "version"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL ); + if (isRemoteDesktop) { + print_gvariant_content("checkVersion Remote Desktop", retVersion); + } else { + print_gvariant_content("checkVersion ScreenCast", retVersion); + } + if (!retVersion) { //no backend on system - DEBUG_SCREENCAST("!!! could not detect the screencast version\n", - NULL); + DEBUG_SCREENCAST("!!! could not detect the %s version\n", interface); return FALSE; } @@ -197,8 +216,7 @@ if (!varVersion){ gtk->g_variant_unref(retVersion); - DEBUG_SCREENCAST("!!! could not get the screencast version\n", - NULL); + DEBUG_SCREENCAST("!!! could not get the %s version\n", interface); return FALSE; } @@ -209,16 +227,22 @@ } - DEBUG_SCREENCAST("ScreenCast protocol version %d\n", version); - if (version < 4) { - DEBUG_SCREENCAST("!!! ScreenCast protocol version %d < 4," + gboolean isVersionOk = isRemoteDesktop + ? version >= PORTAL_MIN_VERSION_REMOTE_DESKTOP + : version >= PORTAL_MIN_VERSION_SCREENCAST; + + if (!isVersionOk) { + DEBUG_SCREENCAST("!!! %s protocol version %d < %d," " session restore is not available\n", - version); + interface, + version, + isRemoteDesktop + ? PORTAL_MIN_VERSION_REMOTE_DESKTOP + : PORTAL_MIN_VERSION_SCREENCAST + ); } - // restore_token was added in version 4, without it, - // user confirmation is required for every screenshot. - return version >= 4; + return isVersionOk; } /** @@ -263,9 +287,9 @@ portal->connection, G_DBUS_PROXY_FLAGS_NONE, NULL, - "org.freedesktop.portal.Desktop", - "/org/freedesktop/portal/desktop", - "org.freedesktop.portal.ScreenCast", + PORTAL_DESKTOP_BUS_NAME, + PORTAL_DESKTOP_OBJECT_PATH, + PORTAL_IFACE_SCREENCAST, NULL, &err ); @@ -274,6 +298,29 @@ DEBUG_SCREENCAST("Failed to get ScreenCast portal: %s", err->message); ERR_HANDLE(err); return FALSE; + } else { + DEBUG_SCREENCAST("%s: connection/sender name %s / %s\n", + "ScreenCast", name, + portal->senderName); + } + + if (isRemoteDesktop) { + portal->remoteDesktopProxy = gtk->g_dbus_proxy_new_sync( + portal->connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + PORTAL_DESKTOP_BUS_NAME, + PORTAL_DESKTOP_OBJECT_PATH, + PORTAL_IFACE_REMOTE_DESKTOP, + NULL, + &err + ); + + if (err) { + DEBUG_SCREENCAST("Failed to get Remote Desktop portal: %s", err->message); + ERR_HANDLE(err); + return FALSE; + } } return checkVersion(); @@ -334,8 +381,8 @@ ) { helper->id = gtk->g_dbus_connection_signal_subscribe( portal->connection, - "org.freedesktop.portal.Desktop", - "org.freedesktop.portal.Request", + PORTAL_DESKTOP_BUS_NAME, + PORTAL_IFACE_REQUEST, "Response", path, NULL, @@ -380,7 +427,8 @@ if (status != 0) { DEBUG_SCREENCAST("Failed to create ScreenCast: %u\n", status); } else { - gtk->g_variant_lookup(result, "session_handle", "s", helper->data); + gboolean returned = gtk->g_variant_lookup(result, "session_handle", "s", helper->data); + DEBUG_SCREENCAST("session_handle returned %b %p\n", returned, helper->data) } helper->isDone = TRUE; @@ -427,6 +475,9 @@ gtk->g_variant_new_string(requestToken) ); + + DEBUG_SCREENCAST("sessionToken %s \n", sessionToken) + gtk->g_variant_builder_add( &builder, "{sv}", @@ -434,8 +485,14 @@ gtk->g_variant_new_string(sessionToken) ); + DEBUG_SCREENCAST("portalScreenCastCreateSession: proxy %s %p (rd: %p / sc: %p)\n", + isRemoteDesktop ? "remoteDesktop" : "screencast", + getProxy(), + portal->remoteDesktopProxy, + portal->screenCastProxy); + GVariant *response = gtk->g_dbus_proxy_call_sync( - portal->screenCastProxy, + getProxy(), "CreateSession", gtk->g_variant_new("(a{sv})", &builder), G_DBUS_CALL_FLAGS_NONE, @@ -444,6 +501,8 @@ &err ); + print_gvariant_content("CreateSession", response); + if (err) { DEBUG_SCREENCAST("Failed to create ScreenCast session: %s\n", err->message); @@ -452,6 +511,8 @@ waitForCallback(&helper); } + DEBUG_SCREENCAST("portal->screenCastSessionHandle %s\n", portal->screenCastSessionHandle); + unregisterScreenCastCallback(&helper); if (response) { gtk->g_variant_unref(response); @@ -497,6 +558,39 @@ callbackEnd(); } +static void callbackRemoteDesktopSelectDevices( + GDBusConnection *connection, + const char *senderName, + const char *objectPath, + const char *interfaceName, + const char *signalName, + GVariant *parameters, + void *data +) { + struct DBusCallbackHelper *helper = data; + + helper->data = (void *) 0; + + uint32_t status; + GVariant* result = NULL; + + gtk->g_variant_get(parameters, "(u@a{sv})", &status, &result); + + if (status != 0) { + DEBUG_SCREENCAST("Failed select devices: %u\n", status); + } else { + helper->data = (void *) 1; + } + + helper->isDone = TRUE; + + if (result) { + gtk->g_variant_unref(result); + } + + callbackEnd(); +} + gboolean portalScreenCastSelectSources(const gchar *token) { GError* err = NULL; @@ -542,25 +636,33 @@ gtk->g_variant_new_uint32(1) ); + // In the case of Remote Desktop, + // we add the restore_token and persist_mode to the SelectDevices call. + // 0: Do not persist (default) // 1: Permissions persist as long as the application is running // 2: Permissions persist until explicitly revoked - gtk->g_variant_builder_add( - &builder, - "{sv}", - "persist_mode", - gtk->g_variant_new_uint32(2) - ); - - if (validateToken(token)) { + if (!isRemoteDesktop) { gtk->g_variant_builder_add( &builder, "{sv}", - "restore_token", - gtk->g_variant_new_string(token) + "persist_mode", + gtk->g_variant_new_uint32(2) ); } + if (!isRemoteDesktop) { + if (validateToken(token)) { + DEBUG_SCREENCAST(">>> adding token %s\n", token); + gtk->g_variant_builder_add( + &builder, + "{sv}", + "restore_token", + gtk->g_variant_new_string(token) + ); + } + } + GVariant *response = gtk->g_dbus_proxy_call_sync( portal->screenCastProxy, "SelectSources", @@ -571,6 +673,8 @@ &err ); + print_gvariant_content("SelectSources", response); + if (err) { DEBUG_SCREENCAST("Failed to call SelectSources: %s\n", err->message); ERR_HANDLE(err); @@ -621,6 +725,15 @@ G_VARIANT_TYPE_ARRAY ); + print_gvariant_content("Streams", streams); + + if (!streams) { + DEBUG_SCREENCAST("No streams available with current token\n", NULL); + startHelper->result = RESULT_NO_STREAMS; + helper->isDone = TRUE; + return; + } + GVariantIter iter; gtk->g_variant_iter_init( &iter, @@ -658,9 +771,7 @@ helper->isDone = TRUE; - if (streams) { - gtk->g_variant_unref(streams); - } + gtk->g_variant_unref(streams); callbackEnd(); } @@ -703,7 +814,7 @@ ); GVariant *response = gtk->g_dbus_proxy_call_sync( - portal->screenCastProxy, + getProxy(), "Start", gtk->g_variant_new("(osa{sv})", portal->screenCastSessionHandle, "", &builder), G_DBUS_CALL_FLAGS_NONE, @@ -712,6 +823,8 @@ &err ); + print_gvariant_content("Start", response); + if (err) { DEBUG_SCREENCAST("Failed to start session: %s\n", err->message); ERR_HANDLE(err); @@ -805,9 +918,9 @@ if (portal->screenCastSessionHandle) { gtk->g_dbus_connection_call_sync( portal->connection, - "org.freedesktop.portal.Desktop", + PORTAL_DESKTOP_BUS_NAME, portal->screenCastSessionHandle, - "org.freedesktop.portal.Session", + PORTAL_IFACE_SESSION, "Close", NULL, NULL, @@ -886,33 +999,140 @@ return true; } +gboolean remoteDesktopSelectDevicesIfNeeded(const gchar* token) { + if (!isRemoteDesktop || !portal->remoteDesktopProxy) { + DEBUG_SCREENCAST("Skipping, remote desktop is not selected \n", NULL); + return TRUE; + } + + GError* err = NULL; + + gchar *requestPath = NULL; + gchar *requestToken = NULL; + + struct DBusCallbackHelper helper = {0}; + + + updateRequestPath( + &requestPath, + &requestToken + ); + + registerScreenCastCallback( + requestPath, + &helper, + callbackRemoteDesktopSelectDevices + ); + + GVariantBuilder builder; + + gtk->g_variant_builder_init( + &builder, + G_VARIANT_TYPE_VARDICT + ); + + gtk->g_variant_builder_add( + &builder, + "{sv}", "handle_token", + gtk->g_variant_new_string(requestToken) + ); + + // 1: KEYBOARD + // 2: POINTER + // 4: TOUCHSCREEN + gtk->g_variant_builder_add( + &builder, "{sv}", "types", + gtk->g_variant_new_uint32(1 | 2) + ); + + // 0: Do not persist (default) + // 1: Permissions persist as long as the application is running + // 2: Permissions persist until explicitly revoked + gtk->g_variant_builder_add( + &builder, + "{sv}", + "persist_mode", + gtk->g_variant_new_uint32(2) + ); + + if (validateToken(token)) { + gtk->g_variant_builder_add( + &builder, + "{sv}", + "restore_token", + gtk->g_variant_new_string(token) + ); + } + + GVariant *response = gtk->g_dbus_proxy_call_sync( + portal->remoteDesktopProxy, + "SelectDevices", + gtk->g_variant_new("(oa{sv})", portal->screenCastSessionHandle, &builder), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &err + ); + + print_gvariant_content("SelectDevices", response); + + if (err) { + DEBUG_SCREENCAST("Failed to call SelectDevices: %s\n", err->message); + ERR_HANDLE(err); + } else { + waitForCallback(&helper); + } + + unregisterScreenCastCallback(&helper); + if (response) { + gtk->g_variant_unref(response); + } + + free(requestPath); + free(requestToken); + + return helper.data != NULL; +} + +gboolean initAndStartSession(const gchar *token, int *retVal) { + + *retVal = RESULT_ERROR; -int getPipewireFd(const gchar *token, - GdkRectangle *affectedBounds, - gint affectedBoundsLength) { if (!portalScreenCastCreateSession()) { DEBUG_SCREENCAST("Failed to create ScreenCast session\n", NULL); - return RESULT_ERROR; + return FALSE; } if (!portalScreenCastSelectSources(token)) { DEBUG_SCREENCAST("Failed to select sources\n", NULL); - return RESULT_ERROR; + return FALSE; + } + + if (!remoteDesktopSelectDevicesIfNeeded(token)) { + return FALSE; } ScreenCastResult startResult = portalScreenCastStart(token); DEBUG_SCREENCAST("portalScreenCastStart result |%i|\n", startResult); + if (startResult != RESULT_OK) { - DEBUG_SCREENCAST("Failed to start\n", NULL); - return startResult; - } else { - if (!checkCanCaptureAllRequiredScreens(affectedBounds, - affectedBoundsLength)) { - DEBUG_SCREENCAST("The location of the screens has changed, " - "the capture area is outside the allowed " - "area.\n", NULL) - return RESULT_OUT_OF_BOUNDS; - } + DEBUG_SCREENCAST("Failed to start %d\n", startResult); + *retVal = startResult; + return FALSE; + } + + *retVal = RESULT_OK; + return TRUE; +} + +int getPipewireFd(GdkRectangle *affectedBounds, + gint affectedBoundsLength) { + if (!checkCanCaptureAllRequiredScreens(affectedBounds, + affectedBoundsLength)) { + DEBUG_SCREENCAST("The location of the screens has changed, " + "the capture area is outside the allowed " + "area.\n", NULL) + return RESULT_OUT_OF_BOUNDS; } DEBUG_SCREENCAST("--- portalScreenCastStart\n", NULL); @@ -925,3 +1145,182 @@ DEBUG_SCREENCAST("pwFd %i\n", pipewireFd); return pipewireFd; } + + +void print_gvariant_content(gchar *caption, GVariant *response) { + if (!DEBUG_SCREENCAST_ENABLED) { + return; + } + + gchar *str = NULL; + if (response != NULL) { + str = gtk->g_variant_print(response, TRUE); + } + + DEBUG_SCREENCAST("%s response:\n\t%s\n", + caption, str); + + gtk->g_free(str); +} + +static gboolean callRemoteDesktop(const gchar* methodName, GVariant *params) { + GError *err = NULL; + GVariantBuilder builder; + gtk->g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT); + + GVariant *response = gtk->g_dbus_proxy_call_sync( + portal->remoteDesktopProxy, + methodName, + params, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &err + ); + + gchar * caption = gtk->g_strconcat("callRemoteDesktop ", methodName, NULL); + print_gvariant_content(caption, response); + gtk->g_free(caption); + + DEBUG_SCREENCAST("%s: response %p err %p\n", methodName, response, err); + + if (err) { + DEBUG_SCREENCAST("Failed to call %s: %s\n", methodName, err->message); + ERR_HANDLE(err); + + // e.g. user denied mouse keyboard/interaction + return FALSE; + } + + return TRUE; +} + +void clampCoordsIfNeeded(int *x, int *y) { + if (screenSpace.screenCount <= 0 || x == NULL || y == NULL) { + return; + } + + GdkRectangle s0 = screenSpace.screens[0].bounds; + int minX = s0.x; + int minY = s0.y; + int maxX = s0.x + s0.width; + int maxY = s0.y + s0.height; + + for (int i = 1; i < screenSpace.screenCount; ++i) { + GdkRectangle s = screenSpace.screens[i].bounds; + if (s.x < minX) minX = s.x; + if (s.y < minY) minY = s.y; + if (s.x + s.width > maxX) maxX = s.x + s.width; + if (s.y + s.height > maxY) maxY = s.y + s.height; + } + + if (*x < minX) { + *x = minX; + } else if (*x > maxX) { + *x = maxX - 1; + } + + if (*y < minY) { + *y = minY; + } else if (*y > maxY) { + *y = maxY - 1; + } +} + +gboolean remoteDesktopMouseMove(int x, int y) { + guint32 streamId = 0; + int relX = -1; + int relY = -1; + + DEBUG_SCREENCAST("mouseMove %d %d\n", x, y); + clampCoordsIfNeeded(&x, &y); + DEBUG_SCREENCAST("after clamping %d %d\n", x, y); + + for (int i = 0; i < screenSpace.screenCount; ++i) { + struct ScreenProps *screenProps = &screenSpace.screens[i]; + GdkRectangle rect = screenProps->bounds; + + if (x >= rect.x && + y >= rect.y && + x < rect.x + rect.width && + y < rect.y + rect.height) { + streamId = screenProps->id; + relX = x - rect.x; + relY = y - rect.y; + + DEBUG_SCREENCAST("screenId#%i point %dx%d (rel %i %i) inside of screen (%d, %d, %d, %d)\n", + streamId, + x, y, relX, relY, + rect.x, rect.y, rect.width, rect.height); + + break; + } + } + + if (streamId == 0) { + DEBUG_SCREENCAST("outside of available screens\n", NULL); + return TRUE; + } + + GVariantBuilder builder; + gtk->g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT); + GVariant *params = gtk->g_variant_new("(oa{sv}udd)", portal->screenCastSessionHandle, &builder, + streamId, (double) relX, (double) relY); + return callRemoteDesktop("NotifyPointerMotionAbsolute", params); +} + +gboolean callRemoteDesktopNotifyPointerButton(gboolean isPress, int evdevButton) { + DEBUG_SCREENCAST("isPress %d evdevButton %d\n", isPress, evdevButton); + + GVariantBuilder builder; + gtk->g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); + GVariant *params = gtk->g_variant_new("(oa{sv}iu)", + portal->screenCastSessionHandle, &builder, evdevButton, isPress); + return callRemoteDesktop("NotifyPointerButton", params); +} + +gboolean remoteDesktopMouse(gboolean isPress, int buttons) { + DEBUG_SCREENCAST("isPress %d awt buttons mask %d\n", isPress, buttons); + + if (buttons & java_awt_event_InputEvent_BUTTON1_MASK + || buttons & java_awt_event_InputEvent_BUTTON1_DOWN_MASK) { + if (!callRemoteDesktopNotifyPointerButton(isPress, 0x110)) { // BTN_LEFT + return FALSE; + } + } + if (buttons & java_awt_event_InputEvent_BUTTON2_MASK + || buttons & java_awt_event_InputEvent_BUTTON2_DOWN_MASK) { + if (!callRemoteDesktopNotifyPointerButton(isPress, 0x112)) { // BTN_MIDDLE + return FALSE; + } + + } + if (buttons & java_awt_event_InputEvent_BUTTON3_MASK + || buttons & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) { + if (!callRemoteDesktopNotifyPointerButton(isPress, 0x111)) { // BTN_RIGHT + return FALSE; + } + } + + return TRUE; +} + +gboolean remoteDesktopMouseWheel(int wheelAmt) { + DEBUG_SCREENCAST("MouseWheel %d\n", wheelAmt); + + GVariantBuilder builder; + gtk->g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); + GVariant *params = gtk->g_variant_new("(oa{sv}ui)", portal->screenCastSessionHandle, &builder, 0, wheelAmt); + return callRemoteDesktop("NotifyPointerAxisDiscrete", params); +} + +gboolean remoteDesktopKey(gboolean isPress, int key) { + DEBUG_SCREENCAST("Key%s key %d -> \n", isPress ? "Press" : "Release", key); + + GVariantBuilder builder; + gtk->g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); + GVariant *params = gtk->g_variant_new ("(oa{sv}iu)", portal->screenCastSessionHandle, &builder, key, isPress); + return callRemoteDesktop("NotifyKeyboardKeysym", params); +} + +#endif diff -Nru openjdk-21-21.0.8+9/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.h openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.h --- openjdk-21-21.0.8+9/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.h 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.h 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,11 +36,21 @@ #define PORTAL_REQUEST_TEMPLATE "/org/freedesktop/portal/desktop/" \ "request/%s/awtPipewire%lu" +#define PORTAL_DESKTOP_BUS_NAME "org.freedesktop.portal.Desktop" +#define PORTAL_DESKTOP_OBJECT_PATH "/org/freedesktop/portal/desktop" + +#define PORTAL_IFACE_REQUEST "org.freedesktop.portal.Request" +#define PORTAL_IFACE_SESSION "org.freedesktop.portal.Session" +#define PORTAL_IFACE_SCREENCAST "org.freedesktop.portal.ScreenCast" +#define PORTAL_IFACE_REMOTE_DESKTOP "org.freedesktop.portal.RemoteDesktop" + +#define PORTAL_MIN_VERSION_SCREENCAST 4 +#define PORTAL_MIN_VERSION_REMOTE_DESKTOP 2 + void debug_screencast(const char *__restrict fmt, ...); -int getPipewireFd(const gchar *token, - GdkRectangle *affectedBounds, - gint affectedBoundsLength); +gboolean initAndStartSession(const gchar *token, int *retVal); +int getPipewireFd(GdkRectangle *affectedBounds, gint affectedBoundsLength); void portalScreenCastCleanup(); @@ -48,8 +58,14 @@ void errHandle(GError *error, const gchar *functionName, int lineNum); +gboolean remoteDesktopMouseMove(int x, int y); +gboolean remoteDesktopMouseWheel(int wheelAmt); +gboolean remoteDesktopMouse(gboolean isPress, int buttons); +gboolean remoteDesktopKey(gboolean isPress, int key); + struct XdgDesktopPortalApi { GDBusConnection *connection; + GDBusProxy *remoteDesktopProxy; GDBusProxy *screenCastProxy; gchar *senderName; char *screenCastSessionHandle; @@ -66,8 +82,15 @@ RESULT_ERROR = -1, RESULT_DENIED = -11, RESULT_OUT_OF_BOUNDS = -12, + RESULT_NO_STREAMS = -13, } ScreenCastResult; +typedef enum { + XDG_METHOD_SCREENCAST = 0, + XDG_METHOD_REMOTE_DESKTOP = 1, +} XdgPortalMethod; + + struct StartHelper { const gchar *token; ScreenCastResult result; diff -Nru openjdk-21-21.0.8+9/src/java.desktop/unix/native/libpipewire/include/spa/utils/endian.h openjdk-21-21.0.9+10/src/java.desktop/unix/native/libpipewire/include/spa/utils/endian.h --- openjdk-21-21.0.8+9/src/java.desktop/unix/native/libpipewire/include/spa/utils/endian.h 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/unix/native/libpipewire/include/spa/utils/endian.h 2025-10-13 07:49:24.000000000 +0000 @@ -18,10 +18,6 @@ #define bswap_16 _byteswap_ushort #define bswap_32 _byteswap_ulong #define bswap_64 _byteswap_uint64 -#elif defined(AIX) -#include -#define __BIG_ENDIAN BIG_ENDIAN -#define __BYTE_ORDER BIG_ENDIAN #else #include #include diff -Nru openjdk-21-21.0.8+9/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java openjdk-21-21.0.9+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java --- openjdk-21-21.0.8+9/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.awt.Rectangle; import javax.swing.ButtonModel; +import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JMenuItem; import javax.swing.plaf.ComponentUI; @@ -71,6 +72,26 @@ } super.paintBackground(g, menuItem, bgColor); } + + /** + * Paint MenuItem. + */ + protected void paintMenuItem(Graphics g, JComponent c, + Icon checkIcon, Icon arrowIcon, + Color background, Color foreground, + int defaultTextIconGap) { + if (WindowsMenuItemUI.isVistaPainting()) { + WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon, + arrowIcon, background, foreground, + disabledForeground, acceleratorSelectionForeground, + acceleratorForeground, defaultTextIconGap, + menuItem, getPropertyPrefix()); + return; + } + super.paintMenuItem(g, c, checkIcon, arrowIcon, background, + foreground, defaultTextIconGap); + } + /** * Method which renders the text of the current menu item. * diff -Nru openjdk-21-21.0.8+9/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java openjdk-21-21.0.9+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java --- openjdk-21-21.0.8+9/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -857,6 +857,7 @@ } assert menuItem == null || c == menuItem; Icon icon = getIcon(); + if (type == JCheckBoxMenuItem.class || type == JRadioButtonMenuItem.class) { AbstractButton b = (AbstractButton) c; @@ -880,19 +881,18 @@ } XPStyle xp = XPStyle.getXP(); if (xp != null) { - Skin skin; - skin = xp.getSkin(c, backgroundPart); - skin.paintSkin(g, x, y, - getIconWidth(), getIconHeight(), backgroundState); - if (icon == null) { - skin = xp.getSkin(c, part); + Skin skin = xp.getSkin(c, part); + if (icon == null || icon.getIconHeight() <= 16) { skin.paintSkin(g, x + OFFSET, y + OFFSET, state); + } else { + skin.paintSkin(g, x + OFFSET, y + icon.getIconHeight() / 2, state); } } } } if (icon != null) { - icon.paintIcon(c, g, x + OFFSET, y + OFFSET); + icon.paintIcon(c, g, x + VistaMenuItemCheckIconFactory.getIconWidth(), + y + OFFSET); } } private static WindowsMenuItemUIAccessor getAccessor( diff -Nru openjdk-21-21.0.8+9/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java openjdk-21-21.0.9+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java --- openjdk-21-21.0.8+9/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,13 +26,20 @@ package com.sun.java.swing.plaf.windows; import java.awt.Color; +import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; +import java.awt.Insets; import java.awt.Rectangle; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.util.Enumeration; +import javax.swing.AbstractButton; +import javax.swing.ButtonGroup; import javax.swing.ButtonModel; +import javax.swing.DefaultButtonModel; +import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JMenu; import javax.swing.JMenuItem; @@ -41,6 +48,7 @@ import javax.swing.plaf.UIResource; import javax.swing.plaf.basic.BasicMenuItemUI; +import com.sun.java.swing.SwingUtilities3; import com.sun.java.swing.plaf.windows.TMSchema.Part; import com.sun.java.swing.plaf.windows.TMSchema.State; import com.sun.java.swing.plaf.windows.XPStyle.Skin; @@ -120,6 +128,27 @@ menuItem.addPropertyChangeListener(changeListener); } + protected void installDefaults() { + super.installDefaults(); + String prefix = getPropertyPrefix(); + + if (acceleratorSelectionForeground == null || + acceleratorSelectionForeground instanceof UIResource) { + acceleratorSelectionForeground = + UIManager.getColor(prefix + ".acceleratorSelectionForeground"); + } + if (acceleratorForeground == null || + acceleratorForeground instanceof UIResource) { + acceleratorForeground = + UIManager.getColor(prefix + ".acceleratorForeground"); + } + if (disabledForeground == null || + disabledForeground instanceof UIResource) { + disabledForeground = + UIManager.getColor(prefix + ".disabledForeground"); + } + } + /** * {@inheritDoc} */ @@ -132,6 +161,90 @@ changeListener = null; } + protected void paintMenuItem(Graphics g, JComponent c, + Icon checkIcon, Icon arrowIcon, + Color background, Color foreground, + int defaultTextIconGap) { + if (WindowsMenuItemUI.isVistaPainting()) { + WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon, + arrowIcon, background, foreground, + disabledForeground, acceleratorSelectionForeground, + acceleratorForeground, defaultTextIconGap, menuItem, + getPropertyPrefix()); + return; + } + super.paintMenuItem(g, c, checkIcon, arrowIcon, background, + foreground, defaultTextIconGap); + } + + static void paintMenuItem(WindowsMenuItemUIAccessor accessor, Graphics g, + JComponent c, Icon checkIcon, Icon arrowIcon, + Color background, Color foreground, + Color disabledForeground, + Color acceleratorSelectionForeground, + Color acceleratorForeground, + int defaultTextIconGap, JMenuItem menuItem, String prefix) { + // Save original graphics font and color + Font holdf = g.getFont(); + Color holdc = g.getColor(); + + JMenuItem mi = (JMenuItem) c; + g.setFont(mi.getFont()); + + Rectangle viewRect = new Rectangle(0, 0, mi.getWidth(), mi.getHeight()); + SwingUtilities3.applyInsets(viewRect, mi.getInsets()); + + String acceleratorDelimiter = + UIManager.getString("MenuItem.acceleratorDelimiter"); + if (acceleratorDelimiter == null) { acceleratorDelimiter = "+"; } + Font acceleratorFont = UIManager.getFont("MenuItem.acceleratorFont"); + if (acceleratorFont == null) { + acceleratorFont = UIManager.getFont("MenuItem.font"); + } + + MenuItemLayoutHelper lh = new MenuItemLayoutHelper(mi, checkIcon, + arrowIcon, viewRect, defaultTextIconGap, acceleratorDelimiter, + mi.getComponentOrientation().isLeftToRight(), mi.getFont(), + acceleratorFont, MenuItemLayoutHelper.useCheckAndArrow(menuItem), + prefix); + MenuItemLayoutHelper.LayoutResult lr = lh.layoutMenuItem(); + + paintBackground(accessor, g, mi, background); + SwingUtilities3.paintCheckIcon(g, lh, lr, holdc, foreground); + SwingUtilities3.paintIcon(g, lh, lr, holdc); + + if (lh.getCheckIcon() != null && lh.useCheckAndArrow()) { + Rectangle rect = lr.getTextRect(); + + rect.x += lh.getAfterCheckIconGap(); + + lr.setTextRect(rect); + } + if (!lh.getText().isEmpty()) { + if (lh.getHtmlView() != null) { + // Text is HTML + lh.getHtmlView().paint(g, lr.getTextRect()); + } else { + // Text isn't HTML + paintText(accessor, g, lh.getMenuItem(), + lr.getTextRect(), lh.getText()); + } + } + if (lh.getCheckIcon() != null && lh.useCheckAndArrow()) { + Rectangle rect = lr.getAccRect(); + rect.x += lh.getAfterCheckIconGap(); + lr.setAccRect(rect); + } + SwingUtilities3.paintAccText(g, lh, lr, disabledForeground, + acceleratorSelectionForeground, + acceleratorForeground); + SwingUtilities3.paintArrowIcon(g, lh, lr, foreground); + + // Restore original graphics font and color + g.setColor(holdc); + g.setFont(holdf); + } + /** * Method which renders the text of the current menu item. * diff -Nru openjdk-21-21.0.8+9/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java openjdk-21-21.0.9+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java --- openjdk-21-21.0.8+9/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -128,6 +128,26 @@ } /** + * Paint MenuItem. + */ + protected void paintMenuItem(Graphics g, JComponent c, + Icon checkIcon, Icon arrowIcon, + Color background, Color foreground, + int defaultTextIconGap) { + if (WindowsMenuItemUI.isVistaPainting()) { + WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon, arrowIcon, + background, foreground, + disabledForeground, acceleratorSelectionForeground, + acceleratorForeground, defaultTextIconGap, menuItem, + getPropertyPrefix()); + return; + } + super.paintMenuItem(g, c, checkIcon, arrowIcon, background, + foreground, defaultTextIconGap); + } + + + /** * Draws the background of the menu. * @since 1.4 */ diff -Nru openjdk-21-21.0.8+9/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java openjdk-21-21.0.9+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java --- openjdk-21-21.0.8+9/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.awt.Rectangle; import javax.swing.ButtonModel; +import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JMenuItem; import javax.swing.plaf.ComponentUI; @@ -73,6 +74,25 @@ } /** + * Paint MenuItem. + */ + protected void paintMenuItem(Graphics g, JComponent c, + Icon checkIcon, Icon arrowIcon, + Color background, Color foreground, + int defaultTextIconGap) { + if (WindowsMenuItemUI.isVistaPainting()) { + WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon, + arrowIcon, background, foreground, + disabledForeground, acceleratorSelectionForeground, + acceleratorForeground, defaultTextIconGap, + menuItem, getPropertyPrefix()); + return; + } + super.paintMenuItem(g, c, checkIcon, arrowIcon, background, + foreground, defaultTextIconGap); + } + + /** * Method which renders the text of the current menu item. * * @param g Graphics context diff -Nru openjdk-21-21.0.8+9/src/java.desktop/windows/classes/sun/awt/windows/WClipboard.java openjdk-21-21.0.9+10/src/java.desktop/windows/classes/sun/awt/windows/WClipboard.java --- openjdk-21-21.0.8+9/src/java.desktop/windows/classes/sun/awt/windows/WClipboard.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/windows/classes/sun/awt/windows/WClipboard.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,9 @@ import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.io.IOException; +import java.lang.System.Logger.Level; import java.util.Map; +import java.util.concurrent.locks.ReentrantLock; import sun.awt.datatransfer.DataTransferer; import sun.awt.datatransfer.SunClipboard; @@ -51,8 +53,12 @@ private boolean isClipboardViewerRegistered; + private final ReentrantLock clipboardLocked = new ReentrantLock(); + WClipboard() { super("System"); + // Register java side of the clipboard with the native side + registerClipboard(); } @Override @@ -104,18 +110,42 @@ /** * Call the Win32 OpenClipboard function. If newOwner is non-null, - * we also call EmptyClipboard and take ownership. + * we also call EmptyClipboard and take ownership. If this method call + * succeeds, it must be followed by a call to {@link #closeClipboard()}. * * @throws IllegalStateException if the clipboard has not been opened */ @Override - public native void openClipboard(SunClipboard newOwner) throws IllegalStateException; + public void openClipboard(SunClipboard newOwner) throws IllegalStateException { + if (!clipboardLocked.tryLock()) { + throw new IllegalStateException("Failed to acquire clipboard lock"); + } + try { + openClipboard0(newOwner); + } catch (IllegalStateException ex) { + clipboardLocked.unlock(); + throw ex; + } + } + /** * Call the Win32 CloseClipboard function if we have clipboard ownership, * does nothing if we have not ownership. */ @Override - public native void closeClipboard(); + public void closeClipboard() { + if (clipboardLocked.isLocked()) { + try { + closeClipboard0(); + } finally { + clipboardLocked.unlock(); + } + } + } + + private native void openClipboard0(SunClipboard newOwner) throws IllegalStateException; + private native void closeClipboard0(); + /** * Call the Win32 SetClipboardData function. */ @@ -157,16 +187,12 @@ return; } - long[] formats = null; try { - openClipboard(null); - formats = getClipboardFormats(); - } catch (IllegalStateException exc) { - // do nothing to handle the exception, call checkChange(null) - } finally { - closeClipboard(); + long[] formats = getClipboardFormats(); + checkChange(formats); + } catch (Throwable ex) { + System.getLogger(WClipboard.class.getName()).log(Level.DEBUG, "Failed to process handleContentsChanged", ex); } - checkChange(formats); } /** @@ -214,4 +240,6 @@ } }; } + + private native void registerClipboard(); } diff -Nru openjdk-21-21.0.8+9/src/java.desktop/windows/native/libawt/windows/awt_Clipboard.cpp openjdk-21-21.0.9+10/src/java.desktop/windows/native/libawt/windows/awt_Clipboard.cpp --- openjdk-21-21.0.8+9/src/java.desktop/windows/native/libawt/windows/awt_Clipboard.cpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.desktop/windows/native/libawt/windows/awt_Clipboard.cpp 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,9 +69,8 @@ return; } - if (theCurrentClipboard == NULL) { - theCurrentClipboard = env->NewGlobalRef(jclipboard); - } + DASSERT(AwtClipboard::theCurrentClipboard != NULL); + DASSERT(env->IsSameObject(AwtClipboard::theCurrentClipboard, jclipboard)); jclass cls = env->GetObjectClass(jclipboard); AwtClipboard::handleContentsChangedMID = @@ -128,11 +127,13 @@ * Signature: (Lsun/awt/windows/WClipboard;)V */ JNIEXPORT void JNICALL -Java_sun_awt_windows_WClipboard_openClipboard(JNIEnv *env, jobject self, +Java_sun_awt_windows_WClipboard_openClipboard0(JNIEnv *env, jobject self, jobject newOwner) { TRY; + DASSERT(AwtClipboard::theCurrentClipboard != NULL); + DASSERT(newOwner == NULL || env->IsSameObject(AwtClipboard::theCurrentClipboard, newOwner)); DASSERT(::GetOpenClipboardWindow() != AwtToolkit::GetInstance().GetHWnd()); if (!::OpenClipboard(AwtToolkit::GetInstance().GetHWnd())) { @@ -142,10 +143,6 @@ } if (newOwner != NULL) { AwtClipboard::GetOwnership(); - if (AwtClipboard::theCurrentClipboard != NULL) { - env->DeleteGlobalRef(AwtClipboard::theCurrentClipboard); - } - AwtClipboard::theCurrentClipboard = env->NewGlobalRef(newOwner); } CATCH_BAD_ALLOC; @@ -157,7 +154,7 @@ * Signature: ()V */ JNIEXPORT void JNICALL -Java_sun_awt_windows_WClipboard_closeClipboard(JNIEnv *env, jobject self) +Java_sun_awt_windows_WClipboard_closeClipboard0(JNIEnv *env, jobject self) { TRY; @@ -297,23 +294,25 @@ { TRY; - DASSERT(::GetOpenClipboardWindow() == AwtToolkit::GetInstance().GetHWnd()); + unsigned int cFormats = 128; // Allocate enough space to hold all + unsigned int pcFormatsOut = 0; + unsigned int lpuiFormats[128] = { 0 }; - jsize nFormats = ::CountClipboardFormats(); - jlongArray formats = env->NewLongArray(nFormats); + VERIFY(::GetUpdatedClipboardFormats(lpuiFormats, 128, &pcFormatsOut)); + + jlongArray formats = env->NewLongArray(pcFormatsOut); if (formats == NULL) { throw std::bad_alloc(); } - if (nFormats == 0) { + if (pcFormatsOut == 0) { return formats; } jboolean isCopy; jlong *lFormats = env->GetLongArrayElements(formats, &isCopy), *saveFormats = lFormats; - UINT num = 0; - for (jsize i = 0; i < nFormats; i++, lFormats++) { - *lFormats = num = ::EnumClipboardFormats(num); + for (unsigned int i = 0; i < pcFormatsOut; i++, lFormats++) { + *lFormats = lpuiFormats[i]; } env->ReleaseLongArrayElements(formats, saveFormats, 0); @@ -478,4 +477,16 @@ CATCH_BAD_ALLOC_RET(NULL); } +/* + * Class: sun_awt_windows_WClipboard + * Method: registerClipboard + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_sun_awt_windows_WClipboard_registerClipboard(JNIEnv *env, jobject self) +{ + DASSERT(AwtClipboard::theCurrentClipboard == NULL); + AwtClipboard::theCurrentClipboard = env->NewGlobalRef(self); +} + } /* extern "C" */ diff -Nru openjdk-21-21.0.8+9/src/java.management/share/classes/javax/management/remote/package.html openjdk-21-21.0.9+10/src/java.management/share/classes/javax/management/remote/package.html --- openjdk-21-21.0.8+9/src/java.management/share/classes/javax/management/remote/package.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/src/java.management/share/classes/javax/management/remote/package.html 2025-10-13 07:49:24.000000000 +0000 @@ -2,7 +2,7 @@ JMX Remote API. - - - - - UpdatingBootTime - - - -

UpdatingBootTime
Bug ID:

- -

See the dialog box (usually in upper left corner) for instructions

- - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/Component/UpdatingBootTime/UpdatingBootTime.java openjdk-21-21.0.9+10/test/jdk/java/awt/Component/UpdatingBootTime/UpdatingBootTime.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/Component/UpdatingBootTime/UpdatingBootTime.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/Component/UpdatingBootTime/UpdatingBootTime.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,222 +0,0 @@ -/* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - test - @bug 6461933 7194219 - @summary adjust system boot time in nowMillisUTC() frequently - @author Andrei Dmitriev : area=awt.component - @run applet/manual=yesno UpdatingBootTime.html - */ - -/* - * verifies that time updated by the system is picked up by the Java App. - */ - -import java.applet.Applet; -import java.awt.*; -import java.awt.event.*; -import java.util.Date; - -public class UpdatingBootTime extends Applet -{ - //Declare things used in the test, like buttons and labels here - - public void init() - { - this.setLayout (new BorderLayout ()); - - String[] instructions = - { - "1) Press the mouse over the button.", - "2) A two timestamps would be printed.", - "3) Verify that they are not differ a lot: it is okay to observe a 1 or 2 seconds difference.", - "4) Change the system time significantly(by a month or a year) by using the OS abilities.", - "5) Click on the button once again.", - "6) Printed times should still be the same. Pay attention to the Month/Year if they were changed.", - "7) It is okay to observe a 1 or 2 seconds difference and this is not a fail.", - "8) If the difference is more then 1-2 seconds noticed then the test fail; otherwise pass." - }; - Sysout.createDialogWithInstructions( instructions ); - - }//End init() - - public void start () - { - Button b = new Button("Press me"); - b.addMouseListener(new MouseAdapter(){ - public void mousePressed(MouseEvent e){ - Sysout.println("Event occured : "+e); - Sysout.println("The event time is : "+ (new Date(e.getWhen()))); - Sysout.println("The system time is : "+ (new Date())); - } - }); - add(b); - setSize (200,200); - setVisible(true); - validate(); - }// start() -}// class UpdatingBootTime - -/* Place other classes related to the test after this line */ - - - - - -/**************************************************** - Standard Test Machinery - DO NOT modify anything below -- it's a standard - chunk of code whose purpose is to make user - interaction uniform, and thereby make it simpler - to read and understand someone else's test. - ****************************************************/ - -/** - This is part of the standard test machinery. - It creates a dialog (with the instructions), and is the interface - for sending text messages to the user. - To print the instructions, send an array of strings to Sysout.createDialog - WithInstructions method. Put one line of instructions per array entry. - To display a message for the tester to see, simply call Sysout.println - with the string to be displayed. - This mimics System.out.println but works within the test harness as well - as standalone. - */ - -class Sysout -{ - private static TestDialog dialog; - - public static void createDialogWithInstructions( String[] instructions ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - dialog.printInstructions( instructions ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); - } - - public static void createDialog( ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - String[] defInstr = { "Instructions will appear here. ", "" } ; - dialog.printInstructions( defInstr ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); - } - - - public static void printInstructions( String[] instructions ) - { - dialog.printInstructions( instructions ); - } - - - public static void println( String messageIn ) - { - dialog.displayMessage( messageIn ); - } - -}// Sysout class - -/** - This is part of the standard test machinery. It provides a place for the - test instructions to be displayed, and a place for interactive messages - to the user to be displayed. - To have the test instructions displayed, see Sysout. - To have a message to the user be displayed, see Sysout. - Do not call anything in this dialog directly. - */ -class TestDialog extends Dialog -{ - - TextArea instructionsText; - TextArea messageText; - int maxStringLength = 80; - - //DO NOT call this directly, go through Sysout - public TestDialog( Frame frame, String name ) - { - super( frame, name ); - int scrollBoth = TextArea.SCROLLBARS_BOTH; - instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); - add( "North", instructionsText ); - - messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); - add("Center", messageText); - - pack(); - - setVisible(true); - }// TestDialog() - - //DO NOT call this directly, go through Sysout - public void printInstructions( String[] instructions ) - { - //Clear out any current instructions - instructionsText.setText( "" ); - - //Go down array of instruction strings - - String printStr, remainingStr; - for( int i=0; i < instructions.length; i++ ) - { - //chop up each into pieces maxSringLength long - remainingStr = instructions[ i ]; - while( remainingStr.length() > 0 ) - { - //if longer than max then chop off first max chars to print - if( remainingStr.length() >= maxStringLength ) - { - //Try to chop on a word boundary - int posOfSpace = remainingStr. - lastIndexOf( ' ', maxStringLength - 1 ); - - if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; - - printStr = remainingStr.substring( 0, posOfSpace + 1 ); - remainingStr = remainingStr.substring( posOfSpace + 1 ); - } - //else just print - else - { - printStr = remainingStr; - remainingStr = ""; - } - - instructionsText.append( printStr + "\n" ); - - }// while - - }// for - - }//printInstructions() - - //DO NOT call this directly, go through Sysout - public void displayMessage( String messageIn ) - { - messageText.append( messageIn + "\n" ); - System.out.println(messageIn); - } - -}// TestDialog class diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/Component/UpdatingBootTime.java openjdk-21-21.0.9+10/test/jdk/java/awt/Component/UpdatingBootTime.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/Component/UpdatingBootTime.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/Component/UpdatingBootTime.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6461933 7194219 + * @summary adjust system boot time in nowMillisUTC() frequently + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual UpdatingBootTime + */ + +/* + * Test verifies that time updated by the system is correctly + * picked up by the Java application. + */ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.lang.reflect.InvocationTargetException; +import java.util.Date; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; + +public class UpdatingBootTime { + private static JFrame initialize () { + JFrame frame = new JFrame("Updating Boot Time Test Frame"); + frame.setLayout(new BorderLayout()); + JTextArea textOutput = new JTextArea("Events on the button:", 14, 40); + textOutput.setLineWrap(true); + JScrollPane textScrollPane = new JScrollPane(textOutput); + frame.add(textScrollPane, BorderLayout.CENTER); + Button b = new Button("Press me"); + frame.add(b, BorderLayout.NORTH); + b.addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent e) { + textOutput.append("\nEvent occurred : " + e); + textOutput.append("\nThe event time is : " + (new Date(e.getWhen()))); + textOutput.append("\nThe system time is : " + (new Date())); + textOutput.append("\n------------------------------------"); + textOutput.setCaretPosition(textOutput.getText().length()); + } + }); + frame.pack(); + return frame; + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + String instructions = + """ + 1) In the test window press "Press me" button. + 2) Two timestamps should be printed. + 3) Verify that they are not differ a lot: + it is okay to observe a 1 or 2 seconds difference. + 4) Change the system time significantly (by a month or a year) + by using the OS abilities. + 5) Click on the button once again. + 6) Printed times should still be the same. + Pay attention to the Month/Year if they were changed. + 7) It is okay to observe a 1 or 2 seconds difference and this is not a fail. + 8) If the difference is more then 1-2 seconds noticed press fail, + otherwise press pass. + """; + + PassFailJFrame.builder() + .title("Updating Boot Time Test Instructions") + .instructions(instructions) + .rows((int) instructions.lines().count() + 1) + .columns(40) + .testUI(UpdatingBootTime::initialize) + .build() + .awaitAndCheck(); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/Cursor/CursorOverlappedPanelsTest/CursorOverlappedPanelsTest.html openjdk-21-21.0.9+10/test/jdk/java/awt/Cursor/CursorOverlappedPanelsTest/CursorOverlappedPanelsTest.html --- openjdk-21-21.0.8+9/test/jdk/java/awt/Cursor/CursorOverlappedPanelsTest/CursorOverlappedPanelsTest.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/Cursor/CursorOverlappedPanelsTest/CursorOverlappedPanelsTest.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ - - - - - CursorOverlappedPanelsTest, bug ID 8007155 - - - -

See the dialog box (usually in upper left corner) for instructions

- - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/Cursor/CursorOverlappedPanelsTest/CursorOverlappedPanelsTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/Cursor/CursorOverlappedPanelsTest/CursorOverlappedPanelsTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/Cursor/CursorOverlappedPanelsTest/CursorOverlappedPanelsTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/Cursor/CursorOverlappedPanelsTest/CursorOverlappedPanelsTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2013, 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.*; -//import java.applet.Applet; -import javax.swing.BorderFactory; -import javax.swing.JApplet; -import javax.swing.JFrame; -import javax.swing.JLayeredPane; -import javax.swing.JPanel; - -/** - * @test - * @bug 8007155 - * @summary [macosx] Disabled panel takes mouse input in JLayeredPane - * @author Alexander Scherbatiy: area=java.awt.Cursor - * @run applet/manual=yesno CursorOverlappedPanelsTest.html - */ -public class CursorOverlappedPanelsTest extends JApplet { - //Declare things used in the test, like buttons and labels here - - public void init() { - //Create instructions for the user here, as well as set up - // the environment -- set the layout manager, add buttons, - // etc. - this.setLayout(new BorderLayout()); - - String[] instructions = { - "Verify that the Crosshair cursor from enabled panel" - + " is displayed on the panels intersection", - "1) Move the mosue cursor on the Enabled and Disabled panels" - + " intersection", - "2) Check that the Crosshair cursor is displayed ", - "If so, press PASS, else press FAIL." - }; - Sysout.createDialogWithInstructions(instructions); - - }//End init() - - public void start() { - //Get things going. Request focus, set size, et cetera - setSize(200, 200); - setVisible(true); - validate(); - try { - EventQueue.invokeAndWait(new Runnable() { - public void run() { - createAndShowGUI(); - } - }); - } catch (Exception e) { - throw new RuntimeException(e); - } - }// start() - - //The rest of this class is the actions which perform the test... - //Use Sysout.println to communicate with the user NOT System.out!! - //Sysout.println ("Something Happened!"); - private static JPanel createPanel(Point location, boolean enabled) { - final JPanel panel = new JPanel(); - panel.setOpaque(false); - panel.setEnabled(enabled); - panel.setSize(new Dimension(200, 200)); - panel.setLocation(location); - panel.setBorder(BorderFactory.createTitledBorder( - enabled ? "Enabled" : "Disabled")); - panel.setCursor(Cursor.getPredefinedCursor( - enabled ? Cursor.CROSSHAIR_CURSOR : Cursor.DEFAULT_CURSOR)); - System.out.println("cursor: " + Cursor.getPredefinedCursor(enabled ? Cursor.CROSSHAIR_CURSOR : Cursor.DEFAULT_CURSOR)); - return panel; - } - - private static void createAndShowGUI() { - final JFrame frame = new JFrame("Test"); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - - JLayeredPane layeredPane = new JLayeredPane(); - layeredPane.setPreferredSize(new Dimension(400, 400)); - JPanel enabledPanel = createPanel(new Point(10, 10), true); - JPanel disabledPanel = createPanel(new Point(100, 100), false); - layeredPane.add(disabledPanel, JLayeredPane.PALETTE_LAYER); - layeredPane.add(enabledPanel, JLayeredPane.DEFAULT_LAYER); - - frame.getContentPane().add(layeredPane); - frame.pack(); - frame.setVisible(true); - } -}// class BlockedWindowTest - -/* Place other classes related to the test after this line */ -/** - * ************************************************** - * Standard Test Machinery DO NOT modify anything below -- it's a standard chunk - * of code whose purpose is to make user interaction uniform, and thereby make - * it simpler to read and understand someone else's test. - * ************************************************** - */ -/** - * This is part of the standard test machinery. It creates a dialog (with the - * instructions), and is the interface for sending text messages to the user. To - * print the instructions, send an array of strings to Sysout.createDialog - * WithInstructions method. Put one line of instructions per array entry. To - * display a message for the tester to see, simply call Sysout.println with the - * string to be displayed. This mimics System.out.println but works within the - * test harness as well as standalone. - */ -class Sysout { - - private static TestDialog dialog; - - public static void createDialogWithInstructions(String[] instructions) { - dialog = new TestDialog(new Frame(), "Instructions"); - dialog.printInstructions(instructions); - dialog.setVisible(true); - println("Any messages for the tester will display here."); - } - - public static void createDialog() { - dialog = new TestDialog(new Frame(), "Instructions"); - String[] defInstr = {"Instructions will appear here. ", ""}; - dialog.printInstructions(defInstr); - dialog.setVisible(true); - println("Any messages for the tester will display here."); - } - - public static void printInstructions(String[] instructions) { - dialog.printInstructions(instructions); - } - - public static void println(String messageIn) { - dialog.displayMessage(messageIn); - } -}// Sysout class - -/** - * This is part of the standard test machinery. It provides a place for the test - * instructions to be displayed, and a place for interactive messages to the - * user to be displayed. To have the test instructions displayed, see Sysout. To - * have a message to the user be displayed, see Sysout. Do not call anything in - * this dialog directly. - */ -class TestDialog extends Dialog { - - TextArea instructionsText; - TextArea messageText; - int maxStringLength = 80; - - //DO NOT call this directly, go through Sysout - public TestDialog(Frame frame, String name) { - super(frame, name); - int scrollBoth = TextArea.SCROLLBARS_BOTH; - instructionsText = new TextArea("", 15, maxStringLength, scrollBoth); - add("North", instructionsText); - - messageText = new TextArea("", 5, maxStringLength, scrollBoth); - add("Center", messageText); - - pack(); - - setVisible(true); - }// TestDialog() - - //DO NOT call this directly, go through Sysout - public void printInstructions(String[] instructions) { - //Clear out any current instructions - instructionsText.setText(""); - - //Go down array of instruction strings - - String printStr, remainingStr; - for (int i = 0; i < instructions.length; i++) { - //chop up each into pieces maxSringLength long - remainingStr = instructions[ i]; - while (remainingStr.length() > 0) { - //if longer than max then chop off first max chars to print - if (remainingStr.length() >= maxStringLength) { - //Try to chop on a word boundary - int posOfSpace = remainingStr. - lastIndexOf(' ', maxStringLength - 1); - - if (posOfSpace <= 0) { - posOfSpace = maxStringLength - 1; - } - - printStr = remainingStr.substring(0, posOfSpace + 1); - remainingStr = remainingStr.substring(posOfSpace + 1); - } //else just print - else { - printStr = remainingStr; - remainingStr = ""; - } - - instructionsText.append(printStr + "\n"); - - }// while - - }// for - - }//printInstructions() - - //DO NOT call this directly, go through Sysout - public void displayMessage(String messageIn) { - messageText.append(messageIn + "\n"); - System.out.println(messageIn); - } -}// TestDialog class diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/Cursor/CursorOverlappedPanelsTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/Cursor/CursorOverlappedPanelsTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/Cursor/CursorOverlappedPanelsTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/Cursor/CursorOverlappedPanelsTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Point; +import java.lang.reflect.InvocationTargetException; +import javax.swing.BorderFactory; +import javax.swing.JFrame; +import javax.swing.JLayeredPane; +import javax.swing.JPanel; + +/* + * @test + * @bug 8007155 + * @summary [macosx] Disabled panel takes mouse input in JLayeredPane + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual CursorOverlappedPanelsTest + */ + +public class CursorOverlappedPanelsTest extends Frame { + public static JFrame initialize() { + final JFrame frame = new JFrame("Overlapping Panels Cursor Test"); + + JLayeredPane layeredPane = new JLayeredPane(); + layeredPane.setPreferredSize(new Dimension(400, 400)); + JPanel enabledPanel = createPanel(new Point(10, 10), true); + JPanel disabledPanel = createPanel(new Point(100, 100), false); + layeredPane.add(disabledPanel, JLayeredPane.PALETTE_LAYER); + layeredPane.add(enabledPanel, JLayeredPane.DEFAULT_LAYER); + + frame.getContentPane().add(layeredPane); + frame.pack(); + return frame; + } + + private static JPanel createPanel(Point location, boolean enabled) { + final JPanel panel = new JPanel(); + panel.setOpaque(false); + panel.setEnabled(enabled); + panel.setSize(new Dimension(200, 200)); + panel.setLocation(location); + panel.setBorder(BorderFactory.createTitledBorder( + enabled ? "Enabled" : "Disabled")); + panel.setCursor(Cursor.getPredefinedCursor( + enabled ? Cursor.CROSSHAIR_CURSOR : Cursor.DEFAULT_CURSOR)); + return panel; + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + String instructions = """ + 1) Move the mouse cursor into the area + of Enabled and Disabled panels intersection; + 2) Check that the crosshair cursor is displayed. + If so, press PASS, otherwise press FAIL. + """; + + PassFailJFrame.builder() + .title("Overlapping Panels Cursor Test Instructions") + .instructions(instructions) + .rows((int) instructions.lines().count() + 1) + .columns(30) + .testUI(CursorOverlappedPanelsTest::initialize) + .build() + .awaitAndCheck(); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/Desktop/BrowseTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/Desktop/BrowseTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/Desktop/BrowseTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/Desktop/BrowseTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,8 @@ * @test * @bug 6255196 * @summary Verifies the function of method browse(java.net.URI uri). - * @library /java/awt/regtesthelpers - * @build PassFailJFrame + * @library /java/awt/regtesthelpers /test/lib + * @build PassFailJFrame jtreg.SkippedException * @run main/manual BrowseTest */ @@ -36,6 +36,8 @@ import java.net.URI; import javax.swing.JPanel; +import jtreg.SkippedException; + public class BrowseTest extends JPanel { static final String INSTRUCTIONS = """ This test could launch default file manager to open user's home @@ -47,12 +49,6 @@ """; public BrowseTest() { - if (!Desktop.isDesktopSupported()) { - PassFailJFrame.log("Class java.awt.Desktop is not supported on " + - "current platform. Farther testing will not be performed"); - PassFailJFrame.forcePass(); - } - Desktop desktop = Desktop.getDesktop(); URI dirURI = new File(System.getProperty("user.home")).toURI(); @@ -77,6 +73,11 @@ public static void main(String[] args) throws InterruptedException, InvocationTargetException { + if (!Desktop.isDesktopSupported()) { + throw new SkippedException("Class java.awt.Desktop is not supported " + + "on current platform. Further testing will not be performed"); + } + PassFailJFrame.builder() .title("Browser Test") .splitUI(BrowseTest::new) diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/Desktop/EditAndPrintTest/EditAndPrintTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/Desktop/EditAndPrintTest/EditAndPrintTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/Desktop/EditAndPrintTest/EditAndPrintTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/Desktop/EditAndPrintTest/EditAndPrintTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,8 @@ * @bug 6255196 * @summary Verifies the function of methods edit(java.io.File file) and * print(java.io.File file) - * @library /java/awt/regtesthelpers - * @build PassFailJFrame + * @library /java/awt/regtesthelpers /test/lib + * @build PassFailJFrame jtreg.SkippedException * @run main/manual EditAndPrintTest */ @@ -40,6 +40,8 @@ import java.lang.reflect.InvocationTargetException; import javax.swing.JPanel; +import jtreg.SkippedException; + public class EditAndPrintTest extends JPanel { static final String INSTRUCTIONS = """ @@ -49,20 +51,9 @@ If you see any EXCEPTION messages in the output press FAIL. """; - public EditAndPrintTest() { - if (!Desktop.isDesktopSupported()) { - PassFailJFrame.log("Class java.awt.Desktop is not supported on " + - "current platform. Further testing will not be performed"); - PassFailJFrame.forcePass(); - } - - Desktop desktop = Desktop.getDesktop(); - - if (!desktop.isSupported(Action.PRINT) && !desktop.isSupported(Action.EDIT)) { - PassFailJFrame.log("Neither EDIT nor PRINT actions are supported. Nothing to test."); - PassFailJFrame.forcePass(); - } + static Desktop desktop; + public EditAndPrintTest() { /* * Part 1: print or edit a directory, which should throw an IOException. */ @@ -111,7 +102,7 @@ writer.write("This is a temp file used to test print() method of Desktop."); writer.flush(); writer.close(); - } catch (java.io.IOException ioe){ + } catch (IOException ioe){ PassFailJFrame.log("EXCEPTION: " + ioe.getMessage()); PassFailJFrame.forceFail("Failed to create temp file for testing."); } @@ -139,6 +130,16 @@ public static void main(String args[]) throws InterruptedException, InvocationTargetException { + if (!Desktop.isDesktopSupported()) { + throw new SkippedException("Class java.awt.Desktop is not supported " + + "on current platform. Further testing will not be performed"); + } + + desktop = Desktop.getDesktop(); + if (!desktop.isSupported(Action.PRINT) && !desktop.isSupported(Action.EDIT)) { + throw new SkippedException("Neither EDIT nor PRINT actions are supported. Nothing to test."); + } + PassFailJFrame.builder() .title("Edit and Print test") .splitUI(EditAndPrintTest::new) diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/Desktop/OpenTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/Desktop/OpenTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/Desktop/OpenTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/Desktop/OpenTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,8 @@ * @test * @bug 6255196 * @summary Verifies the function of method open(java.io.File file). - * @library /java/awt/regtesthelpers - * @build PassFailJFrame + * @library /java/awt/regtesthelpers /test/lib + * @build PassFailJFrame jtreg.SkippedException * @run main/manual/othervm OpenTest */ @@ -36,6 +36,8 @@ import java.lang.reflect.InvocationTargetException; import javax.swing.JPanel; +import jtreg.SkippedException; + public class OpenTest extends JPanel { static final String INSTRUCTIONS = """ @@ -48,12 +50,6 @@ """; public OpenTest() { - if (!Desktop.isDesktopSupported()) { - PassFailJFrame.log("Class java.awt.Desktop is not supported on " + - "current platform. Further testing will not be performed"); - PassFailJFrame.forcePass(); - } - Desktop desktop = Desktop.getDesktop(); /* @@ -85,7 +81,7 @@ testFile = File.createTempFile("JDIC-test", ".txt", new File(System.getProperty("java.io.tmpdir"))); testFile.deleteOnExit(); - } catch (java.io.IOException ioe) { + } catch (IOException ioe) { PassFailJFrame.log("EXCEPTION: " + ioe.getMessage()); PassFailJFrame.log("Failed to create test file"); } @@ -101,6 +97,11 @@ public static void main(String[] args) throws InterruptedException, InvocationTargetException { + if (!Desktop.isDesktopSupported()) { + throw new SkippedException("Class java.awt.Desktop is not supported " + + "on current platform. Further testing will not be performed"); + } + PassFailJFrame.builder() .title("Mail Test") .splitUI(OpenTest::new) diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogForDirectories/FileDialogForDirectories.html openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogForDirectories/FileDialogForDirectories.html --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogForDirectories/FileDialogForDirectories.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogForDirectories/FileDialogForDirectories.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ - - - - - - FileDialogForDirectories - - - -

FileDialogForDirectories
Bug ID: 7161437

- -

See the dialog box (usually in upper left corner) for instructions

- - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogForDirectories/FileDialogForDirectories.java openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogForDirectories/FileDialogForDirectories.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogForDirectories/FileDialogForDirectories.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogForDirectories/FileDialogForDirectories.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -import jdk.test.lib.Platform; -import test.java.awt.regtesthelpers.Sysout; - -import java.applet.Applet; -import java.awt.Button; -import java.awt.FileDialog; -import java.awt.Frame; -import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -public class FileDialogForDirectories extends Applet implements ActionListener { - private volatile Button showBtn; - private volatile FileDialog fd; - - @Override - public void init() { - if (!Platform.isOSX()) { - Sysout.createDialogWithInstructions(new String[]{ - "Press PASS, this test is for MacOS X only."}); - return; - } - - System.setProperty("apple.awt.fileDialogForDirectories", "true"); - - setLayout(new GridLayout(1, 1)); - - fd = new FileDialog(new Frame(), "Open"); - - showBtn = new Button("Show File Dialog"); - showBtn.addActionListener(this); - add(showBtn); - String[] instructions = { - "1) Click on 'Show File Dialog' button. A file dialog will come up.", - "2) Check that files can't be selected.", - "3) Check that directories can be selected.", - "4) Repeat steps 1 - 3 a few times for different files and directories.", - "5) If it's true then the test passed, otherwise it failed."}; - Sysout.createDialogWithInstructions(instructions); - }//End init() - - @Override - public void start() { - setSize(200, 200); - show(); - }// start() - - @Override - public void actionPerformed(ActionEvent e) { - if (e.getSource() == showBtn) { - fd.setVisible(true); - String output = fd.getFile(); - if (output != null) { - Sysout.println(output + " is selected"); - } - } - } -}// class ManualYesNoTest diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogForDirectories.java openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogForDirectories.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogForDirectories.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogForDirectories.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.FileDialog; +import java.awt.Frame; +import java.lang.reflect.InvocationTargetException; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; + +/* + * @test + * @bug 7161437 + * @summary We should support "apple.awt.fileDialogForDirectories" property. + * @requires (os.family == "mac") + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual FileDialogForDirectories + */ + +public class FileDialogForDirectories { + + private static JFrame initialize() { + System.setProperty("apple.awt.fileDialogForDirectories", "true"); + + JFrame frame = new JFrame("Directory File Dialog Test Frame"); + frame.setLayout(new BorderLayout()); + JTextArea textOutput = new JTextArea(8, 30); + textOutput.setLineWrap(true); + JScrollPane textScrollPane = new JScrollPane(textOutput); + frame.add(textScrollPane, BorderLayout.CENTER); + + FileDialog fd = new FileDialog(new Frame(), "Open"); + + Button showBtn = new Button("Show File Dialog"); + showBtn.addActionListener(e -> { + fd.setVisible(true); + String output = fd.getFile(); + if (output != null) { + textOutput.append(output + " is selected\n"); + textOutput.setCaretPosition(textOutput.getText().length()); + } + }); + frame.add(showBtn, BorderLayout.NORTH); + frame.pack(); + return frame; + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + String instructions = """ + 1) Click on 'Show File Dialog' button. A file dialog will come up. + 2) Check that files can't be selected. + 3) Check that directories can be selected. + 4) Repeat steps 1 - 3 a few times for different files and directories. + 5) If it's true then the press Pass, otherwise press Fail. + """; + + PassFailJFrame.builder() + .title("Directory File Dialog Test Instructions") + .instructions(instructions) + .rows((int) instructions.lines().count() + 1) + .columns(40) + .testUI(FileDialogForDirectories::initialize) + .build() + .awaitAndCheck(); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogForPackages/FileDialogForPackages.html openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogForPackages/FileDialogForPackages.html --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogForPackages/FileDialogForPackages.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogForPackages/FileDialogForPackages.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ - - - - - - FileDialogForPackages - - - -

FileDialogForPackages
Bug ID: 8026869

- -

See the dialog box (usually in upper left corner) for instructions

- - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogForPackages/FileDialogForPackages.java openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogForPackages/FileDialogForPackages.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogForPackages/FileDialogForPackages.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogForPackages/FileDialogForPackages.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -import jdk.test.lib.Platform; -import test.java.awt.regtesthelpers.Sysout; - -import java.applet.Applet; -import java.awt.Button; -import java.awt.FileDialog; -import java.awt.Frame; -import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -public class FileDialogForPackages extends Applet implements ActionListener { - private static final String APPLICATIONS_FOLDER = "/Applications"; - - private volatile Button showBtn; - private volatile FileDialog fd; - - @Override - public void init() { - if (!Platform.isOSX()) { - Sysout.createDialogWithInstructions(new String[]{ - "Press PASS, this test is for MacOS X only."}); - return; - } - - System.setProperty("apple.awt.use-file-dialog-packages", "true"); - - setLayout(new GridLayout(1, 1)); - - fd = new FileDialog(new Frame(), "Open"); - fd.setDirectory(APPLICATIONS_FOLDER); - - showBtn = new Button("Show File Dialog"); - showBtn.addActionListener(this); - add(showBtn); - String[] instructions = { - "1) Click on 'Show File Dialog' button. A file dialog will come up.", - "2) Navigate to the Applications folder if not already there", - "3) Check that the application bundles can be selected and can not be navigated", - "4) If it's true then the test passed, otherwise it failed."}; - Sysout.createDialogWithInstructions(instructions); - } - - @Override - public void start() { - setSize(200, 200); - show(); - } - - @Override - public void actionPerformed(ActionEvent e) { - if (e.getSource() == showBtn) { - fd.setVisible(true); - String output = fd.getFile(); - if (output != null) { - Sysout.println(output + " is selected"); - } - } - } -} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogForPackages.java openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogForPackages.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogForPackages.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogForPackages.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.FileDialog; +import java.awt.Frame; +import java.lang.reflect.InvocationTargetException; +import javax.swing.JButton; + +/* + * @test + * @bug 8026869 + * @summary Support apple.awt.use-file-dialog-packages property. + * @requires (os.family == "mac") + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual FileDialogForPackages +*/ + +public class FileDialogForPackages { + + private static JButton initialize() { + System.setProperty("apple.awt.use-file-dialog-packages", "true"); + + FileDialog fd = new FileDialog((Frame) null, "Open"); + String APPLICATIONS_FOLDER = "/Applications"; + fd.setDirectory(APPLICATIONS_FOLDER); + + JButton showBtn = new JButton("Show File Dialog"); + showBtn.addActionListener(e -> { + fd.setVisible(true); + String output = fd.getFile(); + if (output != null) { + PassFailJFrame.log(output + " is selected\n"); + } + }); + return showBtn; + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + String instructions = """ + 1) Click on 'Show File Dialog' button. A file dialog will come up. + 2) Navigate to the Applications folder if not already there. + 3) Check that the application bundles can be selected + but can not be navigated. + 4) If it's true then press Pass, otherwise press Fail. + """; + + PassFailJFrame.builder() + .title("Directory File Dialog Test Instructions") + .instructions(instructions) + .rows((int) instructions.lines().count() + 1) + .columns(40) + .logArea(8) + .splitUIBottom(FileDialogForPackages::initialize) + .build() + .awaitAndCheck(); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogOpenDirTest/FileDialogOpenDirTest.html openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogOpenDirTest/FileDialogOpenDirTest.html --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogOpenDirTest/FileDialogOpenDirTest.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogOpenDirTest/FileDialogOpenDirTest.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ - - - - - -FileDialogOpenDirTest - - - -

FileDialogOpenDirTest
Bug ID: 4974135

- -

See the dialog box (usually in upper left corner) for instructions

- - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogOpenDirTest/FileDialogOpenDirTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogOpenDirTest/FileDialogOpenDirTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogOpenDirTest/FileDialogOpenDirTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogOpenDirTest/FileDialogOpenDirTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,239 +0,0 @@ -/* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - test - @bug 4974135 - @summary FileDialog should open current directory by default. - @author tav@sparc.spb.su area=awt.filedialog - @run applet/manual=yesno FileDialogOpenDirTest.html -*/ - -import java.awt.*; -import java.awt.event.*; -import java.applet.*; - -public class FileDialogOpenDirTest extends Applet { - - public static void main(String[] args) { - Applet a = new FileDialogOpenDirTest(); - a.init(); - a.start(); - } - - public void init() - { - System.setProperty("sun.awt.disableGtkFileDialogs","true"); - //Create instructions for the user here, as well as set up - // the environment -- set the layout manager, add buttons, - // etc. - this.setLayout (new BorderLayout ()); - - String curdir = System.getProperty("user.dir"); - - String[] instructions1 = - { - "After test started you will see 'Test Frame' with a button inside.", - "Click the button to open FileDialog.", - "Verify that the directory opened is current directory, that is:", - curdir, - "If so press PASSED, otherwise FAILED." - }; - - String[] instructions2 = - { - "The test is not applicable for current platform. Press PASSED." - }; - - Sysout.createDialogWithInstructions(Toolkit.getDefaultToolkit().getClass().getName(). - equals("sun.awt.X11.XToolkit") ? - instructions1 : instructions2); - } - - public void start() { - Frame frame = new Frame("Test Frame"); - Button open = new Button("Open File Dialog"); - - open.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - new FileDialog(new Frame()).show(); - } - }); - - frame.setLayout(new FlowLayout()); - frame.add(open); - - int x = 0; - int y = 0; - Component dlg = null; - - if ((dlg = Sysout.getDialog()) != null) { - x = dlg.getBounds().x + dlg.getBounds().width; - y = dlg.getBounds().y; - } - frame.setBounds(x, y, 150, 70); - frame.setVisible(true); - } -} - - -/**************************************************** - Standard Test Machinery - DO NOT modify anything below -- it's a standard - chunk of code whose purpose is to make user - interaction uniform, and thereby make it simpler - to read and understand someone else's test. - ****************************************************/ - -/** - This is part of the standard test machinery. - It creates a dialog (with the instructions), and is the interface - for sending text messages to the user. - To print the instructions, send an array of strings to Sysout.createDialog - WithInstructions method. Put one line of instructions per array entry. - To display a message for the tester to see, simply call Sysout.println - with the string to be displayed. - This mimics System.out.println but works within the test harness as well - as standalone. - */ - -class Sysout -{ - private static TestDialog dialog; - - public static void createDialogWithInstructions( String[] instructions ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - dialog.printInstructions( instructions ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); - } - - public static void createDialog( ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - String[] defInstr = { "Instructions will appear here. ", "" } ; - dialog.printInstructions( defInstr ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); - } - - - public static void printInstructions( String[] instructions ) - { - dialog.printInstructions( instructions ); - } - - - public static void println( String messageIn ) - { - dialog.displayMessage( messageIn ); - } - - public static Component getDialog() { - return dialog; - } - -}// Sysout class - -/** - This is part of the standard test machinery. It provides a place for the - test instructions to be displayed, and a place for interactive messages - to the user to be displayed. - To have the test instructions displayed, see Sysout. - To have a message to the user be displayed, see Sysout. - Do not call anything in this dialog directly. - */ -class TestDialog extends Dialog -{ - - TextArea instructionsText; - TextArea messageText; - int maxStringLength = 80; - - //DO NOT call this directly, go through Sysout - public TestDialog( Frame frame, String name ) - { - super( frame, name ); - int scrollBoth = TextArea.SCROLLBARS_BOTH; - instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); - add( "North", instructionsText ); - - messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); - add("Center", messageText); - - pack(); - - setVisible(true); - }// TestDialog() - - //DO NOT call this directly, go through Sysout - public void printInstructions( String[] instructions ) - { - //Clear out any current instructions - instructionsText.setText( "" ); - - //Go down array of instruction strings - - String printStr, remainingStr; - for( int i=0; i < instructions.length; i++ ) - { - //chop up each into pieces maxSringLength long - remainingStr = instructions[ i ]; - while( remainingStr.length() > 0 ) - { - //if longer than max then chop off first max chars to print - if( remainingStr.length() >= maxStringLength ) - { - //Try to chop on a word boundary - int posOfSpace = remainingStr. - lastIndexOf( ' ', maxStringLength - 1 ); - - if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; - - printStr = remainingStr.substring( 0, posOfSpace + 1 ); - remainingStr = remainingStr.substring( posOfSpace + 1 ); - } - //else just print - else - { - printStr = remainingStr; - remainingStr = ""; - } - - instructionsText.append( printStr + "\n" ); - - }// while - - }// for - - }//printInstructions() - - //DO NOT call this directly, go through Sysout - public void displayMessage( String messageIn ) - { - messageText.append( messageIn + "\n" ); - System.out.println(messageIn); - } - -}// TestDialog class diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogOpenDirTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogOpenDirTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogOpenDirTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogOpenDirTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.FileDialog; +import java.awt.Frame; +import java.awt.Toolkit; +import java.lang.reflect.InvocationTargetException; +import javax.swing.JButton; +import jtreg.SkippedException; + +/* + * @test + * @bug 4974135 + * @summary FileDialog should open current directory by default. + * @requires (os.family == "linux") + * @library /java/awt/regtesthelpers + * @library /test/lib + * @build PassFailJFrame + * @build jtreg.SkippedException + * @run main/manual FileDialogOpenDirTest + */ + +public class FileDialogOpenDirTest { + private static JButton initialize() { + System.setProperty("sun.awt.disableGtkFileDialogs", "true"); + + JButton open = new JButton("Open File Dialog"); + open.addActionListener(e -> { + new FileDialog((Frame) null).setVisible(true); + }); + + return open; + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + String toolkit = Toolkit.getDefaultToolkit().getClass().getName(); + if (!toolkit.equals("sun.awt.X11.XToolkit")) { + throw new SkippedException("Test is not designed for toolkit " + toolkit); + } + + String curdir = System.getProperty("user.dir"); + String instructions = """ + Click the \"Open File Dialog\" button below to open FileDialog. + Verify that the directory opened is current directory, that is: + $curdir, + If so press Pass, otherwise press Fail + """.replace("$curdir", curdir); + + PassFailJFrame.builder() + .title("Directory File Dialog Test Instructions") + .instructions(instructions) + .rows((int) instructions.lines().count() + 1) + .columns(40) + .splitUIBottom(FileDialogOpenDirTest::initialize) + .build() + .awaitAndCheck(); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogReturnTest/FileDialogReturnTest.html openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogReturnTest/FileDialogReturnTest.html --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogReturnTest/FileDialogReturnTest.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogReturnTest/FileDialogReturnTest.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ - - - - - - FileDialogReturnTest - - - -

FileDialogReturnTest
Bug ID:

- -

See the dialog box (usually in upper left corner) for instructions

- - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogReturnTest/FileDialogReturnTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogReturnTest/FileDialogReturnTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogReturnTest/FileDialogReturnTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogReturnTest/FileDialogReturnTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,246 +0,0 @@ -/* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - test - @bug 6260676 - @summary FileDialog.setDirectory() does not work properly, XToolkit - @author Dmitry.Cherepanov area=awt.filedialog - @run applet/manual=yesno FileDialogReturnTest.html -*/ - -import java.applet.Applet; -import java.awt.*; -import java.awt.event.*; - -/* - * Current implementation of the FileDialog class doesn't provide - * any explicit method to get the return value after the user closes - * the dialog. The only way to detect whether the user cancels the - * dialog or the user selects any file is to use the getFile() method. - * The getFile() method should return null value if the user cancels - * the dialog or non-null value if the user selects any file. - */ -public class FileDialogReturnTest extends Applet -{ - - public static void main(String[] args) { - Applet a = new FileDialogReturnTest(); - a.init(); - a.start(); - } - - public void init() - { - this.setLayout (new BorderLayout ()); - - String[] instructions = - { - " 1. The test shows the 'FileDialogReturnTest' applet which contains two text fields and one button, ", - " 2. Input something into the 'File:' text field or just keep the field empty, ", - " 3. Input something into the 'Dir:' text field or just keep the field empty, ", - " 4. Press the 'Show' button and a file dialog will appear, ", - " 5-1. Cancel the file dialog, e.g. by selecting the 'close' menu item, ", - " If the output window shows that 'file'/'dir' values is null then the test passes, otherwise the test fails, ", - " 5-2. Select any file, e.g. by pressing the 'OK' button, ", - " If the output window shows that 'file'/'dir' values is not-null then the test passes, otherwise the test fails. " - }; - Sysout.createDialogWithInstructions( instructions ); - - }//End init() - - final TextField fileField = new TextField("", 20); - final TextField dirField = new TextField("", 20); - final Button button = new Button("Show"); - - public void start () - { - setLayout(new FlowLayout()); - - add(new Label("File:")); - add(fileField); - add(new Label("Dir:")); - add(dirField); - add(button); - - button.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - showDialog(); - } - }); - - setSize (200,200); - setVisible(true); - validate(); - } - - void showDialog() - { - FileDialog fd = new FileDialog(new Frame()); - fd.setFile(fileField.getText()); - fd.setDirectory(dirField.getText()); - fd.setVisible(true); - - Sysout.println("[file=" + fd.getFile()+"]"); - Sysout.println("[dir=" + fd.getDirectory()+"]"); - } - -} - - -/**************************************************** - Standard Test Machinery - DO NOT modify anything below -- it's a standard - chunk of code whose purpose is to make user - interaction uniform, and thereby make it simpler - to read and understand someone else's test. - ****************************************************/ - -/** - This is part of the standard test machinery. - It creates a dialog (with the instructions), and is the interface - for sending text messages to the user. - To print the instructions, send an array of strings to Sysout.createDialog - WithInstructions method. Put one line of instructions per array entry. - To display a message for the tester to see, simply call Sysout.println - with the string to be displayed. - This mimics System.out.println but works within the test harness as well - as standalone. - */ - -class Sysout -{ - private static TestDialog dialog; - - public static void createDialogWithInstructions( String[] instructions ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - dialog.printInstructions( instructions ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); - } - - public static void createDialog( ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - String[] defInstr = { "Instructions will appear here. ", "" } ; - dialog.printInstructions( defInstr ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); - } - - - public static void printInstructions( String[] instructions ) - { - dialog.printInstructions( instructions ); - } - - - public static void println( String messageIn ) - { - dialog.displayMessage( messageIn ); - } - -}// Sysout class - -/** - This is part of the standard test machinery. It provides a place for the - test instructions to be displayed, and a place for interactive messages - to the user to be displayed. - To have the test instructions displayed, see Sysout. - To have a message to the user be displayed, see Sysout. - Do not call anything in this dialog directly. - */ -class TestDialog extends Dialog -{ - - TextArea instructionsText; - TextArea messageText; - int maxStringLength = 100; - - //DO NOT call this directly, go through Sysout - public TestDialog( Frame frame, String name ) - { - super( frame, name ); - int scrollBoth = TextArea.SCROLLBARS_BOTH; - instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); - add( "North", instructionsText ); - - messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); - add("Center", messageText); - - pack(); - - setVisible(true); - }// TestDialog() - - //DO NOT call this directly, go through Sysout - public void printInstructions( String[] instructions ) - { - //Clear out any current instructions - instructionsText.setText( "" ); - - //Go down array of instruction strings - - String printStr, remainingStr; - for( int i=0; i < instructions.length; i++ ) - { - //chop up each into pieces maxSringLength long - remainingStr = instructions[ i ]; - while( remainingStr.length() > 0 ) - { - //if longer than max then chop off first max chars to print - if( remainingStr.length() >= maxStringLength ) - { - //Try to chop on a word boundary - int posOfSpace = remainingStr. - lastIndexOf( ' ', maxStringLength - 1 ); - - if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; - - printStr = remainingStr.substring( 0, posOfSpace + 1 ); - remainingStr = remainingStr.substring( posOfSpace + 1 ); - } - //else just print - else - { - printStr = remainingStr; - remainingStr = ""; - } - - instructionsText.append( printStr + "\n" ); - - }// while - - }// for - - }//printInstructions() - - //DO NOT call this directly, go through Sysout - public void displayMessage( String messageIn ) - { - messageText.append( messageIn + "\n" ); - System.out.println(messageIn); - } - -}// TestDialog class diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogReturnTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogReturnTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileDialogReturnTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileDialogReturnTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Button; +import java.awt.FileDialog; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Label; +import java.awt.TextField; +import java.awt.Toolkit; +import java.lang.reflect.InvocationTargetException; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import jtreg.SkippedException; + +/* + * @test + * @bug 6260676 + * @summary FileDialog.setDirectory() does not work properly, XToolkit + * @requires (os.family == "linux") + * @library /java/awt/regtesthelpers + * @library /test/lib + * @build PassFailJFrame + * @build jtreg.SkippedException + * @run main/manual FileDialogReturnTest + */ + +public class FileDialogReturnTest { + + private static JFrame initialize() { + JFrame frame = new JFrame("File Dialog Return Test Frame"); + GridBagConstraints gbc = new GridBagConstraints(); + GridBagLayout grid = new GridBagLayout(); + frame.setLayout(grid); + JTextArea textOutput = new JTextArea(8, 30); + textOutput.setLineWrap(true); + JScrollPane textScrollPane = new JScrollPane(textOutput); + gbc.insets = new Insets(5, 5, 5, 5); + + gbc.gridx = 0; + gbc.gridy = 0; + gbc.gridwidth = 1; + gbc.fill = GridBagConstraints.WEST; + frame.add(new Label("File:"), gbc); + + TextField fileField = new TextField("", 20); + gbc.gridx = 1; + gbc.gridy = 0; + gbc.fill = GridBagConstraints.HORIZONTAL; + frame.add(fileField, gbc); + + gbc.gridx = 0; + gbc.gridy = 1; + gbc.fill = GridBagConstraints.WEST; + frame.add(new Label("Dir:"), gbc); + + TextField dirField = new TextField("", 20); + gbc.gridx = 1; + gbc.gridy = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + frame.add(dirField, gbc); + + Button button = new Button("Show"); + gbc.gridx = 0; + gbc.gridy = 2; + gbc.gridwidth = 2; + gbc.fill = GridBagConstraints.CENTER; + frame.add(button, gbc); + + gbc.gridx = 0; + gbc.gridy = 3; + gbc.gridwidth = 2; + frame.add(textScrollPane, gbc); + + button.addActionListener(e -> { + FileDialog fd = new FileDialog(frame); + fd.setFile(fileField.getText()); + fd.setDirectory(dirField.getText()); + fd.setVisible(true); + + textOutput.append("[file=" + fd.getFile()+"]\n"); + textOutput.append("[dir=" + fd.getDirectory()+"]\n"); + textOutput.setCaretPosition(textOutput.getText().length()); + + }); + frame.pack(); + return frame; + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + String instructions = """ + 1) The test shows the 'File Dialog Return Test Frame' frame + that contains two text fields, one button and an output area. + 2) Input something into the 'File:' text field or just keep the field empty. + 3) Input something into the 'Dir:' text field or just keep the field empty. + 4) Press the 'Show' button and a file dialog will appear. + 5-1) Cancel the file dialog, e.g. by selecting the 'close' menu item. + If the output window shows that 'file'/'dir' values are null + then the test passes, otherwise the test fails. + 5-2) Select any file by double clicking on it. + If the output window shows that 'file'/'dir' values are not-null + then the test passes, otherwise the test fails. + """; + + String toolkit = Toolkit.getDefaultToolkit().getClass().getName(); + if (!toolkit.equals("sun.awt.X11.XToolkit")) { + throw new SkippedException("Test is not designed for toolkit " + toolkit); + } + + PassFailJFrame.builder() + .title("File Dialog Return Test Instructions") + .instructions(instructions) + .rows((int) instructions.lines().count() + 1) + .columns(50) + .testUI(FileDialogReturnTest::initialize) + .build() + .awaitAndCheck(); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileNameOverrideTest/FileNameOverrideTest.html openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileNameOverrideTest/FileNameOverrideTest.html --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileNameOverrideTest/FileNameOverrideTest.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileNameOverrideTest/FileNameOverrideTest.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ - - - - - - FileNameOverrideTest - - - -

FileNameOverrideTest
Bug ID: 6260659

- -

See the dialog box (usually in upper left corner) for instructions

- - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileNameOverrideTest/FileNameOverrideTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileNameOverrideTest/FileNameOverrideTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileNameOverrideTest/FileNameOverrideTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileNameOverrideTest/FileNameOverrideTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - test - @bug 6260659 - @summary File Name set programmatically in FileDialog is overridden during navigation, XToolkit - @author Dmitry.Cherepanov@SUN.COM area=awt.filedialog - @library ../../regtesthelpers - @build Sysout - @run applet/manual=yesno FileNameOverrideTest.html -*/ - -import test.java.awt.regtesthelpers.Sysout; - -import java.applet.Applet; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.File; -import java.io.IOException; - -public class FileNameOverrideTest extends Applet implements ActionListener { - private final static String fileName = "input"; - private final static String clickDirName = "Directory for double click"; - private final static String dirPath = "."; - private Button showBtn; - private FileDialog fd; - - public void init() { - this.setLayout(new GridLayout(1, 1)); - - fd = new FileDialog(new Frame(), "Open"); - - showBtn = new Button("Show File Dialog"); - showBtn.addActionListener(this); - add(showBtn); - - try { - File tmpFileUp = new File(dirPath + File.separator + fileName); - File tmpDir = new File(dirPath + File.separator + clickDirName); - File tmpFileIn = new File(tmpDir.getAbsolutePath() + File.separator + fileName); - tmpDir.mkdir(); - tmpFileUp.createNewFile(); - tmpFileIn.createNewFile(); - } catch (IOException ex) { - throw new RuntimeException("Cannot create test folder", ex); - } - - String[] instructions = { - "1) Click on 'Show File Dialog' button. A file dialog will come up.", - "2) Double-click on '" + clickDirName + "' and click OK.", - "3) See result of the test below" - }; - Sysout.createDialogWithInstructions(instructions); - }//End init() - - public void start() { - setSize(200, 200); - show(); - }// start() - - public void actionPerformed(ActionEvent e) { - if (e.getSource() == showBtn) { - fd.setFile(fileName); - fd.setDirectory(dirPath); - fd.setVisible(true); - String output = fd.getFile(); - if (fileName.equals(output)) { - Sysout.println("TEST PASSED"); - } else { - Sysout.println("TEST FAILED (output file - " + output + ")"); - } - } - } -}// class ManualYesNoTest diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileNameOverrideTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileNameOverrideTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/FileNameOverrideTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/FileNameOverrideTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.FileDialog; +import java.awt.Frame; +import java.awt.Toolkit; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import javax.swing.JButton; +import jtreg.SkippedException; + +/* + * @test + * @bug 6260659 + * @summary File Name set programmatically in FileDialog is overridden during navigation, XToolkit + * @requires (os.family == "linux") + * @library /java/awt/regtesthelpers + * @library /test/lib + * @build PassFailJFrame + * @build jtreg.SkippedException + * @run main/manual FileNameOverrideTest + */ + +public class FileNameOverrideTest { + private final static String clickDirName = "Directory for double click"; + + private static JButton initialize() { + final String fileName = "input"; + final String dirPath = System.getProperty("user.dir");; + + JButton showBtn = new JButton("Show File Dialog"); + showBtn.addActionListener(w -> { + FileDialog fd = new FileDialog((Frame) null, "Open"); + fd.setFile(fileName); + fd.setDirectory(dirPath); + fd.setVisible(true); + String output = fd.getFile(); + fd.dispose(); + if (fileName.equals(output)) { + PassFailJFrame.forcePass(); + } else { + PassFailJFrame.forceFail("File name mismatch: " + + fileName + " vs " + output); + } + }); + + try { + File tmpFileUp = new File(dirPath + File.separator + fileName); + File tmpDir = new File(dirPath + File.separator + clickDirName); + File tmpFileIn = new File(tmpDir.getAbsolutePath() + File.separator + fileName); + tmpDir.mkdir(); + tmpFileUp.createNewFile(); + tmpFileIn.createNewFile(); + } catch (IOException ex) { + throw new RuntimeException("Cannot create test folder", ex); + } + + return showBtn; + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + String instructions = """ + 1) Click on 'Show File Dialog' button. A file dialog will come up. + 2) Double-click on '$clickDirName' and click OK or Open + to confirm selection (label on the button depends on the current window manager). + 3) Test will pass or fail automatically. + """.replace("$clickDirName", clickDirName); + + String toolkit = Toolkit.getDefaultToolkit().getClass().getName(); + if (!toolkit.equals("sun.awt.X11.XToolkit")) { + throw new SkippedException("Test is not designed for toolkit " + toolkit); + } + + PassFailJFrame.builder() + .title("File Dialog Return Test Instructions") + .instructions(instructions) + .rows((int) instructions.lines().count() + 1) + .columns(50) + .splitUIBottom(FileNameOverrideTest::initialize) + .build() + .awaitAndCheck(); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/MultipleMode/MultipleMode.html openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/MultipleMode/MultipleMode.html --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/MultipleMode/MultipleMode.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/MultipleMode/MultipleMode.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ - - - - - - MultipleMode - - - -

MultipleMode
Bug ID: 6467204

- -

See the dialog box (usually in upper left corner) for instructions

- - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/MultipleMode/MultipleMode.java openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/MultipleMode/MultipleMode.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/MultipleMode/MultipleMode.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/MultipleMode/MultipleMode.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - test - @bug 6467204 - @summary Need to implement "extended" native FileDialog for JFileChooser - @author dmitry.cherepanov@sun.com area=awt.filedialog - @run applet/manual=yesno MultipleMode.html -*/ - -// Note there is no @ in front of test above. This is so that the -// harness will not mistake this file as a test file. It should -// only see the html file as a test file. (the harness runs all -// valid test files, so it would run this test twice if this file -// were valid as well as the html file.) -// Also, note the area= after Your Name in the author tag. Here, you -// should put which functional area the test falls in. See the -// AWT-core home page -> test areas and/or -> AWT team for a list of -// areas. -// There are several places where ManualYesNoTest appear. It is -// recommended that these be changed by a global search and replace, -// such as ESC-% in xemacs. - - - -/** - * MultipleMode.java - * - * summary: - */ - -import java.applet.Applet; -import java.awt.*; -import java.awt.event.*; -import java.io.File; - - -//Manual tests should run as applet tests if possible because they -// get their environments cleaned up, including AWT threads, any -// test created threads, and any system resources used by the test -// such as file descriptors. (This is normally not a problem as -// main tests usually run in a separate VM, however on some platforms -// such as the Mac, separate VMs are not possible and non-applet -// tests will cause problems). Also, you don't have to worry about -// synchronisation stuff in Applet tests the way you do in main -// tests... - - -public class MultipleMode extends Applet -{ - //Declare things used in the test, like buttons and labels here - - public void init() - { - //Create instructions for the user here, as well as set up - // the environment -- set the layout manager, add buttons, - // etc. - this.setLayout (new BorderLayout ()); - - String[] instructions = - { - " 1. Turn the 'multiple' checkbox off and press the 'open' button ", - " 2. Verify that the file dialog doesn't allow the multiple file selection ", - " 3. Select any file and close the file dialog ", - " 4. The results will be displayed, verify the results ", - " 5. Turn the 'multiple' checkbox on and press the 'open' button ", - " 6. Verify that the file dialog allows the multiple file selection ", - " 7. Select several files and close the file dialog ", - " 8. The results will be displayed, verify the results " - }; - Sysout.createDialogWithInstructions( instructions ); - - }//End init() - - public void start () - { - final Checkbox mode = new Checkbox("multiple", true); - Button open = new Button("open"); - open.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - FileDialog d = new FileDialog((Frame)null); - d.setMultipleMode(mode.getState()); - d.setVisible(true); - - // print the results - Sysout.println("DIR:"); - Sysout.println(d.getDirectory()); - Sysout.println("FILE:"); - Sysout.println(d.getFile()); - Sysout.println("FILES:"); - File files[] = d.getFiles(); - for (File f : files) { - Sysout.println(String.valueOf(f)); - } - } - }); - - setLayout(new FlowLayout()); - add(mode); - add(open); - - //Get things going. Request focus, set size, et cetera - setSize (200,200); - setVisible(true); - validate(); - - }// start() - - //The rest of this class is the actions which perform the test... - - //Use Sysout.println to communicate with the user NOT System.out!! - //Sysout.println ("Something Happened!"); - -}// class ManualYesNoTest - -/* Place other classes related to the test after this line */ - - - - - -/**************************************************** - Standard Test Machinery - DO NOT modify anything below -- it's a standard - chunk of code whose purpose is to make user - interaction uniform, and thereby make it simpler - to read and understand someone else's test. - ****************************************************/ - -/** - This is part of the standard test machinery. - It creates a dialog (with the instructions), and is the interface - for sending text messages to the user. - To print the instructions, send an array of strings to Sysout.createDialog - WithInstructions method. Put one line of instructions per array entry. - To display a message for the tester to see, simply call Sysout.println - with the string to be displayed. - This mimics System.out.println but works within the test harness as well - as standalone. - */ - -class Sysout -{ - private static TestDialog dialog; - private static boolean numbering = false; - private static int messageNumber = 0; - - public static void createDialogWithInstructions( String[] instructions ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - dialog.printInstructions( instructions ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); - } - - public static void createDialog( ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - String[] defInstr = { "Instructions will appear here. ", "" } ; - dialog.printInstructions( defInstr ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); - } - - /* Enables message counting for the tester. */ - public static void enableNumbering(boolean enable){ - numbering = enable; - } - - public static void printInstructions( String[] instructions ) - { - dialog.printInstructions( instructions ); - } - - - public static void println( String messageIn ) - { - if (numbering) { - messageIn = "" + messageNumber + " " + messageIn; - messageNumber++; - } - dialog.displayMessage( messageIn ); - } - -}// Sysout class - -/** - This is part of the standard test machinery. It provides a place for the - test instructions to be displayed, and a place for interactive messages - to the user to be displayed. - To have the test instructions displayed, see Sysout. - To have a message to the user be displayed, see Sysout. - Do not call anything in this dialog directly. - */ -class TestDialog extends Dialog -{ - - TextArea instructionsText; - TextArea messageText; - int maxStringLength = 80; - - //DO NOT call this directly, go through Sysout - public TestDialog( Frame frame, String name ) - { - super( frame, name ); - int scrollBoth = TextArea.SCROLLBARS_BOTH; - instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); - add( "North", instructionsText ); - - messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); - add("Center", messageText); - - pack(); - - setVisible(true); - }// TestDialog() - - //DO NOT call this directly, go through Sysout - public void printInstructions( String[] instructions ) - { - //Clear out any current instructions - instructionsText.setText( "" ); - - //Go down array of instruction strings - - String printStr, remainingStr; - for( int i=0; i < instructions.length; i++ ) - { - //chop up each into pieces maxSringLength long - remainingStr = instructions[ i ]; - while( remainingStr.length() > 0 ) - { - //if longer than max then chop off first max chars to print - if( remainingStr.length() >= maxStringLength ) - { - //Try to chop on a word boundary - int posOfSpace = remainingStr. - lastIndexOf( ' ', maxStringLength - 1 ); - - if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; - - printStr = remainingStr.substring( 0, posOfSpace + 1 ); - remainingStr = remainingStr.substring( posOfSpace + 1 ); - } - //else just print - else - { - printStr = remainingStr; - remainingStr = ""; - } - - instructionsText.append( printStr + "\n" ); - - }// while - - }// for - - }//printInstructions() - - //DO NOT call this directly, go through Sysout - public void displayMessage( String messageIn ) - { - messageText.append( messageIn + "\n" ); - System.out.println(messageIn); - } - -}// TestDialog class diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/MultipleMode.java openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/MultipleMode.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/MultipleMode.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/MultipleMode.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Checkbox; +import java.awt.FileDialog; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.TextArea; +import java.io.File; + +/* + * @test + * @bug 6467204 + * @summary Need to implement "extended" native FileDialog for JFileChooser + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual MultipleMode +*/ + +public class MultipleMode { + + private static final String INSTRUCTIONS = + """ + 1. Verify that the 'multiple' checkbox is off and press the 'open' button + 2. Verify that the file dialog doesn't allow the multiple file selection + 3. Select any file and close the file dialog + 4. The results will be displayed, verify the results + 5. Turn the 'multiple' checkbox on and press the 'open' button + 6. Verify that the file dialog allows the multiple file selection + 7. Select several files and close the file dialog + 8. The results will be displayed, verify the results. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame + .builder() + .title("MultipleMode test instructions") + .instructions(INSTRUCTIONS) + .rows(15) + .columns(40) + .position(PassFailJFrame.Position.TOP_LEFT_CORNER) + .testUI(MultipleMode::init) + .build() + .awaitAndCheck(); + } + + private static Frame init() { + Frame frame = new Frame("MultipleMode"); + TextArea sysout = new TextArea("", 20, 70); + sysout.setEditable(false); + + final Checkbox mode = new Checkbox("multiple", false); + + Button open = new Button("open"); + open.addActionListener(e -> { + FileDialog d = new FileDialog(frame); + d.setMultipleMode(mode.getState()); + d.setVisible(true); + + // print the results + sysout.append("DIR:\n"); + sysout.append(" %s\n".formatted(d.getDirectory())); + sysout.append("FILE:\n"); + sysout.append(" %s\n".formatted(d.getFile())); + sysout.append("FILES:\n"); + for (File f : d.getFiles()) { + sysout.append(" %s\n".formatted(f)); + } + }); + + Panel panel = new Panel(new FlowLayout()); + panel.add(mode); + panel.add(open); + + frame.setLayout(new BorderLayout()); + frame.add(panel, BorderLayout.NORTH); + frame.add(sysout, BorderLayout.CENTER); + + frame.pack(); + + return frame; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/RegexpFilterTest/RegexpFilterTest.html openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/RegexpFilterTest/RegexpFilterTest.html --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/RegexpFilterTest/RegexpFilterTest.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/RegexpFilterTest/RegexpFilterTest.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ - - - - - - RegexpFilterTest - - - -


Bug ID:

- -

See the dialog box (usually in upper left corner) for instructions

- - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/RegexpFilterTest/RegexpFilterTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/RegexpFilterTest/RegexpFilterTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/RegexpFilterTest/RegexpFilterTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/RegexpFilterTest/RegexpFilterTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - test - @bug 4934185 - @summary JCK1.5-runtime-interactive: XToolkit FileDialog does not work as expected - @author Dmitry.Cherepanov area=awt.filedialog - @run applet/manual=yesno RegexpFilterTest.html -*/ - -import java.applet.Applet; -import java.awt.*; -import java.awt.event.*; - -/* - * Motif file dialogs let the user specify a filter that controls the files that - * are displayed in the dialog. This filter is generally specified as a regular - * expression. The test verifies that Motif-like filtering works fine using - * XAWT-toolkit also. - */ -public class RegexpFilterTest extends Applet -{ - - public static void main(String[] args) { - Applet a = new RegexpFilterTest(); - a.init(); - a.start(); - } - - public void init() - { - this.setLayout (new BorderLayout ()); - - String[] instructions = - { - " 0. The test is only for X platforms", - " 1. Press the 'Show' button and a file dialog will appear, ", - " 2. Input any string into the 'Filter' text field, ", - " This filter is generally specified as a regular expression ", - " (e.g., * matches all files, while *.c matches all files that end in .c) ", - " 3. Press 'Enter' to refresh the displayed files with the filter, ", - " 4. If the list of the files contains all actual files matched the filter, ", - " then the test passed; otherwise it failed. " - }; - Sysout.createDialogWithInstructions( instructions ); - - }//End init() - - public void start () - { - setLayout(new FlowLayout()); - Button button = new Button("Show"); - add(button); - - button.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - FileDialog fd = new FileDialog(new Frame()); - fd.setVisible(true); - } - }); - - setSize (200,200); - setVisible(true); - validate(); - } - -} - - -/**************************************************** - Standard Test Machinery - DO NOT modify anything below -- it's a standard - chunk of code whose purpose is to make user - interaction uniform, and thereby make it simpler - to read and understand someone else's test. - ****************************************************/ - -/** - This is part of the standard test machinery. - It creates a dialog (with the instructions), and is the interface - for sending text messages to the user. - To print the instructions, send an array of strings to Sysout.createDialog - WithInstructions method. Put one line of instructions per array entry. - To display a message for the tester to see, simply call Sysout.println - with the string to be displayed. - This mimics System.out.println but works within the test harness as well - as standalone. - */ - -class Sysout -{ - private static TestDialog dialog; - - public static void createDialogWithInstructions( String[] instructions ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - dialog.printInstructions( instructions ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); - } - - public static void createDialog( ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - String[] defInstr = { "Instructions will appear here. ", "" } ; - dialog.printInstructions( defInstr ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); - } - - - public static void printInstructions( String[] instructions ) - { - dialog.printInstructions( instructions ); - } - - - public static void println( String messageIn ) - { - dialog.displayMessage( messageIn ); - } - -}// Sysout class - -/** - This is part of the standard test machinery. It provides a place for the - test instructions to be displayed, and a place for interactive messages - to the user to be displayed. - To have the test instructions displayed, see Sysout. - To have a message to the user be displayed, see Sysout. - Do not call anything in this dialog directly. - */ -class TestDialog extends Dialog -{ - - TextArea instructionsText; - TextArea messageText; - int maxStringLength = 100; - - //DO NOT call this directly, go through Sysout - public TestDialog( Frame frame, String name ) - { - super( frame, name ); - int scrollBoth = TextArea.SCROLLBARS_BOTH; - instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); - add( "North", instructionsText ); - - messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); - add("Center", messageText); - - pack(); - - setVisible(true); - }// TestDialog() - - //DO NOT call this directly, go through Sysout - public void printInstructions( String[] instructions ) - { - //Clear out any current instructions - instructionsText.setText( "" ); - - //Go down array of instruction strings - - String printStr, remainingStr; - for( int i=0; i < instructions.length; i++ ) - { - //chop up each into pieces maxSringLength long - remainingStr = instructions[ i ]; - while( remainingStr.length() > 0 ) - { - //if longer than max then chop off first max chars to print - if( remainingStr.length() >= maxStringLength ) - { - //Try to chop on a word boundary - int posOfSpace = remainingStr. - lastIndexOf( ' ', maxStringLength - 1 ); - - if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; - - printStr = remainingStr.substring( 0, posOfSpace + 1 ); - remainingStr = remainingStr.substring( posOfSpace + 1 ); - } - //else just print - else - { - printStr = remainingStr; - remainingStr = ""; - } - - instructionsText.append( printStr + "\n" ); - - }// while - - }// for - - }//printInstructions() - - //DO NOT call this directly, go through Sysout - public void displayMessage( String messageIn ) - { - messageText.append( messageIn + "\n" ); - System.out.println(messageIn); - } - -}// TestDialog class diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/RegexpFilterTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/RegexpFilterTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/RegexpFilterTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/RegexpFilterTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.JButton; +import java.awt.Frame; +import java.awt.FileDialog; + +/* + * Motif file dialogs let the user specify a filter that controls the files that + * are displayed in the dialog. This filter is generally specified as a regular + * expression. The test verifies that Motif-like filtering works fine using + * XAWT-toolkit also. + */ + +/* + * @test + * @bug 4934185 + * @summary JCK1.5-runtime-interactive: XToolkit FileDialog does not work as expected + * @requires (os.family == "linux") + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/othervm/manual -Dsun.awt.disableGtkFileDialogs=true RegexpFilterTest +*/ +public class RegexpFilterTest { + + private static final String INSTRUCTIONS = + """ + 0. The test is only for X platforms + 1. Press the 'Show' button and a file dialog will appear, + 2. Input any string into the 'Filter' text field, + This filter is generally specified as a regular expression + (e.g., * matches all files, while *.c matches all files that end in .c) + 3. Press 'Enter' to refresh the displayed files with the filter, + 4. If the list of the files contains all actual files matched the filter, + then the test passed; otherwise it failed. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame + .builder() + .title("RegexpFilterTest Instructions") + .instructions(INSTRUCTIONS) + .splitUIRight(() -> { + JButton show = new JButton("show"); + show.addActionListener(e -> + new FileDialog((Frame) null).setVisible(true)); + return show; + }) + .rows(15) + .columns(40) + .build() + .awaitAndCheck(); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/SaveFileNameOverrideTest/SaveFileNameOverrideTest.html openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/SaveFileNameOverrideTest/SaveFileNameOverrideTest.html --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/SaveFileNameOverrideTest/SaveFileNameOverrideTest.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/SaveFileNameOverrideTest/SaveFileNameOverrideTest.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ - - - - - - SaveFileNameOverrideTest - - - -

SaveFileNameOverrideTest
Bug ID: 6260659

- -

See the dialog box (usually in upper left corner) for instructions

- - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/SaveFileNameOverrideTest/SaveFileNameOverrideTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/SaveFileNameOverrideTest/SaveFileNameOverrideTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/SaveFileNameOverrideTest/SaveFileNameOverrideTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/SaveFileNameOverrideTest/SaveFileNameOverrideTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - test - @bug 6998877 8022531 - @summary After double-click on the folder names, FileNameOverrideTest FAILED - @author Sergey.Bylokhov@oracle.com area=awt.filedialog - @library ../../regtesthelpers - @build Sysout - @run applet/manual=yesno SaveFileNameOverrideTest.html -*/ - -import test.java.awt.regtesthelpers.Sysout; - -import java.applet.Applet; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.File; - -public class SaveFileNameOverrideTest extends Applet implements ActionListener { - private final static String clickDirName = "Directory for double click"; - private final static String dirPath = "."; - private Button showBtn; - private FileDialog fd; - - public void init() { - this.setLayout(new GridLayout(1, 1)); - - fd = new FileDialog(new Frame(), "Save", FileDialog.SAVE); - - showBtn = new Button("Show File Dialog"); - showBtn.addActionListener(this); - add(showBtn); - - File tmpDir = new File(dirPath + File.separator + clickDirName); - tmpDir.mkdir(); - - String[] instructions = { - "1) Click on 'Show File Dialog' button. A file dialog will come up.", - "2) Double-click on '" + clickDirName + "' and click a confirmation", - " button, it can be 'OK', 'Save' or any other platform-dependent name.", - "3) See result of the test below" - }; - - Sysout.createDialogWithInstructions(instructions); - - }//End init() - - public void start() { - setSize(200, 200); - show(); - }// start() - - public void actionPerformed(ActionEvent e) { - if (e.getSource() == showBtn) { - fd.setFile("input"); - fd.setDirectory(dirPath); - fd.setVisible(true); - String output = fd.getFile(); - if ("input".equals(output)) { - Sysout.println("TEST PASSED"); - } else { - Sysout.println("TEST FAILED (output file - " + output + ")"); - } - } - } -}// class ManualYesNoTest diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/SaveFileNameOverrideTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/SaveFileNameOverrideTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/FileDialog/SaveFileNameOverrideTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FileDialog/SaveFileNameOverrideTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.JButton; +import java.awt.FileDialog; +import java.awt.Frame; +import java.io.File; + +/* + * @test + * @bug 6998877 8022531 + * @summary After double-click on the folder names, FileNameOverrideTest FAILED + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual SaveFileNameOverrideTest + */ + +public class SaveFileNameOverrideTest { + + private final static String clickDirName = "Directory for double click"; + private static final String INSTRUCTIONS = + """ + 1) Click on the 'Show File Dialog' button. A file dialog will appear. + 2) Double-click on '%s' + 3) Click on a confirmation button. + (It can be 'OK', 'Save' or any other name depending on the platform). + 3) The test will automatically pass or fail. + """ + .formatted(clickDirName); + private final static String dirPath = "."; + + public static void main(String[] args) throws Exception { + System.out.println(System.getProperties()); + System.out.println(new File(dirPath).getAbsolutePath()); + File tmpDir = new File(dirPath + File.separator + clickDirName); + if (!tmpDir.mkdir()) { + throw new RuntimeException("Cannot create directory."); + } + tmpDir.deleteOnExit(); + + PassFailJFrame + .builder() + .title("SaveFileNameOverrideTest Instructions") + .instructions(INSTRUCTIONS) + .splitUIRight(SaveFileNameOverrideTest::getButton) + .rows(8) + .columns(40) + .build() + .awaitAndCheck(); + } + + public static JButton getButton() { + JButton showBtn = new JButton("Show File Dialog"); + showBtn.addActionListener(e -> { + FileDialog fd = + new FileDialog((Frame) null, "Save", FileDialog.SAVE); + + fd.setFile("input"); + fd.setDirectory(new File(dirPath).getAbsolutePath()); + fd.setVisible(true); + + String output = fd.getFile(); + if ("input".equals(output)) { + PassFailJFrame.forcePass(); + } else { + PassFailJFrame.forceFail("TEST FAILED (output file - " + output + ")"); + } + }); + return showBtn; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/FontMetrics/ExtremeFontSizeTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/FontMetrics/ExtremeFontSizeTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/FontMetrics/ExtremeFontSizeTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/FontMetrics/ExtremeFontSizeTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,16 +24,19 @@ import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; +import java.awt.GraphicsEnvironment; import java.awt.Rectangle; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; +import java.util.HashMap; +import java.util.Map; /* * @test - * @bug 8328896 + * @bug 8328896 8357672 * @summary test that using very large font sizes used don't break later uses */ @@ -49,34 +52,106 @@ static double[] scales = { 1.0, 900.0}; static boolean[] fms = { false, true }; + static class Key { + int fontSize; + double scale; + boolean fm; + String str; + + + Key(int fs, double sc, boolean f, String s) { + fontSize = fs; + scale = sc; + fm = f; + str = s; + } + + public boolean equals(Object o) { + return + (o instanceof Key k) && + this.fontSize == k.fontSize && + this.scale == k.scale && + this.fm == k.fm && + this.str.equals(k.str); + } + + public int hashCode() { + return fontSize + (int)scale + (fm ? 1 : 0) + str.hashCode(); + } + } + + static class Value { + int height; + double strBounds; + Rectangle pixelBounds; + Rectangle2D visualBounds; + + Value(int h, double sb, Rectangle pb, Rectangle2D vb) { + height = h; + strBounds = sb; + pixelBounds = pb; + visualBounds = vb; + } + + public boolean equals(Object o) { + return + (o instanceof Value v) && + this.height == v.height && + this.strBounds == v.strBounds && + this.pixelBounds.equals(v.pixelBounds) && + this.visualBounds.equals(v.visualBounds); + } + + public int hashCode() { + return height + (int)strBounds + pixelBounds.hashCode() + visualBounds.hashCode(); + } + } + + static Map metricsMap = new HashMap(); + public static void main(String[] args) { + Font[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts(); + for (Font f : fonts) { + font = f.deriveFont(Font.PLAIN, 12); + System.out.println("Test font : " + font); + if (font.canDisplayUpTo(testString) != -1) { + System.out.println("Skipping since cannot display test string"); + continue; + } + metricsMap = new HashMap(); + testFont(); + } + } + + static void testFont() { /* run tests validating bounds etc are non-zero * then run with extreme scales for which zero is allowed - but not required * then run the first tests again to be sure they are still reasonable. */ - runTests(); - test(5_000_000, 10_000, false, testString, false); - test(5_000_000, 10_000, true, testString, false); - test(0, 0.00000001, false, testString, false); - runTests(); + runTests(true, false); + test(5_000_000, 10_000, false, testString, false, false, false); + test(5_000_000, 10_000, true, testString, false, false, false); + test(0, 0.00000001, false, testString, false, false, false); + runTests(false, true); if (failed) { throw new RuntimeException("Test failed. Check stdout log."); } } - static void runTests() { + static void runTests(boolean add, boolean check) { for (int fontSize : fontSizes) { for (double scale : scales) { for (boolean fm : fms) { - test(fontSize, scale, fm, testString, true); + test(fontSize, scale, fm, testString, true, add, check); } } } } - static void test(int size, double scale, boolean fm, String str, boolean checkAll) { + static void test(int size, double scale, boolean fm, String str, + boolean checkAll, boolean add, boolean check) { AffineTransform at = AffineTransform.getScaleInstance(scale, scale); FontRenderContext frc = new FontRenderContext(at, false, fm); @@ -114,5 +189,22 @@ System.out.println(" *** RESULTS NOT AS EXPECTED *** "); } System.out.println(); + + Key k = null; + Value v = null; + if (add || check) { + k = new Key(size, scale, fm, str); + v = new Value(height, width, pixelBounds, visualBounds); + } + if (add) { + metricsMap.put(k, v); + } + if (check) { + Value vmap = metricsMap.get(k); + if (!v.equals(vmap)) { + failed = true; + System.out.println("Values differ"); + } + } } } diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/Frame/DisposeParentGC/DisposeParentGC.java openjdk-21-21.0.9+10/test/jdk/java/awt/Frame/DisposeParentGC/DisposeParentGC.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/Frame/DisposeParentGC/DisposeParentGC.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/Frame/DisposeParentGC/DisposeParentGC.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,7 +21,25 @@ * questions. */ -import java.awt.*; +import java.awt.Button; +import java.awt.Canvas; +import java.awt.Checkbox; +import java.awt.CheckboxGroup; +import java.awt.Choice; +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Label; +import java.awt.List; +import java.awt.Point; +import java.awt.Scrollbar; +import java.awt.TextArea; +import java.awt.TextField; +import java.awt.Toolkit; +import java.awt.Frame; +import java.awt.FlowLayout; import java.awt.image.BufferedImage; import java.lang.ref.PhantomReference; import java.lang.ref.ReferenceQueue; @@ -34,7 +52,6 @@ * @summary Display a dialog with a parent, the dialog contains all awt components * added to it & each components are setted with different cursors types. * Dispose the parent & collect GC. Garbage collection should happen - * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com) * @library /lib/client * @build ExtendedRobot * @run main/othervm -Xmx20m DisposeParentGC @@ -100,7 +117,7 @@ child.setLocation(20, 140 * number); Button button = new Button("Press Me") ; - TextArea textArea = new TextArea(5,5); + TextArea textArea = new TextArea(5, 5); TextField textField = new TextField(10); Choice choice = new Choice(); choice.add("One"); @@ -115,15 +132,15 @@ list.add("Four"); list.add("Five"); Checkbox checkBox = new Checkbox("Hai"); - Scrollbar scrollBar = new Scrollbar(Scrollbar.VERTICAL,0,1,0,200); + Scrollbar scrollBar = new Scrollbar(Scrollbar.VERTICAL, 0, 1, 0, 200); CheckboxGroup checkboxGroup = new CheckboxGroup(); - Checkbox radioButton = new Checkbox("Hello" ,true, checkboxGroup); + Checkbox radioButton = new Checkbox("Hello", true, checkboxGroup); Canvas canvas = new Canvas(); Label label = new Label("I am label!"); Cursor customCursor = null; child.setLayout(new FlowLayout()); - canvas.setSize(100,100); + canvas.setSize(100, 100); canvas.setBackground(Color.red); button.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR)); @@ -138,13 +155,17 @@ /* create a custom cursor */ Toolkit toolkit = Toolkit.getDefaultToolkit(); - Dimension d = toolkit.getBestCursorSize(32,32); + Dimension d = toolkit.getBestCursorSize(32, 32); int color = toolkit.getMaximumCursorColors(); - if(!d.equals(new Dimension(0,0)) && color != 0 ) - customCursor = toolkit.createCustomCursor(new BufferedImage( 16, 16, BufferedImage.TYPE_INT_RGB ), new Point(10, 10), "custom cursor."); - else + if (!d.equals(new Dimension(0,0)) && color != 0) { + customCursor = toolkit.createCustomCursor( + new BufferedImage(16, 16, BufferedImage.TYPE_INT_RGB), + new Point(10, 10), "custom cursor."); + } + else { System.err.println("Platform doesn't support to create a custom cursor."); + } textArea.setCursor(customCursor); child.add(label); diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/Frame/InitialMaximizedTest/InitialMaximizedTest.html openjdk-21-21.0.9+10/test/jdk/java/awt/Frame/InitialMaximizedTest/InitialMaximizedTest.html --- openjdk-21-21.0.8+9/test/jdk/java/awt/Frame/InitialMaximizedTest/InitialMaximizedTest.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/Frame/InitialMaximizedTest/InitialMaximizedTest.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ - - - - - - InitialMaximizedTest - - - -

InitialMaximizedTest
Bug ID: 4464714

- -

See the dialog box (usually in upper left corner) for instructions

- - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/Frame/InitialMaximizedTest/InitialMaximizedTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/Frame/InitialMaximizedTest/InitialMaximizedTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/Frame/InitialMaximizedTest/InitialMaximizedTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/Frame/InitialMaximizedTest/InitialMaximizedTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,197 +21,82 @@ * questions. */ +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.GraphicsConfiguration; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + /* - test - @bug 4464714 6365898 - @summary Frames cannot be shown initially maximized - @author Valeriy Ushakov: area=toplevel - @run applet/manual=yesno InitialMaximizedTest.html + * @test + * @bug 4464714 6365898 + * @key headful + * @summary Frames cannot be shown initially maximized */ +public class InitialMaximizedTest { -/** - * InitialMaximizedTest.java - * - * summary: - */ - -import java.applet.Applet; -import java.awt.*; - - -public class InitialMaximizedTest extends Applet -{ - Frame f; - - public void init() - { - this.setLayout (new BorderLayout ()); - - String[] instructions = - { - "This test creates a frame that is initially maximized.", - "Press PASS if frame is shown initially maximized, else press FAIL" - }; - Sysout.createDialogWithInstructions( instructions ); - - }//End init() - - public void start () - { - //Get things going. Request focus, set size, et cetera - setSize (200,200); - setVisible(true); - validate(); - - f = new Frame("The frame SHOULD be shown MAXIMIZED"); - f.setSize(300, 300); - f.setLocation(50, 50); - f.setExtendedState(Frame.MAXIMIZED_BOTH); - f.setVisible(true); - }// start() - -}// class InitialMaximizedTest - -/* Place other classes related to the test after this line */ - - - - - -/**************************************************** - Standard Test Machinery - DO NOT modify anything below -- it's a standard - chunk of code whose purpose is to make user - interaction uniform, and thereby make it simpler - to read and understand someone else's test. - ****************************************************/ - -/** - This is part of the standard test machinery. - It creates a dialog (with the instructions), and is the interface - for sending text messages to the user. - To print the instructions, send an array of strings to Sysout.createDialog - WithInstructions method. Put one line of instructions per array entry. - To display a message for the tester to see, simply call Sysout.println - with the string to be displayed. - This mimics System.out.println but works within the test harness as well - as standalone. - */ - -class Sysout -{ - private static TestDialog dialog; - - public static void createDialogWithInstructions( String[] instructions ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - dialog.printInstructions( instructions ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); - } + static Frame frame; - public static void createDialog( ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - String[] defInstr = { "Instructions will appear here. ", "" } ; - dialog.printInstructions( defInstr ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); + public static void main(String[] args) throws Exception { + if (!Toolkit.getDefaultToolkit() + .isFrameStateSupported(Frame.MAXIMIZED_BOTH)) { + return; + } + + Robot robot = new Robot(); + try { + EventQueue.invokeAndWait(InitialMaximizedTest::createAndShowFrame); + robot.waitForIdle(); + robot.delay(1000); + EventQueue.invokeAndWait(InitialMaximizedTest::checkMaximized); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } } + private static void checkMaximized() { + Rectangle frameBounds = frame.getBounds(); - public static void printInstructions( String[] instructions ) - { - dialog.printInstructions( instructions ); - } - + GraphicsConfiguration gc = frame.getGraphicsConfiguration(); + Rectangle workArea = gc.getBounds(); - public static void println( String messageIn ) - { - dialog.displayMessage( messageIn ); + Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(gc); + workArea.x += screenInsets.left; + workArea.y += screenInsets.top; + workArea.width -= screenInsets.left + screenInsets.right; + workArea.height -= screenInsets.top + screenInsets.bottom; + + System.out.println("Frame bounds " + frameBounds); + System.out.println("GraphicsConfiguration bounds " + gc.getBounds()); + System.out.println("Screen insets: " + screenInsets); + System.out.println("Work area: " + workArea); + + //frame bounds can exceed screen size on Windows, see 8231043 + if (!frameBounds.contains(workArea)) { + throw new RuntimeException("Frame is not maximized"); + } } -}// Sysout class - -/** - This is part of the standard test machinery. It provides a place for the - test instructions to be displayed, and a place for interactive messages - to the user to be displayed. - To have the test instructions displayed, see Sysout. - To have a message to the user be displayed, see Sysout. - Do not call anything in this dialog directly. - */ -class TestDialog extends Dialog -{ - - TextArea instructionsText; - TextArea messageText; - int maxStringLength = 80; - - //DO NOT call this directly, go through Sysout - public TestDialog( Frame frame, String name ) - { - super( frame, name ); - int scrollBoth = TextArea.SCROLLBARS_BOTH; - instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); - add( "North", instructionsText ); - - messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); - add("Center", messageText); - - pack(); - - setVisible(true); - }// TestDialog() - - //DO NOT call this directly, go through Sysout - public void printInstructions( String[] instructions ) - { - //Clear out any current instructions - instructionsText.setText( "" ); - - //Go down array of instruction strings - - String printStr, remainingStr; - for( int i=0; i < instructions.length; i++ ) - { - //chop up each into pieces maxSringLength long - remainingStr = instructions[ i ]; - while( remainingStr.length() > 0 ) - { - //if longer than max then chop off first max chars to print - if( remainingStr.length() >= maxStringLength ) - { - //Try to chop on a word boundary - int posOfSpace = remainingStr. - lastIndexOf( ' ', maxStringLength - 1 ); - - if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; - - printStr = remainingStr.substring( 0, posOfSpace + 1 ); - remainingStr = remainingStr.substring( posOfSpace + 1 ); - } - //else just print - else - { - printStr = remainingStr; - remainingStr = ""; - } - - instructionsText.append( printStr + "\n" ); - - }// while - - }// for - - }//printInstructions() - - //DO NOT call this directly, go through Sysout - public void displayMessage( String messageIn ) - { - messageText.append( messageIn + "\n" ); - System.out.println(messageIn); + private static void createAndShowFrame() { + frame = new Frame("The frame SHOULD be shown MAXIMIZED"); + frame.setSize(300, 300); + frame.setLocation(50, 50); + frame.setExtendedState(Frame.MAXIMIZED_BOTH); + frame.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + frame.dispose(); + } + }); + frame.setVisible(true); } - -}// TestDialog class +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/Frame/MiscUndecorated/ActiveAWTWindowTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/Frame/MiscUndecorated/ActiveAWTWindowTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/Frame/MiscUndecorated/ActiveAWTWindowTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/Frame/MiscUndecorated/ActiveAWTWindowTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,15 +25,24 @@ * @test * @key headful * @summary To check proper WINDOW_EVENTS are triggered when Frame gains or losses the focus - * @author Jitender(jitender.singh@eng.sun.com) area=AWT - * @author yan * @library /lib/client * @build ExtendedRobot * @run main ActiveAWTWindowTest */ -import java.awt.*; -import java.awt.event.*; +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.TextField; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.event.WindowFocusListener; public class ActiveAWTWindowTest { @@ -47,12 +56,12 @@ private boolean passed = true; private final int delay = 150; - public static void main(String[] args) { + public static void main(String[] args) throws Exception { ActiveAWTWindowTest test = new ActiveAWTWindowTest(); try { test.doTest(); } finally { - EventQueue.invokeLater(() -> { + EventQueue.invokeAndWait(() -> { if (test.frame != null) { test.frame.dispose(); } diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/Frame/ShapeNotSetSometimes/ShapeNotSetSometimes.java openjdk-21-21.0.9+10/test/jdk/java/awt/Frame/ShapeNotSetSometimes/ShapeNotSetSometimes.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/Frame/ShapeNotSetSometimes/ShapeNotSetSometimes.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/Frame/ShapeNotSetSometimes/ShapeNotSetSometimes.java 2025-10-13 07:49:24.000000000 +0000 @@ -33,6 +33,7 @@ import java.awt.geom.Area; import java.awt.geom.Ellipse2D; import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; @@ -42,7 +43,7 @@ * @key headful * @bug 6988428 * @summary Tests whether shape is always set - * @run main/othervm -Dsun.java2d.uiScale=1 ShapeNotSetSometimes + * @run main/othervm/timeout=300 -Dsun.java2d.uiScale=1 ShapeNotSetSometimes */ public class ShapeNotSetSometimes { @@ -147,15 +148,20 @@ robot.waitForIdle(); robot.delay(500); + Rectangle screenBounds = window.getGraphicsConfiguration().getBounds(); + BufferedImage screenCapture = robot.createScreenCapture(screenBounds); try { - colorCheck(innerPoint.x, innerPoint.y, SHAPE_COLOR, true); + colorCheck(innerPoint.x, innerPoint.y, SHAPE_COLOR, + true, screenCapture); for (Point point : pointsOutsideToCheck) { - colorCheck(point.x, point.y, BACKGROUND_COLOR, true); + colorCheck(point.x, point.y, BACKGROUND_COLOR, + true, screenCapture); } for (Point point : shadedPointsToCheck) { - colorCheck(point.x, point.y, SHAPE_COLOR, false); + colorCheck(point.x, point.y, SHAPE_COLOR, + false, screenCapture); } } finally { EventQueue.invokeAndWait(() -> { @@ -169,15 +175,12 @@ } } - private void colorCheck(int x, int y, Color expectedColor, boolean mustBeExpectedColor) { + private void colorCheck(int x, int y, Color expectedColor, + boolean mustBeExpectedColor, BufferedImage screenCapture) { int screenX = window.getX() + x; int screenY = window.getY() + y; - robot.mouseMove(screenX, screenY); - robot.waitForIdle(); - robot.delay(50); - - Color actualColor = robot.getPixelColor(screenX, screenY); + Color actualColor = new Color(screenCapture.getRGB(screenX, screenY)); System.out.printf( "Checking %3d, %3d, %35s should %sbe %35s\n", diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/InputMethods/InputMethodsTest/InputMethodsTest.html openjdk-21-21.0.9+10/test/jdk/java/awt/InputMethods/InputMethodsTest/InputMethodsTest.html --- openjdk-21-21.0.8+9/test/jdk/java/awt/InputMethods/InputMethodsTest/InputMethodsTest.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/InputMethods/InputMethodsTest/InputMethodsTest.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ - - - - - InputMethodsTest - - - - -This test is for Linux only. For other platforms please simply push "Pass". - -Test run requires some Japanese input method to be installed. - -To test JDK-7146572 fix please perform the following steps: -1. Switch on input method and type Japanese in the above text fields. -2. Push "Disable Input Methods" button. -3. Try to type Japanese again. If it can be done then the test is failed; otherwise passed. - - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/InputMethods/InputMethodsTest/InputMethodsTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/InputMethods/InputMethodsTest/InputMethodsTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/InputMethods/InputMethodsTest/InputMethodsTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/InputMethods/InputMethodsTest/InputMethodsTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,68 +21,75 @@ * questions. */ +import java.awt.TextArea; +import java.awt.TextField; +import javax.swing.Box; +import javax.swing.JButton; +import javax.swing.JComponent; /* - @test - @bug 7146572 8024122 - @summary Check if 'enableInputMethods' works properly for TextArea and TextField on Linux platform - @author a.stepanov - @run applet/manual=yesno InputMethodsTest.html + * @test + * @bug 7146572 8024122 + * @summary Check if 'enableInputMethods' works properly for TextArea and TextField on Linux platform + * @requires (os.family == "linux") + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual InputMethodsTest */ +public class InputMethodsTest { -import java.applet.Applet; -import java.awt.*; -import javax.swing.*; -import java.awt.event.*; + private static final String INSTRUCTIONS = """ + Test run requires some Japanese input method to be installed. - -public class InputMethodsTest extends Applet { - - TextArea txtArea = null; - TextField txtField = null; - JButton btnIM = null; - boolean inputMethodsEnabled = true; - - public void init() { - this.setLayout(new BorderLayout()); + To test the JDK-7146572 fix, please follow these steps: + 1. Enable the input method. + 2. Type Japanese in the text area and the text field to the right. + 2. Press the "Disable Input Methods" button. + 3. Try typing Japanese again. + 4. If input methods are not disabled, then press fail; + otherwise, press pass. + """; + + static boolean inputMethodsEnabled = true; + + public static void main(String[] args) throws Exception { + PassFailJFrame + .builder() + .title("InputMethodsTest Instructions") + .instructions(INSTRUCTIONS) + .splitUIRight(InputMethodsTest::createPanel) + .testTimeOut(10) + .rows(10) + .columns(40) + .build() + .awaitAndCheck(); } - public void start() { - - setSize(350, 200); + public static JComponent createPanel() { + Box verticalBox = Box.createVerticalBox(); - JPanel panel = new JPanel(); - panel.setLayout(new GridLayout(2, 1)); + TextArea textArea = new TextArea(); + verticalBox.add(textArea); - txtArea = new TextArea(); - panel.add(txtArea); + TextField textField = new TextField(); + verticalBox.add(textField); - txtField = new TextField(); - panel.add(txtField); - - add(panel, BorderLayout.CENTER); - - btnIM = new JButton(); - setBtnText(); - - btnIM.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - inputMethodsEnabled = !inputMethodsEnabled; - setBtnText(); - txtArea.enableInputMethods(inputMethodsEnabled); - txtField.enableInputMethods(inputMethodsEnabled); - } + JButton btnIM = new JButton(); + setBtnText(btnIM); + + btnIM.addActionListener(e -> { + inputMethodsEnabled = !inputMethodsEnabled; + setBtnText(btnIM); + textArea.enableInputMethods(inputMethodsEnabled); + textField.enableInputMethods(inputMethodsEnabled); }); - add(btnIM, BorderLayout.SOUTH); - - validate(); - setVisible(true); + verticalBox.add(btnIM); + return verticalBox; } - private void setBtnText() { + private static void setBtnText(JButton btnIM) { String s = inputMethodsEnabled ? "Disable" : "Enable"; btnIM.setText(s + " Input Methods"); } diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/Label/ContainerValidateTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/Label/ContainerValidateTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/Label/ContainerValidateTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/Label/ContainerValidateTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,169 @@ +/* + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Label; +import java.awt.Panel; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.TextField; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +/* + * @test + * @key headful + * @bug 4247913 + * @summary Tests that Label repaints after call Container.validate() + * @run main ContainerValidateTest + */ + +public class ContainerValidateTest extends Frame implements MouseListener { + private static Robot robot; + private static Panel currentPanel; + private static Button currentBtn; + private static Panel updatedPanel; + private static Label updatedLabel; + private static TextField updatedTxtField; + private static Button updatedBtn; + + private static volatile Rectangle btnBounds; + + Panel pnl1 = new Panel(); + Panel pnl2 = new Panel(); + Label lbl1 = new Label("Label 1"); + Label lbl2 = new Label("Label 2"); + TextField txt1 = new TextField("field1", 20); + TextField txt2 = new TextField("field2", 20); + Button btn1 = new Button("Swap 1"); + Button btn2 = new Button("Swap 2"); + + public static void main(String[] args) throws Exception { + robot = new Robot(); + + ContainerValidateTest containerValidate = new ContainerValidateTest(); + EventQueue.invokeAndWait(containerValidate::createAndShowUI); + robot.waitForIdle(); + robot.delay(1000); + + containerValidate.testUI(); + } + + private void createAndShowUI() { + this.setTitle("ContainerValidateTest Test"); + pnl1.add(lbl1); + pnl1.add(txt1); + pnl1.add(btn1); + + pnl2.add(lbl2); + pnl2.add(txt2); + pnl2.add(btn2); + + btn1.addMouseListener(this); + btn2.addMouseListener(this); + + this.add(pnl1, BorderLayout.CENTER); + pack(); + setLocationRelativeTo(null); + setVisible(true); + } + + private void testUI() throws Exception { + EventQueue.invokeAndWait(() -> btnBounds + = new Rectangle(btn1.getLocationOnScreen().x, + btn1.getLocationOnScreen().y, + btn1.getWidth(), + btn1.getHeight())); + for (int i= 1; i < 4 ; i++) { + EventQueue.invokeAndWait(() -> { + currentPanel = (Panel) this.getComponent(0); + currentBtn = (Button) currentPanel.getComponent(2); + }); + + robot.mouseMove(btnBounds.x + (int) btnBounds.getWidth() / 2, + btnBounds.y + (int) btnBounds.getHeight() / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + //large delay set for completion of UI validate() + robot.delay(500); + + EventQueue.invokeAndWait(() -> { + updatedPanel = (Panel) this.getComponent(0); + updatedLabel = (Label) updatedPanel.getComponent(0); + updatedTxtField = (TextField) updatedPanel.getComponent(1); + updatedBtn = (Button) updatedPanel.getComponent(2); + }); + testPanelComponents(currentBtn.getLabel()); + } + } + + private void testPanelComponents(String btnLabel) { + if (btnLabel.equals("Swap 1")) { + if (!(updatedLabel.getText().equals(lbl2.getText()) + && updatedTxtField.getText().equals(txt2.getText()) + && updatedBtn.getLabel().equals(btn2.getLabel()))) { + throw new RuntimeException("Test Failed!! Labels not repainted" + + " after Container.validate()"); + } + } else { + if (!(updatedLabel.getText().equals(lbl1.getText()) + && updatedTxtField.getText().equals(txt1.getText()) + && updatedBtn.getLabel().equals(btn1.getLabel()))) { + throw new RuntimeException("Test Failed!! Labels not repainted" + + " after Container.validate()"); + } + } + } + + @Override + public void mousePressed(MouseEvent evt) { + if (evt.getComponent() instanceof Button btn) { + if (btn.equals(btn1)) { + remove(pnl1); + add(pnl2, BorderLayout.CENTER); + } else { + remove(pnl2); + add(pnl1, BorderLayout.CENTER); + } + invalidate(); + validate(); + } + } + + @Override + public void mouseReleased(MouseEvent e) {} + + @Override + public void mouseEntered(MouseEvent e) {} + + @Override + public void mouseExited(MouseEvent e) {} + + @Override + public void mouseClicked(MouseEvent e) {} +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/List/KeyEventsTest/KeyEventsTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/List/KeyEventsTest/KeyEventsTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/List/KeyEventsTest/KeyEventsTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/List/KeyEventsTest/KeyEventsTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,9 +22,8 @@ */ import java.awt.BorderLayout; -import java.awt.EventQueue; -import java.awt.KeyboardFocusManager; import java.awt.Frame; +import java.awt.KeyboardFocusManager; import java.awt.List; import java.awt.Panel; import java.awt.Point; @@ -51,7 +50,7 @@ * @run main KeyEventsTest */ public class KeyEventsTest { - TestState currentState; + private volatile TestState currentState; final Object LOCK = new Object(); final int ACTION_TIMEOUT = 500; @@ -66,16 +65,14 @@ r = new Robot(); KeyEventsTest app = new KeyEventsTest(); try { - EventQueue.invokeAndWait(app::initAndShowGui); + app.initAndShowGui(); r.waitForIdle(); r.delay(500); app.doTest(); } finally { - EventQueue.invokeAndWait(() -> { - if (app.keyFrame != null) { - app.keyFrame.dispose(); - } - }); + if (app.keyFrame != null) { + app.keyFrame.dispose(); + } } } @@ -184,52 +181,51 @@ throw new RuntimeException("Test failed - list isn't focus owner."); } - EventQueue.invokeAndWait(() -> { - list.deselect(0); - list.deselect(1); - list.deselect(2); - list.deselect(3); - list.deselect(4); - list.deselect(5); - list.deselect(6); - list.deselect(7); - list.deselect(8); - - int selectIndex = 0; - int visibleIndex = 0; - - if (currentState.getScrollMoved()) { - if (currentState.getKeyID() == KeyEvent.VK_PAGE_UP || - currentState.getKeyID() == KeyEvent.VK_HOME) { - selectIndex = 8; - visibleIndex = 8; - } else if (currentState.getKeyID() == KeyEvent.VK_PAGE_DOWN || - currentState.getKeyID() == KeyEvent.VK_END) { + list.deselect(0); + list.deselect(1); + list.deselect(2); + list.deselect(3); + list.deselect(4); + list.deselect(5); + list.deselect(6); + list.deselect(7); + list.deselect(8); + + int selectIndex = 0; + int visibleIndex = 0; + + if (currentState.getScrollMoved()) { + if (currentState.getKeyID() == KeyEvent.VK_PAGE_UP || + currentState.getKeyID() == KeyEvent.VK_HOME) { + selectIndex = 8; + visibleIndex = 8; + } else if (currentState.getKeyID() == KeyEvent.VK_PAGE_DOWN || + currentState.getKeyID() == KeyEvent.VK_END) { + selectIndex = 0; + visibleIndex = 0; + } + } else { + if (currentState.getKeyID() == KeyEvent.VK_PAGE_UP || + currentState.getKeyID() == KeyEvent.VK_HOME) { + if (currentState.getSelectedMoved()) { + selectIndex = 1; + } else { selectIndex = 0; - visibleIndex = 0; } - } else { - if (currentState.getKeyID() == KeyEvent.VK_PAGE_UP || - currentState.getKeyID() == KeyEvent.VK_HOME) { - if (currentState.getSelectedMoved()) { - selectIndex = 1; - } else { - selectIndex = 0; - } - visibleIndex = 0; - } else if (currentState.getKeyID() == KeyEvent.VK_PAGE_DOWN || - currentState.getKeyID() == KeyEvent.VK_END) { - if (currentState.getSelectedMoved()) { - selectIndex = 7; - } else { - selectIndex = 8; - } - visibleIndex = 8; + visibleIndex = 0; + } else if (currentState.getKeyID() == KeyEvent.VK_PAGE_DOWN || + currentState.getKeyID() == KeyEvent.VK_END) { + if (currentState.getSelectedMoved()) { + selectIndex = 7; + } else { + selectIndex = 8; } + visibleIndex = 8; } - list.select(selectIndex); - list.makeVisible(visibleIndex); - }); + } + list.select(selectIndex); + list.makeVisible(visibleIndex); + r.delay(10); r.waitForIdle(); @@ -309,7 +305,7 @@ private final boolean scrollMoved; private final int keyID; private final boolean template; - private boolean action; + private volatile boolean action; public TestState(boolean multiple, boolean selectedMoved, boolean scrollMoved, int keyID, boolean template){ this.multiple = multiple; diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/Paint/ButtonRepaint.java openjdk-21-21.0.9+10/test/jdk/java/awt/Paint/ButtonRepaint.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/Paint/ButtonRepaint.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/Paint/ButtonRepaint.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,28 +21,32 @@ * questions. */ - -import java.awt.*; +import java.awt.Button; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; /** * @test * @key headful * @bug 7090424 - * @author Sergey Bylokhov */ public final class ButtonRepaint extends Button { public static void main(final String[] args) { for (int i = 0; i < 10; ++i) { - final Frame frame = new Frame(); - frame.setSize(300, 300); - frame.setLocationRelativeTo(null); - ButtonRepaint button = new ButtonRepaint(); - frame.add(button); - frame.setVisible(true); - sleep(); - button.test(); - frame.dispose(); + Frame frame = new Frame(); + try { + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + ButtonRepaint button = new ButtonRepaint(); + frame.add(button); + frame.setVisible(true); + sleep(); + button.test(); + } finally { + frame.dispose(); + } } } diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/Paint/CheckboxRepaint.java openjdk-21-21.0.9+10/test/jdk/java/awt/Paint/CheckboxRepaint.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/Paint/CheckboxRepaint.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/Paint/CheckboxRepaint.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,27 +21,32 @@ * questions. */ -import java.awt.*; +import java.awt.Checkbox; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; /** * @test * @key headful * @bug 7090424 - * @author Sergey Bylokhov */ public final class CheckboxRepaint extends Checkbox { public static void main(final String[] args) { for (int i = 0; i < 10; ++i) { - final Frame frame = new Frame(); - frame.setSize(300, 300); - frame.setLocationRelativeTo(null); - CheckboxRepaint checkbox = new CheckboxRepaint(); - frame.add(checkbox); - frame.setVisible(true); - sleep(); - checkbox.test(); - frame.dispose(); + Frame frame = new Frame(); + try { + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + CheckboxRepaint checkbox = new CheckboxRepaint(); + frame.add(checkbox); + frame.setVisible(true); + sleep(); + checkbox.test(); + } finally { + frame.dispose(); + } } } diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/Paint/LabelRepaint.java openjdk-21-21.0.9+10/test/jdk/java/awt/Paint/LabelRepaint.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/Paint/LabelRepaint.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/Paint/LabelRepaint.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,21 +30,23 @@ * @test * @key headful * @bug 7090424 - * @author Sergey Bylokhov */ public final class LabelRepaint extends Label { public static void main(final String[] args) { for (int i = 0; i < 10; ++i) { - final Frame frame = new Frame(); - frame.setSize(300, 300); - frame.setLocationRelativeTo(null); - LabelRepaint label = new LabelRepaint(); - frame.add(label); - frame.setVisible(true); - sleep(); - label.test(); - frame.dispose(); + Frame frame = new Frame(); + try { + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + LabelRepaint label = new LabelRepaint(); + frame.add(label); + frame.setVisible(true); + sleep(); + label.test(); + } finally { + frame.dispose(); + } } } diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/Paint/ListRepaint.java openjdk-21-21.0.9+10/test/jdk/java/awt/Paint/ListRepaint.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/Paint/ListRepaint.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/Paint/ListRepaint.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,26 +30,27 @@ * @test * @key headful * @bug 7090424 - * @author Sergey Bylokhov */ public final class ListRepaint extends List { - static ListRepaint listRepaint; - static Frame frame; - - public static void main(final String[] args) throws Exception { + public static void main(final String[] args) { for (int i = 0; i < 10; ++i) { + Frame frame = new Frame(); try { - EventQueue.invokeLater(ListRepaint::createAndShowGUI); + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + ListRepaint list = new ListRepaint(); + list.add("1"); + list.add("2"); + list.add("3"); + list.add("4"); + list.select(0); + frame.add(list); + frame.setVisible(true); sleep(); - EventQueue.invokeAndWait(listRepaint::test); + list.test(); } finally { - EventQueue.invokeAndWait(() -> { - if (frame != null) { - frame.dispose(); - frame = null; - } - }); + frame.dispose(); } } } @@ -61,22 +62,6 @@ } } - static void createAndShowGUI() { - frame = new Frame(); - frame.setSize(300, 300); - frame.setLocationRelativeTo(null); - - listRepaint = new ListRepaint(); - listRepaint.add("1"); - listRepaint.add("2"); - listRepaint.add("3"); - listRepaint.add("4"); - listRepaint.select(0); - - frame.add(listRepaint); - frame.setVisible(true); - } - @Override public void paint(final Graphics g) { super.paint(g); diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.html openjdk-21-21.0.9+10/test/jdk/java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.html --- openjdk-21-21.0.8+9/test/jdk/java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ - - - - - - HoveringAndDraggingTest - - - -

HoveringAndDraggingTest
Bug ID: 6497109

- -

See the dialog box (usually in upper left corner) for instructions

- - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,71 +21,122 @@ * questions. */ -/* - test - @bug 6497109 - @summary Mouse cursor icons for TextArea should be correct in case of hovering or dragging mouse over different subcomponents. - @author Konstantin Voloshin: area=awt.TextArea - @run applet/manual=yesno HoveringAndDraggingTest.html -*/ - -/** - * HoveringAndDraggingTest.java - * - * summary: Mouse cursor icons for TextArea should be correct in case - * of hovering or dragging mouse over different subcomponents. - */ - +import java.awt.Button; +import java.awt.Dimension; +import java.awt.EventQueue; import java.awt.Frame; -import java.awt.Panel; +import java.awt.GridBagLayout; import java.awt.GridLayout; +import java.awt.Panel; import java.awt.TextArea; -import java.awt.Dialog; +import java.util.concurrent.CountDownLatch; -public class HoveringAndDraggingTest extends java.applet.Applet { - public void start() { - String[] instructions = new String[] { - "1. Notice components in test window: main-panel, box-for-text," - +" 2 scroll-sliders, and 4 scroll-buttons.", - "2. Hover mouse over box-for-text." - +" Make sure, that mouse cursor is TextCursor (a.k.a. \"beam\").", - "3. Hover mouse over each of components (see item 1), except for box-for-text." - +" Make sure, that cursor is DefaultCursor (arrow).", - "4. Drag mouse (using any mouse button) from box-for-text to every" - +" component in item 1, and also outside application window." - +" Make sure, that cursor remains TextCursor while mouse button is pressed.", - "5. Repeat item 4 for each other component in item 1, except for box-for-text," - +" _but_ now make sure that cursor is DefaultCursor.", - "6. If cursor behaves as described in items 2-3-4-5, then test passed; otherwise it failed." - }; - Sysout.createDialogWithInstructions( instructions ); +/* + * @test + * @bug 6497109 + * @summary Mouse cursor icons for TextArea should be correct in case of + * hovering or dragging mouse over different subcomponents. + * @run main/manual HoveringAndDraggingTest + */ + +public class HoveringAndDraggingTest { + static Frame frame; + static Frame instructionsFrame; + static CountDownLatch countDownLatch; + public static CountDownLatch createCountDownLatch() { + return new CountDownLatch(1); + } + + public static void main(String[] args) throws Exception { + countDownLatch = createCountDownLatch(); + EventQueue.invokeAndWait(() -> { + initialize(); + showInstructionFrame(); + }); + countDownLatch.await(); + System.out.println("Test Pass"); + } + public static void initialize() { Panel panel = new Panel(); - panel.setLayout( new GridLayout(3,3) ); + panel.setLayout(new GridLayout(3, 3)); - for( int y=0; y<3; ++y ) { - for( int x=0; x<3; ++x ) { - if( x==1 && y==1 ) { - panel.add( new TextArea( bigString() ) ); + for (int y = 0; y < 3; ++y) { + for (int x = 0; x < 3; ++x) { + if (x == 1 && y == 1) { + panel.add(new TextArea(bigString())); } else { - panel.add( new Panel() ); + panel.add(new Panel()); } } } - Frame frame = new Frame( "TextArea cursor icon test" ); - frame.setSize( 300, 300 ); - frame.add( panel ); - frame.setVisible( true ); + frame = new Frame("TextArea cursor icon test"); + frame.setSize(300, 300); + frame.setLocation(450, 400); + frame.add(panel); + frame.setVisible(true); + } + + static void showInstructionFrame() { + String INSTRUCTIONS = """ + 1. Notice components in test window: main-panel,box-for-text, + 2 scroll-sliders, and 4 scroll-buttons. + 2. Hover mouse over box-for-text. + Make sure, that mouse cursor is TextCursor(a.k.a. \"beam\"). + 3. Hover mouse over each of components (see item 1), + except for box-for-text. + Make sure, that cursor is DefaultCursor (arrow). + 4. Drag mouse (using any mouse button) from box-for-text to every" + component in item 1, and also outside application window." + Make sure, that cursor remains TextCursor + while mouse button is pressed. + 5. Repeat item 4 for each other component in item 1, + except for box-for-text + _but_ now make sure that cursor is DefaultCursor. + 6. If cursor behaves as described in items 2-3-4-5, + then test is PASS otherwise it FAILED. + """; + TextArea textArea = new TextArea(INSTRUCTIONS, 16, 65, TextArea.SCROLLBARS_NONE); + Button passBtn = new Button("PASS"); + Button failBtn = new Button("FAIL"); + Panel btnPanel = new Panel(new GridBagLayout()); + Panel panel = new Panel(new GridBagLayout()); + instructionsFrame = new Frame("Test Instructions"); + passBtn.setMaximumSize(new Dimension(100, 30)); + failBtn.setMaximumSize(new Dimension(100, 30)); + btnPanel.add(passBtn); + btnPanel.add(failBtn); + passBtn.addActionListener(e -> disposeFrames()); + failBtn.addActionListener(e -> { + disposeFrames(); + throw new RuntimeException("Test Failed"); + }); + panel.add(textArea); + panel.add(btnPanel); + instructionsFrame.add(panel); + instructionsFrame.pack(); + instructionsFrame.setLocation(300, 100); + instructionsFrame.setVisible(true); + } + + static void disposeFrames() { + countDownLatch.countDown(); + if (frame != null) { + frame.dispose(); + } + if (instructionsFrame != null) { + instructionsFrame.dispose(); + } } static String bigString() { String s = ""; - for( int lines=0; ; ++lines ) { - for( int symbols=0; symbols<100; ++symbols ) { + for (int lines = 0; ; ++lines) { + for (int symbols = 0; symbols < 100; ++symbols) { s += "0"; } - if( lines<50 ) { + if (lines < 50) { s += "\n"; } else { break; @@ -94,141 +145,3 @@ return s; } } - - -/**************************************************** - Standard Test Machinery - DO NOT modify anything below -- it's a standard - chunk of code whose purpose is to make user - interaction uniform, and thereby make it simpler - to read and understand someone else's test. - ****************************************************/ - -/** - This is part of the standard test machinery. - It creates a dialog (with the instructions), and is the interface - for sending text messages to the user. - To print the instructions, send an array of strings to Sysout.createDialog - WithInstructions method. Put one line of instructions per array entry. - To display a message for the tester to see, simply call Sysout.println - with the string to be displayed. - This mimics System.out.println but works within the test harness as well - as standalone. - */ - -class Sysout -{ - private static TestDialog dialog; - - public static void createDialogWithInstructions( String[] instructions ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - dialog.printInstructions( instructions ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); - } - - public static void createDialog( ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - String[] defInstr = { "Instructions will appear here. ", "" } ; - dialog.printInstructions( defInstr ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); - } - - - public static void printInstructions( String[] instructions ) - { - dialog.printInstructions( instructions ); - } - - - public static void println( String messageIn ) - { - dialog.displayMessage( messageIn ); - } - -}// Sysout class - -/** - This is part of the standard test machinery. It provides a place for the - test instructions to be displayed, and a place for interactive messages - to the user to be displayed. - To have the test instructions displayed, see Sysout. - To have a message to the user be displayed, see Sysout. - Do not call anything in this dialog directly. - */ -class TestDialog extends Dialog -{ - - TextArea instructionsText; - TextArea messageText; - int maxStringLength = 80; - - //DO NOT call this directly, go through Sysout - public TestDialog( Frame frame, String name ) - { - super( frame, name ); - int scrollBoth = TextArea.SCROLLBARS_BOTH; - instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); - add( "North", instructionsText ); - - messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); - add("Center", messageText); - - pack(); - - setVisible(true); - }// TestDialog() - - //DO NOT call this directly, go through Sysout - public void printInstructions( String[] instructions ) - { - //Clear out any current instructions - instructionsText.setText( "" ); - - //Go down array of instruction strings - - String printStr, remainingStr; - for( int i=0; i < instructions.length; i++ ) - { - //chop up each into pieces maxSringLength long - remainingStr = instructions[ i ]; - while( remainingStr.length() > 0 ) - { - //if longer than max then chop off first max chars to print - if( remainingStr.length() >= maxStringLength ) - { - //Try to chop on a word boundary - int posOfSpace = remainingStr. - lastIndexOf( ' ', maxStringLength - 1 ); - - if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; - - printStr = remainingStr.substring( 0, posOfSpace + 1 ); - remainingStr = remainingStr.substring( posOfSpace + 1 ); - } - //else just print - else - { - printStr = remainingStr; - remainingStr = ""; - } - - instructionsText.append( printStr + "\n" ); - - }// while - - }// for - - }//printInstructions() - - //DO NOT call this directly, go through Sysout - public void displayMessage( String messageIn ) - { - messageText.append( messageIn + "\n" ); - System.out.println(messageIn); - } - -}// TestDialog class diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/TextField/SetEchoCharTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/TextField/SetEchoCharTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/TextField/SetEchoCharTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/TextField/SetEchoCharTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,178 @@ +/* + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Button; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Label; +import java.awt.Point; +import java.awt.Robot; +import java.awt.TextField; +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.StringSelection; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; + +import jdk.test.lib.Platform; + +/* + * @test + * @bug 4124697 + * @key headful + * @summary Make sure that after setting and then changing the echo + * character again, the TextField continues to function as expected. + * @library /test/lib + * @build jdk.test.lib.Platform + * @run main SetEchoCharTest + */ + +public class SetEchoCharTest { + private static Frame frame; + private static Robot robot; + private static TextField tfPassword; + private static Button btn1; + private static Button btn2; + private static volatile Point btn1Loc; + private static volatile Point btn2Loc; + + private static final String CHANGE = "Change echo char"; + private static final String PRINT = "Print text"; + private static final String INITIAL_TEXT = "DefaultPwd"; + private static final String CHANGED_TEXT = "NewPwd"; + private static final char NEW_ECHO_CHAR = '*'; + + public static void main(String[] args) throws Exception { + try { + robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.setAutoDelay(50); + + EventQueue.invokeAndWait(() -> createAndShowUI()); + robot.waitForIdle(); + robot.delay(1000); + + testEchoChar(); + robot.waitForIdle(); + robot.delay(200); + + testNewEchoChar(); + robot.waitForIdle(); + robot.delay(200); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void createAndShowUI() { + frame = new Frame("SetEchoCharTest"); + frame.setLayout(new FlowLayout()); + + Label label = new Label("Pwd:"); + tfPassword = new TextField(INITIAL_TEXT, 10); + tfPassword.setEchoChar('X'); + tfPassword.addActionListener((ActionListener) e -> { + if (e.getActionCommand().equals(CHANGED_TEXT)) { + //check the 2nd condition only if ActionEvent + //is triggered by changed text + if (!(tfPassword.getText().equals(CHANGED_TEXT) + && tfPassword.getEchoChar() == NEW_ECHO_CHAR)) { + throw new RuntimeException("Test Failed!!! TextField not working" + + " as expected after echo char change"); + } + } + }); + frame.add(label); + frame.add(tfPassword); + + btn1 = new Button(PRINT); + btn1.addActionListener(new BtnActionListener()); + frame.add(btn1); + + btn2 = new Button(CHANGE); + btn2.addActionListener(new BtnActionListener()); + frame.add(btn2); + frame.setSize(200,200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private static void testEchoChar() throws Exception { + EventQueue.invokeAndWait(() -> { + btn1Loc = btn1.getLocationOnScreen(); + btn2Loc = btn2.getLocationOnScreen(); + }); + + robot.mouseMove(btn1Loc.x + btn1.getWidth() / 2, + btn1Loc.y + btn1.getHeight() / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(1000); + + robot.mouseMove(btn2Loc.x + btn2.getWidth() / 2, + btn2Loc.y + btn2.getHeight() / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(1000); + } + + private static void testNewEchoChar() { + StringSelection stringSelection = new StringSelection(CHANGED_TEXT); + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + clipboard.setContents(stringSelection, stringSelection); + + int ctrlKey = Platform.isOSX() ? KeyEvent.VK_META : KeyEvent.VK_CONTROL; + robot.keyPress(ctrlKey); + robot.keyPress(KeyEvent.VK_V); + robot.keyRelease(KeyEvent.VK_V); + robot.keyRelease(ctrlKey); + + robot.keyPress(KeyEvent.VK_ENTER); + robot.keyRelease(KeyEvent.VK_ENTER); + } + + private static class BtnActionListener implements ActionListener { + public void actionPerformed(ActionEvent evt) { + String ac = evt.getActionCommand(); + if (CHANGE.equals(ac)) { + tfPassword.setText(""); + tfPassword.setEchoChar(NEW_ECHO_CHAR); + tfPassword.requestFocus(); + } + if (PRINT.equals(ac)) { + if (!tfPassword.getText().equals(INITIAL_TEXT)) { + throw new RuntimeException("Test Failed!!!" + + " Initial text not as expected"); + } + } + } + } +} + diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/TextField/SetEchoCharWordOpsTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/TextField/SetEchoCharWordOpsTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/TextField/SetEchoCharWordOpsTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/TextField/SetEchoCharWordOpsTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.FlowLayout; +import java.awt.Label; +import java.awt.TextField; +import javax.swing.JPanel; + +import jdk.test.lib.Platform; + +/* + * @test + * @bug 6191897 + * @summary Verifies that ctrl+left/right does not move word-by-word in a TextField + * with echo character set + * @library /java/awt/regtesthelpers /test/lib + * @build PassFailJFrame jdk.test.lib.Platform + * @run main/manual SetEchoCharWordOpsTest + */ + +public class SetEchoCharWordOpsTest { + + public static void main(String[] args) throws Exception { + String selectAllKey; + String moveKeys; + String selectKeys; + + if (Platform.isOSX()) { + selectAllKey = "Cmd + A"; + moveKeys = "Alt + Right/Left"; + selectKeys = "Shift + Alt + Right/Left"; + } else { + selectAllKey = "Ctrl + A"; + moveKeys = "Ctrl + Right/Left"; + selectKeys = "Shift + Ctrl + Right/Left"; + } + + String instructions = + "The password field (in the bottom panel) in this test contains" + + " a few words (3 words).\n" + + "Move the focus to the text field and press " + selectAllKey + ".\n" + + "Try moving the caret word-by-word with " + moveKeys + " or" + + " extending selection with " + selectKeys + "." + + " You should NOT be able to do that.\n\n" + + "If you are able to move the caret word-by-word press FAIL," + + " else press PASS."; + + PassFailJFrame.builder() + .title("SetEchoCharClipboard Instructions") + .instructions(instructions) + .rows((int) instructions.lines().count() + 3) + .columns(45) + .splitUIBottom(SetEchoCharWordOpsTest::createAndShowUI) + .build() + .awaitAndCheck(); + } + + + private static JPanel createAndShowUI() { + JPanel jPanel = new JPanel(); + TextField tf = new TextField("one two three", 15); + Label tfLabel = new Label("Password Field:"); + + jPanel.setLayout(new FlowLayout()); + tf.setEchoChar('*'); + jPanel.add(tfLabel); + jPanel.add(tf); + return jPanel; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/TrayIcon/DblClickActionEventTest/DblClickActionEventTest.html openjdk-21-21.0.9+10/test/jdk/java/awt/TrayIcon/DblClickActionEventTest/DblClickActionEventTest.html --- openjdk-21-21.0.8+9/test/jdk/java/awt/TrayIcon/DblClickActionEventTest/DblClickActionEventTest.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/TrayIcon/DblClickActionEventTest/DblClickActionEventTest.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ - - - - - - - DblClickActionEventTest - - - -

DblClickActionEventTest
Bug ID: 6284070

- -

See the dialog box (usually in upper left corner) for instructions

- - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/TrayIcon/DblClickActionEventTest/DblClickActionEventTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/TrayIcon/DblClickActionEventTest/DblClickActionEventTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/TrayIcon/DblClickActionEventTest/DblClickActionEventTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/TrayIcon/DblClickActionEventTest/DblClickActionEventTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - test - @bug 6284070 - @summary Tests that ActionEvent is generated when a tray icon is double-clicked - @library ../../regtesthelpers - @build Sysout - @author artem.ananiev: area=awt.tray - @run applet/manual=yesno DblClickActionEventTest.html -*/ - -import java.applet.*; - -import java.awt.*; -import java.awt.event.*; -import java.awt.image.*; - -import jdk.test.lib.Platform; -import test.java.awt.regtesthelpers.Sysout; - -public class DblClickActionEventTest extends Applet { - boolean traySupported; - - public void init() { - this.setLayout(new BorderLayout()); - - String[] instructions; - traySupported = SystemTray.isSupported(); - if (traySupported) { - String clickInstruction; - if (Platform.isOSX()) { - clickInstruction = "right"; - } else { - clickInstruction = "left"; - } - instructions = new String[]{ - "When the test starts an icon is added to the SystemTray area.", - " Double-click on it with a " + clickInstruction + " button and make sure that", - " ACTION_PERFORMED event is sent to Java (all the clicks and", - " action events are shown below these instructions).", - "Then, if your system allows the tray icon to get focus (for", - " example, windows 2000 or windows XP), double-click on the", - " icon with SPACE button and single-click with RETURN button.", - " Both of them must also trigger ACTION_PERFORMED event.", - "If you see ACTION_PERFORMED events after each of your actions", - " (either mouse clicks or key presses), press PASS, else FAIL" - }; - } else { - instructions = new String[]{ - "The test cannot be run because SystemTray is not supported.", - "Simply press PASS button." - }; - } - Sysout.createDialogWithInstructions(instructions); - } - - public void start() { - setSize(200, 200); - setVisible(true); - validate(); - - if (!traySupported) { - return; - } - - BufferedImage img = new BufferedImage(32, 32, BufferedImage.TYPE_INT_ARGB); - Graphics g = img.createGraphics(); - g.setColor(Color.WHITE); - g.fillRect(0, 0, 32, 32); - g.setColor(Color.RED); - g.fillRect(6, 6, 20, 20); - g.dispose(); - - SystemTray tray = SystemTray.getSystemTray(); - TrayIcon icon = new TrayIcon(img); - icon.setImageAutoSize(true); - icon.addActionListener(ev -> Sysout.println(ev.toString())); - icon.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent ev) { - Sysout.println(ev.toString()); - } - } - ); - - try { - tray.add(icon); - } catch (AWTException e) { - Sysout.println(e.toString()); - Sysout.println("!!! The test coudn't be performed !!!"); - } - } -} - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/dnd/ImageDecoratedDnD/ImageDecoratedDnD.html openjdk-21-21.0.9+10/test/jdk/java/awt/dnd/ImageDecoratedDnD/ImageDecoratedDnD.html --- openjdk-21-21.0.8+9/test/jdk/java/awt/dnd/ImageDecoratedDnD/ImageDecoratedDnD.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/dnd/ImageDecoratedDnD/ImageDecoratedDnD.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ - - - - - - ImageDecoratedDnD - - - -

ImageDecoratedDnD
Bug ID: 4874070

- -

See the dialog box (usually in upper left corner) for instructions

- - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/dnd/ImageDecoratedDnD/ImageDecoratedDnD.java openjdk-21-21.0.9+10/test/jdk/java/awt/dnd/ImageDecoratedDnD/ImageDecoratedDnD.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/dnd/ImageDecoratedDnD/ImageDecoratedDnD.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/dnd/ImageDecoratedDnD/ImageDecoratedDnD.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,177 +21,87 @@ * questions. */ -/* - test %W% %E% - @bug 4874070 - @summary Tests basic DnD functionality - @author Your Name: Alexey Utkin area=dnd - @run applet/manual=yesno ImageDecoratedDnD.html -*/ - -import java.applet.Applet; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Frame; +import java.awt.Panel; import java.awt.dnd.DragSource; +/* + * @test + * @bug 4874070 + * @summary Tests CTRL + DnD functionality + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ImageDecoratedDnD + */ +public class ImageDecoratedDnD { + private static final String INSTRUCTIONS = """ + When test runs a Frame which contains a yellow button labeled + "Drag ME!" and a RED Panel will appear. + + 1. Click on the button and drag it to the red panel while holding + the "CTRL" key on the keyboard. + + 2. When the mouse enters the red panel during the drag, the panel + should turn yellow. + + On systems that supports pictured drag, the image under the + drag-cursor should appear. + "Image under drag-cursor" is a translucent blue rectangle + red + circle and includes an anchor that is shifted from top-left + corner of the picture to inside the picture to 10pt + in both dimensions. + + On Windows, the image under the cursor would be visible ONLY over + drop targets with activated extended D'n'D support. + It means the image may not be displayed when dragging over some + windows, this is not an error. + The image should be displayed when dragging over the red/yellow panel. + + 3. Release the mouse button. + + The panel should turn red again and a yellow button labeled + "Drag ME!" should appear inside the panel. You should be able + to repeat this operation multiple times. + + If above is true press PASS, else press FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .rows((int) INSTRUCTIONS.lines().count() + 2) + .columns(38) + .testUI(ImageDecoratedDnD::createUI) + .build() + .awaitAndCheck(); + } -public class ImageDecoratedDnD extends Applet { - //Declare things used in the test, like buttons and labels here - - public void init() { - //Create instructions for the user here, as well as set up - // the environment -- set the layout manager, add buttons, - // etc. - this.setLayout(new BorderLayout()); - - String[] instructions = - { - "A Frame, which contains a yellow button labeled \"Drag ME!\" and ", - "a red panel, will appear below. ", - "1. Click on the button and drag to the red panel. ", - "2. When the mouse enters the red panel during the drag, the panel ", - "should turn yellow. On the systems that supports pictured drag, ", - "the image under the drag-cursor should appear (ancor is shifted ", - "from top-left corner of the picture inside the picture to 10pt in both dimensions ). ", - "In WIN32 systems the image under cursor would be visible ONLY over ", - "the drop targets with activated extended OLE D\'n\'D support (that are ", - "the desktop and IE ).", - "3. Release the mouse button.", - "The panel should turn red again and a yellow button labeled ", - "\"Drag ME!\" should appear inside the panel. You should be able ", - "to repeat this operation multiple times." - }; - Sysout.createDialogWithInstructions(instructions); - - }//End init() - - public void start() { - Frame f = new Frame("Use keyboard for DnD change"); + public static Frame createUI() { + Frame frame = new Frame("Ctrl + Drag - Image DnD test"); Panel mainPanel; Component dragSource, dropTarget; - f.setBounds(0, 400, 200, 200); - f.setLayout(new BorderLayout()); + frame.setSize(400, 400); + frame.setLayout(new BorderLayout()); mainPanel = new Panel(); mainPanel.setLayout(new BorderLayout()); - mainPanel.setBackground(Color.blue); + mainPanel.setBackground(Color.BLUE); - dropTarget = new DnDTarget(Color.red, Color.yellow); - dragSource = new DnDSource("Drag ME! (" + (DragSource.isDragImageSupported()?"with ":"without") + " image)" ); + dropTarget = new DnDTarget(Color.RED, Color.YELLOW); + dragSource = new DnDSource("Drag ME! (" + + (DragSource.isDragImageSupported() ? "with " : "without") + " image)"); mainPanel.add(dragSource, "North"); mainPanel.add(dropTarget, "Center"); - f.add(mainPanel, BorderLayout.CENTER); - - f.setVisible(true); - }// start() -}// class DnDAcceptanceTest - - -/** - * ************************************************* - * Standard Test Machinery - * DO NOT modify anything below -- it's a standard - * chunk of code whose purpose is to make user - * interaction uniform, and thereby make it simpler - * to read and understand someone else's test. - * ************************************************** - */ -class Sysout { - private static TestDialog dialog; - - public static void createDialogWithInstructions(String[] instructions) { - dialog = new TestDialog(new Frame(), "Instructions"); - dialog.printInstructions(instructions); - dialog.show(); - println("Any messages for the tester will display here."); - } - - public static void createDialog() { - dialog = new TestDialog(new Frame(), "Instructions"); - String[] defInstr = {"Instructions will appear here. ", ""}; - dialog.printInstructions(defInstr); - dialog.show(); - println("Any messages for the tester will display here."); - } - - - public static void printInstructions(String[] instructions) { - dialog.printInstructions(instructions); - } - - - public static void println(String messageIn) { - dialog.displayMessage(messageIn); + frame.add(mainPanel, BorderLayout.CENTER); + frame.setAlwaysOnTop(true); + return frame; } - -}// Sysout class - - -class TestDialog extends Dialog { - - TextArea instructionsText; - TextArea messageText; - int maxStringLength = 80; - - //DO NOT call this directly, go through Sysout - public TestDialog(Frame frame, String name) { - super(frame, name); - int scrollBoth = TextArea.SCROLLBARS_BOTH; - instructionsText = new TextArea("", 15, maxStringLength, scrollBoth); - add("North", instructionsText); - - messageText = new TextArea("", 5, maxStringLength, scrollBoth); - add("South", messageText); - - pack(); - - show(); - }// TestDialog() - - //DO NOT call this directly, go through Sysout - public void printInstructions(String[] instructions) { - //Clear out any current instructions - instructionsText.setText(""); - - //Go down array of instruction strings - - String printStr, remainingStr; - for (int i = 0; i < instructions.length; i++) { - //chop up each into pieces maxSringLength long - remainingStr = instructions[i]; - while (remainingStr.length() > 0) { - //if longer than max then chop off first max chars to print - if (remainingStr.length() >= maxStringLength) { - //Try to chop on a word boundary - int posOfSpace = remainingStr. - lastIndexOf(' ', maxStringLength - 1); - - if (posOfSpace <= 0) posOfSpace = maxStringLength - 1; - - printStr = remainingStr.substring(0, posOfSpace + 1); - remainingStr = remainingStr.substring(posOfSpace + 1); - } - //else just print - else { - printStr = remainingStr; - remainingStr = ""; - } - - instructionsText.append(printStr + "\n"); - - }// while - - }// for - - }//printInstructions() - - //DO NOT call this directly, go through Sysout - public void displayMessage(String messageIn) { - messageText.append(messageIn + "\n"); - } - -}// TestDialog class - +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/event/ClickEventsTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/event/ClickEventsTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/event/ClickEventsTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/event/ClickEventsTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4087762 + @summary Sometimes click events are missing when you click the color components alternately. + @key headful + @library /test/jdk/java/awt/regtesthelpers + @build Util + @run main ClickEventsTest +*/ + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Robot; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import test.java.awt.regtesthelpers.Util; + +public class ClickEventsTest { + static Frame frame; + static ColorComponent redComponent; + static ColorComponent blueComponent; + static Robot robot; + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(ClickEventsTest::createAndShowGUI); + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void test() throws Exception { + robot = new Robot(); + robot.waitForIdle(); + robot.delay(500); + + for (int i = 0; i < 10; i++) { + redComponent.clickAndCheck(); + blueComponent.clickAndCheck(); + } + } + + private static void createAndShowGUI() { + frame = new Frame("ClickEventsTest"); + redComponent = new ColorComponent(Color.RED); + blueComponent = new ColorComponent(Color.BLUE); + + frame.add("North", redComponent); + frame.add("South", blueComponent); + + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + static class ColorComponent extends Component { + public Color myColor; + + private final CyclicBarrier barrier = new CyclicBarrier(2); + + private final MouseAdapter mouseAdapter = new MouseAdapter() { + public void mouseClicked(MouseEvent event) { + System.out.println(myColor + " area clicked"); + try { + barrier.await(1, TimeUnit.SECONDS); + } catch (InterruptedException | BrokenBarrierException | TimeoutException e) { + throw new RuntimeException(e); + } + } + }; + + public ColorComponent(Color c) { + myColor = c; + addMouseListener(mouseAdapter); + } + + public Dimension getPreferredSize() { + return new Dimension(200, 100); + } + + public void paint(Graphics g) { + g.setColor(myColor); + g.fillRect(0, 0, 200, 100); + } + + public void clickAndCheck() throws InterruptedException, BrokenBarrierException { + barrier.reset(); + Util.clickOnComp(this, robot); + try { + barrier.await(1, TimeUnit.SECONDS); + } catch (TimeoutException e) { + throw new RuntimeException(myColor + " was not clicked"); + } + } + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/event/KeyEvent/FrenchKeyboard.java openjdk-21-21.0.9+10/test/jdk/java/awt/event/KeyEvent/FrenchKeyboard.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/event/KeyEvent/FrenchKeyboard.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/event/KeyEvent/FrenchKeyboard.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4308606 + * @summary Tests whether the keys on the numeric keyboard work + * correctly under French input locale. + * @key i18n + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual FrenchKeyboard + */ + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.TextField; +import java.lang.reflect.InvocationTargetException; + +public class FrenchKeyboard extends Frame { + static String INSTRUCTIONS = """ + This test is intended for computers with French input method. If French + input method can not be enabled or your keyboard does not have a numeric + keypad press "Pass" to skip the test. + Make sure that French input method is active and the NumLock is on. + Click on the text field in the window called "Check your keys" + and type once of each of the following keys on the numeric keypad: + /*-+1234567890 + If all the expected characters are displayed exactly once press "Pass". + If any characters do not display or display multiple times press "Fail". + """; + + public FrenchKeyboard() { + super("Check your keys"); + setLayout(new BorderLayout()); + TextField tf = new TextField(30); + add(tf, BorderLayout.CENTER); + pack(); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .title("FrenchKeyboard Instructions") + .instructions(INSTRUCTIONS) + .testUI(FrenchKeyboard::new) + .build() + .awaitAndCheck(); + } +} + diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/event/KeyEvent/HomeEndKeyTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/event/KeyEvent/HomeEndKeyTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/event/KeyEvent/HomeEndKeyTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/event/KeyEvent/HomeEndKeyTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,126 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * bug 4268912 4115514 + * summary Ensures that KeyEvent has right results for the following + * non-numpad keys: Home/Eng/PageUp/PageDn + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual HomeEndKeyTest + */ + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.TextField; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.lang.reflect.InvocationTargetException; + + +public class HomeEndKeyTest extends Frame implements KeyListener { + static String INSTRUCTIONS = """ + Before starting this test make sure that system shortcuts and + keybindings for the keys in the list below are disabled. + For example pressing "Print Screen" key should not launch + screen capturing software. + Click on the text field in the window named "Check keyCode values" + and one by one start typing the keys in the list below. + (If you do not have some of the keys on your keyboard skip it + and move to the next line). + After clicking each key look at the log area - the printed name + and key code should correspond to the ones for the key you typed. + Note that on some systems the graphical symbol for the key + can be printed instead of the symbolic name. + If you do not encounter unexpected key codes for the keys you typed, + press "Pass". Otherwise press "Fail". + + Key Keycode + ------------------------- + PrintScreen 154 + ScrollLock 145 + Pause 19 + + Insert 155 + Del 127 + Home 36 + End 35 + PageUp 33 + PageDown 34 + + Left Arrow 37 + Up Arrow 38 + Right Arrow 39 + Down Arrow 40 + """; + + public HomeEndKeyTest() { + super("Check KeyCode values"); + setLayout(new BorderLayout()); + TextField tf = new TextField(30); + tf.addKeyListener(this); + add(tf, BorderLayout.CENTER); + pack(); + } + + public void keyPressed(KeyEvent evt) { + printKey(evt); + } + + public void keyTyped(KeyEvent ignore) { + } + + public void keyReleased(KeyEvent evt) { + printKey(evt); + } + + protected void printKey(KeyEvent evt) { + String str; + switch (evt.getID()) { + case KeyEvent.KEY_PRESSED: + str = "KEY_PRESSED"; + break; + case KeyEvent.KEY_RELEASED: + str = "KEY_RELEASED"; + break; + default: + str = "unknown type"; + } + + str = str + ":name=" + KeyEvent.getKeyText(evt.getKeyCode()) + + " keyCode=" + evt.getKeyCode(); + PassFailJFrame.log(str); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .title("HomeEndKeyTest Instructions") + .instructions(INSTRUCTIONS) + .logArea(20) + .testUI(HomeEndKeyTest::new) + .build() + .awaitAndCheck(); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/event/KeyEvent/KeyCharTest/KeyCharTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/event/KeyEvent/KeyCharTest/KeyCharTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/event/KeyEvent/KeyCharTest/KeyCharTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/event/KeyEvent/KeyCharTest/KeyCharTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* @test - @bug 5013984 + @bug 5013984 8360647 @summary Tests KEY_PRESSED has the same KeyChar as KEY_RELEASED @key headful @run main KeyCharTest @@ -37,7 +37,7 @@ import java.util.HashMap; public class KeyCharTest extends Frame implements KeyListener { - HashMap transMap = new HashMap(); + HashMap transMap = new HashMap<>(); public void keyTyped(KeyEvent e){ } @@ -47,22 +47,35 @@ } public void keyReleased(KeyEvent e){ - Object value = transMap.get(e.getKeyCode()); - if (value != null && e.getKeyChar() != ((Character)value).charValue()) { + Character value = transMap.get(e.getKeyCode()); + if (value != null && e.getKeyChar() != value) { throw new RuntimeException("Wrong KeyChar on KEY_RELEASED "+ KeyEvent.getKeyText(e.getKeyCode())); } } - public void start () { + private void testKeyRange(Robot robot, int start, int end) { + System.out.printf("\nTesting range on %d to %d\n", start, end); + for(int vkey = start; vkey <= end; vkey++) { + try { + robot.keyPress(vkey); + robot.keyRelease(vkey); + System.out.println(KeyEvent.getKeyText(vkey) + " " + vkey); + } catch (RuntimeException ignored) {} + } + robot.delay(100); + } + + public void start() throws Exception { + Robot robot = new Robot(); addKeyListener(this); setLocationRelativeTo(null); setSize(200, 200); setVisible(true); requestFocus(); + boolean wasNumlockPressed = false; try { - Robot robot = new Robot(); robot.setAutoDelay(10); robot.setAutoWaitForIdle(true); robot.delay(100); @@ -72,22 +85,25 @@ robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); - for(int vkey = 0x20; vkey < 0x7F; vkey++) { - try { - robot.keyPress(vkey); - robot.keyRelease(vkey); - System.out.println(KeyEvent.getKeyText(vkey) + " " + vkey); - } catch (RuntimeException e) { - } - } - robot.delay(100); + testKeyRange(robot, 0x20, 0x7E); + + // Try again with a different numpad state. + robot.keyPress(KeyEvent.VK_NUM_LOCK); + robot.keyRelease(KeyEvent.VK_NUM_LOCK); + wasNumlockPressed = true; + + testKeyRange(robot, KeyEvent.VK_NUMPAD0, KeyEvent.VK_DIVIDE); } catch(Exception e){ - e.printStackTrace(); throw new RuntimeException("Exception while performing Robot actions."); + } finally { + if (wasNumlockPressed) { + robot.keyPress(KeyEvent.VK_NUM_LOCK); + robot.keyRelease(KeyEvent.VK_NUM_LOCK); + } } } - public static void main(String[] args) { + public static void main(String[] args) throws Exception { KeyCharTest test = new KeyCharTest(); try { test.start(); diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/event/KeyEvent/NumpadTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/event/KeyEvent/NumpadTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/event/KeyEvent/NumpadTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/event/KeyEvent/NumpadTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,119 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4083691 + * @summary Ensures that KeyEvent has right results for the following + * keys \*-+ + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual NumpadTest + */ + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.TextField; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.lang.reflect.InvocationTargetException; + + +public class NumpadTest extends Frame implements KeyListener { + static String INSTRUCTIONS = """ + This test requires a keyboard with a numeric keypad (numpad). + If your keyboard does not have a numpad press "Pass" to skip testing. + Make sure NumLock is on. + Click on the text field in the window named "Check KeyChar values". + Then, type the following keys/characters in the TextField. + using the numpad keys: + /*-+ + + Verify that the keyChar and keyCode is correct for each key pressed. + Remember that the keyCode for the KEY_TYPED event should be zero. + Also verify that the character you typed appears in the TextField. + + Key Name keyChar Keycode + ------------------------------------- + / Divide / 47 111 + * Multiply * 42 106 + - Subtract - 45 109 + + Add + 43 107 + + Now repeat with the NumLock off. + + If all keycodes are valid and expected characters appear + in the text field press "Pass". Otherwise press "Fail". + """; + + public NumpadTest() { + super("Check KeyChar values"); + setLayout(new BorderLayout()); + TextField tf = new TextField(30); + tf.addKeyListener(this); + add(tf, BorderLayout.CENTER); + pack(); + } + public void keyPressed(KeyEvent evt) { + printKey(evt); + } + + public void keyTyped(KeyEvent evt) { + printKey(evt); + } + + public void keyReleased(KeyEvent evt) { + printKey(evt); + } + + protected void printKey(KeyEvent evt) { + switch (evt.getID()) { + case KeyEvent.KEY_TYPED: + break; + case KeyEvent.KEY_PRESSED: + break; + case KeyEvent.KEY_RELEASED: + break; + default: + return; + } + + if (evt.isActionKey()) { + PassFailJFrame.log("params= " + evt.paramString() + " KeyChar: " + + (int) evt.getKeyChar() + " Action Key"); + } else { + PassFailJFrame.log("params= " + evt.paramString() + " KeyChar: " + + (int) evt.getKeyChar()); + } + } + + public static void main(String[] args) throws InterruptedException, InvocationTargetException { + PassFailJFrame.builder() + .title("NumpadTest Instructions") + .instructions(INSTRUCTIONS) + .logArea(20) + .testUI(NumpadTest::new) + .build() + .awaitAndCheck(); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/event/MouseEvent/AWTPanelSmoothWheel/AWTPanelSmoothWheel.html openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/AWTPanelSmoothWheel/AWTPanelSmoothWheel.html --- openjdk-21-21.0.8+9/test/jdk/java/awt/event/MouseEvent/AWTPanelSmoothWheel/AWTPanelSmoothWheel.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/AWTPanelSmoothWheel/AWTPanelSmoothWheel.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ - - - - - - AWTPanelSmoothWheel - - - -

AWTPanelSmoothWheel
Bug ID: 6730447

- -

See the dialog box (usually in upper left corner) for instructions

- - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/event/MouseEvent/AWTPanelSmoothWheel/AWTPanelSmoothWheel.java openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/AWTPanelSmoothWheel/AWTPanelSmoothWheel.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/event/MouseEvent/AWTPanelSmoothWheel/AWTPanelSmoothWheel.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/AWTPanelSmoothWheel/AWTPanelSmoothWheel.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,251 +0,0 @@ -/* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - test - @bug 6730447 - @summary Support for high resolution mouse wheel is still incomplete. AWT panel needs to be supported - @author dmitry.cherepanov@...: area=awt.mouse - @run applet/manual=yesno AWTPanelSmoothWheel.html -*/ - -/** - * AWTPanelSmoothWheel.java - * - * summary: - */ - -import java.applet.Applet; -import java.awt.*; -import java.awt.event.*; - -//Manual tests should run as applet tests if possible because they -// get their environments cleaned up, including AWT threads, any -// test created threads, and any system resources used by the test -// such as file descriptors. (This is normally not a problem as -// main tests usually run in a separate VM, however on some platforms -// such as the Mac, separate VMs are not possible and non-applet -// tests will cause problems). Also, you don't have to worry about -// synchronisation stuff in Applet tests the way you do in main -// tests... - - -public class AWTPanelSmoothWheel extends Applet -{ - //Declare things used in the test, like buttons and labels here - - public void init() - { - //Create instructions for the user here, as well as set up - // the environment -- set the layout manager, add buttons, - // etc. - this.setLayout (new BorderLayout ()); - - String[] instructions = - { - " the test is relevant for windows platforms and ", - " mouses with high-resolution wheel, please just press pass if it's not the case ", - " place the mouse cursor above the green panel and rotate the mouse wheel " , - " the test will print all mouse wheel messages into the logging panel, ", - " please make sure that some of the messages have non-zero 'wheelRotation' value ", - " in this case the test passes, otherwise it fails, ", - " please make sure the test works OK if the mouse wheel is rotated very slow " - }; - Sysout.createDialogWithInstructions( instructions ); - - }//End init() - - public void start () - { - Panel panel = new Panel(); - panel.setBackground(Color.green); - panel.addMouseWheelListener(new MouseWheelListener() { - public void mouseWheelMoved(MouseWheelEvent e) { - Sysout.println(e.toString()); - } - }); - - //Get things going. Request focus, set size, et cetera - setSize (200,200); - setLayout(new BorderLayout()); - add(panel, BorderLayout.CENTER); - setVisible(true); - validate(); - - //What would normally go into main() will probably go here. - //Use System.out.println for diagnostic messages that you want - // to read after the test is done. - //Use Sysout.println for messages you want the tester to read. - - }// start() - - //The rest of this class is the actions which perform the test... - - //Use Sysout.println to communicate with the user NOT System.out!! - //Sysout.println ("Something Happened!"); - -}// class ManualYesNoTest - -/* Place other classes related to the test after this line */ - - - - - -/**************************************************** - Standard Test Machinery - DO NOT modify anything below -- it's a standard - chunk of code whose purpose is to make user - interaction uniform, and thereby make it simpler - to read and understand someone else's test. - ****************************************************/ - -/** - This is part of the standard test machinery. - It creates a dialog (with the instructions), and is the interface - for sending text messages to the user. - To print the instructions, send an array of strings to Sysout.createDialog - WithInstructions method. Put one line of instructions per array entry. - To display a message for the tester to see, simply call Sysout.println - with the string to be displayed. - This mimics System.out.println but works within the test harness as well - as standalone. - */ - -class Sysout -{ - private static TestDialog dialog; - - public static void createDialogWithInstructions( String[] instructions ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - dialog.printInstructions( instructions ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); - } - - public static void createDialog( ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - String[] defInstr = { "Instructions will appear here. ", "" } ; - dialog.printInstructions( defInstr ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); - } - - - public static void printInstructions( String[] instructions ) - { - dialog.printInstructions( instructions ); - } - - - public static void println( String messageIn ) - { - dialog.displayMessage( messageIn ); - } - -}// Sysout class - -/** - This is part of the standard test machinery. It provides a place for the - test instructions to be displayed, and a place for interactive messages - to the user to be displayed. - To have the test instructions displayed, see Sysout. - To have a message to the user be displayed, see Sysout. - Do not call anything in this dialog directly. - */ -class TestDialog extends Dialog -{ - - TextArea instructionsText; - TextArea messageText; - int maxStringLength = 80; - - //DO NOT call this directly, go through Sysout - public TestDialog( Frame frame, String name ) - { - super( frame, name ); - int scrollBoth = TextArea.SCROLLBARS_BOTH; - instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); - add( "North", instructionsText ); - - messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); - add("Center", messageText); - - pack(); - - setVisible(true); - }// TestDialog() - - //DO NOT call this directly, go through Sysout - public void printInstructions( String[] instructions ) - { - //Clear out any current instructions - instructionsText.setText( "" ); - - //Go down array of instruction strings - - String printStr, remainingStr; - for( int i=0; i < instructions.length; i++ ) - { - //chop up each into pieces maxSringLength long - remainingStr = instructions[ i ]; - while( remainingStr.length() > 0 ) - { - //if longer than max then chop off first max chars to print - if( remainingStr.length() >= maxStringLength ) - { - //Try to chop on a word boundary - int posOfSpace = remainingStr. - lastIndexOf( ' ', maxStringLength - 1 ); - - if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; - - printStr = remainingStr.substring( 0, posOfSpace + 1 ); - remainingStr = remainingStr.substring( posOfSpace + 1 ); - } - //else just print - else - { - printStr = remainingStr; - remainingStr = ""; - } - - instructionsText.append( printStr + "\n" ); - - }// while - - }// for - - }//printInstructions() - - //DO NOT call this directly, go through Sysout - public void displayMessage( String messageIn ) - { - messageText.append( messageIn + "\n" ); - System.out.println(messageIn); - } - -}// TestDialog class - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/event/MouseEvent/AWTPanelSmoothWheel.java openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/AWTPanelSmoothWheel.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/event/MouseEvent/AWTPanelSmoothWheel.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/AWTPanelSmoothWheel.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.event.MouseWheelEvent; +import javax.swing.JOptionPane; + +/* + * @test + * @bug 6730447 + * @summary To verify the support for high resolution mouse wheel. + * AWT panel needs to support high-res mouse wheel rotation. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual AWTPanelSmoothWheel + */ + +public class AWTPanelSmoothWheel { + private static int wheelEventCount = 0; + private static int hiResWheelCount = 0; + private static final String WARNING_MSG = "WARNING !!!" + + " You might NOT be using a hi-res mouse."; + private static final String INSTRUCTIONS = """ + + + This test is relevant on platforms with high-resolution mouse wheel + or a trackpad can be used too. + Please press PASS if this is not the case.

+ + Place the mouse cursor above the green panel and rotate the mouse wheel, + the test will print mouse wheel event messages in the format + [Event#, WheelRotation, PreciseWheelRotation] into the logging + panel below the instruction window.

+ + A hi-res mouse/trackpad is one which produces MouseWheelEvents having: +
 Math.abs(preciseWheelRotation) < 1. 

+ + Check if the test works OK when the mouse-wheel/trackpad is scrolled + very slowly.

+ This is a semi-automated test, if you are using a hi-res mouse/trackpad + and it satisfies the hi-res MouseWheelEvents as described below, + the test should automatically pass.

+ + When preciseWheelRotation adds up, wheelRotation becomes non-zero + (can be negative when mouse wheel is scrolled down).
+ You should see many events where the absolute value of + preciseWheelRotation < 1 & wheelRotation = 0 followed by + an event where wheelRotation != 0 in the logs.

+ +
+ NOTE: +
    +
  • If you don't see events with preciseWheelRotation < 1, + then the mouse doesn't support high-resolution scrolling.
  • +
  • A warning is shown if you are not using a hi-res mouse.
  • +
  • MouseWheelEvent logs are displayed in the log area + for user reference.
  • +
  • When mouse is scrolled up, preciseWheelRotation & wheelRotation + are positive and they are negative when scrolled down.
  • +
+ + + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .rows(30) + .columns(54) + .testTimeOut(10) + .logArea(10) + .testUI(AWTPanelSmoothWheel::createUI) + .build() + .awaitAndCheck(); + } + + private static Frame createUI() { + Frame frame = new Frame("Test Wheel Rotation"); + Panel panel = new Panel(); + panel.setBackground(Color.GREEN); + panel.addMouseWheelListener(e -> { + if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) { + PassFailJFrame.log("WheelEvent#" + (++wheelEventCount) + + " --- Wheel Rotation: " + e.getWheelRotation() + + " --- Precise Wheel Rotation: " + + String.format("%.2f", e.getPreciseWheelRotation())); + if (Math.abs(e.getPreciseWheelRotation()) < 1) { + hiResWheelCount++; + } + if (wheelEventCount >= 5 && hiResWheelCount == 0) { + PassFailJFrame.log(WARNING_MSG); + JOptionPane.showMessageDialog(frame, WARNING_MSG, + "Warning", JOptionPane.WARNING_MESSAGE); + } + if (e.getWheelRotation() != 0 && hiResWheelCount > 0) { + PassFailJFrame.log("The test passes: hiResWheelCount = " + + hiResWheelCount); + PassFailJFrame.forcePass(); + } + } + }); + frame.setSize(400, 200); + frame.setLayout(new BorderLayout()); + frame.add(panel, BorderLayout.CENTER); + return frame; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/event/MouseEvent/DragMouseEventTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/DragMouseEventTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/event/MouseEvent/DragMouseEventTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/DragMouseEventTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,438 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4327618 4327623 4327639 4327654 4327664 4327666 4327676 4327679 4507822 + * @summary Tests that MouseDragged and MouseReleased are triggered by Button, + * Checkbox, Choice, Label, List, Scrollbar, TextArea, TextField + * for Left, Middle and Right mouse buttons + * @key headful + * @library /lib/client /java/awt/regtesthelpers + * @build ExtendedRobot Util + * @run main/othervm -Dsun.java2d.uiScale=1 DragMouseEventTest +*/ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Checkbox; +import java.awt.Choice; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Label; +import java.awt.List; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Scrollbar; +import java.awt.TextArea; +import java.awt.TextField; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.Arrays; + +import test.java.awt.regtesthelpers.Util; + +public class DragMouseEventTest { + private static ExtendedRobot robot; + private static DragMouseEventFrame dmef; + private static final int DELAY = 200; + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(DragMouseEventTest::createAndShowGUI); + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (dmef != null) { + dmef.dispose(); + } + }); + } + } + + private static void createAndShowGUI() { + dmef = new DragMouseEventFrame(); + dmef.setVisible(true); + } + + private static void test() throws Exception { + robot = new ExtendedRobot(); + robot.waitForIdle(); + robot.delay(500); + + testComponent(dmef.scrollbar); + testComponent(dmef.choice); + testComponent(dmef.textarea); + testComponent(dmef.textfield); + testComponent(dmef.checkbox); + testComponent(dmef.label); + testComponent(dmef.list); + testComponent(dmef.button); + } + + private static void testComponent(Component component) throws Exception { + Rectangle componentBounds = Util.invokeOnEDT(() -> { + Point locationOnScreen = component.getLocationOnScreen(); + Dimension size = component.getSize(); + return new Rectangle(locationOnScreen, size); + }); + + Rectangle frameBounds = Util.invokeOnEDT(() -> dmef.getBounds()); + + Point start = new Point(componentBounds.x + 10, componentBounds.y + 10); + + Adapter adapter = getAdapterFromComponent(component); + + testItemStateChanged(component, adapter, start, componentBounds); + testActionListener(component, adapter, start); + + Point mid = getEndPoint(start, frameBounds, 3); + Point end = getEndPoint(start, frameBounds, 15); + + testButtonDrag(component, adapter, MouseEvent.BUTTON1_DOWN_MASK, start, mid, end); + testButtonDrag(component, adapter, MouseEvent.BUTTON2_DOWN_MASK, start, mid, end); + testButtonDrag(component, adapter, MouseEvent.BUTTON3_DOWN_MASK, start, mid, end); + } + + private static Adapter getAdapterFromComponent(Component component) { + return (Adapter) Arrays + .stream(component.getMouseListeners()) + .filter((m) -> m instanceof Adapter) + .findFirst() + .orElseThrow(); + } + + private static void testItemStateChanged(Component component, + Adapter adapter, + Point start, + Rectangle componentBounds) { + if (!(component instanceof Choice + || component instanceof Checkbox + || component instanceof List)) { + return; + } + + System.out.println("\ntestItemStateChanged " + component); + + adapter.reset(); + robot.mouseMove(start.x, start.y); + robot.waitForIdle(); + robot.click(); + + if (component instanceof Choice) { + robot.mouseMove(start.x, componentBounds.y + componentBounds.height + 25); + robot.waitForIdle(); + robot.click(); + } + + robot.waitForIdle(); + + if (!adapter.itemStateChangedReceived) { + throw new RuntimeException("itemStateChanged was not received for " + component); + } + } + + private static void testActionListener(Component component, + Adapter adapter, + Point start) { + if (!(component instanceof Button || component instanceof List)) { + // skip for not applicable components + return; + } + + System.out.println("\ntestActionListener " + component); + adapter.reset(); + + robot.mouseMove(start.x, start.y); + robot.waitForIdle(); + + if (component instanceof List) { + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.delay(25); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + robot.delay(25); + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.delay(25); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(DELAY); + } else { + robot.click(); + } + + robot.waitForIdle(); + robot.delay(DELAY); + + if (!adapter.actionPerformedReceived) { + throw new RuntimeException("actionPerformed was not received for " + component); + } + } + + private static String getButtonName(int button) { + return switch (button) { + case MouseEvent.BUTTON1_DOWN_MASK -> "BUTTON1"; + case MouseEvent.BUTTON2_DOWN_MASK -> "BUTTON2"; + case MouseEvent.BUTTON3_DOWN_MASK -> "BUTTON3"; + default -> throw new IllegalStateException("Unexpected value: " + button); + }; + } + + private static void testButtonDrag(Component component, + Adapter adapter, + int button, + Point start, Point mid, Point end) { + String buttonName = getButtonName(button); + System.out.printf("\n> testButtonDrag: %s on %s\n", + buttonName, component); + + robot.mouseMove(start.x, start.y); + robot.waitForIdle(); + + robot.mousePress(button); + robot.waitForIdle(); + + System.out.printf("> gliding from (%d,%d) to (%d,%d)\n", + start.x, start.y, mid.x, mid.y); + robot.glide(start, mid); + robot.waitForIdle(); + robot.delay(DELAY); + + + // Catch events only after we leave the frame boundaries + adapter.reset(); + + System.out.printf("> gliding after crossing the border (%d,%d) to (%d,%d)\n", + mid.x, mid.y, end.x, end.y); + robot.glide(mid, end); + + robot.mouseRelease(button); + robot.waitForIdle(); + robot.delay(DELAY); + System.out.printf("> %s released\n", buttonName); + + boolean mouseDraggedReceived = adapter.mouseDraggedReceived; + boolean mouseReleasedReceived = adapter.mouseReleasedReceived; + + if (component instanceof Choice) { + // Close the popup if it is still open + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.delay(25); + robot.keyRelease(KeyEvent.VK_ESCAPE); + robot.waitForIdle(); + robot.delay(DELAY); + } + + + if (!mouseDraggedReceived || !mouseReleasedReceived) { + throw new RuntimeException(("%d: Mouse drag or release was not received\n" + + "mouseDraggedReceived %b mouseReleasedReceived %b") + .formatted(button, mouseDraggedReceived, mouseReleasedReceived)); + } + } + + /* + * returns the closest border point with a specified offset + */ + private static Point getEndPoint(Point start, Rectangle bounds, int offset) { + int left = bounds.x; + int right = bounds.x + bounds.width; + int top = bounds.y; + int bottom = bounds.y + bounds.height; + + int distanceLeft = start.x - left; + int distanceRight = right - start.x; + int distanceTop = start.y - top; + int distanceBottom = bottom - start.y; + + int minDistance = Math.min( + Math.min(distanceLeft, distanceRight), + Math.min(distanceTop, distanceBottom) + ); + + if (minDistance == distanceLeft) { + return new Point(left - offset, start.y); + } else if (minDistance == distanceRight) { + return new Point(right + offset, start.y); + } else if (minDistance == distanceTop) { + return new Point(start.x, top - offset); + } else { + return new Point(start.x, bottom + offset); + } + } + + private static class DragMouseEventFrame extends Frame { + TextArea textarea = new TextArea("TextArea", 20, 30); + Label label = new Label("Label"); + Panel panel = new Panel(); + List list = new List(); + Choice choice = new Choice(); + Button button = new Button("Button"); + TextField textfield = new TextField("TextField"); + Checkbox checkbox = new Checkbox("CheckBox"); + Scrollbar scrollbar = new Scrollbar(); + Panel centerPanel = new Panel(); + + public DragMouseEventFrame() { + setTitle("DragMouseEventTest"); + + add(centerPanel, BorderLayout.CENTER); + centerPanel.setLayout(new FlowLayout()); + + add(panel, BorderLayout.NORTH); + panel.setLayout(new FlowLayout()); + + choice.add("choice item 1"); + choice.add("choice item 2"); + choice.add("choice item 3"); + panel.add(choice); + + Adapter adapter = new Adapter(); + choice.addMouseMotionListener(adapter); + choice.addMouseListener(adapter); + choice.addItemListener(adapter); + + adapter = new Adapter(); + panel.add(label); + label.addMouseMotionListener(adapter); + label.addMouseListener(adapter); + + adapter = new Adapter(); + panel.add(button); + button.addMouseMotionListener(adapter); + button.addMouseListener(adapter); + button.addActionListener(adapter); + + adapter = new Adapter(); + panel.add(checkbox); + checkbox.addMouseMotionListener(adapter); + checkbox.addMouseListener(adapter); + checkbox.addItemListener(adapter); + + adapter = new Adapter(); + panel.add(textfield, BorderLayout.EAST); + textfield.addMouseMotionListener(adapter); + textfield.addMouseListener(adapter); + textfield.addActionListener(adapter); + + adapter = new Adapter(); + add(textarea, BorderLayout.EAST); + textarea.addMouseMotionListener(adapter); + textarea.addMouseListener(adapter); + + adapter = new Adapter(); + list.add("list item 1"); + list.add("list item 2"); + add(list, BorderLayout.SOUTH); + list.addMouseMotionListener(adapter); + list.addMouseListener(adapter); + list.addActionListener(adapter); + list.addItemListener(adapter); + + adapter = new Adapter(); + add(scrollbar, BorderLayout.WEST); + scrollbar.addMouseMotionListener(adapter); + scrollbar.addMouseListener(adapter); + + setSize(500, 400); + setLocationRelativeTo(null); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + DragMouseEventFrame.this.dispose(); + } + }); + } + } + + private static class Adapter extends MouseAdapter + implements ActionListener, ItemListener { + + public volatile boolean mouseDraggedReceived = false; + public volatile boolean mouseReleasedReceived = false; + public volatile boolean itemStateChangedReceived = false; + public volatile boolean actionPerformedReceived = false; + + + public void mouseDragged(MouseEvent me) { + mouseDraggedReceived = true; + System.out.println(me.paramString()); + } + + private void consumeIfNeeded(MouseEvent me) { + Component c = me.getComponent(); + // do not show popup menu for the following components, + // as it may interfere with the testing. + if (c instanceof TextArea + || c instanceof TextField + || c instanceof Scrollbar) { + if (me.isPopupTrigger()) { + System.out.println("CONSUMED: " + me); + me.consume(); + } + } + } + + public void mouseReleased(MouseEvent me) { + consumeIfNeeded(me); + mouseReleasedReceived = true; + System.out.println(me.paramString()); + } + + public void mousePressed(MouseEvent me) { + consumeIfNeeded(me); + System.out.println(me.paramString()); + } + + public void mouseClicked(MouseEvent me) { + System.out.println(me.paramString()); + } + + public void actionPerformed(ActionEvent e) { + actionPerformedReceived = true; + System.out.println(e.paramString()); + } + + public void itemStateChanged(ItemEvent e) { + itemStateChangedReceived = true; + System.out.println(e.paramString()); + } + + public void reset() { + mouseDraggedReceived = false; + mouseReleasedReceived = false; + itemStateChangedReceived = false; + actionPerformedReceived = false; + } + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/event/MouseEvent/DragToLightweightTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/DragToLightweightTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/event/MouseEvent/DragToLightweightTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/DragToLightweightTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4417964 + * @summary tests that drag events continue to arrive to heavyweight + * when the mouse is moved to lightweight while dragging. + * @key headful + * @library /lib/client /java/awt/regtesthelpers + * @build ExtendedRobot Util + * @run main DragToLightweightTest +*/ + +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.HeadlessException; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import test.java.awt.regtesthelpers.Util; + +public class DragToLightweightTest { + + private static final CountDownLatch latch = new CountDownLatch(1); + private static volatile MouseTest mouseTest; + + public static void main(String[] args) throws Exception { + + EventQueue.invokeAndWait(() -> mouseTest = new MouseTest()); + + try { + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (mouseTest != null) { + mouseTest.dispose(); + } + }); + } + } + + private static void test() throws Exception { + ExtendedRobot robot = new ExtendedRobot(); + robot.waitForIdle(); + robot.delay(500); + + Rectangle componentBounds = mouseTest.getLightweightComponentBounds(); + + robot.dragAndDrop( + componentBounds.x + componentBounds.width / 2, componentBounds.y + componentBounds.height + 30, + componentBounds.x + componentBounds.width / 2, componentBounds.y + 2 * componentBounds.height / 3 + ); + + if (!latch.await(5, TimeUnit.SECONDS)) { + throw new RuntimeException("The test failed: no mouse release event received"); + } + + System.out.println("Mouse release event received, the test PASSED"); + } + + private static class MouseTest extends Frame { + + final Foo foo; + + public MouseTest() throws HeadlessException { + super("DragToLightweightTest"); + + setLayout(new FlowLayout()); + + addMouseListener(new MouseAdapter() { + @Override + public void mouseReleased(MouseEvent e) { + System.out.println("mouseReleased"); + latch.countDown(); + } + }); + + // Create a Component that will be a child of the Frame and add + // a MouseListener to it. + foo = new Foo(); + foo.setBackground(Color.red); + + System.out.println(foo.getPreferredSize()); + foo.setPreferredSize(new Dimension(350, 200)); + System.out.println(foo.getPreferredSize()); + + foo.addMouseListener(new DummyAdapter()); + + add(foo); + + setSize(400, 400); + setLocationRelativeTo(null); + setVisible(true); + } + + public Rectangle getLightweightComponentBounds() throws Exception { + return Util.invokeOnEDT(() -> { + Point locationOnScreen = foo.getLocationOnScreen(); + Dimension size = foo.getSize(); + return new Rectangle(locationOnScreen.x, locationOnScreen.y, size.width, size.height); + }); + } + + private static class Foo extends Container { + public void paint(Graphics g) { + g.setColor(getBackground()); + g.fillRect(0, 0, getWidth(), getHeight()); + g.setColor(Color.white); + g.drawString(getBounds().toString(), 5, 20); + super.paint(g); + } + } + + private static class DummyAdapter extends MouseAdapter {} + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/event/MouseEvent/MouseEnterTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/MouseEnterTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/event/MouseEvent/MouseEnterTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/MouseEnterTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4095172 + * @summary Test for no proper mouse coordinates on MOUSE_ENTER/MOUSE_EXIT events for Win boxes. + * @key headful + * @library /lib/client /java/awt/regtesthelpers + * @build ExtendedRobot Util + * @run main MouseEnterTest + */ + +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; + +import test.java.awt.regtesthelpers.Util; + +public class MouseEnterTest { + private static Frame frame; + private static final TestMouseAdapter mouseAdapter = new TestMouseAdapter(); + + public static void main(String[] args) throws Exception { + EventQueue.invokeAndWait(MouseEnterTest::initAndShowGUI); + try { + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void initAndShowGUI() { + frame = new Frame("MouseEnterTest"); + frame.setLayout(null); + frame.setSize(300, 200); + frame.setLocationRelativeTo(null); + frame.addMouseListener(mouseAdapter); + frame.setVisible(true); + } + + private static void test() throws Exception { + ExtendedRobot robot = new ExtendedRobot(); + robot.waitForIdle(); + robot.delay(500); + + Rectangle bounds = Util.invokeOnEDT(frame::getBounds); + + java.util.List points = getBorderGlidePoints(bounds); + for (int i = 0; i < points.size(); i += 2) { + Point p1 = points.get(i); + Point p2 = points.get(i + 1); + + System.out.println("\n------------------\n"); + + System.out.printf("%s > %s > %s\n", p1, p2, p1); + robot.glide(p1, p2); + robot.waitForIdle(); + robot.glide(p2, p1); + robot.waitForIdle(); + robot.delay(200); + mouseAdapter.testEvents(); + + System.out.println("\n------------------\n"); + + System.out.printf("%s > %s > %s\n", p2, p1, p2); + robot.glide(p2, p1); + robot.waitForIdle(); + robot.glide(p1, p2); + robot.waitForIdle(); + robot.delay(200); + mouseAdapter.testEvents(); + } + } + + private static java.util.List getBorderGlidePoints(Rectangle bounds) { + java.util.List list = new ArrayList<>(); + + int d = 10; + + // left + list.add(new Point(bounds.x - d, bounds.y + bounds.height / 2)); + list.add(new Point(bounds.x + d, bounds.y + bounds.height / 2)); + + // right + list.add(new Point(bounds.x + bounds.width - d, bounds.y + bounds.height / 2)); + list.add(new Point(bounds.x + bounds.width + d, bounds.y + bounds.height / 2)); + + // top + list.add(new Point(bounds.x + bounds.width / 2, bounds.y - d)); + list.add(new Point(bounds.x + bounds.width / 2, bounds.y + d)); + + // bottom + list.add(new Point(bounds.x + bounds.width / 2, bounds.y + bounds.height - d)); + list.add(new Point(bounds.x + bounds.width / 2, bounds.y + bounds.height + d)); + + return list; + } + + private static final class TestMouseAdapter extends MouseAdapter { + private static final int THRESHOLD = 5; + private volatile MouseEvent lastEnteredEvent = null; + private volatile MouseEvent lastExitedEvent = null; + + @Override + public void mouseEntered(MouseEvent e) { + System.out.println("MouseEntered " + e); + lastEnteredEvent = e; + } + + @Override + public void mouseExited(MouseEvent e) { + System.out.println("MouseExited " + e); + lastExitedEvent = e; + } + + public void testEvents() { + if (lastEnteredEvent == null || lastExitedEvent == null) { + throw new RuntimeException("Missing lastEnteredEvent or lastExitedEvent"); + } + + System.out.println("\nTesting:"); + System.out.println(lastEnteredEvent); + System.out.println(lastExitedEvent); + System.out.println(); + + int diffX = Math.abs(lastEnteredEvent.getX() - lastExitedEvent.getX()); + int diffScreenX = Math.abs(lastEnteredEvent.getY() - lastExitedEvent.getY()); + int diffY = Math.abs(lastEnteredEvent.getXOnScreen() - lastExitedEvent.getXOnScreen()); + int diffScreenY = Math.abs(lastEnteredEvent.getYOnScreen() - lastExitedEvent.getYOnScreen()); + + System.out.printf("THRESHOLD %d, diffX %d diffScreenX %d " + + "diffY %d diffScreenY %d\n", + THRESHOLD, + diffX, diffScreenX, + diffY, diffScreenY + ); + + if (diffX > THRESHOLD + || diffScreenX > THRESHOLD + || diffY > THRESHOLD + || diffScreenY > THRESHOLD) { + throw new RuntimeException("Mouse enter vs exit event is too different"); + } + } + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/event/MouseEvent/MouseEventsDuringDrag.java openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/MouseEventsDuringDrag.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/event/MouseEvent/MouseEventsDuringDrag.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/MouseEventsDuringDrag.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,307 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4017222 + * @summary Checks whether mouse events are reported correctly during drag. + * @author Stuart Lawrence, Brent Christian: area=event + * @key headful + * @library /lib/client /java/awt/regtesthelpers + * @build ExtendedRobot Util + * @run main MouseEventsDuringDrag + */ + + +/* + * MouseEventsDuringDrag.java + * + * summary: + * On Solaris drag enter/exit events are only reported for the + * component where drag started, they're not reported on other + * components. On Win32 enter/exit events are reported correctly. + */ + +import test.java.awt.regtesthelpers.Util; + +import java.awt.Canvas; +import java.awt.Choice; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Label; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.InputEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +public class MouseEventsDuringDrag { + + private static ExtendedRobot robot; + private static Frame frame; + + private static final MouseHandler mouseHandler = new MouseHandler(); + + static Label lab; + static Canvas c1, c2; + static Choice choice; + + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(MouseEventsDuringDrag::createAndShowGUI); + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void test() throws Exception { + robot = new ExtendedRobot(); + robot.waitForIdle(); + robot.delay(500); + + // Part 1: Press and hold down the mouse button inside the red box. + // Drag the mouse over to the blue box (whilst still holding down + // the mouse button). + // Whilst dragging the mouse from the red box, enter and exit + // events should be reported for the blue box. + testcase(c2, "c1 to c2"); + + // Part 2: Again, press and hold down the mouse button inside the red box. + // This time drag the mouse over to the Choice menu. + // Enter and exit events should be reported for the Choice menu. + testcase(choice, "c1 to choice"); + } + + private static void testcase(Component moveTo, String message) throws Exception { + System.out.println("\ntestcase: " + message); + Rectangle c1bounds = getBounds(c1); + Rectangle moveToBound = getBounds(moveTo); + + Point startDragLocation = + new Point(c1bounds.x + c1bounds.width - 10, + c1bounds.y + c1bounds.height / 2); + + Point endDragLocation = + new Point(moveToBound.x + 10, moveToBound.y + moveToBound.height / 2); + + robot.mouseMove(startDragLocation); + robot.waitForIdle(); + robot.delay(200); + mouseHandler.reset(); + + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + + robot.glide(startDragLocation, endDragLocation); + robot.waitForIdle(); + + robot.glide(endDragLocation.x, endDragLocation.y, endDragLocation.x - 20, endDragLocation.y); + + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + robot.waitForIdle(); + robot.delay(200); + + List actual = mouseHandler.getRecordedEvents(); + + List expected = List.of( + new EventRecord(MouseEvent.MOUSE_PRESSED, c1), + new EventRecord(MouseEvent.MOUSE_EXITED, c1), + new EventRecord(MouseEvent.MOUSE_ENTERED, moveTo), + new EventRecord(MouseEvent.MOUSE_EXITED, moveTo), + new EventRecord(MouseEvent.MOUSE_RELEASED, c1) + ); + + System.out.println("Expected:\n" + expected); + System.out.println("Actual:\n" + actual); + if (!actual.equals(expected)) { + throw new RuntimeException("Mismatch between expected and actual events\n%s\n%s" + .formatted(expected, actual)); + } + } + + private static Rectangle getBounds(Component c) throws Exception { + return Util.invokeOnEDT(() -> { + Point locationOnScreen = c.getLocationOnScreen(); + Dimension size = c.getSize(); + return new Rectangle(locationOnScreen.x, locationOnScreen.y, size.width, size.height); + }); + } + + private static void createAndShowGUI() { + frame = new Frame(); + MouseHandler mouseHandler = new MouseHandler(); + frame.setLayout(new GridBagLayout()); + + int canvasSize = 100; + c1 = new Canvas(); + c1.setPreferredSize(new Dimension(canvasSize, canvasSize)); + c1.setBackground(Color.red); + c1.addMouseListener(mouseHandler); + + c2 = new Canvas(); + c2.setPreferredSize(new Dimension(canvasSize, canvasSize)); + c2.setBackground(Color.blue); + c2.addMouseListener(mouseHandler); + + GridBagConstraints gbc = new GridBagConstraints(); + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.insets = new Insets(5, 5, 5, 5); + + gbc.gridx = 0; + gbc.gridy = 0; + frame.add(c1, gbc); + + gbc.gridx = 2; + frame.add(c2, gbc); + + Panel p1 = new Panel(); + p1.setLayout(new FlowLayout()); + choice = new Choice(); + choice.addItem("Choice"); + choice.addItem("One"); + choice.addItem("Two"); + choice.addMouseListener(mouseHandler); + p1.add(choice); + + gbc.gridx = 1; + gbc.gridy = 1; + frame.add(p1, gbc); + + lab = new Label(); + + gbc.gridx = 0; + gbc.gridy = 2; + gbc.gridwidth = 3; + frame.add(lab, gbc); + + frame.pack(); + frame.setLocationRelativeTo(null); + + frame.setVisible(true); + } + + record EventRecord(int eventId, Component component) { + + @Override + public String toString() { + StringBuilder str = new StringBuilder(80); + switch(eventId) { + case MouseEvent.MOUSE_PRESSED: + str.append("MOUSE_PRESSED"); + break; + case MouseEvent.MOUSE_RELEASED: + str.append("MOUSE_RELEASED"); + break; + case MouseEvent.MOUSE_CLICKED: + str.append("MOUSE_CLICKED"); + break; + case MouseEvent.MOUSE_ENTERED: + str.append("MOUSE_ENTERED"); + break; + case MouseEvent.MOUSE_EXITED: + str.append("MOUSE_EXITED"); + break; + case MouseEvent.MOUSE_MOVED: + str.append("MOUSE_MOVED"); + break; + case MouseEvent.MOUSE_DRAGGED: + str.append("MOUSE_DRAGGED"); + break; + case MouseEvent.MOUSE_WHEEL: + str.append("MOUSE_WHEEL"); + break; + default: + str.append("unknown type"); + } + return str.append(" ").append(component).toString(); + } + } + + static class MouseHandler extends MouseAdapter { + static final List list = new CopyOnWriteArrayList<>(); + + public void mousePressed(MouseEvent e) { + list.add(new EventRecord(e.getID(), e.getComponent())); + if (e.getSource() == c1) { + lab.setText("Mouse pressed in red box"); + } else if (e.getSource() == c2) { + lab.setText("Mouse pressed in blue box"); + } else if (e.getSource() == choice) { + lab.setText("Mouse pressed in choice"); + } + } + + public void mouseReleased(MouseEvent e) { + list.add(new EventRecord(e.getID(), e.getComponent())); + lab.setText("Mouse released"); + } + + public void mouseEntered(MouseEvent e) { + list.add(new EventRecord(e.getID(), e.getComponent())); + if (e.getSource() == c1) { + lab.setText("Mouse entered red box"); + } else if (e.getSource() == c2) { + lab.setText("Mouse entered blue box"); + } else if (e.getSource() == choice) { + lab.setText("Mouse entered choice"); + } + } + + public void mouseExited(MouseEvent e) { + list.add(new EventRecord(e.getID(), e.getComponent())); + if (e.getSource() == c1) { + lab.setText("Mouse exited red box"); + } else if (e.getSource() == c2) { + lab.setText("Mouse exited blue box"); + } else if (e.getSource() == choice) { + lab.setText("Mouse exited choice"); + } + } + + public void reset() { + list.clear(); + } + + public List getRecordedEvents() { + return new ArrayList<>(list); + } + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/event/MouseEvent/MouseModifierTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/MouseModifierTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/event/MouseEvent/MouseModifierTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/MouseModifierTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,181 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4117523 + * @summary Solaris: MousePressed event has modifier=0 when left button is pressed + * @key headful + * @library /javax/swing/regtesthelpers /test/lib + * @build Util jdk.test.lib.Platform + * @run main MouseModifierTest +*/ + + +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import jdk.test.lib.Platform; + +public class MouseModifierTest { + private static Frame frame; + private static volatile MouseEvent lastMousePressedEvent = null; + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(MouseModifierTest::createAndShowGUI); + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void test() throws Exception { + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(500); + + Point centerPoint = Util.getCenterPoint(frame); + + System.out.println("MOUSE1 press case"); + + robot.mouseMove(centerPoint.x, centerPoint.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(25); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(300); + + if (lastMousePressedEvent == null + || lastMousePressedEvent.getModifiers() != InputEvent.BUTTON1_MASK) { + throw new RuntimeException("Test failed"); + } + + if (Platform.isWindows()) { + System.out.println("Windows: Testing ALT + MOUSE1 press case"); + lastMousePressedEvent = null; + robot.waitForIdle(); + robot.delay(300); + + robot.keyPress(KeyEvent.VK_ALT); + robot.delay(25); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(25); + robot.keyRelease(KeyEvent.VK_ALT); + robot.delay(25); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(300); + + int expectedModifiers = InputEvent.BUTTON1_MASK + | InputEvent.BUTTON2_MASK + | InputEvent.ALT_MASK; + if (lastMousePressedEvent == null + || lastMousePressedEvent.getModifiers() != expectedModifiers) { + throw new RuntimeException("Test failed"); + } + } + } + + private static void createAndShowGUI() { + frame = new Frame("MouseModifierTest"); + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + frame.addMouseListener(new MouseHandler()); + frame.setVisible(true); + } + + private static class MouseHandler extends MouseAdapter { + public void mouseClicked(MouseEvent e) { + System.out.println("\nmouseClicked:"); + printMouseEventDetail(e); + } + + public void mousePressed(MouseEvent e) { + lastMousePressedEvent = e; + System.out.println("\nmousePressed:"); + printMouseEventDetail(e); + } + + public void mouseReleased(MouseEvent e) { + System.out.println("\nmouseReleased:"); + printMouseEventDetail(e); + } + + public void mouseEntered(MouseEvent e) { + System.out.println("\nmouseEntered:"); + printMouseEventDetail(e); + } + + public void mouseExited(MouseEvent e) { + System.out.println("\nmouseExited:"); + printMouseEventDetail(e); + } + + private void printMouseEventDetail(MouseEvent e) { + System.out.println(e.toString()); + System.out.println("Modifiers: "); + printModifiers(e); + } + + private void printModifiers(MouseEvent e) { + if (e == null) { + return; + } + + int mod = e.getModifiers(); + + if ((mod & InputEvent.ALT_MASK) != 0) { + System.out.println("\tALT_MASK"); + } + if ((mod & InputEvent.BUTTON1_MASK) != 0) { + System.out.println("\tBUTTON1_MASK"); + } + if ((mod & InputEvent.BUTTON2_MASK) != 0) { + System.out.println("\tBUTTON2_MASK"); + } + if ((mod & InputEvent.BUTTON3_MASK) != 0) { + System.out.println("\tBUTTON3_MASK"); + } + if ((mod & InputEvent.CTRL_MASK) != 0) { + System.out.println("\tCTRL_MASK"); + } + if ((mod & InputEvent.META_MASK) != 0) { + System.out.println("\tMETA_MASK"); + } + if ((mod & InputEvent.SHIFT_MASK) != 0) { + System.out.println("\tSHIFT_MASK"); + } + } + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/event/MouseEvent/MouseRButTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/MouseRButTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/event/MouseEvent/MouseRButTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/MouseRButTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4037521 + * @summary Mouse Right button does not send mouseClick action + * @key headful + * @library /javax/swing/regtesthelpers + * @build Util + * @run main MouseRButTest + */ + +import java.awt.Button; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public class MouseRButTest { + private static Frame frame; + private static Button button; + private static final CountDownLatch latch = new CountDownLatch(1); + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + try { + EventQueue.invokeAndWait(MouseRButTest::createAndShowGUI); + + robot.waitForIdle(); + robot.delay(500); + + Point point = Util.getCenterPoint(button); + robot.mouseMove(point.x, point.y); + robot.waitForIdle(); + robot.mousePress(InputEvent.BUTTON3_DOWN_MASK); + robot.delay(50); + robot.mouseRelease(InputEvent.BUTTON3_DOWN_MASK); + + if (!latch.await(2, TimeUnit.SECONDS)) { + throw new RuntimeException("mouse click action was not sent"); + } + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void createAndShowGUI() { + button = new Button("Click Me"); + button.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + System.out.println(e); + if (e.getModifiers() == e.BUTTON3_MASK) { + System.out.println("right mouse button clicked"); + latch.countDown(); + } + } + }); + + frame = new Frame(); + frame.setLayout(new FlowLayout()); + frame.add(button); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/event/MouseEvent/TitleBarGetsMousePressed.java openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/TitleBarGetsMousePressed.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/event/MouseEvent/TitleBarGetsMousePressed.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/event/MouseEvent/TitleBarGetsMousePressed.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.Frame; +import java.awt.Window; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/* + * @test + * @bug 4074498 + * @summary Test: MOUSE_PRESSED events in the title bar of a frame + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TitleBarGetsMousePressed + */ +public class TitleBarGetsMousePressed { + private static final String INSTRUCTIONS = """ + 1. You will see a Frame window next to this window with instructions + 2. Clicking in the title bar of the Frame and even moving around the Frame + should not generate MOUSE_PRESSED / MOUSE_RELEASED / MOUSE_CLICKED events. + (printed below in the log area). + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("TitleBarGetsMousePressed Instructions") + .instructions(INSTRUCTIONS) + .columns(45) + .testUI(TitleBarGetsMousePressed::createTestUI) + .logArea(5) + .build() + .awaitAndCheck(); + } + + private static Window createTestUI() { + Frame frame = new Frame("TitleBarGetsMousePressed"); + frame.setSize(300, 200); + frame.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent ev) { + PassFailJFrame.log("mouseClicked at x:" + ev.getX() + + " y:" + ev.getY()); + } + + public void mousePressed(MouseEvent ev) { + PassFailJFrame.log("mousePressed at x:" + ev.getX() + + " y:" + ev.getY()); + } + + public void mouseReleased(MouseEvent ev) { + PassFailJFrame.log("mouseReleased at x:" + ev.getX() + + " y:" + ev.getY()); + } + }); + + return frame; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/event/StressTest/LargeAWTEventMulticasterTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/event/StressTest/LargeAWTEventMulticasterTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/event/StressTest/LargeAWTEventMulticasterTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/event/StressTest/LargeAWTEventMulticasterTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import java.awt.AWTEventMulticaster; + +/* + * @test + * @bug 8342782 + * @summary Tests large AWTEventMulticasters for StackOverflowErrors + * @run main LargeAWTEventMulticasterTest + */ +public class LargeAWTEventMulticasterTest { + + /** + * This is an empty ActionListener that also has a numeric index. + */ + static class IndexedActionListener implements ActionListener { + private final int index; + + public IndexedActionListener(int index) { + this.index = index; + } + + @Override + public void actionPerformed(ActionEvent e) { + + } + + public int getIndex() { + return index; + } + + @Override + public String toString() { + return Integer.toString(index); + } + } + + public static void main(String[] args) { + int maxA = 0; + try { + for (int a = 1; a < 200_000; a *= 2) { + maxA = a; + testAddingActionListener(a); + } + } finally { + System.out.println("maximum a = " + maxA); + } + } + + private static void testAddingActionListener(int numberOfListeners) { + // step 1: create the large AWTEventMulticaster + ActionListener l = null; + for (int a = 0; a < numberOfListeners; a++) { + l = AWTEventMulticaster.add(l, new IndexedActionListener(a)); + } + + // Prior to 8342782 we could CREATE a large AWTEventMulticaster, but we couldn't + // always interact with it. + + // step 2: dispatch an event + // Here we're making sure we don't get a StackOverflowError when we traverse the tree: + l.actionPerformed(null); + + // step 3: make sure getListeners() returns elements in the correct order + // The resolution for 8342782 introduced a `rebalance` method; we want to + // double-check that the rebalanced tree preserves the appropriate order. + IndexedActionListener[] array = AWTEventMulticaster.getListeners(l, IndexedActionListener.class); + for (int b = 0; b < array.length; b++) { + if (b != array[b].getIndex()) + throw new Error("the listeners are in the wrong order. " + b + " != " + array[b].getIndex()); + } + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/event/WindowActivatedEventTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/event/WindowActivatedEventTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/event/WindowActivatedEventTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/event/WindowActivatedEventTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,169 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4219344 + * @summary tests that WINDOW_ACTIVATED events are generated properly + * @key headful + * @library /test/jdk/java/awt/regtesthelpers + * @build Util + * @run main WindowActivatedEventTest + */ + +import test.java.awt.regtesthelpers.Util; + +import java.awt.Dialog; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Robot; +import java.awt.Window; +import java.awt.event.WindowEvent; +import java.awt.event.WindowAdapter; +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicInteger; + +public class WindowActivatedEventTest { + + static Robot robot; + static Frame frame; + static Dialog dialog; + + public static void main(String[] args) throws Exception { + robot = new Robot(); + + try { + EventQueue.invokeAndWait(WindowActivatedEventTest::createAndShowGUI); + robot.waitForIdle(); + robot.delay(500); + + Util.clickOnComp(dialog, robot); + + robot.waitForIdle(); + robot.delay(500); + + for (int i = 0; i < 3 ; i++) { + clickAndCheck(frame); + clickAndCheck(dialog); + } + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + if (dialog != null) { + dialog.dispose(); + } + }); + } + } + + private static void clickAndCheck(Window windowToFocus) + throws InterruptedException, InvocationTargetException { + Window oppositeWindow = (windowToFocus == frame) ? dialog : frame; + + System.out.println("Clicking on " + windowToFocus); + + EventQueue.invokeAndWait(() -> { + if (windowToFocus.isFocused() || !oppositeWindow.isFocused()) { + throw new RuntimeException("%s isFocused %b, %s isFocused %b".formatted( + windowToFocus.getName(), windowToFocus.isFocused(), + oppositeWindow.getName(), oppositeWindow.isFocused() + )); + } + }); + + WindowEventLogger windowLogger = WindowEventLogger.getFromWindow(windowToFocus); + WindowEventLogger oppositeWindowLogger = WindowEventLogger.getFromWindow(oppositeWindow); + + windowLogger.resetCounters(); + oppositeWindowLogger.resetCounters(); + + Util.clickOnComp(windowToFocus, robot); + + robot.delay(500); + + int windowActivatedCount = windowLogger.activatedCount.get(); + int windowDeactivatedCount = windowLogger.deactivatedCount.get(); + int oppositeWindowActivatedCount = oppositeWindowLogger.activatedCount.get(); + int oppositeWindowDeactivatedCount = oppositeWindowLogger.deactivatedCount.get(); + + if (windowActivatedCount != 1 + || windowDeactivatedCount != 0 + || oppositeWindowActivatedCount != 0 + || oppositeWindowDeactivatedCount != 1) { + throw new RuntimeException( + "Invalid activated/deactivated count: %s (%d/%d) / %s (%d/%d)" + .formatted( + windowToFocus.getName(), + windowActivatedCount, + windowDeactivatedCount, + oppositeWindow.getName(), + oppositeWindowActivatedCount, + oppositeWindowDeactivatedCount + )); + } + } + + private static void createAndShowGUI() { + frame = new Frame("frame WindowActivatedEventTest"); + dialog = new Dialog(frame, "dialog WindowActivatedEventTest"); + + frame.addWindowListener(new WindowEventLogger()); + dialog.addWindowListener(new WindowEventLogger()); + + frame.setBounds(400, 0, 200, 200); + frame.setVisible(true); + + dialog.setBounds(400, 200, 200, 200); + dialog.setVisible(true); + } + + private static class WindowEventLogger extends WindowAdapter { + final AtomicInteger activatedCount = new AtomicInteger(0); + final AtomicInteger deactivatedCount = new AtomicInteger(0); + + public void windowActivated(WindowEvent e) { + activatedCount.incrementAndGet(); + System.out.println(e); + } + + public void windowDeactivated(WindowEvent e) { + deactivatedCount.incrementAndGet(); + System.out.println(e); + } + + public void resetCounters() { + activatedCount.set(0); + deactivatedCount.set(0); + } + + public static WindowEventLogger getFromWindow(Window window) { + return (WindowEventLogger) Arrays + .stream(window.getWindowListeners()) + .filter(listener -> listener instanceof WindowEventLogger) + .findFirst().get(); + } + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/font/TextLayout/MyanmarTextTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/font/TextLayout/MyanmarTextTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/font/TextLayout/MyanmarTextTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/font/TextLayout/MyanmarTextTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,12 +27,15 @@ * @key headful * @summary Verifies that Myanmar script is rendered correctly: * two characters combined into one glyph + * @library /test/lib + * @build jtreg.SkippedException * @run main MyanmarTextTest */ import java.awt.Font; import java.awt.GraphicsEnvironment; import java.util.Arrays; +import java.util.List; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.JFrame; @@ -45,12 +48,16 @@ import javax.swing.text.BadLocationException; import javax.swing.text.Position; +import jtreg.SkippedException; + public class MyanmarTextTest { private static final String TEXT = "\u1000\u103C"; - private static final String FONT_WINDOWS = "Myanmar Text"; - private static final String FONT_LINUX = "Padauk"; - private static final String FONT_MACOS = "Myanmar MN"; + private static final List FONT_CANDIDATES = + List.of("Myanmar MN", + "Padauk", + "Myanmar Text", + "Noto Sans Myanmar"); private static final String FONT_NAME = selectFontName(); @@ -61,12 +68,8 @@ public static void main(String[] args) throws Exception { if (FONT_NAME == null) { - System.err.println("Unsupported OS: exiting"); - return; - } - if (!fontExists()) { - System.err.println("Required font is not installed: " + FONT_NAME); - return; + throw new SkippedException("No suitable font found out of the list: " + + String.join(", ", FONT_CANDIDATES)); } try { @@ -130,22 +133,12 @@ } private static String selectFontName() { - String osName = System.getProperty("os.name").toLowerCase(); - if (osName.contains("windows")) { - return FONT_WINDOWS; - } else if (osName.contains("linux")) { - return FONT_LINUX; - } else if (osName.contains("mac")) { - return FONT_MACOS; - } else { - return null; - } + return Arrays.stream(GraphicsEnvironment + .getLocalGraphicsEnvironment() + .getAvailableFontFamilyNames()) + .filter(FONT_CANDIDATES::contains) + .findFirst() + .orElse(null); } - private static boolean fontExists() { - String[] fontFamilyNames = GraphicsEnvironment - .getLocalGraphicsEnvironment() - .getAvailableFontFamilyNames(); - return Arrays.asList(fontFamilyNames).contains(FONT_NAME); - } } diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/im/4490692/bug4490692.html openjdk-21-21.0.9+10/test/jdk/java/awt/im/4490692/bug4490692.html --- openjdk-21-21.0.8+9/test/jdk/java/awt/im/4490692/bug4490692.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/im/4490692/bug4490692.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ - - - - - - Test for KEY_PRESS event for accented characters - - - -

Test for KEY_PRESS event for accented characters: Bug id 4490692

- -This test is for unix platforms only. Press OK if you are not -testing on those platforms. - -Before the test, you need to modify the keyboard mapping for X by issueing -the following command: - -xmodmap -e 'keycode 60 = aacute' (this is for Solaris Sparc keyboard) -xmodmap -e 'keycode 23 = aacute' (this is for Linux PC keyboard) - -This command lets you type 'a with acute' character when you press 'Tab' keytop. Please -do not fail to restore the original key mapping by doing the following after the test - -xmodmap -e 'keycode 60 = Tab' (this is for Solaris Sparc keyboard) -xmodmap -e 'keycode 23 = Tab' (this is for Linux PC keyboard) - -Confirm the following two behaviors: - - "KEYPRESS received for aacute" is displayed when you press 'Tab' keytop. - On Solaris Sparc keyboard, The key sequence ("Compose", "a", "'") generates a-acute character in en_US locale - - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/im/4490692/bug4490692.java openjdk-21-21.0.9+10/test/jdk/java/awt/im/4490692/bug4490692.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/im/4490692/bug4490692.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/im/4490692/bug4490692.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2007, 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. - */ - -/** - * - * @bug 4490692 - * @author Naoto Sato - */ - -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; - -public class bug4490692 extends javax.swing.JApplet { - public void init() { - new TestFrame(); - } -} - -class TestFrame extends JFrame implements KeyListener { - JTextField text; - JLabel label; - - TestFrame () { - text = new JTextField(); - text.addKeyListener(this); - label = new JLabel(" "); - Container c = getContentPane(); - BorderLayout borderLayout1 = new BorderLayout(); - c.setLayout(borderLayout1); - c.add(text, BorderLayout.CENTER); - c.add(label, BorderLayout.SOUTH); - setSize(300, 200); - setVisible(true); - } - - public void keyPressed(KeyEvent e) { - if (e.getKeyChar() == 0x00e1) { - label.setText("KEYPRESS received for aacute"); - } else { - label.setText(" "); - } - } - - public void keyTyped(KeyEvent e) { - } - - public void keyReleased(KeyEvent e) { - } -} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/im/8132503/bug8132503.html openjdk-21-21.0.9+10/test/jdk/java/awt/im/8132503/bug8132503.html --- openjdk-21-21.0.8+9/test/jdk/java/awt/im/8132503/bug8132503.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/im/8132503/bug8132503.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ - - - - -Verify that Chinese full stop symbol can be entered in JTextArea with Pinyin input method (IM). - -This test is for OS X only. For other platforms please simply press "Pass". - -1. Go to "System Preferences -> Keyboard -> Input Sources" and add "Pinyin – Traditional" or "Pinyin – Simplified" IM from Chinese language group. -2. Set current IM to "Pinyin". -3. Set focus to the text area of the test and press "dot" character on the keyboard. -4. Set current IM to the IM used before "Pinyin" was set. -5. If "。" character is displayed in the text area, press "Pass", if "." character is displayed, press "Fail". - - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/im/8132503/bug8132503.java openjdk-21-21.0.9+10/test/jdk/java/awt/im/8132503/bug8132503.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/im/8132503/bug8132503.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/im/8132503/bug8132503.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* @test - @bug 8132503 - @summary [macosx] Chinese full stop symbol cannot be entered with Pinyin IM on OS X - @author Anton Litvinov - @run applet/manual=yesno bug8132503.html - */ - -import javax.swing.JApplet; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.SwingUtilities; - -public class bug8132503 extends JApplet { - @Override - public void init() { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - JTextArea textArea = new JTextArea("Text area of the test.", 40, 40); - add(new JScrollPane(textArea)); - } - }); - } -} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/im/8148984/bug8148984.html openjdk-21-21.0.9+10/test/jdk/java/awt/im/8148984/bug8148984.html --- openjdk-21-21.0.8+9/test/jdk/java/awt/im/8148984/bug8148984.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/im/8148984/bug8148984.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ - - - - -Verify that Chinese comma can be entered in JTextField with Pinyin input method (IM). - -This test is for OS X only. For other platforms please simply press "Pass". - -1. Go to "System Preferences -> Keyboard -> Input Sources" and add "Pinyin – Traditional" or "Pinyin – Simplified" IM from Chinese language group. -2. Set current IM to "Pinyin". -3. Set focus to the text field of the test and press "comma" character on the keyboard. -4. Set current IM to the IM used before "Pinyin" was set. -5. If "," character is displayed in the text area, press "Pass", if "," character is displayed, press "Fail". - - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/im/8148984/bug8148984.java openjdk-21-21.0.9+10/test/jdk/java/awt/im/8148984/bug8148984.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/im/8148984/bug8148984.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/im/8148984/bug8148984.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* @test - * @bug 8148984 - * @summary Chinese Comma cannot be entered using Pinyin Input Method on OS X - * @author Dmitry Markov - * @run applet/manual=yesno bug8148984.html - */ - -import javax.swing.*; - -public class bug8148984 extends JApplet { - @Override - public void init() { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - JPanel panel = new JPanel(); - panel.add(new JLabel("Text field:")); - panel.add(new JTextField(20)); - add(panel); - } - }); - } -} - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/im/8154816/bug8154816.html openjdk-21-21.0.9+10/test/jdk/java/awt/im/8154816/bug8154816.html --- openjdk-21-21.0.8+9/test/jdk/java/awt/im/8154816/bug8154816.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/im/8154816/bug8154816.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ - - - - -Verify that Caps Lock key works properly with Pinyin input method, (i.e. if -Caps Lock is pressed, input should be swithced to lowercase latin letters). - -This test is for OS X only. For other platforms please simply press "Pass". - -1. Go to "System Preferences -> Keyboard -> Input Sources" and add "Pinyin – Traditional" or "Pinyin – Simplified" IM from Chinese language group. -2. Set current IM to "Pinyin". -3. Set focus to the text field of the test and press Caps Lock key on the keyboard. -4. Press "a" character on the keyboard -5. If "a" character is displayed in the text field, press "Pass", if "A" character is displayed, press "Fail". - - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/im/8154816/bug8154816.java openjdk-21-21.0.9+10/test/jdk/java/awt/im/8154816/bug8154816.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/im/8154816/bug8154816.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/im/8154816/bug8154816.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* @test - * @bug 8154816 - * @summary Caps Lock doesn't work as expected when using Pinyin Simplified input method - * @author Dmitry Markov - * @run applet/manual=yesno bug8154816.html - */ - -import javax.swing.*; - -public class bug8154816 extends JApplet { - @Override - public void init() { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - JPanel panel = new JPanel(); - panel.add(new JLabel("Text field:")); - panel.add(new JTextField(20)); - add(panel); - } - }); - } -} - diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/im/PinyinIMCapsTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/im/PinyinIMCapsTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/im/PinyinIMCapsTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/im/PinyinIMCapsTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import jtreg.SkippedException; +import sun.awt.OSInfo; + +/* + * @test + * @bug 8154816 + * @summary Caps Lock doesn't work as expected when using Pinyin Simplified input method + * @requires (os.family == "mac") + * @modules java.desktop/sun.awt + * @library /java/awt/regtesthelpers /test/lib + * @build PassFailJFrame jtreg.SkippedException Util + * @run main/manual PinyinIMCapsTest + */ + +public class PinyinIMCapsTest { + private static final String INSTRUCTIONS = """ + The test verifies if the Caps Lock key works properly with Pinyin + input method, (i.e. if Caps Lock is pressed, input should be + switched to lowercase latin letters). + + Test settings: + Go to "System Preferences -> Keyboard -> Input Sources" and + add "Pinyin – Traditional" or "Pinyin – Simplified" IM from Chinese language group. + Set current IM to "Pinyin". + + 1. Set focus to the text field shown below and press Caps Lock key on the keyboard. + 2. Press "a" character on the keyboard + 3. If "a" character is displayed in the text field, press "Pass", + if "A" character is displayed, press "Fail". + """; + + public static void main(String[] args) throws Exception { + if (OSInfo.getOSType() != OSInfo.OSType.MACOSX) { + throw new SkippedException("This test is for MacOS only"); + } + PassFailJFrame.builder() + .title("Test Pinyin Input Method") + .instructions(INSTRUCTIONS) + .rows((int) INSTRUCTIONS.lines().count() + 2) + .columns(45) + .splitUIBottom(PinyinIMCapsTest::createUI) + .testTimeOut(10) + .build() + .awaitAndCheck(); + } + + private static JComponent createUI() { + JPanel panel = new JPanel(); + JTextField input = new JTextField(20); + panel.add(new JLabel("Text field:")); + panel.add(input); + return panel; + } +} + diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/im/PinyinIMCommaTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/im/PinyinIMCommaTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/im/PinyinIMCommaTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/im/PinyinIMCommaTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +/* + * @test + * @bug 8148984 + * @summary Verify that Chinese comma can be entered in JTextField + * with Pinyin input method (IM) on OS X. + * @requires (os.family == "mac") + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual PinyinIMCommaTest + */ + +public class PinyinIMCommaTest { + private static final String INSTRUCTIONS = """ + This test verifies if Chinese comma can be entered in JTextField + with Pinyin input method (IM). + + Test settings: + Go to "System Preferences -> Keyboard -> Input Sources" and + add "Pinyin – Traditional" or "Pinyin – Simplified" IM from Chinese language group. + Set current IM to "Pinyin". + + 1. Set focus to the text field below and press "comma" character + on the keyboard. + 2. Now change the current IM to the IM used before "Pinyin" or to "U.S". + Press comma character again. + 3. You should notice a difference in the comma. Pinyin IM should output + full width comma "\uff0c" and the other IM should output a Latin comma "\u002c". + + If above is true press "PASS", if "\u002c" character is displayed for Pinyin IM, press "FAIL". + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("Test Comma using Pinyin Input Method") + .instructions(INSTRUCTIONS) + .rows((int) INSTRUCTIONS.lines().count() + 2) + .columns(45) + .splitUIBottom(PinyinIMCommaTest::createUI) + .testTimeOut(10) + .build() + .awaitAndCheck(); + } + + private static JComponent createUI() { + JPanel panel = new JPanel(); + panel.add(new JLabel("Text field:")); + panel.add(new JTextField(20)); + return panel; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/im/PinyinIMFullstopTest.java openjdk-21-21.0.9+10/test/jdk/java/awt/im/PinyinIMFullstopTest.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/im/PinyinIMFullstopTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/im/PinyinIMFullstopTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextArea; + +/* + * @test + * @bug 8132503 + * @summary [macosx] Chinese full stop symbol cannot be entered with Pinyin IM on OS X + * @requires (os.family == "mac") + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual PinyinIMFullstopTest + */ + +public class PinyinIMFullstopTest { + private static final String INSTRUCTIONS = """ + This test verifies if Chinese full stop symbol can be entered in JTextArea + with Pinyin input method (IM). + + Test settings: + Go to "System Preferences -> Keyboard -> Input Sources" and + add "Pinyin – Traditional" or "Pinyin – Simplified" IM from Chinese language group. + Set current IM to "Pinyin". + + 1. Set focus to the text area below and press "dot" character + on the keyboard. + 2. Now change the current IM to the IM used before "Pinyin" or to "U.S". + Press dot character again. + 3. You should notice a difference in the dot. Pinyin IM should output + "。" and the other IM should output "." + + If above is true press "PASS", if normal fullstop "." character is displayed + for Pinyin IM, press "FAIL". + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("Test Dot using Pinyin Input Method") + .instructions(INSTRUCTIONS) + .rows((int) INSTRUCTIONS.lines().count() + 2) + .columns(45) + .splitUIBottom(PinyinIMFullstopTest::createUI) + .testTimeOut(10) + .build() + .awaitAndCheck(); + } + + private static JComponent createUI() { + JPanel panel = new JPanel(); + JTextArea textArea = new JTextArea(5, 40); + panel.add(new JLabel("Text Area:")); + panel.add(textArea); + return panel; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/im/bug4490692.java openjdk-21-21.0.9+10/test/jdk/java/awt/im/bug4490692.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/im/bug4490692.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/im/bug4490692.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +/* + * @test + * @bug 4490692 + * @summary [Linux] Test for KEY_PRESS event for accented characters. + * @requires (os.family == "linux") + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4490692 + */ + +public class bug4490692 { + private static final String INSTRUCTIONS = """ + This test is for unix platforms only. + Before the test, you need to modify the keyboard mapping for + Tab by issuing the following command: + + xmodmap -e 'keycode 23 = aacute' (this is for Linux) + xmodmap -e 'keycode 60 = aacute' (this is for Solaris Sparc) + + This command lets you type 'a with acute (à)' character when you press + 'Tab' key in the JTextField provided below the logging area. + After the test, please DO NOT fail to restore the original + key mapping by doing the following. + + xmodmap -e 'keycode 23 = Tab' (this is for Linux) + xmodmap -e 'keycode 60 = Tab' (this is for Solaris Sparc) + + CASE 1: This is a manual check and for SOLARIS SPARC keyboard + only. Check whether the key sequence ("Compose", "a", " ' ") + generates a-acute character in en_US locale. + + CASE 2: This step is automated and applicable for both + keyboards - LINUX & SOLARIS SPARC. + When Tab key is pressed it should generate a-acute (à) + character, this test automatically passes if the correct character + is generated on keypress else fails. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .rows((int) INSTRUCTIONS.lines().count() + 2) + .columns(45) + .testTimeOut(10) + .splitUIBottom(bug4490692::createUI) + .logArea(8) + .build() + .awaitAndCheck(); + } + + private static JComponent createUI() { + JPanel panel = new JPanel(); + JTextField textField = new JTextField("", 20); + panel.add(new JLabel("Text field:")); + + textField.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + PassFailJFrame.log(e.paramString()); + if (e.getKeyCode() == 23 || e.getKeyCode() == 60 + || e.paramString().contains("rawCode=23") + || e.paramString().contains("rawCode=60")) { + if (e.getKeyChar() == 0x00e1) { + PassFailJFrame.forcePass(); + } else { + PassFailJFrame.forceFail("Tab keypress DID NOT" + + " produce the expected accented character - aacute"); + } + } + } + }); + + panel.add(textField); + return panel; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/print/PrinterJob/PrintNullString.java openjdk-21-21.0.9+10/test/jdk/java/awt/print/PrinterJob/PrintNullString.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/print/PrinterJob/PrintNullString.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/print/PrinterJob/PrintNullString.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,164 +21,113 @@ * questions. */ -import java.awt.Button; -import java.awt.Dimension; -import java.awt.Frame; import java.awt.Graphics; import java.awt.Graphics2D; -import java.awt.Panel; import java.awt.print.PageFormat; import java.awt.print.Printable; import java.awt.print.PrinterException; import java.awt.print.PrinterJob; +import java.io.File; import java.text.AttributedCharacterIterator; import java.text.AttributedString; -import javax.swing.JOptionPane; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.PrintRequestAttributeSet; +import javax.print.attribute.standard.Destination; /* * @test * @bug 4223328 - * @summary Printer graphics must behave the same as screen graphics + * @summary Printer graphics must throw expected exceptions * @key printer - * @library /java/awt/regtesthelpers - * @build PassFailJFrame - * @run main/manual PrintNullString + * @run main PrintNullString */ -public class PrintNullString extends Frame { - private static final String INSTRUCTIONS = - "This test should print a page which contains the same\n" + - "text messages as in the test window on the screen.\n" + - "\n" + - "The messages should contain only 'OK' and 'expected' messages.\n" + - "Press Pass if it's the case; otherwise press Fail.\n" + - "\n" + - "If the page fails to print, but there were no exceptions\n" + - "then the problem is likely elsewhere (i.e. your printer)"; +public class PrintNullString implements Printable { + private final String nullStr = null; + private final String emptyStr = ""; + private final AttributedString emptyAttStr = new AttributedString(emptyStr); + private final AttributedCharacterIterator nullIterator = null; + private final AttributedCharacterIterator emptyIterator = emptyAttStr.getIterator(); public static void main(String[] args) throws Exception { if (PrinterJob.lookupPrintServices().length == 0) { throw new RuntimeException("Printer not configured or available."); } - PassFailJFrame.builder() - .instructions(INSTRUCTIONS) - .testUI(PrintNullString::new) - .rows((int) INSTRUCTIONS.lines().count() + 1) - .columns(45) - .build() - .awaitAndCheck(); + new PrintNullString(); } - public PrintNullString() { - super("PrintNullString"); + public PrintNullString() throws PrinterException { + PrinterJob pj = PrinterJob.getPrinterJob(); + pj.setPrintable(this, new PageFormat()); + PrintRequestAttributeSet pSet = new HashPrintRequestAttributeSet(); + File file = new File("out.prn"); + file.deleteOnExit(); + pSet.add(new Destination(file.toURI())); + pj.print(pSet); + } + + @Override + public int print(Graphics g, PageFormat pgFmt, int pgIndex) { + if (pgIndex > 0) { + return NO_SUCH_PAGE; + } - TextCanvas c = new TextCanvas(); - add("Center", c); + Graphics2D g2d = (Graphics2D) g; + g2d.translate(pgFmt.getImageableX(), pgFmt.getImageableY()); - Button b = new Button("Print"); - add("South", b); - b.addActionListener(e -> { - PrinterJob pj = PrinterJob.getPrinterJob(); - if (pj.printDialog()) { - pj.setPrintable(c); - try { - pj.print(); - } catch (PrinterException ex) { - ex.printStackTrace(); - String msg = "PrinterException: " + ex.getMessage(); - JOptionPane.showMessageDialog(b, msg, "Error occurred", - JOptionPane.ERROR_MESSAGE); - PassFailJFrame.forceFail(msg); - } - } - }); - pack(); - } + // API 1: null & empty drawString(String, int, int); + try { + g2d.drawString(nullStr, 20, 40); + throw new RuntimeException("FAILURE: No NPE for null String, int"); + } catch (NullPointerException e) { + g2d.drawString("caught expected NPE for null String, int", 20, 40); + } + + g2d.drawString(emptyStr, 20, 60); + g2d.drawString("OK for empty String, int", 20, 60); + + // API 2: null & empty drawString(String, float, float); + try { + g2d.drawString(nullStr, 20.0f, 80.0f); + throw new RuntimeException("FAILURE: No NPE for null String, float"); + } catch (NullPointerException e) { + g2d.drawString("caught expected NPE for null String, float", 20, 80); + } - private static class TextCanvas extends Panel implements Printable { - private final String nullStr = null; - private final String emptyStr = ""; - private final AttributedString emptyAttStr = new AttributedString(emptyStr); - private final AttributedCharacterIterator nullIterator = null; - private final AttributedCharacterIterator emptyIterator = emptyAttStr.getIterator(); - - @Override - public void paint(Graphics g) { - Graphics2D g2d = (Graphics2D) g; - paint(g2d); - } - - @Override - public int print(Graphics g, PageFormat pgFmt, int pgIndex) { - if (pgIndex > 0) { - return NO_SUCH_PAGE; - } - - Graphics2D g2d = (Graphics2D) g; - g2d.translate(pgFmt.getImageableX(), pgFmt.getImageableY()); - paint(g2d); - - return PAGE_EXISTS; - } - - private void paint(Graphics2D g2d) { - // API 1: null & empty drawString(String, int, int); - try { - g2d.drawString(nullStr, 20, 40); - g2d.drawString("FAILURE: No NPE for null String, int", 20, 40); - } catch (NullPointerException e) { - g2d.drawString("caught expected NPE for null String, int", 20, 40); - } - - g2d.drawString(emptyStr, 20, 60); - g2d.drawString("OK for empty String, int", 20, 60); - - // API 2: null & empty drawString(String, float, float); - try { - g2d.drawString(nullStr, 20.0f, 80.0f); - g2d.drawString("FAILURE: No NPE for null String, float", 20, 80); - } catch (NullPointerException e) { - g2d.drawString("caught expected NPE for null String, float", 20, 80); - } - - g2d.drawString(emptyStr, 20.0f, 100.0f); - g2d.drawString("OK for empty String, float", 20.0f, 100.f); - - // API 3: null & empty drawString(Iterator, int, int); - try { - g2d.drawString(nullIterator, 20, 120); - g2d.drawString("FAILURE: No NPE for null iterator, int", 20, 120); - } catch (NullPointerException e) { - g2d.drawString("caught expected NPE for null iterator, int", 20, 120); - } - - try { - g2d.drawString(emptyIterator, 20, 140); - g2d.drawString("FAILURE: No IAE for empty iterator, int", 20, 140); - } catch (IllegalArgumentException e) { - g2d.drawString("caught expected IAE for empty iterator, int", 20, 140); - } - - // API 4: null & empty drawString(Iterator, float, int); - try { - g2d.drawString(nullIterator, 20.0f, 160.0f); - g2d.drawString("FAILURE: No NPE for null iterator, float", 20, 160); - } catch (NullPointerException e) { - g2d.drawString("caught expected NPE for null iterator, float", 20, 160); - } - - try { - g2d.drawString(emptyIterator, 20.0f, 180.0f); - g2d.drawString("FAILURE: No IAE for empty iterator, float", 20, 180); - } catch (IllegalArgumentException e) { - g2d.drawString("caught expected IAE for empty iterator, float", 20, 180); - } - } - - @Override - public Dimension getPreferredSize() { - return new Dimension(450, 250); + g2d.drawString(emptyStr, 20.0f, 100.0f); + g2d.drawString("OK for empty String, float", 20.0f, 100.f); + + // API 3: null & empty drawString(Iterator, int, int); + try { + g2d.drawString(nullIterator, 20, 120); + throw new RuntimeException("FAILURE: No NPE for null iterator, int"); + } catch (NullPointerException e) { + g2d.drawString("caught expected NPE for null iterator, int", 20, 120); + } + + try { + g2d.drawString(emptyIterator, 20, 140); + throw new RuntimeException("FAILURE: No IAE for empty iterator, int"); + } catch (IllegalArgumentException e) { + g2d.drawString("caught expected IAE for empty iterator, int", 20, 140); + } + + // API 4: null & empty drawString(Iterator, float, int); + try { + g2d.drawString(nullIterator, 20.0f, 160.0f); + throw new RuntimeException("FAILURE: No NPE for null iterator, float"); + } catch (NullPointerException e) { + g2d.drawString("caught expected NPE for null iterator, float", 20, 160); + } + + try { + g2d.drawString(emptyIterator, 20.0f, 180.0f); + throw new RuntimeException("FAILURE: No IAE for empty iterator, float"); + } catch (IllegalArgumentException e) { + g2d.drawString("caught expected IAE for empty iterator, float", 20, 180); } + + return PAGE_EXISTS; } } diff -Nru openjdk-21-21.0.8+9/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java openjdk-21-21.0.9+10/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java --- openjdk-21-21.0.8+9/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java 2025-10-13 07:49:24.000000000 +0000 @@ -150,6 +150,17 @@ * Before returning from {@code awaitAndCheck}, the framework disposes of * all the windows and frames. * + *

+ * For semi-automatic tests, use {@code forcePass} or + * {@code forceFail} methods to forcibly pass or fail the test + * when it's determined that the required conditions are already met + * or cannot be met correspondingly. + * These methods release {@code awaitAndCheck}, and + * the test will complete successfully or fail. + *

+ * Refer to examples of using these methods in the description of the + * {@link #forcePass() forcePass} and {@link #forceFail() forceFail} methods. + * *

Sample Manual Test

* A simple test would look like this: * {@snippet id='sampleManualTestCode' lang='java': @@ -1294,28 +1305,50 @@ /** * Forcibly pass the test. - *

The sample usage: - *


-     *      PrinterJob pj = PrinterJob.getPrinterJob();
-     *      if (pj == null || pj.getPrintService() == null) {
-     *          System.out.println(""Printer not configured or available.");
-     *          PassFailJFrame.forcePass();
-     *      }
-     * 
+ *

+ * Use this method in semi-automatic tests when + * the test determines that all the conditions for passing the test are met. + *

+ * Do not use this method in cases where a resource is unavailable or a + * feature isn't supported, throw {@code jtreg.SkippedException} instead. + * + *

A sample usage can be found in + * {@code + * SaveFileNameOverrideTest.java} */ public static void forcePass() { latch.countDown(); } /** - * Forcibly fail the test. + * Forcibly fail the test. + *

+ * Use this method in semi-automatic tests when + * it is determined that the conditions for passing the test cannot be met. + *

+ * Do not use this method in cases where a resource is unavailable or a + * feature isn't supported, throw {@code jtreg.SkippedException} instead. + * + *

A sample usage can be found in + * {@code + * HorizScrollers.java} */ public static void forceFail() { forceFail("forceFail called"); } /** - * Forcibly fail the test and provide a reason. + * Forcibly fail the test and provide a reason. + *

+ * Use this method in semi-automatic tests when + * it is determined that the conditions for passing the test cannot be met. + *

+ * Do not use this method in cases where a resource is unavailable or a + * feature isn't supported, throw {@code jtreg.SkippedException} instead. + * + *

A sample usage can be found in + * {@code + * SaveFileNameOverrideTest.java} * * @param reason the reason why the test is failed */ @@ -1714,7 +1747,7 @@ * * @throws IllegalStateException if a {@code PanelCreator} is * already set - * @throws IllegalArgumentException if {panelCreator} is {@code null} + * @throws IllegalArgumentException if {@code panelCreator} is {@code null} */ public Builder splitUI(PanelCreator panelCreator) { return splitUIRight(panelCreator); @@ -1731,7 +1764,7 @@ * * @throws IllegalStateException if a {@code PanelCreator} is * already set - * @throws IllegalArgumentException if {panelCreator} is {@code null} + * @throws IllegalArgumentException if {@code panelCreator} is {@code null} */ public Builder splitUIRight(PanelCreator panelCreator) { return splitUI(panelCreator, JSplitPane.HORIZONTAL_SPLIT); @@ -1748,7 +1781,7 @@ * * @throws IllegalStateException if a {@code PanelCreator} is * already set - * @throws IllegalArgumentException if {panelCreator} is {@code null} + * @throws IllegalArgumentException if {@code panelCreator} is {@code null} */ public Builder splitUIBottom(PanelCreator panelCreator) { return splitUI(panelCreator, JSplitPane.VERTICAL_SPLIT); @@ -1764,7 +1797,7 @@ * * @throws IllegalStateException if a {@code PanelCreator} is * already set - * @throws IllegalArgumentException if {panelCreator} is {@code null} + * @throws IllegalArgumentException if {@code panelCreator} is {@code null} */ private Builder splitUI(PanelCreator panelCreator, int splitUIOrientation) { diff -Nru openjdk-21-21.0.8+9/test/jdk/java/beans/Introspector/DefaultMethodBeanPropertyTest.java openjdk-21-21.0.9+10/test/jdk/java/beans/Introspector/DefaultMethodBeanPropertyTest.java --- openjdk-21-21.0.8+9/test/jdk/java/beans/Introspector/DefaultMethodBeanPropertyTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/beans/Introspector/DefaultMethodBeanPropertyTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,20 +23,26 @@ /* * @test - * @bug 8071693 + * @bug 8071693 8347826 * @summary Verify that the Introspector finds default methods inherited * from interfaces */ +import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; +import java.beans.MethodDescriptor; import java.beans.PropertyDescriptor; +import java.beans.SimpleBeanInfo; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.NavigableSet; +import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; public class DefaultMethodBeanPropertyTest { @@ -78,11 +84,17 @@ } public static void testScenario1() { + verifyMethods(D1.class, + "public static int DefaultMethodBeanPropertyTest$A1.getStaticValue()", + "public default int DefaultMethodBeanPropertyTest$A1.getValue()", + "public java.lang.Integer DefaultMethodBeanPropertyTest$D1.getFoo()", + "public java.lang.Float DefaultMethodBeanPropertyTest$D1.getObj()" + ); verifyProperties(D1.class, - "getClass", // inherited method - "getValue", // inherited default method - "getFoo", // overridden interface method - "getObj" // overridden default method + "public final native java.lang.Class java.lang.Object.getClass()", + "public default int DefaultMethodBeanPropertyTest$A1.getValue()", + "public java.lang.Integer DefaultMethodBeanPropertyTest$D1.getFoo()", + "public java.lang.Float DefaultMethodBeanPropertyTest$D1.getObj()" ); } @@ -108,9 +120,12 @@ } public static void testScenario2() { + verifyMethods(D2.class, + "public default java.lang.Object DefaultMethodBeanPropertyTest$A2.getFoo()" + ); verifyProperties(D2.class, - "getClass", - "getFoo" + "public final native java.lang.Class java.lang.Object.getClass()", + "public default java.lang.Object DefaultMethodBeanPropertyTest$A2.getFoo()" ); } @@ -144,60 +159,404 @@ } public static void testScenario3() { + verifyMethods(D3.class, + "public java.util.NavigableSet DefaultMethodBeanPropertyTest$D3.getFoo()" + ); verifyProperties(D3.class, - "getClass", - "getFoo" + "public final native java.lang.Class java.lang.Object.getClass()", + "public java.util.NavigableSet DefaultMethodBeanPropertyTest$D3.getFoo()" ); } -// Helper methods +////////////////////////////////////// +// // +// SCENARIO 4 // +// // +////////////////////////////////////// - public static void verifyProperties(Class type, String... getterNames) { + public interface A4 { + default Object getDefault0() { + return null; + } + default Object getDefault1() { + return null; + } + default Object getDefault2() { + return null; + } + default Object getDefault3() { + return null; + } + Object getNonDefault(); + } - // Gather expected properties - final HashSet expected = new HashSet<>(); - for (String methodName : getterNames) { - final String suffix = methodName.substring(3); - final String propName = Introspector.decapitalize(suffix); - final Method getter; + public class B4 implements A4 { + @Override + public Object getDefault1() { + return new B4(); + } + @Override + public String getDefault2() { + return null; + } + @Override + public Float getDefault3() { + return null; + } + public Long getNonDefault() { + return null; + } + } + + public static void testScenario4() { + verifyMethods(B4.class, + "public default java.lang.Object DefaultMethodBeanPropertyTest$A4.getDefault0()", + "public java.lang.Object DefaultMethodBeanPropertyTest$B4.getDefault1()", + "public java.lang.String DefaultMethodBeanPropertyTest$B4.getDefault2()", + "public java.lang.Float DefaultMethodBeanPropertyTest$B4.getDefault3()", + "public java.lang.Long DefaultMethodBeanPropertyTest$B4.getNonDefault()" + ); + verifyProperties(B4.class, + "public final native java.lang.Class java.lang.Object.getClass()", + "public default java.lang.Object DefaultMethodBeanPropertyTest$A4.getDefault0()", + "public java.lang.Object DefaultMethodBeanPropertyTest$B4.getDefault1()", + "public java.lang.String DefaultMethodBeanPropertyTest$B4.getDefault2()", + "public java.lang.Float DefaultMethodBeanPropertyTest$B4.getDefault3()", + "public java.lang.Long DefaultMethodBeanPropertyTest$B4.getNonDefault()" + ); + } + +////////////////////////////////////// +// // +// SCENARIO 5 // +// // +////////////////////////////////////// + + public interface A5 { + public default void setParentFoo(Integer num) { + } + public default void setFoo(String num) { + } + public static int getStaticValue() { + return 0; + } + private int getPrivateValue() { + return 0; + } + } + + public class B5 implements A5 { + public void setFoo(Number num) { + } + public void setLocalFoo(Long num) { + } + public static int getStaticValue() { + return 0; + } + } + + public static void testScenario5() { + verifyMethods(B5.class, + "public static int DefaultMethodBeanPropertyTest$B5.getStaticValue()", + "public default void DefaultMethodBeanPropertyTest$A5.setFoo(java.lang.String)", + "public default void DefaultMethodBeanPropertyTest$A5.setParentFoo(java.lang.Integer)", + "public void DefaultMethodBeanPropertyTest$B5.setFoo(java.lang.Number)", + "public void DefaultMethodBeanPropertyTest$B5.setLocalFoo(java.lang.Long)" + ); + verifyProperties(B5.class, + "public final native java.lang.Class java.lang.Object.getClass()", + "public default void DefaultMethodBeanPropertyTest$A5.setParentFoo(java.lang.Integer)", + "public void DefaultMethodBeanPropertyTest$B5.setFoo(java.lang.Number)", + "public void DefaultMethodBeanPropertyTest$B5.setLocalFoo(java.lang.Long)" + ); + } + +////////////////////////////////////// +// // +// SCENARIO 6 // +// // +////////////////////////////////////// + + public class A6 { + public void setParentFoo(Integer num) { + } + public void setFoo(Integer num) { + } + public static int getStaticValue() { + return 0; + } + private int getPrivateValue() { + return 0; + } + } + + public class B6 extends A6 { + public void setFoo(String num) { + } + public void setLocalFoo(Long num) { + } + public static int getStaticValue() { + return 0; + } + } + + public static void testScenario6() { + verifyMethods(B6.class, + "public static int DefaultMethodBeanPropertyTest$B6.getStaticValue()", + "public void DefaultMethodBeanPropertyTest$A6.setFoo(java.lang.Integer)", + "public void DefaultMethodBeanPropertyTest$A6.setParentFoo(java.lang.Integer)", + "public void DefaultMethodBeanPropertyTest$B6.setFoo(java.lang.String)", + "public void DefaultMethodBeanPropertyTest$B6.setLocalFoo(java.lang.Long)" + ); + verifyProperties(B6.class, + "public final native java.lang.Class java.lang.Object.getClass()", + "public void DefaultMethodBeanPropertyTest$A6.setParentFoo(java.lang.Integer)", + "public void DefaultMethodBeanPropertyTest$B6.setFoo(java.lang.String)", + "public void DefaultMethodBeanPropertyTest$B6.setLocalFoo(java.lang.Long)" + ); + } + +////////////////////////////////////// +// // +// SCENARIO 7 // +// // +////////////////////////////////////// + + interface A7 { + T getValue(); + } + + interface B7 { + Runnable getValue(); + } + + interface AB7 extends B7, A7 { + Runnable getValue(); + } + + abstract class D7 implements AB7 { + public void setValue(Runnable value) { + } + } + + public static void testScenario7() { + verifyMethods(D7.class, + "public void DefaultMethodBeanPropertyTest$D7.setValue(java.lang.Runnable)" + ); + verifyProperties(D7.class, + "public final native java.lang.Class java.lang.Object.getClass()", + "public void DefaultMethodBeanPropertyTest$D7.setValue(java.lang.Runnable)" + ); + } + +////////////////////////////////////// +// // +// SCENARIO 8 // +// // +////////////////////////////////////// + + public interface A8 { + public default void setFoo(Float num) { + } + public default void setFoo2(Integer num) { + } + } + public interface B8 extends A8 { + public default void setFoo(Integer num) { + } + public default void setFoo2(Float num) { + } + } + + public class C8 implements B8 { + } + + public static void testScenario8() { + verifyMethods(C8.class, + "public default void DefaultMethodBeanPropertyTest$A8.setFoo(java.lang.Float)", + "public default void DefaultMethodBeanPropertyTest$A8.setFoo2(java.lang.Integer)", + "public default void DefaultMethodBeanPropertyTest$B8.setFoo(java.lang.Integer)", + "public default void DefaultMethodBeanPropertyTest$B8.setFoo2(java.lang.Float)" + ); + verifyProperties(C8.class, + "public final native java.lang.Class java.lang.Object.getClass()", + "public default void DefaultMethodBeanPropertyTest$B8.setFoo(java.lang.Integer)", + "public default void DefaultMethodBeanPropertyTest$B8.setFoo2(java.lang.Float)" + ); + } + +////////////////////////////////////// +// // +// SCENARIO 9 // +// // +////////////////////////////////////// + + public class A9 { + public void setFoo(Object value) { + } + public void setFoo(String value) { + } + public void setFoo2(Object value) { + } + public void setFoo2(Integer value) { + } + // For the same setters with inconvertible arg types PropertyInfo behavior is undefined. + // public void setLocalFoo3(Long num) { } + // public void setLocalFoo3(Float num) { } + } + + public static void testScenario9() { + verifyMethods(A9.class, + "public void DefaultMethodBeanPropertyTest$A9.setFoo(java.lang.String)", + "public void DefaultMethodBeanPropertyTest$A9.setFoo(java.lang.Object)", + "public void DefaultMethodBeanPropertyTest$A9.setFoo2(java.lang.Integer)", + "public void DefaultMethodBeanPropertyTest$A9.setFoo2(java.lang.Object)" + ); + verifyProperties(A9.class, + "public final native java.lang.Class java.lang.Object.getClass()", + "public void DefaultMethodBeanPropertyTest$A9.setFoo(java.lang.String)", + "public void DefaultMethodBeanPropertyTest$A9.setFoo2(java.lang.Integer)" + ); + } + +////////////////////////////////////// +// // +// SCENARIO 10 // +// // +////////////////////////////////////// + + public static class A10 { + public Object getProp() { + return null; + } + } + + public static interface B10 { + Object getProp(); + } + + public static class C10_1 extends A10 implements B10 { + } + + public static class C10_2 extends A10 implements B10 { + } + + public static class A10BeanInfo extends SimpleBeanInfo { + public MethodDescriptor[] getMethodDescriptors() { try { - getter = type.getMethod(methodName); - } catch (NoSuchMethodException e) { - throw new Error("unexpected error", e); + Class params[] = {}; + MethodDescriptor md = new MethodDescriptor(A10.class.getDeclaredMethod("getProp", params)); + md.setDisplayName("display name"); + MethodDescriptor res[] = { md }; + return res; + } catch (Exception exception) { + throw new Error("unexpected exception", exception); } - final PropertyDescriptor propDesc; + } + } + + public static class C10_1BeanInfo extends SimpleBeanInfo { + public BeanInfo[] getAdditionalBeanInfo() { + try { + BeanInfo res[] = { + Introspector.getBeanInfo(A10.class), + Introspector.getBeanInfo(B10.class) + }; + return res; + } catch (IntrospectionException exception) { + throw new Error("unexpected exception", exception); + } + } + } + + public static class C10_2BeanInfo extends SimpleBeanInfo { + public BeanInfo[] getAdditionalBeanInfo() { try { - propDesc = new PropertyDescriptor(propName, getter, null); - } catch (IntrospectionException e) { - throw new Error("unexpected error", e); + BeanInfo res[] = { + Introspector.getBeanInfo(B10.class), + Introspector.getBeanInfo(A10.class) + }; + return res; + } catch (IntrospectionException exception) { + throw new Error("unexpected exception", exception); } - expected.add(propDesc); } + } - // Verify properties can be found directly - expected.stream() - .map(PropertyDescriptor::getName) - .filter(name -> BeanUtils.getPropertyDescriptor(type, name) == null) - .findFirst() - .ifPresent(name -> { - throw new Error("property \"" + name + "\" not found in " + type); - }); - - // Gather actual properties - final Set actual = - Set.of(BeanUtils.getPropertyDescriptors(type)); + public static void testScenario10() { + { + var md = getMethodDescriptor(C10_1.class, A10.class, "getProp"); + assertEquals("display name", md.getDisplayName(), "getDisplayName()"); + } + { + var md = getMethodDescriptor(C10_2.class, A10.class, "getProp"); + assertEquals("display name", md.getDisplayName(), "getDisplayName()"); + } + } - // Verify the two sets are the same +// Helper methods + + private static void verifyEquality(String title, Set expected, Set actual) { if (!actual.equals(expected)) { - throw new Error("mismatch: " + type - + "\nACTUAL:\n " - + actual.stream() - .map(Object::toString) - .collect(Collectors.joining("\n ")) - + "\nEXPECTED:\n " - + expected.stream() - .map(Object::toString) - .collect(Collectors.joining("\n "))); + throw new Error(title + " mismatch: " + + "\nACTUAL:\n " + + actual.stream() + .map(Object::toString) + .collect(Collectors.joining("\n ")) + + "\nEXPECTED:\n " + + expected.stream() + .map(Object::toString) + .collect(Collectors.joining("\n "))); + } + } + + public static void verifyProperties(Class type, String... methodNames) { + try { + final Set expected = new HashSet<>(Arrays.asList(methodNames)); + final Set actual = Arrays + .stream(Introspector.getBeanInfo(type) + .getPropertyDescriptors()) + .flatMap(pd -> Stream.of(pd.getReadMethod(), pd.getWriteMethod())) + .filter(Objects::nonNull) + .map((Method m) -> m.toString()) + .collect(Collectors.toSet()); + verifyEquality("properties", expected, actual); + } catch (IntrospectionException exception) { + throw new Error("unexpected exception", exception); + } + } + + public static void verifyMethods(Class type, String... methodNames) { + try { + final Set expected = new HashSet<>(Arrays.asList(methodNames)); + final Set actual = Arrays + .stream(Introspector.getBeanInfo(type, Object.class) + .getMethodDescriptors()) + .map(MethodDescriptor::getMethod) + .map(Method::toString) + .collect(Collectors.toSet()); + verifyEquality("methods", expected, actual); + } catch (IntrospectionException exception) { + throw new Error("unexpected exception", exception); + } + } + + private static MethodDescriptor getMethodDescriptor(Class cls, Class stop, String name) { + try { + for (var md : Introspector.getBeanInfo(cls, stop).getMethodDescriptors()) { + if (md.getName().equals(name)) { + return md; + } + } + return null; + } catch (IntrospectionException exception) { + throw new Error("unexpected exception", exception); + } + } + + private static void assertEquals(Object expected, Object actual, String msg) { + if (!expected.equals(actual)) { + throw new Error(msg + ":\nACTUAL: " + actual + "\nEXPECTED: " + expected); } } @@ -207,5 +566,12 @@ testScenario1(); testScenario2(); testScenario3(); + testScenario4(); + testScenario5(); + testScenario6(); + testScenario7(); + testScenario8(); + testScenario9(); + testScenario10(); } } diff -Nru openjdk-21-21.0.8+9/test/jdk/java/lang/Class/ProtectionDomainRace.java openjdk-21-21.0.9+10/test/jdk/java/lang/Class/ProtectionDomainRace.java --- openjdk-21-21.0.8+9/test/jdk/java/lang/Class/ProtectionDomainRace.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/lang/Class/ProtectionDomainRace.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8334394 + * @summary ensure there is no race condition in Class::protectionDomain + * @run main/othervm ProtectionDomainRace + */ +import javax.security.auth.Subject; +import java.security.PrivilegedAction; + +/** + * Without the code fix, this test would fail with + * java.lang.AssertionError: sun.security.util.ResourcesMgr (PD) + * at java.base/java.lang.invoke.MethodHandleImpl$BindCaller.checkInjectedInvoker(MethodHandleImpl.java:1209) + * at java.base/java.lang.invoke.MethodHandleImpl$BindCaller.makeInjectedInvoker(MethodHandleImpl.java:1110) + * at java.base/java.lang.invoke.MethodHandleImpl$BindCaller$1.computeValue(MethodHandleImpl.java:1117) + * at java.base/java.lang.invoke.MethodHandleImpl$BindCaller$1.computeValue(MethodHandleImpl.java:1114) + * at java.base/java.lang.ClassValue.getFromHashMap(ClassValue.java:229) + * at java.base/java.lang.ClassValue.getFromBackup(ClassValue.java:211) + * at java.base/java.lang.ClassValue.get(ClassValue.java:117) + * at java.base/java.lang.invoke.MethodHandleImpl$BindCaller.bindCallerWithInjectedInvoker(MethodHandleImpl.java:1089) + * at java.base/java.lang.invoke.MethodHandleImpl$BindCaller.bindCaller(MethodHandleImpl.java:1077) + * at java.base/java.lang.invoke.MethodHandleImpl.bindCaller(MethodHandleImpl.java:1032) + * at java.base/java.lang.invoke.MethodHandles$Lookup.maybeBindCaller(MethodHandles.java:4149) + * at java.base/java.lang.invoke.MethodHandles$Lookup.getDirectMethodCommon(MethodHandles.java:4133) + * at java.base/java.lang.invoke.MethodHandles$Lookup.getDirectMethodNoSecurityManager(MethodHandles.java:4077) + * at java.base/java.lang.invoke.MethodHandles$Lookup.getDirectMethodForConstant(MethodHandles.java:4326) + * at java.base/java.lang.invoke.MethodHandles$Lookup.linkMethodHandleConstant(MethodHandles.java:4274) + * at java.base/java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:628) + * at java.base/sun.security.util.ResourcesMgr.getBundle(ResourcesMgr.java:54) + * at java.base/sun.security.util.ResourcesMgr.getString(ResourcesMgr.java:40) + * at java.base/javax.security.auth.Subject.doAs(Subject.java:517) + * ... + * as the Class::protectionDomain might assign different objects to the (original) allPermDomain field. + */ +public class ProtectionDomainRace { + private static volatile Throwable failed = null; + public static void main(String[] args) throws Throwable { + PrivilegedAction pa = () -> null; + Thread[] threads = new Thread[100]; + for (int i = 0; i < 100; i++) { + threads[i] = new Thread(() -> { + try { + Subject.doAs(null, pa); + } catch (Throwable t) { + failed = t; + } + }); + threads[i].start(); + } + for (int i = 0; i < 100; i++) { + threads[i].join(); + } + if (failed != null) { + throw failed; + } + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/lang/ProcessBuilder/Basic.java openjdk-21-21.0.9+10/test/jdk/java/lang/ProcessBuilder/Basic.java --- openjdk-21-21.0.8+9/test/jdk/java/lang/ProcessBuilder/Basic.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/lang/ProcessBuilder/Basic.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,8 +36,8 @@ * @requires !vm.musl * @requires vm.flagless * @library /test/lib - * @run main/othervm/native/timeout=300 -Djava.security.manager=allow Basic - * @run main/othervm/native/timeout=300 -Djava.security.manager=allow -Djdk.lang.Process.launchMechanism=fork Basic + * @run main/othervm/native/timeout=360 -Djava.security.manager=allow Basic + * @run main/othervm/native/timeout=360 -Djava.security.manager=allow -Djdk.lang.Process.launchMechanism=fork Basic * @author Martin Buchholz */ @@ -209,7 +209,7 @@ private static final Runtime runtime = Runtime.getRuntime(); - private static final String[] winEnvCommand = {"cmd.exe", "/c", "set"}; + private static final String[] winEnvCommand = {"cmd.exe", "/d", "/c", "set"}; private static String winEnvFilter(String env) { return env.replaceAll("\r", "") @@ -1914,7 +1914,9 @@ // Test Runtime.exec(...envp...) with envstrings without any `=' //---------------------------------------------------------------- try { - String[] cmdp = {"echo"}; + // In Windows CMD (`cmd.exe`), `echo/` outputs a newline (i.e., an empty line). + // Wrapping it with `cmd.exe /c` ensures compatibility in both native Windows and Cygwin environments. + String[] cmdp = Windows.is() ? new String[]{"cmd.exe", "/c", "echo/"} : new String[]{"echo"}; String[] envp = {"Hello", "World"}; // Yuck! Process p = Runtime.getRuntime().exec(cmdp, envp); equal(commandOutput(p), "\n"); diff -Nru openjdk-21-21.0.8+9/test/jdk/java/lang/management/ThreadMXBean/Locks.java openjdk-21-21.0.9+10/test/jdk/java/lang/management/ThreadMXBean/Locks.java --- openjdk-21-21.0.8+9/test/jdk/java/lang/management/ThreadMXBean/Locks.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/lang/management/ThreadMXBean/Locks.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -422,6 +422,9 @@ lock + " expected to have owner"); } for (ThreadInfo info1 : infos) { + if (info1 == null) { + continue; // Missing thread, e.g. completed. Ignore. + } if (info1.getThreadId() == threadId) { ownerInfo = info1; break; diff -Nru openjdk-21-21.0.8+9/test/jdk/java/lang/management/ThreadMXBean/VirtualThreadDeadlocks.java openjdk-21-21.0.9+10/test/jdk/java/lang/management/ThreadMXBean/VirtualThreadDeadlocks.java --- openjdk-21-21.0.8+9/test/jdk/java/lang/management/ThreadMXBean/VirtualThreadDeadlocks.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/lang/management/ThreadMXBean/VirtualThreadDeadlocks.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,6 +47,7 @@ import java.lang.management.ThreadMXBean; import java.util.Arrays; import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Stream; import jdk.test.lib.thread.VThreadRunner; @@ -55,6 +56,8 @@ private static final Object LOCK2 = new Object(); private static final CyclicBarrier barrier = new CyclicBarrier(2); + private static final AtomicBoolean reached1 = new AtomicBoolean(); + private static final AtomicBoolean reached2 = new AtomicBoolean(); /** * PP = test deadlock with two platform threads @@ -72,6 +75,7 @@ Thread thread1 = builder1.start(() -> { synchronized (LOCK1) { try { barrier.await(); } catch (Exception ie) {} + reached1.set(true); synchronized (LOCK2) { } } }); @@ -84,14 +88,15 @@ Thread thread2 = builder2.start(() -> { synchronized (LOCK2) { try { barrier.await(); } catch (Exception ie) {} + reached2.set(true); synchronized (LOCK1) { } } }); System.out.println("thread2 => " + thread2); System.out.println("Waiting for thread1 and thread2 to deadlock ..."); - awaitBlocked(thread1); - awaitBlocked(thread2); + awaitTrueAndBlocked(thread1, reached1); + awaitTrueAndBlocked(thread2, reached2); ThreadMXBean bean = ManagementFactory.getPlatformMXBean(ThreadMXBean.class); long[] deadlockedThreads = sorted(bean.findMonitorDeadlockedThreads()); @@ -108,8 +113,8 @@ throw new RuntimeException("Unexpected result"); } - private static void awaitBlocked(Thread thread) throws InterruptedException { - while (thread.getState() != Thread.State.BLOCKED) { + private static void awaitTrueAndBlocked(Thread thread, AtomicBoolean flag) throws InterruptedException { + while (!flag.get() || thread.getState() != Thread.State.BLOCKED) { Thread.sleep(10); if (!thread.isAlive()) { throw new RuntimeException("Thread " + thread + " is terminated."); diff -Nru openjdk-21-21.0.8+9/test/jdk/java/math/BigInteger/ByteArrayConstructorTest.java openjdk-21-21.0.9+10/test/jdk/java/math/BigInteger/ByteArrayConstructorTest.java --- openjdk-21-21.0.8+9/test/jdk/java/math/BigInteger/ByteArrayConstructorTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/math/BigInteger/ByteArrayConstructorTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import jdk.test.lib.RandomFactory; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.math.Accessor; +import java.math.BigInteger; +import java.util.Random; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * @test + * @bug 8319174 + * @summary Exercises minimality of BigInteger.mag field (use -Dseed=X to set PRANDOM seed) + * @library /test/lib + * @build jdk.test.lib.RandomFactory + * @build java.base/java.math.Accessor + * @key randomness + * @run junit/othervm -DmaxDurationMillis=3000 ByteArrayConstructorTest + */ +public class ByteArrayConstructorTest { + + private static final int DEFAULT_MAX_DURATION_MILLIS = 3_000; + + public static final int N = 1_024; + + private static int maxDurationMillis; + private static final Random rnd = RandomFactory.getRandom(); + private volatile boolean stop = false; + + @BeforeAll + static void setMaxDurationMillis() { + maxDurationMillis = Math.max(maxDurationMillis(), 0); + } + + @Test + public void testNonNegative() throws InterruptedException { + byte[] ba = nonNegativeBytes(); + doBigIntegers(ba, ba[0]); // a mask to flip to 0 and back to ba[0] + } + + @Test + public void testNegative() throws InterruptedException { + byte[] ba = negativeBytes(); + doBigIntegers(ba, (byte) ~ba[0]); // a mask to flip to -1 and back to ba[0] + } + + /* + * Starts a thread th that keeps flipping the "sign" byte in the array ba + * from the original value to 0 or -1 and back, depending on ba[0] being + * non-negative or negative, resp. + * (ba is "big endian", the least significant byte is the one with the + * highest index.) + * + * In the meantime, the current thread keeps creating BigInteger instances + * with ba and checks that the internal invariant holds, despite the + * attempts by thread th to racily modify ba. + * It does so at least as indicated by maxDurationMillis. + * + * Finally, this thread requests th to stop and joins with it, either + * because maxDurationMillis has expired, or because of an invalid invariant. + */ + private void doBigIntegers(byte[] ba, byte mask) throws InterruptedException { + Thread th = new Thread(() -> { + while (!stop) { + ba[0] ^= mask; + } + }); + th.start(); + + try { + createBigIntegers(maxDurationMillis, ba); + } finally { + stop = true; + th.join(1_000); + } + } + + private void createBigIntegers(int maxDurationMillis, byte[] ba) { + long start = System.currentTimeMillis(); + while (System.currentTimeMillis() - start < maxDurationMillis) { + BigInteger bi = new BigInteger(ba); + int[] mag = Accessor.mag(bi); + assertTrue(mag.length == 0 || mag[0] != 0, + String.format("inconsistent BigInteger: mag.length=%d, mag[0]=%d", + mag.length, mag[0])); + } + } + + private byte[] nonNegativeBytes() { + byte[] ba = new byte[1 + N]; + byte b0; + while ((b0 = (byte) rnd.nextInt()) < 0); // empty body + rnd.nextBytes(ba); + ba[0] = b0; + /* Except for ba[0], fill most significant half with zeros. */ + for (int i = 1; i <= N / 2; ++i) { + ba[i] = 0; + } + return ba; + } + + private byte[] negativeBytes() { + byte[] ba = new byte[1 + N]; + byte b0; + while ((b0 = (byte) rnd.nextInt()) >= 0); // empty body + rnd.nextBytes(ba); + ba[0] = b0; + /* Except for ba[0], fill most significant half with -1 bytes. */ + for (int i = 1; i <= N / 2; ++i) { + ba[i] = -1; + } + return ba; + } + + private static int maxDurationMillis() { + try { + return Integer.parseInt(System.getProperty("maxDurationMillis", + Integer.toString(DEFAULT_MAX_DURATION_MILLIS))); + } catch (NumberFormatException ignore) { + } + return DEFAULT_MAX_DURATION_MILLIS; + } + +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/math/BigInteger/java.base/java/math/Accessor.java openjdk-21-21.0.9+10/test/jdk/java/math/BigInteger/java.base/java/math/Accessor.java --- openjdk-21-21.0.8+9/test/jdk/java/math/BigInteger/java.base/java/math/Accessor.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/math/BigInteger/java.base/java/math/Accessor.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.math; + +public class Accessor { + + public static int[] mag(BigInteger bi) { + return bi.mag; + } + +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/net/CookieHandler/B6644726.java openjdk-21-21.0.9+10/test/jdk/java/net/CookieHandler/B6644726.java --- openjdk-21-21.0.8+9/test/jdk/java/net/CookieHandler/B6644726.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/net/CookieHandler/B6644726.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,8 +46,8 @@ // Let's test the default path lst.add("myCookie1=foo"); // Then some alternate expires format - lst.add("myCookie2=bar; path=/dir; expires=Tue, 19 Aug 2025 16:00:00 GMT"); - lst.add("myCookie3=test; path=/dir; expires=Tue Aug 19 2025 16:00:00 GMT-0100"); + lst.add("myCookie2=bar; path=/dir; expires=Fri, 19 Aug 4242 16:00:00 GMT"); + lst.add("myCookie3=test; path=/dir; expires=Fri Aug 19 4242 16:00:00 GMT-0100"); // Then Netscape draft cookies and domains lst.add("myCookie4=test; domain=.sun.com; path=/dir/foo"); HashMap> map = new HashMap>(); @@ -64,7 +64,8 @@ List cookies = cs.getCookies(); // There should be 5 cookies if all dates parsed correctly if (cookies.size() != 5) { - fail("Should have 5 cookies. Got only "+ cookies.size() + ", expires probably didn't parse correctly"); + fail("unexpected cookies: " + cookies + ", should have 5 cookies. Got only " + + cookies.size() + ", expires probably didn't parse correctly"); } // Check Path for first Cookie for (HttpCookie c : cookies) { diff -Nru openjdk-21-21.0.8+9/test/jdk/java/net/HttpURLConnection/HttpURLConnectionExpect100Test.java openjdk-21-21.0.9+10/test/jdk/java/net/HttpURLConnection/HttpURLConnectionExpect100Test.java --- openjdk-21-21.0.8+9/test/jdk/java/net/HttpURLConnection/HttpURLConnectionExpect100Test.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/net/HttpURLConnection/HttpURLConnectionExpect100Test.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8314978 + * @summary Multiple server call from connection failing with expect100 in + * getOutputStream + * @library /test/lib + * @run junit/othervm HttpURLConnectionExpect100Test + */ +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.URL; +import java.net.HttpURLConnection; + +import jdk.test.lib.net.URIBuilder; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class HttpURLConnectionExpect100Test { + + private HttpServer server; + private int port; + static final String RESPONSE = "This is default response."; + + @BeforeAll + void setup() throws Exception { + server = HttpServer.create(); + port = server.getPort(); + } + + @AfterAll + void teardown() throws Exception { + server.close(); + } + + @Test + public void expect100ContinueHitCountTest() throws Exception { + server.resetHitCount(); + URL url = URIBuilder.newBuilder() + .scheme("http") + .loopback() + .port(port) + .toURL(); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("PUT"); + //send expect continue + conn.setRequestProperty("Expect", "100-continue"); + sendRequest(conn); + getHeaderField(conn); + assertEquals(1, server.getServerHitCount()); + // Server rejects the expect 100-continue request with 417 response + assertEquals(417, conn.getResponseCode()); + } + + @Test + public void defaultRequestHitCountTest() throws Exception { + server.resetHitCount(); + URL url = URIBuilder.newBuilder() + .scheme("http") + .loopback() + .port(port) + .toURL(); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("PUT"); + sendRequest(conn); + getHeaderField(conn); + assertEquals(1, server.getServerHitCount()); + assertEquals(200, conn.getResponseCode()); + try ( InputStream in = conn.getInputStream()) { + byte[] data = in.readAllBytes(); + assertEquals(RESPONSE.length(), data.length); + } + } + + private void sendRequest(final HttpURLConnection conn) throws Exception { + conn.setDoOutput(true); + conn.setFixedLengthStreamingMode(10); + byte[] payload = new byte[10]; + try ( OutputStream os = conn.getOutputStream()) { + os.write(payload); + os.flush(); + } catch (IOException e) { + // intentional, server will reject the expect 100 + } + } + + private void getHeaderField(final HttpURLConnection conn) { + // Call getHeaderFiels in loop, this should not hit server. + for (int i = 0; i < 5; i++) { + System.out.println("Getting: field" + i); + conn.getHeaderField("field" + i); + } + } + + static class HttpServer extends Thread { + + private final ServerSocket ss; + private static HttpServer inst; + private volatile int hitCount; + private volatile boolean isRunning; + private final int port; + + private HttpServer() throws IOException { + InetAddress loopback = InetAddress.getLoopbackAddress(); + ss = new ServerSocket(); + ss.bind(new InetSocketAddress(loopback, 0)); + port = ss.getLocalPort(); + isRunning = true; + } + + static HttpServer create() throws IOException { + if (inst != null) { + return inst; + } else { + inst = new HttpServer(); + inst.setDaemon(true); + inst.start(); + return inst; + } + } + + int getServerHitCount() { + return hitCount; + } + + void resetHitCount() { + hitCount = 0; + } + + int getPort() { + return port; + } + + void close() { + isRunning = false; + if (ss != null && !ss.isClosed()) { + try { + ss.close(); + } catch (IOException ex) { + } + } + } + + @Override + public void run() { + Socket client; + try { + while (isRunning) { + client = ss.accept(); + System.out.println(client.getRemoteSocketAddress().toString()); + hitCount++; + handleConnection(client); + } + } catch (IOException ex) { + // throw exception only if isRunning is true + if (isRunning) { + throw new RuntimeException(ex); + } + } finally { + if (ss != null && !ss.isClosed()) { + try { + ss.close(); + } catch (IOException ex) { + //ignore + } + } + } + } + + private void handleConnection(Socket client) throws IOException { + try ( BufferedReader in = new BufferedReader( + new InputStreamReader(client.getInputStream())); + PrintStream out = new PrintStream(client.getOutputStream())) { + handle_connection(in, out); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } finally { + try { + client.close(); + } catch (IOException e) { + } + } + } + + private void handle_connection(BufferedReader in, PrintStream out) + throws IOException, InterruptedException { + StringBuilder clientRequest = new StringBuilder(); + String line = null; + do { + line = in.readLine(); + clientRequest.append(line); + } while (line != null && line.length() != 0); + if (clientRequest.toString().contains("100-continue")) { + rejectExpect100Continue(out); + } else { + defaultResponse(out); + } + } + + private void rejectExpect100Continue(PrintStream out) { + out.print("HTTP/1.1 417 Expectation Failed\r\n"); + out.print("Server: Test-Server\r\n"); + out.print("Connection: close\r\n"); + out.print("Content-Length: 0\r\n"); + out.print("\r\n"); + out.flush(); + } + + private void defaultResponse(PrintStream out) { + // send the 200 OK + out.print("HTTP/1.1 200 OK\r\n"); + out.print("Server: Test-Server\r\n"); + out.print("Connection: close\r\n"); + out.print("Content-Length: " + RESPONSE.length() + "\r\n\r\n"); + out.print(RESPONSE); + out.flush(); + } + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/java/net/HttpURLConnection/HttpURLConnectionExpectContinueTest.java openjdk-21-21.0.9+10/test/jdk/java/net/HttpURLConnection/HttpURLConnectionExpectContinueTest.java --- openjdk-21-21.0.8+9/test/jdk/java/net/HttpURLConnection/HttpURLConnectionExpectContinueTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/net/HttpURLConnection/HttpURLConnectionExpectContinueTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -429,7 +429,7 @@ .port(control.serverSocket.getLocalPort()) .toURL(); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY); connection.setDoOutput(true); connection.setReadTimeout(5000); connection.setUseCaches(false); diff -Nru openjdk-21-21.0.8+9/test/jdk/java/net/Inet4Address/PingThis.java openjdk-21-21.0.9+10/test/jdk/java/net/Inet4Address/PingThis.java --- openjdk-21-21.0.8+9/test/jdk/java/net/Inet4Address/PingThis.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/net/Inet4Address/PingThis.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,27 +27,20 @@ /* @test * @bug 7163874 8133015 + * @summary InetAddress.isReachable is returning false for InetAdress 0.0.0.0 and ::0 + * @requires os.family != "windows" * @library /test/lib - * @summary InetAddress.isReachable is returning false - * for InetAdress 0.0.0.0 and ::0 * @run main PingThis * @run main/othervm -Djava.net.preferIPv4Stack=true PingThis */ -import java.net.Inet6Address; import java.net.InetAddress; -import java.net.NetworkInterface; import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; import java.util.List; import jdk.test.lib.net.IPSupport; public class PingThis { public static void main(String args[]) throws Exception { - if (System.getProperty("os.name").startsWith("Windows")) { - return; - } IPSupport.throwSkippedExceptionIfNonOperational(); List addrs = new ArrayList(); diff -Nru openjdk-21-21.0.8+9/test/jdk/java/net/MulticastSocket/NoLoopbackPackets.java openjdk-21-21.0.9+10/test/jdk/java/net/MulticastSocket/NoLoopbackPackets.java --- openjdk-21-21.0.8+9/test/jdk/java/net/MulticastSocket/NoLoopbackPackets.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/net/MulticastSocket/NoLoopbackPackets.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,9 @@ /* * @test * @bug 4742177 - * @library /test/lib * @summary Re-test IPv6 (and specifically MulticastSocket) with latest Linux & USAGI code + * @requires os.family != "windows" + * @library /test/lib */ import java.util.*; import java.net.*; @@ -33,20 +34,10 @@ import jdk.test.lib.net.IPSupport; public class NoLoopbackPackets { - private static String osname; - - static boolean isWindows() { - if (osname == null) - osname = System.getProperty("os.name"); - return osname.contains("Windows"); - } private static final String MESSAGE = "hello world (" + System.nanoTime() + ")"; + public static void main(String[] args) throws Exception { - if (isWindows()) { - System.out.println("The test only run on non-Windows OS. Bye."); - return; - } MulticastSocket msock = null; List failedGroups = new ArrayList(); diff -Nru openjdk-21-21.0.8+9/test/jdk/java/net/MulticastSocket/PromiscuousIPv6.java openjdk-21-21.0.9+10/test/jdk/java/net/MulticastSocket/PromiscuousIPv6.java --- openjdk-21-21.0.8+9/test/jdk/java/net/MulticastSocket/PromiscuousIPv6.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/net/MulticastSocket/PromiscuousIPv6.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,9 @@ /* * @test * @bug 8215294 - * @requires os.family == "linux" + * @requires os.family == "linux" & !(os.version ~= "3\\.10\\.0.*") + * @comment This test should only be run on Linux. + * The behavior under test is known NOT to work on Linux 3.10.0* kernels. * @library /test/lib * @build jdk.test.lib.NetworkConfiguration * PromiscuousIPv6 @@ -148,18 +150,6 @@ } public static void main(String args[]) throws IOException { - String os = System.getProperty("os.name"); - - if (!os.equals("Linux")) { - throw new SkippedException("This test should be run only on Linux"); - } else { - String osVersion = System.getProperty("os.version"); - String prefix = "3.10.0"; - if (osVersion.startsWith(prefix)) { - throw new SkippedException( - String.format("The behavior under test is known NOT to work on '%s' kernels", prefix)); - } - } NetworkConfiguration.printSystemConfiguration(System.out); List nifs = NetworkConfiguration.probe() diff -Nru openjdk-21-21.0.8+9/test/jdk/java/net/MulticastSocket/SetOutgoingIf.java openjdk-21-21.0.9+10/test/jdk/java/net/MulticastSocket/SetOutgoingIf.java --- openjdk-21-21.0.8+9/test/jdk/java/net/MulticastSocket/SetOutgoingIf.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/net/MulticastSocket/SetOutgoingIf.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,10 @@ /* * @test * @bug 4742177 8241786 + * @summary Re-test IPv6 (and specifically MulticastSocket) with latest Linux & USAGI code + * @requires os.family != "windows" * @library /test/lib * @run main/othervm SetOutgoingIf - * @summary Re-test IPv6 (and specifically MulticastSocket) with latest Linux & USAGI code */ import java.io.IOException; import java.net.*; @@ -36,7 +37,7 @@ public class SetOutgoingIf implements AutoCloseable { - private static String osname; + private final MulticastSocket SOCKET; private final int PORT; private final Map sendersMap = new ConcurrentHashMap<>(); @@ -49,12 +50,6 @@ } } - static boolean isWindows() { - if (osname == null) - osname = System.getProperty("os.name"); - return osname.contains("Windows"); - } - static boolean isMacOS() { return System.getProperty("os.name").contains("OS X"); } @@ -82,10 +77,6 @@ } public void run() throws Exception { - if (isWindows()) { - System.out.println("The test only run on non-Windows OS. Bye."); - return; - } if (!hasIPv6()) { System.out.println("No IPv6 available. Bye."); diff -Nru openjdk-21-21.0.8+9/test/jdk/java/net/ServerSocket/AnotherSelectFdsLimit.java openjdk-21-21.0.9+10/test/jdk/java/net/ServerSocket/AnotherSelectFdsLimit.java --- openjdk-21-21.0.8+9/test/jdk/java/net/ServerSocket/AnotherSelectFdsLimit.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/net/ServerSocket/AnotherSelectFdsLimit.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 8035897 * @summary FD_SETSIZE should be set on macosx + * @requires os.family == "mac" * @run main/othervm AnotherSelectFdsLimit 1023 * @run main/othervm AnotherSelectFdsLimit 1024 * @run main/othervm AnotherSelectFdsLimit 1025 @@ -41,10 +42,6 @@ static final int DEFAULT_FDS_TO_USE = 1600; public static void main(String [] args) throws Exception { - if (!System.getProperty("os.name").contains("OS X")) { - System.out.println("Test only run on MAC. Exiting."); - return; - } int fdsToUse = DEFAULT_FDS_TO_USE; if (args.length == 1) diff -Nru openjdk-21-21.0.8+9/test/jdk/java/net/ServerSocket/SelectFdsLimit.java openjdk-21-21.0.9+10/test/jdk/java/net/ServerSocket/SelectFdsLimit.java --- openjdk-21-21.0.8+9/test/jdk/java/net/ServerSocket/SelectFdsLimit.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/net/ServerSocket/SelectFdsLimit.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ * @summary The total number of file descriptors is limited to * 1024(FDSET_SIZE) on MacOSX (the size of fd array passed to select() * call in java.net classes is limited to this value). + * @requires os.family == "mac" * @run main/othervm SelectFdsLimit * @author aleksej.efimov@oracle.com */ @@ -35,7 +36,6 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; -import java.io.InputStream; import java.net.ServerSocket; import java.net.SocketTimeoutException; @@ -72,12 +72,6 @@ public static void main(String [] args) throws IOException, FileNotFoundException { - //The bug 8021820 is a Mac specific and because of that test will pass on all - //other platforms - if (!System.getProperty("os.name").contains("OS X")) { - return; - } - //Create test directory with test files prepareTestEnv(); diff -Nru openjdk-21-21.0.8+9/test/jdk/java/net/URLConnection/UNCTest.java openjdk-21-21.0.9+10/test/jdk/java/net/URLConnection/UNCTest.java --- openjdk-21-21.0.8+9/test/jdk/java/net/URLConnection/UNCTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/net/URLConnection/UNCTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,17 +25,46 @@ * @test * @bug 4401485 * @requires (os.family == "windows") + * @modules java.base/sun.net.www.protocol.file + * @library /test/lib * @summary Check that URL.openConnection() doesn't open connection to UNC - * @run main UNCTest file://jdk/LOCAL-JAVA/jdk1.4/win/README.txt */ +import jtreg.SkippedException; +import sun.net.www.protocol.file.FileURLConnection; + +import java.io.File; +import java.net.InetAddress; +import java.net.URI; import java.net.URL; import java.net.URLConnection; public class UNCTest { - public static void main(String args[]) throws Exception { - URL url = new URL( args[0] ); + public static void main(String[] args) throws Exception { + // Get the "computer name" for this host + String hostName = InetAddress.getLocalHost().getHostName(); + + // UNC path which always exists with Administrative Shares enabled + String path = "\\\\" + hostName + "\\C$\\Windows"; + + // Skip test if Administrative Shares is disabled + if (! new File(path).exists()) { + throw new SkippedException("Administrative Shares not enabled"); + } + + // File URL for the UNC path + URL url = new URI("file://" + hostName + "/C$/Windows").toURL(); + + // Should open a FileURLConnection for the UNC path URLConnection conn = url.openConnection(); + + // Sanity check that the connection is a FileURLConnection + if (! (conn instanceof FileURLConnection)) { + throw new Exception("Expected FileURLConnection, instead got " + + conn.getClass().getName()); + } + + // Verify that the connection is not in an already connected state conn.setRequestProperty( "User-Agent", "Java" ); } } diff -Nru openjdk-21-21.0.8+9/test/jdk/java/net/httpclient/AbstractConnectTimeoutHandshake.java openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/AbstractConnectTimeoutHandshake.java --- openjdk-21-21.0.8+9/test/jdk/java/net/httpclient/AbstractConnectTimeoutHandshake.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/AbstractConnectTimeoutHandshake.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,10 +44,11 @@ import java.net.http.HttpRequest.BodyPublishers; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; + +import jdk.test.lib.net.URIBuilder; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; import org.testng.annotations.DataProvider; -import static java.lang.String.format; import static java.lang.System.out; import static java.net.http.HttpClient.Builder.NO_PROXY; import static java.net.http.HttpClient.Version.HTTP_1_1; @@ -56,7 +57,7 @@ import static java.util.concurrent.TimeUnit.NANOSECONDS; import static org.testng.Assert.fail; -public abstract class AbstractConnectTimeoutHandshake { +abstract class AbstractConnectTimeoutHandshake { // The number of iterations each testXXXClient performs. static final int TIMES = 2; @@ -197,15 +198,15 @@ // -- Infrastructure - static String serverAuthority(Server server) { - return InetAddress.getLoopbackAddress().getHostName() + ":" - + server.getPort(); - } - @BeforeTest public void setup() throws Exception { server = new Server(); - httpsURI = URI.create("https://" + serverAuthority(server) + "/foo"); + httpsURI = URIBuilder.newBuilder() + .scheme("https") + .loopback() + .port(server.getPort()) + .path("/foo") + .build(); out.println("HTTPS URI: " + httpsURI); } diff -Nru openjdk-21-21.0.8+9/test/jdk/java/net/httpclient/AsyncShutdownNow.java openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/AsyncShutdownNow.java --- openjdk-21-21.0.8+9/test/jdk/java/net/httpclient/AsyncShutdownNow.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/AsyncShutdownNow.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -208,7 +208,7 @@ Thread.sleep(sleep); } if (i == step) { - out.printf("%d: shutting down client now%n", i, sleep); + out.printf("%d: shutting down client now%n", i); client.shutdownNow(); } var cf = bodyCF.exceptionally((t) -> { @@ -304,7 +304,7 @@ Thread.sleep(sleep); } if (i == step) { - out.printf("%d: shutting down client now%n", i, sleep); + out.printf("%d: shutting down client now%n", i); client.shutdownNow(); } bodyCF.handle((r, t) -> { diff -Nru openjdk-21-21.0.8+9/test/jdk/java/net/httpclient/ConnectTimeoutHandshakeAsync.java openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/ConnectTimeoutHandshakeAsync.java --- openjdk-21-21.0.8+9/test/jdk/java/net/httpclient/ConnectTimeoutHandshakeAsync.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/ConnectTimeoutHandshakeAsync.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,8 @@ * @test * @summary Tests connection timeouts during SSL handshake * @bug 8208391 + * @library /test/lib + * @build AbstractConnectTimeoutHandshake * @run testng/othervm ConnectTimeoutHandshakeAsync */ diff -Nru openjdk-21-21.0.8+9/test/jdk/java/net/httpclient/ConnectTimeoutHandshakeSync.java openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/ConnectTimeoutHandshakeSync.java --- openjdk-21-21.0.8+9/test/jdk/java/net/httpclient/ConnectTimeoutHandshakeSync.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/ConnectTimeoutHandshakeSync.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,8 @@ * @test * @summary Tests connection timeouts during SSL handshake * @bug 8208391 + * @library /test/lib + * @build AbstractConnectTimeoutHandshake * @run testng/othervm ConnectTimeoutHandshakeSync */ diff -Nru openjdk-21-21.0.8+9/test/jdk/java/net/httpclient/HttpClientShutdown.java openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/HttpClientShutdown.java --- openjdk-21-21.0.8+9/test/jdk/java/net/httpclient/HttpClientShutdown.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/HttpClientShutdown.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -192,7 +192,7 @@ out.println(now() + step + ": Got response: " + response); assertEquals(response.statusCode(), 200); } catch (AssertionError error) { - out.printf(now() + "%s: Closing body due to assertion - %s", error); + out.printf(now() + "%s: Closing body due to assertion - %s", step, error); ensureClosed(this); throw error; } @@ -276,7 +276,7 @@ continue; } if (i == step) { - out.printf(now() + "%d: shutting down client%n", i, sleep); + out.printf(now() + "%d: shutting down client%n", i); client.shutdown(); } var cf = bodyCF.exceptionally((t) -> { @@ -375,7 +375,7 @@ continue; } if (i == step) { - out.printf(now() + "%d: shutting down client%n", i, sleep); + out.printf(now() + "%d: shutting down client%n", i); client.shutdown(); } bodyCF.handle((r, t) -> { diff -Nru openjdk-21-21.0.8+9/test/jdk/java/net/httpclient/ShutdownNow.java openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/ShutdownNow.java --- openjdk-21-21.0.8+9/test/jdk/java/net/httpclient/ShutdownNow.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/ShutdownNow.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -182,7 +182,7 @@ Thread.sleep(sleep); } if (i == step) { - out.printf("%d: shutting down client now%n", i, sleep); + out.printf("%d: shutting down client now%n", i); client.shutdownNow(); } final int si = i; @@ -238,7 +238,7 @@ Thread.sleep(sleep); } if (i == step) { - out.printf("%d: shutting down client now%n", i, sleep); + out.printf("%d: shutting down client now%n", i); client.shutdownNow(); } final int si = i; diff -Nru openjdk-21-21.0.8+9/test/jdk/java/net/httpclient/http2/BasicTest.java openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/http2/BasicTest.java --- openjdk-21-21.0.8+9/test/jdk/java/net/httpclient/http2/BasicTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/http2/BasicTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,14 @@ /* * @test * @bug 8087112 - * @library /test/lib /test/jdk/java/net/httpclient/lib - * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.common.TestUtil - * jdk.httpclient.test.lib.http2.Http2TestServer + * @library /test/jdk/java/net/httpclient/lib + * /test/lib + * @build jdk.httpclient.test.lib.http2.Http2TestServer + * jdk.httpclient.test.lib.http2.Http2TestExchange + * jdk.httpclient.test.lib.http2.Http2EchoHandler + * jdk.test.lib.Asserts + * jdk.test.lib.Utils + * jdk.test.lib.net.SimpleSSLContext * @run testng/othervm -Djdk.httpclient.HttpClient.log=ssl,requests,responses,errors BasicTest */ @@ -44,17 +49,23 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; -import jdk.httpclient.test.lib.common.TestUtil; import jdk.httpclient.test.lib.http2.Http2TestServer; import jdk.httpclient.test.lib.http2.Http2TestExchange; -import jdk.httpclient.test.lib.http2.Http2Handler; import jdk.httpclient.test.lib.http2.Http2EchoHandler; import jdk.test.lib.net.SimpleSSLContext; import org.testng.annotations.Test; + import static java.net.http.HttpClient.Version.HTTP_2; +import static jdk.test.lib.Asserts.assertFileContentsEqual; +import static jdk.test.lib.Utils.createTempFile; +import static jdk.test.lib.Utils.createTempFileOfSize; @Test public class BasicTest { + + private static final String TEMP_FILE_PREFIX = + HttpClient.class.getPackageName() + '-' + BasicTest.class.getSimpleName() + '-'; + static int httpPort, httpsPort; static Http2TestServer httpServer, httpsServer; static HttpClient client = null; @@ -184,14 +195,6 @@ } } - static Void compareFiles(Path path1, Path path2) { - return TestUtil.compareFiles(path1, path2); - } - - static Path tempFile() { - return TestUtil.tempFile(); - } - static final String SIMPLE_STRING = "Hello world Goodbye world"; static final int LOOPS = 13; @@ -202,7 +205,7 @@ System.err.printf("streamTest %b to %s\n" , secure, uri); HttpClient client = getClient(); - Path src = TestUtil.getAFile(FILESIZE * 4); + Path src = createTempFileOfSize(TEMP_FILE_PREFIX, null, FILESIZE * 4); HttpRequest req = HttpRequest.newBuilder(uri) .POST(BodyPublishers.ofFile(src)) .build(); @@ -216,7 +219,7 @@ return resp.body(); }); response.join(); - compareFiles(src, dest); + assertFileContentsEqual(src, dest); System.err.println("streamTest: DONE"); } @@ -269,17 +272,19 @@ // Do loops asynchronously CompletableFuture[] responses = new CompletableFuture[LOOPS]; - final Path source = TestUtil.getAFile(FILESIZE); + final Path source = createTempFileOfSize(TEMP_FILE_PREFIX, null, FILESIZE); HttpRequest request = HttpRequest.newBuilder(uri) .POST(BodyPublishers.ofFile(source)) .build(); for (int i = 0; i < LOOPS; i++) { - responses[i] = client.sendAsync(request, BodyHandlers.ofFile(tempFile())) + responses[i] = client.sendAsync(request, BodyHandlers.ofFile(createTempFile(TEMP_FILE_PREFIX, null))) //.thenApply(resp -> compareFiles(resp.body(), source)); .thenApply(resp -> { + Path body = resp.body(); System.out.printf("Resp status %d body size %d\n", - resp.statusCode(), resp.body().toFile().length()); - return compareFiles(resp.body(), source); + resp.statusCode(), body.toFile().length()); + assertFileContentsEqual(body, source); + return null; }); Thread.sleep(100); } diff -Nru openjdk-21-21.0.8+9/test/jdk/java/net/httpclient/http2/FixedThreadPoolTest.java openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/http2/FixedThreadPoolTest.java --- openjdk-21-21.0.8+9/test/jdk/java/net/httpclient/http2/FixedThreadPoolTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/http2/FixedThreadPoolTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,13 @@ /* * @test * @bug 8087112 8177935 - * @library /test/lib /test/jdk/java/net/httpclient/lib - * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.common.TestUtil - * jdk.httpclient.test.lib.http2.Http2TestServer + * @library /test/jdk/java/net/httpclient/lib + * /test/lib + * @build jdk.httpclient.test.lib.http2.Http2TestServer + * jdk.httpclient.test.lib.http2.Http2EchoHandler + * jdk.test.lib.Asserts + * jdk.test.lib.Utils + * jdk.test.lib.net.SimpleSSLContext * @run testng/othervm -Djdk.httpclient.HttpClient.log=ssl,requests,responses,errors FixedThreadPoolTest */ @@ -37,16 +41,23 @@ import javax.net.ssl.*; import java.nio.file.*; import java.util.concurrent.*; -import jdk.httpclient.test.lib.common.TestUtil; import jdk.httpclient.test.lib.http2.Http2TestServer; -import jdk.httpclient.test.lib.http2.Http2TestExchange; import jdk.httpclient.test.lib.http2.Http2EchoHandler; import jdk.test.lib.net.SimpleSSLContext; + import static java.net.http.HttpClient.Version.HTTP_2; +import static jdk.test.lib.Asserts.assertFileContentsEqual; +import static jdk.test.lib.Utils.createTempFile; +import static jdk.test.lib.Utils.createTempFileOfSize; + import org.testng.annotations.Test; @Test public class FixedThreadPoolTest { + + private static final String TEMP_FILE_PREFIX = + HttpClient.class.getPackageName() + '-' + FixedThreadPoolTest.class.getSimpleName() + '-'; + static int httpPort, httpsPort; static Http2TestServer httpServer, httpsServer; static HttpClient client = null; @@ -142,14 +153,6 @@ } } - static Void compareFiles(Path path1, Path path2) { - return TestUtil.compareFiles(path1, path2); - } - - static Path tempFile() { - return TestUtil.tempFile(); - } - static final String SIMPLE_STRING = "Hello world Goodbye world"; static final int LOOPS = 32; @@ -160,7 +163,7 @@ System.err.printf("streamTest %b to %s\n" , secure, uri); HttpClient client = getClient(); - Path src = TestUtil.getAFile(FILESIZE * 4); + Path src = createTempFileOfSize(TEMP_FILE_PREFIX, null, FILESIZE * 4); HttpRequest req = HttpRequest.newBuilder(uri) .POST(BodyPublishers.ofFile(src)) .build(); @@ -174,7 +177,7 @@ return resp.body(); }); response.join(); - compareFiles(src, dest); + assertFileContentsEqual(src, dest); System.err.println("DONE"); } @@ -239,17 +242,19 @@ // Do loops asynchronously CompletableFuture[] responses = new CompletableFuture[LOOPS]; - final Path source = TestUtil.getAFile(FILESIZE); + final Path source = createTempFileOfSize(TEMP_FILE_PREFIX, null, FILESIZE); HttpRequest request = HttpRequest.newBuilder(uri) .POST(BodyPublishers.ofFile(source)) .build(); for (int i = 0; i < LOOPS; i++) { - responses[i] = client.sendAsync(request, BodyHandlers.ofFile(tempFile())) + responses[i] = client.sendAsync(request, BodyHandlers.ofFile(createTempFile(TEMP_FILE_PREFIX, null))) //.thenApply(resp -> compareFiles(resp.body(), source)); .thenApply(resp -> { + Path body = resp.body(); System.out.printf("Resp status %d body size %d\n", - resp.statusCode(), resp.body().toFile().length()); - return compareFiles(resp.body(), source); + resp.statusCode(), body.toFile().length()); + assertFileContentsEqual(body, source); + return null; }); } CompletableFuture.allOf(responses).join(); diff -Nru openjdk-21-21.0.8+9/test/jdk/java/net/httpclient/http2/ServerPush.java openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/http2/ServerPush.java --- openjdk-21-21.0.8+9/test/jdk/java/net/httpclient/http2/ServerPush.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/http2/ServerPush.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,11 @@ /* * @test * @bug 8087112 8159814 - * @library /test/lib /test/jdk/java/net/httpclient/lib - * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.http2.Http2TestServer - * jdk.httpclient.test.lib.common.TestUtil jdk.httpclient.test.lib.http2.PushHandler + * @library /test/jdk/java/net/httpclient/lib + * /test/lib + * @build jdk.httpclient.test.lib.http2.Http2TestServer + * jdk.httpclient.test.lib.http2.PushHandler + * jdk.test.lib.Utils * @run testng/othervm * -Djdk.httpclient.HttpClient.log=errors,requests,responses * ServerPush @@ -44,19 +46,21 @@ import java.util.*; import java.util.concurrent.*; import java.util.function.Consumer; -import jdk.httpclient.test.lib.common.TestUtil; import jdk.httpclient.test.lib.http2.Http2TestServer; -import jdk.httpclient.test.lib.http2.Http2TestExchange; -import jdk.httpclient.test.lib.http2.Http2Handler; import jdk.httpclient.test.lib.http2.PushHandler; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; + import static java.nio.charset.StandardCharsets.UTF_8; +import static jdk.test.lib.Utils.createTempFileOfSize; import static org.testng.Assert.*; public class ServerPush { + private static final String TEMP_FILE_PREFIX = + HttpClient.class.getPackageName() + '-' + ServerPush.class.getSimpleName() + '-'; + static final int LOOPS = 13; static final int FILE_SIZE = 512 * 1024 + 343; @@ -67,7 +71,7 @@ @BeforeTest public void setup() throws Exception { - tempFile = TestUtil.getAFile(FILE_SIZE); + tempFile = createTempFileOfSize(TEMP_FILE_PREFIX, null, FILE_SIZE); server = new Http2TestServer(false, 0); server.addHandler(new PushHandler(tempFile, LOOPS), "/"); System.out.println("Using temp file:" + tempFile); diff -Nru openjdk-21-21.0.8+9/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/HttpServerAdapters.java openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/HttpServerAdapters.java --- openjdk-21-21.0.8+9/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/HttpServerAdapters.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/HttpServerAdapters.java 2025-10-13 07:49:24.000000000 +0000 @@ -765,7 +765,7 @@ /** * A version agnostic adapter class for HTTP Servers. */ - public static abstract class HttpTestServer { + abstract class HttpTestServer implements AutoCloseable { private static final class ServerLogging { private static final Logger logger = Logger.getLogger("com.sun.net.httpserver"); static void enableLogging() { @@ -782,6 +782,11 @@ public abstract Version getVersion(); public abstract void setRequestApprover(final Predicate approver); + @Override + public void close() throws Exception { + stop(); + } + public String serverAuthority() { InetSocketAddress address = getAddress(); String hostString = address.getHostString(); @@ -971,6 +976,13 @@ System.out.println("Http2TestServerImpl: stop"); impl.stop(); } + + @Override + public void close() throws Exception { + System.out.println("Http2TestServerImpl: close"); + impl.close(); + } + @Override public HttpTestContext addHandler(HttpTestHandler handler, String path) { System.out.println("Http2TestServerImpl[" + getAddress() diff -Nru openjdk-21-21.0.8+9/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/TestUtil.java openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/TestUtil.java --- openjdk-21-21.0.8+9/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/TestUtil.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/TestUtil.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.httpclient.test.lib.common; - -import java.io.*; -import java.nio.file.*; -import java.util.Arrays; - -public class TestUtil { - - static final Path CWD = Paths.get("."); - final static String fileContent = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // repeated - - public static Path getAFile(int size) throws IOException { - Path p = tempFile(); - BufferedWriter writer = Files.newBufferedWriter(p); - int len = fileContent.length(); - int iterations = size / len; - int remainder = size - (iterations * len); - for (int i=0; i newRequestApprover; - private static ThreadFactory defaultThreadFac = - (Runnable r) -> { - Thread t = new Thread(r); - t.setName("Test-server-pool"); - return t; - }; - - - private static ExecutorService getDefaultExecutor() { - return Executors.newCachedThreadPool(defaultThreadFac); + private static ExecutorService createExecutor(String name) { + String threadNamePrefix = "%s-pool".formatted(name); + ThreadFactory threadFactory = Thread.ofPlatform().name(threadNamePrefix, 0).factory(); + return Executors.newCachedThreadPool(threadFactory); } public Http2TestServer(String serverName, boolean secure, int port) throws Exception { - this(serverName, secure, port, getDefaultExecutor(), 50, null, null); + this(serverName, secure, port, null, 50, null, null); } public Http2TestServer(boolean secure, int port) throws Exception { - this(null, secure, port, getDefaultExecutor(), 50, null, null); + this(null, secure, port, null, 50, null, null); } public InetSocketAddress getAddress() { @@ -197,7 +192,7 @@ server = initPlaintext(port, backlog); } this.secure = secure; - this.exec = exec == null ? getDefaultExecutor() : exec; + this.exec = exec == null ? createExecutor(name) : exec; this.handlers = Collections.synchronizedMap(new HashMap<>()); this.properties = properties == null ? new Properties() : properties; this.connections = ConcurrentHashMap.newKeySet(); diff -Nru openjdk-21-21.0.8+9/test/jdk/java/net/ipv6tests/TcpTest.java openjdk-21-21.0.9+10/test/jdk/java/net/ipv6tests/TcpTest.java --- openjdk-21-21.0.8+9/test/jdk/java/net/ipv6tests/TcpTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/net/ipv6tests/TcpTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -31,6 +31,7 @@ * @library /test/lib * @build jdk.test.lib.NetworkConfiguration * jdk.test.lib.Platform + * jtreg.SkippedException * @run main TcpTest -d */ @@ -38,6 +39,8 @@ import java.io.*; import java.util.concurrent.TimeUnit; +import jtreg.SkippedException; + public class TcpTest extends Tests { static ServerSocket server, server1, server2; static Socket c1, c2, c3, s1, s2, s3; @@ -62,12 +65,10 @@ public static void main (String[] args) throws Exception { checkDebug(args); if (ia4addr == null) { - System.out.println ("No IPV4 addresses: exiting test"); - return; + throw new SkippedException("No IPV4 addresses: exiting test"); } if (ia6addr == null) { - System.out.println ("No IPV6 addresses: exiting test"); - return; + throw new SkippedException("No IPV6 addresses: exiting test"); } dprintln ("Local Addresses"); dprintln (ia4addr.toString()); diff -Nru openjdk-21-21.0.8+9/test/jdk/java/nio/charset/Charset/Contains.java openjdk-21-21.0.9+10/test/jdk/java/nio/charset/Charset/Contains.java --- openjdk-21-21.0.8+9/test/jdk/java/nio/charset/Charset/Contains.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/nio/charset/Charset/Contains.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* @test * @summary Unit test for charset containment - * @bug 6798572 + * @bug 6798572 8167252 * @modules jdk.charsets */ @@ -93,6 +93,8 @@ ck(cp1252, cp1252, true); checkUTF(); + + containsSelfTest(); } static void checkUTF() throws Exception { @@ -103,6 +105,27 @@ true); } + /** + * Tests the assertion in the contains() method: "Every charset contains itself." + */ + static void containsSelfTest() { + boolean failed = false; + + for (var entry : Charset.availableCharsets().entrySet()) { + Charset charset = entry.getValue(); + boolean contains = charset.contains(charset); + + System.out.println("Charset(" + charset.name() + ").contains(Charset(" + charset.name() + + ")) returns " + contains); + if (!contains) { + failed = true; + } + } + if (failed) { + throw new RuntimeException("Charset.contains(itself) returns false for some charsets"); + } + } + static String[] utfNames = {"utf-16", "utf-8", "utf-16le", diff -Nru openjdk-21-21.0.8+9/test/jdk/java/security/cert/CertificateFactory/SlowStream.java openjdk-21-21.0.9+10/test/jdk/java/security/cert/CertificateFactory/SlowStream.java --- openjdk-21-21.0.8+9/test/jdk/java/security/cert/CertificateFactory/SlowStream.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/security/cert/CertificateFactory/SlowStream.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,31 +21,74 @@ * questions. */ -import java.io.*; -import java.security.cert.*; +/* + * @test + * @bug 6813340 + * @summary X509Factory should not depend on is.available()==0 + */ -class SlowStreamReader { +import java.io.File; +import java.io.FileInputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.security.cert.CertificateFactory; +import java.util.concurrent.atomic.AtomicBoolean; +public class SlowStream { public static void main(String[] args) throws Exception { - CertificateFactory factory = CertificateFactory.getInstance("X.509"); - if (factory.generateCertificates(System.in).size() != 5) { - throw new Exception("Not all certs read"); - } - } -} + final var outputStream = new PipedOutputStream(); + final var inputStream = new PipedInputStream(outputStream); -class SlowStreamWriter { - public static void main(String[] args) throws Exception { - for (int i=0; i<5; i++) { - FileInputStream fin = new FileInputStream(new File(new File( - System.getProperty("test.src", "."), "openssl"), "pem")); - byte[] buffer = new byte[4096]; - while (true) { - int len = fin.read(buffer); - if (len < 0) break; - System.out.write(buffer, 0, len); + final var failed = new AtomicBoolean(false); + + final var writer = new Thread(() -> { + try { + for (int i = 0; i < 5; i++) { + try (final var fin = new FileInputStream(new File( + new File(System.getProperty("test.src", "."), + "openssl"), + "pem"))) { + + fin.transferTo(outputStream); + + Thread.sleep(2000); + } + } + outputStream.close(); + } catch (final Exception e) { + System.out.println("Writer Thread Error: "); + e.printStackTrace(System.out); + failed.set(true); + } + }); + + final var reader = new Thread(() -> { + try { + final var factory = CertificateFactory.getInstance("X.509"); + final var numOfCerts = factory.generateCertificates(inputStream).size(); + if (numOfCerts != 5) { + throw new Exception( + String.format("Not all certs read. %d found 5 expected", numOfCerts) + ); + } + inputStream.close(); + } catch (final Exception e) { + System.out.println("Reader Thread Error: "); + e.printStackTrace(System.out); + failed.set(true); } - Thread.sleep(2000); + }); + + writer.start(); + reader.start(); + + writer.join(); + reader.join(); + + if (failed.get()) { + throw new RuntimeException( + "The test failed, please check the reader and writer threads output" + ); } } } diff -Nru openjdk-21-21.0.8+9/test/jdk/java/security/cert/CertificateFactory/slowstream.sh openjdk-21-21.0.9+10/test/jdk/java/security/cert/CertificateFactory/slowstream.sh --- openjdk-21-21.0.8+9/test/jdk/java/security/cert/CertificateFactory/slowstream.sh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/security/cert/CertificateFactory/slowstream.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -# -# Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -# @test -# @bug 6813340 -# @summary X509Factory should not depend on is.available()==0 - -if [ "${TESTSRC}" = "" ] ; then - TESTSRC="." -fi -if [ "${TESTJAVA}" = "" ] ; then - echo "TESTJAVA not set. Test cannot execute." - echo "FAILED!!!" - exit 1 -fi -if [ "${COMPILEJAVA}" = "" ]; then - COMPILEJAVA="${TESTJAVA}" -fi - -# set platform-dependent variables -OS=`uname -s` -case "$OS" in - Windows_* ) - FS="\\" - ;; - * ) - FS="/" - ;; -esac - -${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . \ - ${TESTSRC}${FS}SlowStream.java -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${TESTJAVAOPTS} -Dtest.src=${TESTSRC} SlowStreamWriter | \ - ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${TESTJAVAOPTS} SlowStreamReader diff -Nru openjdk-21-21.0.8+9/test/jdk/java/text/Format/MessageFormat/SerializationTest.java openjdk-21-21.0.9+10/test/jdk/java/text/Format/MessageFormat/SerializationTest.java --- openjdk-21-21.0.8+9/test/jdk/java/text/Format/MessageFormat/SerializationTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/text/Format/MessageFormat/SerializationTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -23,7 +23,7 @@ /* * @test - * @bug 8331446 + * @bug 8331446 8340554 * @summary Check correctness of deserialization * @run junit SerializationTest */ @@ -70,7 +70,13 @@ // With null locale. (NPE not thrown, if no format defined) new MessageFormat("{1} {0} foo", null), // With formats - new MessageFormat("{0,number,short} {0} {1,date,long} foo") + new MessageFormat("{0,number,short} {0} {1,date,long} foo"), + // Offset equal to pattern length (0) + new MessageFormat("{0}"), + // Offset equal to pattern length (1) + new MessageFormat("X{0}"), + // Offset 1 under pattern length + new MessageFormat("X{0}X") ); } diff -Nru openjdk-21-21.0.8+9/test/jdk/java/util/Currency/CurrencyTest.java openjdk-21-21.0.9+10/test/jdk/java/util/Currency/CurrencyTest.java --- openjdk-21-21.0.8+9/test/jdk/java/util/Currency/CurrencyTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/util/Currency/CurrencyTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @bug 4290801 4692419 4693631 5101540 5104960 6296410 6336600 6371531 * 6488442 7036905 8008577 8039317 8074350 8074351 8150324 8167143 - * 8264792 8334653 + * 8264792 8334653 8353713 * @summary Basic tests for Currency class. * @modules java.base/java.util:open * jdk.localedata @@ -80,14 +80,41 @@ // Calling getInstance() with an invalid currency code should throw an IAE @ParameterizedTest - @MethodSource("invalidCurrencies") + @MethodSource("non4217Currencies") public void invalidCurrencyTest(String currencyCode) { - assertThrows(IllegalArgumentException.class, () -> + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> Currency.getInstance(currencyCode), "getInstance() did not throw IAE"); + assertEquals("The input currency code: \"%s\" is not a valid ISO 4217 code" + .formatted(currencyCode), ex.getMessage()); } - private static Stream invalidCurrencies() { - return Stream.of("AQD", "US$", "\u20AC"); + private static Stream non4217Currencies() { + return Stream.of("AQD", "US$"); + } + + // Provide 3 length code, but first 2 chars should not be able to index + // the main table, thus resulting as incorrect country code + @Test + void invalidCountryInCodeTest() { + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> + Currency.getInstance("..A"), "getInstance() did not throw IAE"); + assertEquals("The country code: \"%s\" is not a valid ISO 3166 code" + .formatted(".."), ex.getMessage()); + } + + // Calling getInstance() with a currency code not 3 characters long should throw + // an IAE + @ParameterizedTest + @MethodSource("invalidLengthCurrencies") + public void invalidCurrencyLengthTest(String currencyCode) { + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> + Currency.getInstance(currencyCode), "getInstance() did not throw IAE"); + assertEquals("The input currency code: \"%s\" must have a length of 3 characters" + .formatted(currencyCode), ex.getMessage()); + } + + private static Stream invalidLengthCurrencies() { + return Stream.of("\u20AC", "", "12345"); } } @@ -144,7 +171,10 @@ ctryLength == 3 || // UN M.49 code ctryCode.matches("AA|Q[M-Z]|X[A-JL-Z]|ZZ" + // user defined codes, excluding "XK" (Kosovo) "AC|CP|DG|EA|EU|FX|IC|SU|TA|UK")) { // exceptional reservation codes - assertThrows(IllegalArgumentException.class, () -> Currency.getInstance(locale), "Did not throw IAE"); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, + () -> Currency.getInstance(locale), "Did not throw IAE"); + assertEquals("The country of the input locale: \"%s\" is not a valid ISO 3166 country code" + .formatted(locale), ex.getMessage()); } else { goodCountries++; Currency currency = Currency.getInstance(locale); @@ -160,11 +190,15 @@ } } - // Check an invalid country code + // Check an invalid country code supplied via the region override @Test - public void invalidCountryTest() { - assertThrows(IllegalArgumentException.class, ()-> - Currency.getInstance(Locale.of("", "EU")), "Did not throw IAE"); + public void invalidCountryRegionOverrideTest() { + // Override US with nonsensical country + var loc = Locale.forLanguageTag("en-US-u-rg-XXzzzz"); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, + ()-> Currency.getInstance(loc), "Did not throw IAE"); + assertEquals("The country of the input locale: \"%s\" is not a valid ISO 3166 country code" + .formatted(loc), ex.getMessage()); } // Ensure a selection of countries have the expected currency diff -Nru openjdk-21-21.0.8+9/test/jdk/java/util/Currency/ISO4217-list-one.txt openjdk-21-21.0.9+10/test/jdk/java/util/Currency/ISO4217-list-one.txt --- openjdk-21-21.0.8+9/test/jdk/java/util/Currency/ISO4217-list-one.txt 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/util/Currency/ISO4217-list-one.txt 2025-10-13 07:49:24.000000000 +0000 @@ -1,12 +1,12 @@ # # -# Amendments up until ISO 4217 AMENDMENT NUMBER 179 -# (As of 02 May 2025) +# Amendments up until ISO 4217 AMENDMENT NUMBER 180 +# (As of 22 September 2025) # # Version FILEVERSION=3 -DATAVERSION=179 +DATAVERSION=180 # ISO 4217 currency data AF AFN 971 2 @@ -44,7 +44,7 @@ BR BRL 986 2 IO USD 840 2 BN BND 96 2 -BG BGN 975 2 +BG BGN 975 2 2025-12-31-22-00-00 EUR 978 2 BF XOF 952 0 BI BIF 108 0 KH KHR 116 2 @@ -69,7 +69,7 @@ CI XOF 952 0 HR EUR 978 2 CU CUP 192 2 -CW ANG 532 2 2025-04-01-04-00-00 XCG 532 2 +CW XCG 532 2 CY EUR 978 2 CZ CZK 203 2 DK DKK 208 2 @@ -233,7 +233,7 @@ SD SDG 938 2 SR SRD 968 2 SJ NOK 578 2 -SX ANG 532 2 2025-04-01-04-00-00 XCG 532 2 +SX XCG 532 2 SZ SZL 748 2 SE SEK 752 2 CH CHF 756 2 diff -Nru openjdk-21-21.0.8+9/test/jdk/java/util/Currency/ValidateISO4217.java openjdk-21-21.0.9+10/test/jdk/java/util/Currency/ValidateISO4217.java --- openjdk-21-21.0.8+9/test/jdk/java/util/Currency/ValidateISO4217.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/util/Currency/ValidateISO4217.java 2025-10-13 07:49:24.000000000 +0000 @@ -26,7 +26,7 @@ * @bug 4691089 4819436 4942982 5104960 6544471 6627549 7066203 7195759 * 8039317 8074350 8074351 8145952 8187946 8193552 8202026 8204269 * 8208746 8209775 8264792 8274658 8283277 8296239 8321480 8334653 - * 8356096 + * 8356096 8368308 * @summary Validate ISO 4217 data for Currency class. * @modules java.base/java.util:open * jdk.localedata @@ -87,7 +87,7 @@ private static final Set testCurrencies = new HashSet<>(); // Codes that are obsolete, do not have related country, extra currency private static final String otherCodes = - "ADP-AFA-ATS-AYM-AZM-BEF-BGL-BOV-BYB-BYR-CHE-CHW-CLF-COU-CUC-CYP-" + "ADP-AFA-ATS-AYM-AZM-BEF-BGL-BGN-BOV-BYB-BYR-CHE-CHW-CLF-COU-CUC-CYP-" + "DEM-EEK-ESP-FIM-FRF-GHC-GRD-GWP-HRK-IEP-ITL-LTL-LUF-LVL-MGF-MRO-MTL-MXV-MZM-NLG-" + "PTE-ROL-RUR-SDD-SIT-SLL-SKK-SRG-STD-TMM-TPE-TRL-VEF-UYI-USN-USS-VEB-VED-" + "XAD-XAG-XAU-XBA-XBB-XBC-XBD-XDR-XFO-XFU-XPD-XPT-XSU-XTS-XUA-XXX-" diff -Nru openjdk-21-21.0.8+9/test/jdk/java/util/Locale/LanguageSubtagRegistryTest.java openjdk-21-21.0.9+10/test/jdk/java/util/Locale/LanguageSubtagRegistryTest.java --- openjdk-21-21.0.8+9/test/jdk/java/util/Locale/LanguageSubtagRegistryTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/util/Locale/LanguageSubtagRegistryTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,9 @@ * @test * @bug 8025703 8040211 8191404 8203872 8222980 8225435 8241082 8242010 8247432 * 8258795 8267038 8287180 8302512 8304761 8306031 8308021 8313702 8318322 - * 8327631 8332424 8334418 8344589 + * 8327631 8332424 8334418 8344589 8348328 * @summary Checks the IANA language subtag registry data update - * (LSR Revision: 2024-11-19) with Locale and Locale.LanguageRange + * (LSR Revision: 2025-05-15) with Locale and Locale.LanguageRange * class methods. * @run main LanguageSubtagRegistryTest */ @@ -45,9 +45,9 @@ static boolean err = false; private static final String ACCEPT_LANGUAGE = - "Accept-Language: aam, adp, aeb, ajs, aog, apc, ajp, aue, bcg, bic, bpp, cey, cbr, cnp, cqu, crr, csp, csx, dif, dmw, dsz, ehs, ema," - + " en-gb-oed, gti, iba, ilw, jks, kdz, kjh, kmb, koj, kru, ksp, kwq, kxe, kzk, lgs, lii, lmm, lsb, lsc, lsn, lsv, lsw, lvi, meg, mtm," - + " ngv, nns, ola, oyb, pat, pcr, phr, plu, pnd, pub, rib, rnb, rsn, scv, snz, sqx, suj, szy, taj, tdg, tjj, tjp, tpn, tvx," + "Accept-Language: aam, adp, aeb, ajs, aog, apc, ajp, aue, bcg, bic, bpp, cey, cbr, cnp, cqu, crr, csp, csx, dif, dmw, dsz, ehs, eko, ema," + + " en-gb-oed, gti, hnm, iba, ilw, jks, kdz, kjh, kmb, koj, kru, ksp, kwq, kxe, kzk, lgs, lii, lmm, lsb, lsc, lsn, lsv, lsw, luh, lvi, meg, mtm," + + " ngv, nns, ola, oyb, pat, pcr, phr, plu, pnd, pub, rib, rnb, rsn, scv, sjc, snz, sqm, sqx, suj, szy, taj, tdg, tjj, tjp, tpn, tvx," + " umi, uss, uth, xia, yos, ysm, zko, wkr;q=0.9, ar-hyw;q=0.8, yug;q=0.5, gfx;q=0.4"; private static final List EXPECTED_RANGE_LIST = List.of( new LanguageRange("aam", 1.0), @@ -94,12 +94,16 @@ new LanguageRange("sgn-dsz", 1.0), new LanguageRange("ehs", 1.0), new LanguageRange("sgn-ehs", 1.0), + new LanguageRange("eko", 1.0), + new LanguageRange("nte", 1.0), new LanguageRange("ema", 1.0), new LanguageRange("uok", 1.0), new LanguageRange("en-gb-oed", 1.0), new LanguageRange("en-gb-oxendict", 1.0), new LanguageRange("gti", 1.0), new LanguageRange("nyc", 1.0), + new LanguageRange("hnm", 1.0), + new LanguageRange("zh-hnm", 1.0), new LanguageRange("iba", 1.0), new LanguageRange("snb", 1.0), new LanguageRange("blg", 1.0), @@ -142,6 +146,8 @@ new LanguageRange("sgn-lsv", 1.0), new LanguageRange("lsw", 1.0), new LanguageRange("sgn-lsw", 1.0), + new LanguageRange("luh", 1.0), + new LanguageRange("zh-luh", 1.0), new LanguageRange("lvi", 1.0), new LanguageRange("meg", 1.0), new LanguageRange("cir", 1.0), @@ -176,8 +182,12 @@ new LanguageRange("sgn-rsn", 1.0), new LanguageRange("scv", 1.0), new LanguageRange("zir", 1.0), + new LanguageRange("sjc", 1.0), + new LanguageRange("zh-sjc", 1.0), new LanguageRange("snz", 1.0), new LanguageRange("asd", 1.0), + new LanguageRange("sqm", 1.0), + new LanguageRange("dek", 1.0), new LanguageRange("sqx", 1.0), new LanguageRange("sgn-sqx", 1.0), new LanguageRange("suj", 1.0), @@ -264,12 +274,18 @@ System.err.println(" Expected size=" + expectedSize); for (LanguageRange lr : expected) { + if (!got.contains(lr)) { + System.err.print("Error - Actual does not contain:"); + } System.err.println(" range=" + lr.getRange() + ", weight=" + lr.getWeight()); } System.err.println(" Actual size=" + actualSize); for (LanguageRange lr : got) { + if (!expected.contains(lr)) { + System.err.print("Error - Expected does not contain:"); + } System.err.println(" range=" + lr.getRange() + ", weight=" + lr.getWeight()); } diff -Nru openjdk-21-21.0.8+9/test/jdk/java/util/TimeZone/CLDRDisplayNamesTest.java openjdk-21-21.0.9+10/test/jdk/java/util/TimeZone/CLDRDisplayNamesTest.java --- openjdk-21-21.0.8+9/test/jdk/java/util/TimeZone/CLDRDisplayNamesTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/util/TimeZone/CLDRDisplayNamesTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -130,7 +130,7 @@ String displayName = zi.getDisplayName(false, TimeZone.SHORT, Locale.US); Locale.setDefault(originalLocale); if (!displayName.equals("GMT+05:00")) { - System.err.printf("Wrong display name for timezone Etc/GMT-5 : expected GMT+05:00, Actual " + displayName); + System.err.println("Wrong display name for timezone Etc/GMT-5 : expected GMT+05:00, Actual " + displayName); errors++; } diff -Nru openjdk-21-21.0.8+9/test/jdk/java/util/concurrent/tck/ScheduledExecutorTest.java openjdk-21-21.0.9+10/test/jdk/java/util/concurrent/tck/ScheduledExecutorTest.java --- openjdk-21-21.0.8+9/test/jdk/java/util/concurrent/tck/ScheduledExecutorTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/util/concurrent/tck/ScheduledExecutorTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -700,11 +700,13 @@ public void testShutdownNow_delayedTasks() throws InterruptedException { final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); List> tasks = new ArrayList<>(); + final int DELAY = 100; + for (int i = 0; i < 3; i++) { Runnable r = new NoOpRunnable(); - tasks.add(p.schedule(r, 9, SECONDS)); - tasks.add(p.scheduleAtFixedRate(r, 9, 9, SECONDS)); - tasks.add(p.scheduleWithFixedDelay(r, 9, 9, SECONDS)); + tasks.add(p.schedule(r, DELAY, SECONDS)); + tasks.add(p.scheduleAtFixedRate(r, DELAY, DELAY, SECONDS)); + tasks.add(p.scheduleWithFixedDelay(r, DELAY, DELAY, SECONDS)); } if (testImplementationDetails) assertEquals(new HashSet(tasks), new HashSet(p.getQueue())); diff -Nru openjdk-21-21.0.8+9/test/jdk/java/util/zip/EntryCount64k.java openjdk-21-21.0.9+10/test/jdk/java/util/zip/EntryCount64k.java --- openjdk-21-21.0.8+9/test/jdk/java/util/zip/EntryCount64k.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/util/zip/EntryCount64k.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,6 @@ /* * Copyright (c) 2013 Google Inc. All rights reserved. + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,9 +48,12 @@ import jdk.test.lib.process.ProcessTools; public class EntryCount64k { + + private static final String MAIN_CLASS_MSG = "foo bar hello world Main"; + public static class Main { public static void main(String[] args) { - System.out.print("Main"); + System.out.println(MAIN_CLASS_MSG); } } @@ -162,7 +166,10 @@ // Check java -jar OutputAnalyzer a = ProcessTools.executeTestJava("-jar", zipFile.getName()); a.shouldHaveExitValue(0); - a.stdoutShouldMatch("\\AMain\\Z"); + // expect the message from the application on stdout + a.stdoutContains(MAIN_CLASS_MSG); + // nothing is expected on stderr (apart from any probable deprecation + // warnings from the launcher/JVM) a.stderrShouldMatchIgnoreDeprecatedWarnings("\\A\\Z"); } } diff -Nru openjdk-21-21.0.8+9/test/jdk/java/util/zip/GZIP/GZIPInputStreamAvailable.java openjdk-21-21.0.9+10/test/jdk/java/util/zip/GZIP/GZIPInputStreamAvailable.java --- openjdk-21-21.0.8+9/test/jdk/java/util/zip/GZIP/GZIPInputStreamAvailable.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/java/util/zip/GZIP/GZIPInputStreamAvailable.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 7036144 + * @summary Test concatenated gz streams when available() returns zero + * @run junit GZIPInputStreamAvailable + */ + +import org.junit.jupiter.api.Test; + +import java.io.*; +import java.util.*; +import java.util.zip.*; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; + +public class GZIPInputStreamAvailable { + + public static final int NUM_COPIES = 100; + + @Test + public void testZeroAvailable() throws IOException { + + // Create some uncompressed data and then repeat it NUM_COPIES times + byte[] uncompressed1 = "this is a test".getBytes("ASCII"); + byte[] uncompressedN = repeat(uncompressed1, NUM_COPIES); + + // Compress the original data and then repeat that NUM_COPIES times + byte[] compressed1 = deflate(uncompressed1); + byte[] compressedN = repeat(compressed1, NUM_COPIES); + + // (a) Read back inflated data from a stream where available() is accurate and verify + byte[] readback1 = inflate(new ByteArrayInputStream(compressedN)); + assertArrayEquals(uncompressedN, readback1); + + // (b) Read back inflated data from a stream where available() always returns zero and verify + byte[] readback2 = inflate(new ZeroAvailableStream(new ByteArrayInputStream(compressedN))); + assertArrayEquals(uncompressedN, readback2); + } + + public static byte[] repeat(byte[] data, int count) { + byte[] repeat = new byte[data.length * count]; + int off = 0; + for (int i = 0; i < count; i++) { + System.arraycopy(data, 0, repeat, off, data.length); + off += data.length; + } + return repeat; + } + + public static byte[] deflate(byte[] data) throws IOException { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + try (GZIPOutputStream out = new GZIPOutputStream(buf)) { + out.write(data); + } + return buf.toByteArray(); + } + + public static byte[] inflate(InputStream in) throws IOException { + return new GZIPInputStream(in).readAllBytes(); + } + + public static class ZeroAvailableStream extends FilterInputStream { + public ZeroAvailableStream(InputStream in) { + super(in); + } + @Override + public int available() { + return 0; + } + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/accessibility/TestPopupMenuChildCount.java openjdk-21-21.0.9+10/test/jdk/javax/accessibility/TestPopupMenuChildCount.java --- openjdk-21-21.0.8+9/test/jdk/javax/accessibility/TestPopupMenuChildCount.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/accessibility/TestPopupMenuChildCount.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; + +/* + * @test + * @bug 8341311 + * @summary Verifies that VoiceOver announces correct number of child for PopupMenu on macOS + * @requires os.family == "mac" + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TestPopupMenuChildCount + */ + +public class TestPopupMenuChildCount { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + This test is applicable only on macOS. + + Test UI contains an empty JFrame. On press of left/right mouse button, + a PopupMenu will be visible. + + Follow these steps to test the behaviour: + + 1. Start the VoiceOver (Press Command + F5) application + 2. Press Left/Right mouse button inside test frame window to open + the PopupMenu + 3. VO should announce "Menu" with number of child items of the Popupmenu + 4. Press Up/Down arrow to traverse popupmenu child items + 5. Press Right arrow key to open submenu + 6. VO should announce "Menu" with correct number of child items + for the submenu (For e.g. When Submenu-1 is open, VO should announce + "Menu 4 items") + 7. Repeat the process for other submenus + 8. Press Pass if you are able to hear correct announcements + else Fail"""; + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(45) + .testUI(TestPopupMenuChildCount::createUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createUI() { + JFrame frame = new JFrame("Test Frame"); + + JPopupMenu popupmenu = new JPopupMenu(); + JMenuItem mi1 = new JMenuItem("MenuItem-1"); + JMenuItem mi2 = new JMenuItem("MenuItem-2"); + JMenuItem mi3 = new JMenuItem("MenuItem-3"); + popupmenu.add(mi1); + popupmenu.add(mi2); + popupmenu.add(mi3); + + JMenu submenu1 = new JMenu("Submenu-1"); + submenu1.add("subOne"); + submenu1.add("subTwo"); + submenu1.add("subThree"); + + JMenu submenu2 = new JMenu("Submenu-2"); + submenu2.add("subOne"); + submenu2.add("subTwo"); + + JMenu submenu3 = new JMenu ("Submenu-3"); + submenu3.add("subOne"); + submenu1.add(submenu3); + + popupmenu.add(submenu1); + popupmenu.add(submenu2); + + frame.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + popupmenu.show(e.getComponent(), e.getX(), e.getY()); + } + }); + frame.setSize(300, 300); + return frame; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/crypto/CryptoPermissions/InconsistentEntries.java openjdk-21-21.0.9+10/test/jdk/javax/crypto/CryptoPermissions/InconsistentEntries.java --- openjdk-21-21.0.8+9/test/jdk/javax/crypto/CryptoPermissions/InconsistentEntries.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/crypto/CryptoPermissions/InconsistentEntries.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,14 +29,16 @@ * @run testng/othervm InconsistentEntries */ +import java.util.List; +import jdk.test.lib.Utils; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.util.FileUtils; import org.testng.Assert; -import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import javax.crypto.*; import java.io.File; -import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -45,42 +47,35 @@ public class InconsistentEntries { - private static final String JDK_HOME = System.getProperty("test.jdk"); - private static final String TEST_SRC = System.getProperty("test.src"); - private static final Path POLICY_DIR = Paths.get(JDK_HOME, "conf", "security", - "policy", "testlimited"); - private static final Path POLICY_FILE = Paths.get(TEST_SRC, "default_local.policy"); - - Path targetFile = null; + private static final String JDK_HOME = System.getProperty("test.jdk", "."); + private static final String TEST_SRC = System.getProperty("test.src", "."); + private static final Path TEMP_JDK_HOME = Path.of("java"); + private static final Path POLICY_DIR = TEMP_JDK_HOME.resolve(Path.of("conf", "security", + "policy", "testlimited")); + private static final Path POLICY_FILE_SRC = Paths.get(TEST_SRC, "default_local.policy"); + private static final Path POLICY_FILE_TARGET = POLICY_DIR + .resolve(POLICY_FILE_SRC.getFileName()); @BeforeTest - public void setUp() throws IOException { + public void setUp() throws Exception { + // Clone the tested JDK to the scratch directory + FileUtils.copyDirectory(Path.of(JDK_HOME), TEMP_JDK_HOME); + + // create policy directory in the cloned JDK if (!POLICY_DIR.toFile().exists()) { Files.createDirectory(POLICY_DIR); } - targetFile = POLICY_DIR.resolve(POLICY_FILE.getFileName()); - Files.copy(POLICY_FILE, targetFile, StandardCopyOption.REPLACE_EXISTING); - } - - @AfterTest - public void cleanUp() throws IOException { - Files.delete(targetFile); + // copy policy file into policy directory + Files.copy(POLICY_FILE_SRC, POLICY_FILE_TARGET, StandardCopyOption.REPLACE_EXISTING); } - @Test - public void test() throws Exception { - String JAVA_HOME = System.getProperty("java.home"); - String FS = System.getProperty("file.separator"); - Path testlimited = Path.of(JAVA_HOME + FS + "conf" + FS + "security" + - FS + "policy" + FS + "testlimited"); - if (!Files.exists(testlimited)) { + public static void main(String[] args) throws Throwable { + if (!Files.exists(POLICY_DIR)) { throw new RuntimeException( "custom policy subdirectory: testlimited does not exist"); } - - File testpolicy = new File(JAVA_HOME + FS + "conf" + FS + "security" + - FS + "policy" + FS + "testlimited" + FS + "default_local.policy"); + File testpolicy = new File(POLICY_FILE_TARGET.toString()); if (testpolicy.length() == 0) { throw new RuntimeException( "policy: default_local.policy does not exist or is empty"); @@ -91,4 +86,16 @@ Assert.assertThrows(ExceptionInInitializerError.class, () -> Cipher.getMaxAllowedKeyLength("AES")); } + + @Test + public void test() throws Exception { + String tmpJava = TEMP_JDK_HOME.resolve("bin").resolve("java").toString(); + String[] args = Utils.prependTestJavaOpts(InconsistentEntries.class.getName()); + ProcessBuilder pb = new ProcessBuilder(tmpJava); + pb.command().addAll(List.of(args)); + + ProcessTools + .executeProcess(pb) + .shouldHaveExitValue(0); + } } diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/management/remote/mandatory/notif/ListenerScaleTest.java openjdk-21-21.0.9+10/test/jdk/javax/management/remote/mandatory/notif/ListenerScaleTest.java --- openjdk-21-21.0.8+9/test/jdk/javax/management/remote/mandatory/notif/ListenerScaleTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/management/remote/mandatory/notif/ListenerScaleTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -77,6 +77,7 @@ private static final int WARMUP_WITH_ONE_MBEAN = 1000; private static final int NOTIFS_TO_TIME = 100; private static final int EXTRA_MBEANS = 20000; + private static final double RATIO_FAIL_VALUE = 2500.0; private static final ObjectName testObjectName; static { @@ -187,8 +188,9 @@ long manyMBeansTime = timeNotif(mbs); System.out.println("Time with many MBeans: " + manyMBeansTime + "ns"); double ratio = (double) manyMBeansTime / singleMBeanTime; - if (ratio > 500.0) + if (ratio > RATIO_FAIL_VALUE) { throw new Exception("Failed: ratio=" + ratio); + } System.out.println("Test passed: ratio=" + ratio); } } diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/net/ssl/HttpsURLConnection/CriticalSubjectAltName.java openjdk-21-21.0.9+10/test/jdk/javax/net/ssl/HttpsURLConnection/CriticalSubjectAltName.java --- openjdk-21-21.0.8+9/test/jdk/javax/net/ssl/HttpsURLConnection/CriticalSubjectAltName.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/net/ssl/HttpsURLConnection/CriticalSubjectAltName.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,6 +105,7 @@ (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); SSLServerSocket sslServerSocket = (SSLServerSocket) sslssf.createServerSocket(serverPort); + sslServerSocket.setEnabledProtocols(new String[]{"TLSv1.2"}); serverPort = sslServerSocket.getLocalPort(); /* diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/net/ssl/SSLSession/CertMsgCheck.java openjdk-21-21.0.9+10/test/jdk/javax/net/ssl/SSLSession/CertMsgCheck.java --- openjdk-21-21.0.8+9/test/jdk/javax/net/ssl/SSLSession/CertMsgCheck.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/net/ssl/SSLSession/CertMsgCheck.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @library /javax/net/ssl/templates + * @bug 8311644 + * @summary Verify CertificateMessage alerts are correct to the TLS specs + * @run main/othervm -Djdk.tls.client.protocols=TLSv1.2 CertMsgCheck handshake_failure + * @run main/othervm -Djdk.tls.client.protocols=TLSv1.3 CertMsgCheck certificate_required + * + */ + +public class CertMsgCheck { + + public static void main(String[] args) throws Exception { + // Start server + TLSBase.Server server = new TLSBase.ServerBuilder().setClientAuth(true). + build(); + + // Initial client session + TLSBase.Client client1 = new TLSBase.Client(true, false); + + server.getSession(client1).getSessionContext(); + server.done(); + + var eList = server.getExceptionList(); + System.out.println("Exception list size is " + eList.size()); + + for (Exception e : eList) { + System.out.println("Looking at " + e.getClass() + " " + + e.getMessage()); + if (e.getMessage().contains(args[0])) { + System.out.println("Found correct exception: " + args[0] + + " in " + e.getMessage()); + return; + } else { + System.out.println("No \"" + args[0] + "\" found."); + } + } + + throw new Exception("Failed to find expected alert: " + args[0]); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/net/ssl/SSLSession/CheckSessionContext.java openjdk-21-21.0.9+10/test/jdk/javax/net/ssl/SSLSession/CheckSessionContext.java --- openjdk-21-21.0.8+9/test/jdk/javax/net/ssl/SSLSession/CheckSessionContext.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/net/ssl/SSLSession/CheckSessionContext.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,15 +36,11 @@ */ import javax.net.ssl.SSLSession; +import java.util.HexFormat; public class CheckSessionContext { - static void toHex(byte[] id) { - for (byte b : id) { - System.out.printf("%02X ", b); - } - System.out.println(); - } + static HexFormat hex = HexFormat.of(); public static void main(String[] args) throws Exception { TLSBase.Server server = new TLSBase.Server(); @@ -52,20 +48,18 @@ // Initial client session TLSBase.Client client1 = new TLSBase.Client(); if (server.getSession(client1).getSessionContext() == null) { - throw new Exception("Context was null"); + throw new Exception("Context was null. Handshake failure."); } else { System.out.println("Context was found"); } SSLSession ss = server.getSession(client1); System.out.println(ss); byte[] id = ss.getId(); - System.out.print("id = "); - toHex(id); + System.out.println("id = " + hex.formatHex(id)); System.out.println("ss.getSessionContext().getSession(id) = " + ss.getSessionContext().getSession(id)); if (ss.getSessionContext().getSession(id) != null) { id = ss.getSessionContext().getSession(id).getId(); - System.out.print("id = "); - toHex(id); + System.out.println("id = " + hex.formatHex(id)); } server.close(client1); client1.close(); diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/net/ssl/templates/SSLEngineTemplate.java openjdk-21-21.0.9+10/test/jdk/javax/net/ssl/templates/SSLEngineTemplate.java --- openjdk-21-21.0.8+9/test/jdk/javax/net/ssl/templates/SSLEngineTemplate.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/net/ssl/templates/SSLEngineTemplate.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,8 @@ * @build SSLContextTemplate * @run main/othervm SSLEngineTemplate */ + +import java.util.Objects; import javax.net.ssl.*; import javax.net.ssl.SSLEngineResult.HandshakeStatus; import java.nio.ByteBuffer; @@ -264,4 +266,75 @@ a.limit(a.capacity()); b.limit(b.capacity()); } + + /** + * Given a TLS record containing one or more handshake messages, return + * the specific handshake message as a ByteBuffer (a slice of the record) + * + * @param tlsRecord A ByteBuffer containing a TLS record. It is + * assumed that the position of the ByteBuffer is on the + * first byte of the TLS record header. + * @param hsMsgId The message identifier for the handshake message + * being sought. + * + * Message Identifiers + * + * @param isDtls Indicates whether DTLS protocol being used. + * @return a ByteBuffer containing the TLS handshake message. + * The position of the returned ByteBuffer will be on the + * first byte of the TLS handshake message data, + * immediately following the handshake header. + * If the message is not found, null will be returned. + * @throws SSLException if the incoming ByteBuffer does not contain + * a well-formed TLS message. + */ + protected static ByteBuffer extractHandshakeMsg( + ByteBuffer tlsRecord, int hsMsgId, boolean isDtls) + throws SSLException { + Objects.requireNonNull(tlsRecord); + tlsRecord.mark(); + + // Process the TLS record header + int type = Byte.toUnsignedInt(tlsRecord.get()); + int ver_major = Byte.toUnsignedInt(tlsRecord.get()); + int ver_minor = Byte.toUnsignedInt(tlsRecord.get()); + // Skip DTLS-specific bytes + if (isDtls) { + tlsRecord.position(tlsRecord.position() + 8); + } + int recLen = Short.toUnsignedInt(tlsRecord.getShort()); + + if (recLen > tlsRecord.remaining()) { + throw new SSLException("Incomplete record in buffer: " + + "Record length = " + recLen + + ", Remaining = " + + tlsRecord.remaining()); + } + + while (tlsRecord.hasRemaining()) { + // Grab the handshake message header. + int msgHdr = tlsRecord.getInt(); + int msgType = (msgHdr >> 24) & 0x000000FF; + int msgLen = msgHdr & 0x00FFFFFF; + // Skip DTLS-specific bytes + if (isDtls) { + tlsRecord.position(tlsRecord.position() + 8); + } + + if (msgType == hsMsgId) { + // Slice the buffer such that it contains the entire + // handshake message (less the handshake header). + ByteBuffer buf = tlsRecord.slice(tlsRecord.position(), msgLen); + tlsRecord.reset(); + return buf; + } else { + // Skip to the next handshake message, if there is one + tlsRecord.position(tlsRecord.position() + msgLen); + } + } + + tlsRecord.reset(); + return null; + } } diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java openjdk-21-21.0.9+10/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java --- openjdk-21-21.0.8+9/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -245,7 +245,7 @@ // // The server side takes care of the issue if the server cannot // get started in 90 seconds. The client side would just ignore - // the test case if the serer is not ready. + // the test case if the server is not ready. boolean serverIsReady = serverCondition.await(90L, TimeUnit.SECONDS); if (!serverIsReady) { @@ -378,7 +378,7 @@ * Check various exception conditions. */ if ((local != null) && (remote != null)) { - // If both failed, return the curthread's exception. + // If both failed, return the current thread's exception. local.addSuppressed(remote); exception = local; } else if (local != null) { diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/net/ssl/templates/TLSBase.java openjdk-21-21.0.9+10/test/jdk/javax/net/ssl/templates/TLSBase.java --- openjdk-21-21.0.8+9/test/jdk/javax/net/ssl/templates/TLSBase.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/net/ssl/templates/TLSBase.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,19 +21,16 @@ * questions. */ -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLServerSocket; -import javax.net.ssl.SSLServerSocketFactory; -import javax.net.ssl.SSLSession; -import javax.net.ssl.SSLSocket; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; +import javax.net.ssl.*; +import java.io.*; import java.net.InetAddress; import java.net.InetSocketAddress; +import java.security.KeyStore; +import java.security.cert.PKIXBuilderParameters; +import java.security.cert.X509CertSelector; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; /** @@ -68,11 +65,11 @@ TLSBase() { String keyFilename = - System.getProperty("test.src", "./") + "/" + pathToStores + - "/" + keyStoreFile; + System.getProperty("test.src", "./") + "/" + pathToStores + + "/" + keyStoreFile; String trustFilename = - System.getProperty("test.src", "./") + "/" + pathToStores + - "/" + trustStoreFile; + System.getProperty("test.src", "./") + "/" + pathToStores + + "/" + trustStoreFile; System.setProperty("javax.net.ssl.keyStore", keyFilename); System.setProperty("javax.net.ssl.keyStorePassword", passwd); System.setProperty("javax.net.ssl.trustStore", trustFilename); @@ -80,30 +77,65 @@ } // Base read operation - byte[] read(SSLSocket sock) { - try { - BufferedReader reader = new BufferedReader( - new InputStreamReader(sock.getInputStream())); - String s = reader.readLine(); - System.err.println("(read) " + name + ": " + s); - return s.getBytes(); - } catch (Exception e) { - e.printStackTrace(); - } - return null; + byte[] read(SSLSocket sock) throws Exception { + BufferedReader reader = new BufferedReader( + new InputStreamReader(sock.getInputStream())); + String s = reader.readLine(); + System.err.println("(read) " + name + ": " + s); + return s.getBytes(); } // Base write operation - public void write(SSLSocket sock, byte[] data) { - try { - PrintWriter out = new PrintWriter( - new OutputStreamWriter(sock.getOutputStream())); - out.println(new String(data)); - out.flush(); - System.err.println("(write)" + name + ": " + new String(data)); - } catch (Exception e) { - e.printStackTrace(); - } + public void write(SSLSocket sock, byte[] data) throws Exception { + PrintWriter out = new PrintWriter( + new OutputStreamWriter(sock.getOutputStream())); + out.println(new String(data)); + out.flush(); + System.err.println("(write)" + name + ": " + new String(data)); + } + + private static KeyManager[] getKeyManager(boolean empty) throws Exception { + FileInputStream fis = null; + if (!empty) { + fis = new FileInputStream(System.getProperty("test.src", "./") + + "/" + pathToStores + "/" + keyStoreFile); + } + // Load the keystore + char[] pwd = passwd.toCharArray(); + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + ks.load(fis, pwd); + + KeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX"); + kmf.init(ks, pwd); + return kmf.getKeyManagers(); + } + + private static TrustManager[] getTrustManager(boolean empty) throws Exception { + FileInputStream fis = null; + if (!empty) { + fis = new FileInputStream(System.getProperty("test.src", "./") + + "/" + pathToStores + "/" + trustStoreFile); + } + // Load the keystore + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + ks.load(fis, passwd.toCharArray()); + + PKIXBuilderParameters pkixParams = + new PKIXBuilderParameters(ks, new X509CertSelector()); + + // Explicitly set revocation based on the command-line + // parameters, default false + pkixParams.setRevocationEnabled(false); + + // Register the PKIXParameters with the trust manager factory + ManagerFactoryParameters trustParams = + new CertPathTrustManagerParameters(pkixParams); + + // Create the Trust Manager Factory using the PKIX variant + // and initialize it with the parameters configured above + TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); + tmf.init(trustParams); + return tmf.getTrustManagers(); } /** @@ -116,19 +148,22 @@ // Clients sockets are kept in a hash table with the port as the key. ConcurrentHashMap clientMap = new ConcurrentHashMap<>(); - boolean exit = false; Thread t; + List exceptionList = new ArrayList<>(); - Server() { + Server(ServerBuilder builder) { super(); name = "server"; try { - sslContext = SSLContext.getDefault(); + sslContext = SSLContext.getInstance("TLS"); + sslContext.init(TLSBase.getKeyManager(builder.km), + TLSBase.getTrustManager(builder.tm), null); fac = sslContext.getServerSocketFactory(); ssock = (SSLServerSocket) fac.createServerSocket(0); + ssock.setNeedClientAuth(builder.clientauth); serverPort = ssock.getLocalPort(); } catch (Exception e) { - System.err.println(e.getMessage()); + System.err.println("Failure during server initialization"); e.printStackTrace(); } @@ -137,13 +172,15 @@ try { while (true) { System.err.println("Server ready on port " + - serverPort); + serverPort); SSLSocket c = (SSLSocket)ssock.accept(); clientMap.put(c.getPort(), c); try { write(c, read(c)); } catch (Exception e) { + System.out.println("Caught " + e.getMessage()); e.printStackTrace(); + exceptionList.add(e); } } } catch (Exception ex) { @@ -154,11 +191,59 @@ t.start(); } + Server() { + this(new ServerBuilder()); + } + + /** + * @param km - true for an empty key manager + * @param tm - true for an empty trust manager + */ + Server(boolean km, boolean tm) { + super(); + name = "server"; + try { + sslContext = SSLContext.getInstance("TLS"); + sslContext.init(TLSBase.getKeyManager(km), + TLSBase.getTrustManager(tm), null); + fac = sslContext.getServerSocketFactory(); + ssock = (SSLServerSocket) fac.createServerSocket(0); + ssock.setNeedClientAuth(true); + serverPort = ssock.getLocalPort(); + } catch (Exception e) { + System.err.println("Failure during server initialization"); + e.printStackTrace(); + } + + // Thread to allow multiple clients to connect + t = new Thread(() -> { + try { + while (true) { + System.err.println("Server ready on port " + + serverPort); + SSLSocket c = (SSLSocket)ssock.accept(); + clientMap.put(c.getPort(), c); + try { + write(c, read(c)); + } catch (Exception e) { + System.out.println("Caught " + e.getMessage()); + e.printStackTrace(); + exceptionList.add(e); + } + } + } catch (Exception ex) { + System.err.println("Server Down"); + ex.printStackTrace(); + } + }); + t.start(); + } + // Exit test to quit the test. This must be called at the end of the // test or the test will never end. void done() { try { - t.interrupt(); + t.join(5000); ssock.close(); } catch (Exception e) { System.err.println(e.getMessage()); @@ -167,7 +252,7 @@ } // Read from the client - byte[] read(Client client) { + byte[] read(Client client) throws Exception { SSLSocket s = clientMap.get(Integer.valueOf(client.getPort())); if (s == null) { System.err.println("No socket found, port " + client.getPort()); @@ -176,13 +261,13 @@ } // Write to the client - void write(Client client, byte[] data) { + void write(Client client, byte[] data) throws Exception { write(clientMap.get(client.getPort()), data); } // Server writes to the client, then reads from the client. // Return true if the read & write data match, false if not. - boolean writeRead(Client client, String s) { + boolean writeRead(Client client, String s) throws Exception{ write(client, s.getBytes()); return (Arrays.compare(s.getBytes(), client.read()) == 0); } @@ -198,30 +283,61 @@ SSLSocket s = clientMap.get(Integer.valueOf(c.getPort())); s.close(); } + + List getExceptionList() { + return exceptionList; + } } + static class ServerBuilder { + boolean km = false, tm = false, clientauth = false; + + ServerBuilder setKM(boolean b) { + km = b; + return this; + } + + ServerBuilder setTM(boolean b) { + tm = b; + return this; + } + + ServerBuilder setClientAuth(boolean b) { + clientauth = b; + return this; + } + + Server build() { + return new Server(this); + } + } /** * Client side will establish a connection from the constructor and wait. * It must be run after the Server constructor is called. */ static class Client extends TLSBase { SSLSocket sock; - + boolean km, tm; Client() { + this(false, false); + } + + /** + * @param km - true sets an empty key manager + * @param tm - true sets an empty trust manager + */ + Client(boolean km, boolean tm) { super(); - try { - sslContext = SSLContext.getDefault(); - } catch (Exception e) { - System.err.println(e.getMessage()); - e.printStackTrace(); - } + this.km = km; + this.tm = tm; connect(); } // Connect to server. Maybe runnable in the future public SSLSocket connect() { try { - sslContext = SSLContext.getDefault(); + sslContext = SSLContext.getInstance("TLS"); + sslContext.init(TLSBase.getKeyManager(km), TLSBase.getTrustManager(tm), null); sock = (SSLSocket)sslContext.getSocketFactory().createSocket(); sock.connect(new InetSocketAddress(InetAddress.getLoopbackAddress(), serverPort)); System.err.println("Client connected using port " + @@ -236,21 +352,21 @@ } // Read from the client socket - byte[] read() { + byte[] read() throws Exception { return read(sock); } // Write to the client socket - void write(byte[] data) { + void write(byte[] data) throws Exception { write(sock, data); } - void write(String s) { + void write(String s) throws Exception { write(sock, s.getBytes()); } // Client writes to the server, then reads from the server. // Return true if the read & write data match, false if not. - boolean writeRead(Server server, String s) { + boolean writeRead(Server server, String s) throws Exception { write(s.getBytes()); return (Arrays.compare(s.getBytes(), server.read(this)) == 0); } diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/sound/midi/File/SMFInterruptedRunningStatus.java openjdk-21-21.0.9+10/test/jdk/javax/sound/midi/File/SMFInterruptedRunningStatus.java --- openjdk-21-21.0.8+9/test/jdk/javax/sound/midi/File/SMFInterruptedRunningStatus.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/sound/midi/File/SMFInterruptedRunningStatus.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.ByteArrayInputStream; + +import javax.sound.midi.MidiSystem; +import javax.sound.midi.Sequence; +import javax.sound.midi.Track; + +/** + * @test + * @bug 8319598 + * @summary SMFParser bug with running status, interrupted by Meta or SysEx messages + */ +public class SMFInterruptedRunningStatus { + + public static void main(String[] args) throws Exception { + + byte[][] files = new byte[][] {SMF_1, SMF_2, SMF_3}; + for (int i = 0; i < files.length; i++) { + Sequence seq = MidiSystem.getSequence( + new ByteArrayInputStream(files[i])); + testSequence(seq, i + 1); + } + + // no exception thrown, all files have been parsed correctly + System.out.println("Test passed"); + } + + private static void testSequence(Sequence seq, int fileNumber) { + + // check number of tracks and number of events + Track[] tracks = seq.getTracks(); + if (1 != tracks.length) { + throw new RuntimeException("file number " + + fileNumber + " fails (incorrect number of tracks: " + + tracks.length + ")"); + } + Track track = tracks[0]; + if (7 != track.size()) { + throw new RuntimeException("file number " + fileNumber + + " fails (incorrect number of events: " + + track.size() + ")"); + } + + // check status byte of each message + int[] expectedStatusBytes = new int[] { + 0x90, 0xFF, 0x90, 0x90, 0x90, 0xFF, 0xFF}; + for (int i = 0; i < expectedStatusBytes.length; i++) { + int expected = expectedStatusBytes[i]; + if (expected != track.get(i).getMessage().getStatus()) { + throw new RuntimeException("file number " + fileNumber + + " fails (wrong status byte in event " + i + ")"); + } + } + } + + // MIDI file without running status - should work equally before + // and after the bugfix + private static final byte[] SMF_1 = { + 0x4D, 0x54, 0x68, 0x64, 0x00, 0x00, 0x00, 0x06, // file header (start) + 0x00, 0x01, 0x00, 0x01, 0x00, (byte) 0x80, // file header (end) + 0x4D, 0x54, 0x72, 0x6B, 0x00, 0x00, 0x00, 0x24, // track header + 0x00, // delta time + (byte) 0x90, 0x3C, 0x7F, // Note-ON (C) + 0x40, // delta time + (byte) 0xFF, 0x01, 0x04, 0x54, 0x65, 0x73, 0x74, // META (text) + 0x20, // delta time + (byte) 0x90, 0x3C, 0x00, // Note-OFF (C) + 0x20, // delta time + (byte) 0x90, 0x3E, 0x7F, // Note-ON (D) + 0x60, // delta time + (byte) 0x90, 0x3E, 0x00, // Note-OFF (D) + 0x20, // delta time + (byte) 0xFF, 0x01, 0x04, 0x54, 0x65, 0x73, 0x74, // META (text) + 0x00, // delta time + (byte) 0xFF, 0x2F, 0x00 // META (end of track) + }; + + // MIDI file with running status, interrupted by a META message + // - failed before the bugfix + private static final byte[] SMF_2 = { + 0x4D, 0x54, 0x68, 0x64, 0x00, 0x00, 0x00, 0x06, // file header (start) + 0x00, 0x01, 0x00, 0x01, 0x00, (byte) 0x80, // file header (end) + 0x4D, 0x54, 0x72, 0x6B, 0x00, 0x00, 0x00, 0x21, // track header + 0x00, // delta time + (byte) 0x90, 0x3C, 0x7F, // Note-ON (C) + 0x40, // delta time + (byte) 0xFF, 0x01, 0x04, 0x54, 0x65, 0x73, 0x74, // META (interruptor) + 0x20, // delta time + 0x3C, 0x00, // Note-OFF (C) - running status + 0x20, // delta time + 0x3E, 0x7F, // Note-ON (D) - running status + 0x60, // delta time + 0x3E, 0x00, // Note-OFF (D) - running status + 0x20, // delta time + (byte) 0xFF, 0x01, 0x04, 0x54, 0x65, 0x73, 0x74, // META (text) + 0x00, // delta time + (byte) 0xFF, 0x2F, 0x00 // META (end of track) + }; + + // MIDI file with running status, interrupted by a META message + // - succeeded before the bugfix but with wrong interpretation of the data + private static final byte[] SMF_3 = { + 0x4D, 0x54, 0x68, 0x64, 0x00, 0x00, 0x00, 0x06, // file header (start) + 0x00, 0x01, 0x00, 0x01, 0x00, (byte) 0x80, // file header (end) + 0x4D, 0x54, 0x72, 0x6B, 0x00, 0x00, 0x00, 0x21, // track header + 0x00, // delta time + (byte) 0x90, 0x3C, 0x7F, // Note-ON (C) + 0x40, // delta time + (byte) 0xFF, 0x01, 0x04, 0x54, 0x65, 0x73, 0x74, // META (interruptor) + 0x20, // delta time + 0x3C, 0x00, // Note-OFF (C) - running status + 0x0D, // delta time + 0x3E, 0x7F, // Note-ON (D) - running status + 0x60, // delta time + 0x3E, 0x00, // Note-OFF (D) - running status + 0x20, // delta time + (byte) 0xFF, 0x01, 0x04, 0x54, 0x65, 0x73, 0x74, // META (text) + 0x00, // delta time + (byte) 0xFF, 0x2F, 0x00 // META (end of track) + }; +} + diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JColorChooser/Test6977726.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JColorChooser/Test6977726.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JColorChooser/Test6977726.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JColorChooser/Test6977726.java 2025-10-13 07:49:24.000000000 +0000 @@ -41,7 +41,14 @@ String instructions = """ Check that there is a panel with "Text Preview Panel" text and with title "Preview" in the JColorChooser. - Test passes if the panel is as described, test fails otherwise."""; + Test passes if the panel is as described, test fails otherwise. + + Note: "Preview" title is not applicable for GTK Look and Feel."""; + + // In case this test is run with GTK L&F, the preview panel title + // is missing due to the "ColorChooser.showPreviewPanelText" property + // which is set to "Boolean.FALSE" for GTK L&F. Test instructions are + // modified to reflect that "Preview" title is not applicable for GTK L&F. PassFailJFrame.builder() .title("Test6977726") diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JComboBox/6559152/bug6559152.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JComboBox/6559152/bug6559152.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JComboBox/6559152/bug6559152.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JComboBox/6559152/bug6559152.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,8 +48,8 @@ private static JFrame frame; private static JComboBox cb; private static Robot robot; - private static Point p = null; - private static Dimension d; + private static volatile Point p = null; + private static volatile Dimension d; public static void main(String[] args) throws Exception { robot = new Robot(); @@ -84,7 +84,7 @@ } private static void setupUI() { - frame = new JFrame(); + frame = new JFrame("bug6559152"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); DefaultTableModel model = new DefaultTableModel(1, 1); diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JFileChooser/6798062/bug6798062.html openjdk-21-21.0.9+10/test/jdk/javax/swing/JFileChooser/6798062/bug6798062.html --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JFileChooser/6798062/bug6798062.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JFileChooser/6798062/bug6798062.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ - - - - - -The test is suitable only for Windows - -1. Create a link -2. Copy path to the link into TextField -3. Run the Windows Task Manager. Select the Processes tab and find the java process -4. Press the Start button in the test window -5. Wait several minutes and observe in the Windows Task Manager -that Memory Usage of java process is not increasing - - diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JFileChooser/6798062/bug6798062.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JFileChooser/6798062/bug6798062.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JFileChooser/6798062/bug6798062.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JFileChooser/6798062/bug6798062.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,54 +21,82 @@ * questions. */ -/* @test %W% %E% - @bug 6798062 - @summary Memory Leak on using getFiles of FileSystemView - @author Pavel Porvatov - @modules java.desktop/sun.awt - java.desktop/sun.awt.shell - @run applet/manual=done bug6798062.html -*/ +/* + * @test + * @bug 6798062 + * @requires (os.family == "windows") + * @summary Memory Leak on using getFiles of FileSystemView + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @modules java.desktop/sun.awt + * java.desktop/sun.awt.shell + * @run main/manual bug6798062 + */ import sun.awt.OSInfo; import sun.awt.shell.ShellFolder; -import javax.swing.*; +import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.awt.*; import java.io.File; import java.io.FileNotFoundException; - -public class bug6798062 extends JApplet { - - private final JSlider slider = new JSlider(0, 100); - - private final JTextField tfLink = new JTextField(); - - private final JButton btnStart = new JButton("Start"); - - private final JButton btnStop = new JButton("Stop"); - - private final JButton btnGC = new JButton("Run System.gc()"); +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSlider; +import javax.swing.JTextField; + +public class bug6798062 { + + private static final String INSTRUCTIONS = """ + The test is suitable only for Windows. + + 1. Create a shortcut (.lnk) file + 2. Copy path to the shortcut (.lnk file) into TextField + 3. Run the Windows Task Manager. Select the Processes tab and find the java process + 4. Press the Start button in the test window + 5. Wait several minutes and observe in the Windows Task Manager + that Memory Usage of java process is not increasing + If memory usage is increasing, click Fail else click Pass."""; + + private static JSlider slider; + private static JTextField tfLink; + private static JButton btnStart; + private static JButton btnStop; + private static JButton btnGC; private ShellFolder folder; - private Thread thread; - public static void main(String[] args) { + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("JFileChooser Instructions") + .instructions(INSTRUCTIONS) + .testTimeOut(10) + .rows(10) + .columns(35) + .testUI(bug6798062::createUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createUI() { + slider = new JSlider(0, 100); + tfLink = new JTextField(); + btnStart = new JButton("Start"); + btnStop = new JButton("Stop"); + btnGC = new JButton("Run System.gc()"); JFrame frame = new JFrame("bug6798062"); frame.setSize(400, 300); - frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new bug6798062().initialize()); - frame.setVisible(true); - } - - public void init() { - add(initialize()); + return frame; } private JComponent initialize() { @@ -87,7 +115,7 @@ try { folder = ShellFolder.getShellFolder(new File(tempDir)); } catch (FileNotFoundException e) { - fail("Directory " + tempDir + " not found"); + fail("Directory not found"); } slider.setMajorTickSpacing(10); @@ -153,7 +181,7 @@ } private static void fail(String msg) { - throw new RuntimeException(msg); + PassFailJFrame.forceFail(msg); } private class MyThread extends Thread { @@ -169,7 +197,7 @@ try { linkFolder = ShellFolder.getShellFolder(new File(link)); } catch (FileNotFoundException e) { - e.printStackTrace(); + fail("File not found"); linkFolder = null; } @@ -184,7 +212,7 @@ try { link.getLinkLocation(); } catch (FileNotFoundException e) { - e.printStackTrace(); + fail("File not found"); } } diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JFileChooser/FileFilterDescription/FileFilterDescription.html openjdk-21-21.0.9+10/test/jdk/javax/swing/JFileChooser/FileFilterDescription/FileFilterDescription.html --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JFileChooser/FileFilterDescription/FileFilterDescription.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JFileChooser/FileFilterDescription/FileFilterDescription.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ - - - - - - - -Follow the instructions below. -1) Check that current filter in the opened JFileChooser is a "CustomFileFilter". -2) Close the JFileChooser. -3) Test will repeat steps 1 - 2 for all supported look and feels. -4) If it's true for all look and feels then the test passed, otherwise it failed. - - diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JFileChooser/FileFilterDescription/FileFilterDescription.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JFileChooser/FileFilterDescription/FileFilterDescription.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JFileChooser/FileFilterDescription/FileFilterDescription.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JFileChooser/FileFilterDescription/FileFilterDescription.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,44 +21,57 @@ * questions. */ -import java.applet.Applet; import java.io.File; - +import java.awt.BorderLayout; import javax.swing.JFileChooser; +import javax.swing.JFrame; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.filechooser.FileFilter; -public final class FileFilterDescription extends Applet { - - @Override - public void init() { - } - - @Override - public void start() { - try { - test(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } +/* + * @test + * @bug 8029536 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual FileFilterDescription + */ +public final class FileFilterDescription { + private static final String INSTRUCTIONS = """ + 1) Check that current filter in the opened JFileChooser is a "CustomFileFilter". + 2) Close the JFileChooser. + 3) Test will repeat steps 1 - 2 for all supported look and feels. + 4) If it's true for all look and feels then click Pass else click Fail. """; + + public static void main(String[] args) throws Exception { + PassFailJFrame passFailJFrame = PassFailJFrame.builder() + .title("JFileChooser Filefilter Instructions") + .instructions(INSTRUCTIONS) + .rows(10) + .columns(35) + .position(PassFailJFrame.Position.TOP_LEFT_CORNER) + .build(); - public static void test() throws Exception { final UIManager.LookAndFeelInfo[] infos = UIManager .getInstalledLookAndFeels(); for (final UIManager.LookAndFeelInfo info : infos) { SwingUtilities.invokeAndWait(() -> { - final JFileChooser chooser = new JFileChooser(); setLookAndFeel(info); + JFrame frame = new JFrame("JFileChooser FileFilter test"); + final JFileChooser chooser = new JFileChooser(); chooser.setAcceptAllFileFilterUsed(false); chooser.setFileFilter(new CustomFileFilter()); SwingUtilities.updateComponentTreeUI(chooser); + frame.add(chooser, BorderLayout.CENTER); + frame.pack(); + PassFailJFrame.addTestWindow(frame); + PassFailJFrame.positionTestWindow(frame, PassFailJFrame.Position.TOP_LEFT_CORNER); chooser.showDialog(null, "Open"); }); } + passFailJFrame.awaitAndCheck(); } private static void setLookAndFeel(final UIManager.LookAndFeelInfo info) { diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JInternalFrame/6726866/bug6726866.html openjdk-21-21.0.9+10/test/jdk/javax/swing/JInternalFrame/6726866/bug6726866.html --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JInternalFrame/6726866/bug6726866.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JInternalFrame/6726866/bug6726866.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ - - - - - -Drag the internal frame inside the green undecorated window, -if you can drag it the test passes, otherwise fails. - - diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JInternalFrame/6726866/bug6726866.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JInternalFrame/6726866/bug6726866.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JInternalFrame/6726866/bug6726866.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JInternalFrame/6726866/bug6726866.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,11 +21,14 @@ * questions. */ -/* @test - @bug 6726866 8186617 - @summary Repainting artifacts when resizing or dragging JInternalFrames in +/* + * @test + * @bug 6726866 8186617 + * @summary Repainting artifacts when resizing or dragging JInternalFrames in non-opaque toplevel - @run applet/manual=yesno bug6726866.html + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug6726866 */ import java.awt.Color; @@ -36,10 +39,26 @@ import javax.swing.JFrame; import javax.swing.JInternalFrame; import javax.swing.JLabel; +import javax.swing.SwingUtilities; + +public class bug6726866 { -public class bug6726866 extends JApplet { + private static final String INSTRUCTIONS = """ + Drag the internal frame inside the green undecorated window, + if you can drag it the test passes, otherwise fails. """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("JInternalFrame Instructions") + .instructions(INSTRUCTIONS) + .rows(5) + .columns(35) + .testUI(bug6726866::createUI) + .build() + .awaitAndCheck(); + } - public void init() { + private static JFrame createUI() { JFrame frame = new JFrame("bug6726866"); frame.setUndecorated(true); setWindowNonOpaque(frame); @@ -53,10 +72,8 @@ desktop.add(iFrame); frame.add(desktop); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(400, 400); - frame.setVisible(true); - frame.toFront(); + return frame; } public static void setWindowNonOpaque(Window window) { diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JMenu/bug4187996.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JMenu/bug4187996.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JMenu/bug4187996.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JMenu/bug4187996.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4187996 + * @summary Tests that Metal submenus overlap menu + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4187996 + */ + +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.UIManager; + +public class bug4187996 { + + private static final String INSTRUCTIONS = """ + Open the menu "Menu", then "Submenu". + The submenu should be top-aligned with the menu, + and slightly overlap it horizontally. Otherwise test fails."""; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + PassFailJFrame.builder() + .title("bug4187996 Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(bug4187996::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI() { + JFrame frame = new JFrame("bug4187996"); + JMenu submenu = new JMenu("Submenu"); + submenu.add(new JMenuItem("Sub 1")); + submenu.add(new JMenuItem("Sub 2")); + + JMenu menu = new JMenu("Menu"); + menu.add(submenu); + menu.add(new JMenuItem("Item 1")); + menu.add(new JMenuItem("Item 2")); + + JMenuBar mbar = new JMenuBar(); + mbar.add(menu); + frame.setJMenuBar(mbar); + frame.setSize(300, 100); + return frame; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JMenu/bug6471949.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JMenu/bug6471949.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JMenu/bug6471949.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JMenu/bug6471949.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6471949 + * @summary JMenu should stay selected after escape is pressed + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug6471949 +*/ + +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; + +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public class bug6471949 { + + private static final String INSTRUCTIONS = """ + Test the menu and its submenus for different LaF: + + Click on "Menu" and then click on "Inner" submenu + and then click on "One more" submenu. + + For Metal, Nimbus and Aqua Laf the Escape key hides the last open submenu, + Press Esc till the last menu "Inner" is closed. + If the last menu is closed then the menu button (in menubar) gets unselected. + + For Windows Laf the Escape key hides the last open submenu + if the last menu is closed then the menu button remains selected, + until the Escape key is pressed again or any other key letter pressed. + + For GTK and Motif menu, all open submenus must hide when the Escape key is pressed. + + If everything works as described, the test passes and fails otherwise."""; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug6471949 Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(bug6471949::createTestUI) + .logArea() + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI() { + + PassFailJFrame.log("Menu.cancelMode = " + + UIManager.getString("Menu.cancelMode")); + PassFailJFrame.log("Menu.preserveTopLevelSelection = " + + UIManager.getBoolean("Menu.preserveTopLevelSelection")); + PassFailJFrame.log(""); + + JFrame frame = new JFrame("bug6471949"); + JMenuBar bar = new JMenuBar(); + JMenu menu = new JMenu("Menu"); + menu.setMnemonic('m'); + + JMenuItem item = new JMenuItem("Item"); + menu.add(item); + JMenu inner = new JMenu("Inner"); + inner.add(new JMenuItem("Test")); + JMenu oneMore = new JMenu("One more"); + oneMore.add(new JMenuItem("Lala")); + inner.add(oneMore); + menu.add(inner); + + JMenu lafMenu = new JMenu("Change LaF"); + + UIManager.LookAndFeelInfo[] lafs = UIManager.getInstalledLookAndFeels(); + for (final UIManager.LookAndFeelInfo lafInfo : lafs) { + JMenuItem lafItem = new JMenuItem(lafInfo.getName()); + lafItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setLaf(frame, lafInfo.getClassName()); + } + }); + lafMenu.add(lafItem); + } + + frame.setJMenuBar(bar); + bar.add(menu); + bar.add(lafMenu); + + JTextArea field = new JTextArea(); + frame.add(field); + field.requestFocusInWindow(); + frame.pack(); + return frame; + } + + private static void setLaf(JFrame frame, String laf) { + try { + UIManager.setLookAndFeel(laf); + SwingUtilities.updateComponentTreeUI(frame); + PassFailJFrame.log("Menu.cancelMode = " + + UIManager.getString("Menu.cancelMode")); + PassFailJFrame.log("Menu.preserveTopLevelSelection = " + + UIManager.getBoolean("Menu.preserveTopLevelSelection")); + PassFailJFrame.log(""); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JMenu/bug6513492.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JMenu/bug6513492.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JMenu/bug6513492.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JMenu/bug6513492.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* +* @test +* @bug 6513492 +* @summary Escape key needs to be pressed twice to remove focus from an empty/diabled Menu. +* @library /java/awt/regtesthelpers +* @build PassFailJFrame +* @run main/manual bug6513492 +*/ + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public class bug6513492 { + + private static final String INSTRUCTIONS = """ + Test Menu for different LaF: + + * For Windows Laf: + Click the editor + Click EmpyMenu, press Escape -> focus must go to the editor + Click EmpyMenu, press right arrow button, press Escape -> focus must go to the editor + Click SubMenuTest, highlight the first disabled submenu, press Escape + -> focus must stay at the topLevelMenu + + * For Metal, Nimbus and Aqua Laf + Click the editor + Click SubMenuTest, highlight the EmptySubmenu, press Escape -> focus must go to the editor + Click SubMenuTest, highlight the EnabledItem, press Escape -> focus must go to the editor + + * For GTK and Motif + Click the editor + Open any menu or submenu, press Escape -> focus must go to the editor."""; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug6513492 Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(bug6513492::createTestUI) + .logArea() + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI() { + PassFailJFrame.log("Menu.cancelMode = " + + UIManager.getString("Menu.cancelMode")); + PassFailJFrame.log("Menu.preserveTopLevelSelection = " + + UIManager.getBoolean("Menu.preserveTopLevelSelection")); + PassFailJFrame.log(""); + + JFrame frame = new JFrame("bug6513492"); + JMenuBar bar = new JMenuBar(); + bar.add(new JMenu("EmptyMenu")); + + JMenu disabledMenu = new JMenu("NotEmpyButDisabled"); + disabledMenu.add(new JMenuItem("item")); + disabledMenu.setEnabled(false); + bar.add(disabledMenu); + + JMenu menu = new JMenu("SubMenuTest"); + JMenu disabledSubmenu = new JMenu("Submenu"); + disabledSubmenu.add(new JMenuItem("item")); + disabledSubmenu.setEnabled(false); + menu.add(disabledSubmenu); + + JMenu enabledSubmenu = new JMenu("Submenu"); + enabledSubmenu.add(new JMenuItem("item")); + menu.add(enabledSubmenu); + + JMenu emptySubmenu = new JMenu("EmptySubmenu"); + menu.add(emptySubmenu); + + menu.add(new JMenuItem("EnabledItem")); + JMenuItem item = new JMenuItem("DisabledItem"); + item.setEnabled(false); + menu.add(item); + bar.add(menu); + + JMenu lafMenu = new JMenu("Change LaF"); + + UIManager.LookAndFeelInfo[] lafs = UIManager.getInstalledLookAndFeels(); + for (final UIManager.LookAndFeelInfo lafInfo : lafs) { + JMenuItem lafItem = new JMenuItem(lafInfo.getName()); + lafItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setLaf(frame, lafInfo.getClassName()); + } + }); + lafMenu.add(lafItem); + } + + frame.setJMenuBar(bar); + bar.add(menu); + bar.add(lafMenu); + + JTextArea field = new JTextArea("The editor"); + frame.add(field); + field.requestFocusInWindow(); + frame.pack(); + return frame; + } + + private static void setLaf(JFrame frame, String laf) { + try { + UIManager.setLookAndFeel(laf); + SwingUtilities.updateComponentTreeUI(frame); + PassFailJFrame.log("Menu.cancelMode = " + + UIManager.getString("Menu.cancelMode")); + PassFailJFrame.log("Menu.preserveTopLevelSelection = " + + UIManager.getBoolean("Menu.preserveTopLevelSelection")); + PassFailJFrame.log(""); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JMenuItem/TestRadioAndCheckMenuItemWithIcon.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JMenuItem/TestRadioAndCheckMenuItemWithIcon.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JMenuItem/TestRadioAndCheckMenuItemWithIcon.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JMenuItem/TestRadioAndCheckMenuItemWithIcon.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8348760 + * @summary Verify if RadioButtonMenuItem bullet and + * JCheckboxMenuItem checkmark is shown if + * JRadioButtonMenuItem and JCheckboxMenuItem + * is rendered with ImageIcon in WindowsLookAndFeel + * @requires (os.family == "windows") + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TestRadioAndCheckMenuItemWithIcon + */ + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.awt.image.BufferedImage; + +import javax.swing.AbstractButton; +import javax.swing.ButtonGroup; +import javax.swing.ImageIcon; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.KeyStroke; +import javax.swing.UIManager; + +public class TestRadioAndCheckMenuItemWithIcon { + + private static final String INSTRUCTIONS = """ + A top level Menu will be shown. + + Clicking on the Menu will show a + JRadioButtonMenuItem group with 3 radiobutton menuitems + and a JCheckBoxMenuItem group with 3 checkbox menuitems. + + First radiobutton menuitem is selected with imageicon of a red square. + Second radiobutton menuitem is unselected with imageicon. + Third radiobutton menuItem is unselected without imageicon. + + First checkbox menuitem is selected with imageicon. + Second checkbox menuitem is unselected with imageicon. + Third checkbox menuItem is unselected without imageicon. + + Verify that for first JRadioButtonMenuItem with imageicon, + a bullet is shown alongside the imageicon and + for first JCheckBoxMenuItem with imageicon + a checkmark is shown alongside the imageicon. + + If bullet and checkmark is shown, test passes else fails."""; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + PassFailJFrame.builder() + .title("JRadioButtonMenuItem Instructions") + .instructions(INSTRUCTIONS) + .columns(60) + .testUI(TestRadioAndCheckMenuItemWithIcon::doTest) + .build() + .awaitAndCheck(); + } + + public static JFrame doTest() { + BufferedImage img = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB); + Graphics g = img.getGraphics(); + g.setColor(Color.red); + g.fillRect(0, 0, img.getWidth(), img.getHeight()); + g.dispose(); + + BufferedImage img2 = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB); + Graphics g2 = img2.getGraphics(); + g2.setColor(Color.red); + g2.fillRect(0, 0, img2.getWidth(), img2.getHeight()); + g2.dispose(); + + JFrame frame = new JFrame("RadioButtonWithImageIcon"); + ImageIcon imageIcon1 = new ImageIcon(img); + ImageIcon imageIcon2 = new ImageIcon(img2); + AbstractButton button1; + JRadioButtonMenuItem m1 = new JRadioButtonMenuItem("JRadioButtonMenuItem 1", + imageIcon1); + m1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, ActionEvent.ALT_MASK|ActionEvent.CTRL_MASK|ActionEvent.SHIFT_MASK)); + button1 = m1; + button1.setSelected(true); + AbstractButton button2 = new JRadioButtonMenuItem("JRadioButtonMenuItem 2", imageIcon2); + AbstractButton button3 = new JRadioButtonMenuItem("JRadioButtonMenuItem 3"); + + ButtonGroup buttonGroup = new ButtonGroup(); + buttonGroup.add(button1); + buttonGroup.add(button2); + buttonGroup.add(button3); + + AbstractButton check1 = new JCheckBoxMenuItem("JCheckBoxMenuItem 1", + imageIcon1); + check1.setSelected(true); + AbstractButton check2 = new JCheckBoxMenuItem("JCheckBoxMenuItem 2", imageIcon1); + JCheckBoxMenuItem c3; + AbstractButton check3 = c3 = new JCheckBoxMenuItem("JCheckBoxMenuItem 3"); + c3.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F5, ActionEvent.ALT_MASK|ActionEvent.CTRL_MASK|ActionEvent.SHIFT_MASK)); + + JMenu topLevel = new JMenu("Menu"); + + topLevel.add(button1); + topLevel.add(button2); + topLevel.add(button3); + + topLevel.addSeparator(); + + topLevel.add(check1); + topLevel.add(check2); + topLevel.add(check3); + + AbstractButton menuitem1 = new JMenuItem("MenuItem1"); + AbstractButton menuitem2 = new JMenuItem("MenuItem2", imageIcon1); + topLevel.addSeparator(); + topLevel.add(menuitem1); + topLevel.add(menuitem2); + + JMenuBar menuBar = new JMenuBar(); + menuBar.add(topLevel); + + frame.setJMenuBar(menuBar); + frame.setSize(300, 300); + return frame; + + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JOptionPane/4174551/bug4174551.html openjdk-21-21.0.9+10/test/jdk/javax/swing/JOptionPane/4174551/bug4174551.html --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JOptionPane/4174551/bug4174551.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JOptionPane/4174551/bug4174551.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ - - - - - Message Dialog should pop up - with a button font size 10 - and message font size 24. - - It should be true even on OS X. - If it is not so press "Fail" else press "Pass". - - - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JOptionPane/4174551/bug4174551.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JOptionPane/4174551/bug4174551.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JOptionPane/4174551/bug4174551.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JOptionPane/4174551/bug4174551.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 4174551 - * @summary JOptionPane should allow custom buttons - * @author Xhipra Tyagi(xhipra.tyagi@india.sun.com) area=Swing - * @run applet/manual=yesno bug4174551.html - */ -import java.awt.Font; -import javax.swing.JApplet; -import javax.swing.UIManager; -import javax.swing.JOptionPane; - -public class bug4174551 extends JApplet { - - public void init() { - try { - java.awt.EventQueue.invokeLater( () -> { - UIManager.getDefaults().put("OptionPane.buttonFont", new Font("Dialog", Font.PLAIN, 10)); - UIManager.getDefaults().put("OptionPane.messageFont", new Font("Dialog", Font.PLAIN, 24)); - JOptionPane.showMessageDialog(null, "HI 24!"); - - System.out.println(UIManager.getDefaults().get("OptionPane.buttonFont")); - System.out.println(UIManager.getDefaults().get("OptionPane.messageFont")); - }); - }catch(Exception ex) { - ex.printStackTrace(); - } - } -} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JOptionPane/8024926/bug8024926.html openjdk-21-21.0.9+10/test/jdk/javax/swing/JOptionPane/8024926/bug8024926.html --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JOptionPane/8024926/bug8024926.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JOptionPane/8024926/bug8024926.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ - - - - - High resolution icon test, bug ID 8024926 - - - -

See the dialog box (usually in upper left corner) for instructions

- - diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JOptionPane/8024926/bug8024926.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JOptionPane/8024926/bug8024926.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JOptionPane/8024926/bug8024926.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JOptionPane/8024926/bug8024926.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,212 +0,0 @@ -/* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -import java.awt.BorderLayout; -import java.awt.Dialog; -import java.awt.EventQueue; -import java.awt.Frame; -import java.awt.TextArea; -import javax.swing.JApplet; -import javax.swing.JOptionPane; - -import jdk.test.lib.Platform; - -/** - * @test - * @bug 8024926 8040279 - * @summary [macosx] AquaIcon HiDPI support - * @author Alexander Scherbatiy - * @library /test/lib - * @build jdk.test.lib.Platform - * @run applet/manual=yesno bug8024926.html - */ -public class bug8024926 extends JApplet { - //Declare things used in the test, like buttons and labels here - - public void init() { - //Create instructions for the user here, as well as set up - // the environment -- set the layout manager, add buttons, - // etc. - this.setLayout(new BorderLayout()); - - - if (Platform.isOSX()) { - String[] instructions = { - "Verify that high resolution system icons are used" - + " in JOptionPane on HiDPI displays.", - "1) Run the test on Retina display or enable the Quartz Debug" - + " and select the screen resolution with (HiDPI) label", - "2) Check that the error icon on the JOptionPane is smooth", - "If so, press PASS, else press FAIL." - }; - Sysout.createDialogWithInstructions(instructions); - - } else { - String[] instructions = { - "This test is not applicable to the current platform. Press PASS." - }; - Sysout.createDialogWithInstructions(instructions); - } - - - }//End init() - - public void start() { - //Get things going. Request focus, set size, et cetera - setSize(200, 200); - setVisible(true); - validate(); - EventQueue.invokeLater(new Runnable() { - - public void run() { - createAndShowGUI(); - } - }); - }// start() - - //The rest of this class is the actions which perform the test... - //Use Sysout.println to communicate with the user NOT System.out!! - //Sysout.println ("Something Happened!"); - private static void createAndShowGUI() { - JOptionPane.showMessageDialog(null, - "Icons should have high resolution.", - "High resolution icon test.", - JOptionPane.ERROR_MESSAGE); - } -}// class BlockedWindowTest - -/* Place other classes related to the test after this line */ -/** - * ************************************************** - * Standard Test Machinery DO NOT modify anything below -- it's a standard chunk - * of code whose purpose is to make user interaction uniform, and thereby make - * it simpler to read and understand someone else's test. - * ************************************************** - */ -/** - * This is part of the standard test machinery. It creates a dialog (with the - * instructions), and is the interface for sending text messages to the user. To - * print the instructions, send an array of strings to Sysout.createDialog - * WithInstructions method. Put one line of instructions per array entry. To - * display a message for the tester to see, simply call Sysout.println with the - * string to be displayed. This mimics System.out.println but works within the - * test harness as well as standalone. - */ -class Sysout { - - private static TestDialog dialog; - - public static void createDialogWithInstructions(String[] instructions) { - dialog = new TestDialog(new Frame(), "Instructions"); - dialog.printInstructions(instructions); - dialog.setVisible(true); - println("Any messages for the tester will display here."); - } - - public static void createDialog() { - dialog = new TestDialog(new Frame(), "Instructions"); - String[] defInstr = {"Instructions will appear here. ", ""}; - dialog.printInstructions(defInstr); - dialog.setVisible(true); - println("Any messages for the tester will display here."); - } - - public static void printInstructions(String[] instructions) { - dialog.printInstructions(instructions); - } - - public static void println(String messageIn) { - dialog.displayMessage(messageIn); - } -}// Sysout class - -/** - * This is part of the standard test machinery. It provides a place for the test - * instructions to be displayed, and a place for interactive messages to the - * user to be displayed. To have the test instructions displayed, see Sysout. To - * have a message to the user be displayed, see Sysout. Do not call anything in - * this dialog directly. - */ -class TestDialog extends Dialog { - - TextArea instructionsText; - TextArea messageText; - int maxStringLength = 80; - - //DO NOT call this directly, go through Sysout - public TestDialog(Frame frame, String name) { - super(frame, name); - int scrollBoth = TextArea.SCROLLBARS_BOTH; - instructionsText = new TextArea("", 15, maxStringLength, scrollBoth); - add("North", instructionsText); - - messageText = new TextArea("", 5, maxStringLength, scrollBoth); - add("Center", messageText); - - pack(); - - setVisible(true); - }// TestDialog() - - //DO NOT call this directly, go through Sysout - public void printInstructions(String[] instructions) { - //Clear out any current instructions - instructionsText.setText(""); - - //Go down array of instruction strings - - String printStr, remainingStr; - for (int i = 0; i < instructions.length; i++) { - //chop up each into pieces maxSringLength long - remainingStr = instructions[ i]; - while (remainingStr.length() > 0) { - //if longer than max then chop off first max chars to print - if (remainingStr.length() >= maxStringLength) { - //Try to chop on a word boundary - int posOfSpace = remainingStr.lastIndexOf(' ', maxStringLength - 1); - - if (posOfSpace <= 0) { - posOfSpace = maxStringLength - 1; - } - - printStr = remainingStr.substring(0, posOfSpace + 1); - remainingStr = remainingStr.substring(posOfSpace + 1); - } //else just print - else { - printStr = remainingStr; - remainingStr = ""; - } - - instructionsText.append(printStr + "\n"); - - }// while - - }// for - - }//printInstructions() - - //DO NOT call this directly, go through Sysout - public void displayMessage(String messageIn) { - messageText.append(messageIn + "\n"); - System.out.println(messageIn); - } -}// TestDialog class diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JOptionPane/bug4174551.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JOptionPane/bug4174551.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JOptionPane/bug4174551.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JOptionPane/bug4174551.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4174551 + * @summary JOptionPane should allow custom buttons + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4174551 + */ +import java.awt.FlowLayout; +import java.awt.Font; +import javax.swing.JDialog; +import javax.swing.JOptionPane; +import javax.swing.UIManager; + +public class bug4174551 { + private static final String INSTRUCTIONS = """ + Two Message Dialog should pop up side-by-side + one with a custom message font size 24 with message "HI 24" + and another with default optionpane message font size with message "HI default" + If custom message font size is not more than default message fontsize + AND + custom message buttonfont size is more than default message buttonfont size + press "Fail" else press "Pass". """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("JOptionPane Instructions") + .instructions(INSTRUCTIONS) + .rows(8) + .columns(40) + .testUI(bug4174551::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JDialog createTestUI() { + JOptionPane defaultPane = new JOptionPane(); + defaultPane.setMessage("HI default"); + defaultPane.setMessageType(JOptionPane.INFORMATION_MESSAGE); + UIManager.getDefaults().put("OptionPane.buttonFont", new Font("Dialog", Font.PLAIN, 10)); + UIManager.getDefaults().put("OptionPane.messageFont", new Font("Dialog", Font.PLAIN, 24)); + JOptionPane optionPane = new JOptionPane(); + optionPane.setMessage("HI 24!"); + optionPane.setMessageType(JOptionPane.INFORMATION_MESSAGE); + JDialog dialog = new JDialog(); + dialog.setLayout(new FlowLayout()); + dialog.add(optionPane); + dialog.add(defaultPane); + dialog.pack(); + + System.out.println(UIManager.getDefaults().get("OptionPane.buttonFont")); + System.out.println(UIManager.getDefaults().get("OptionPane.messageFont")); + return dialog; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JOptionPane/bug8024926.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JOptionPane/bug8024926.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JOptionPane/bug8024926.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JOptionPane/bug8024926.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.awt.BorderLayout; +import java.awt.Dialog; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.TextArea; +import javax.swing.JDialog; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; + +/** + * @test + * @bug 8024926 8040279 + * @requires (os.family == "mac") + * @summary [macosx] AquaIcon HiDPI support + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug8024926 + */ +public class bug8024926 { + + private static final String INSTRUCTIONS = """ + Verify that high resolution system icons are used + in JOptionPane on HiDPI displays. + 1) Run the test on Retina display or enable the Quartz Debug + and select the screen resolution with (HiDPI) label. + "2) Check that the error icon on the JOptionPane is smooth. + "If so, press PASS, else press FAIL."""; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("AquaIcon HIDPI Instructions") + .instructions(INSTRUCTIONS) + .rows(10) + .columns(35) + .testUI(bug8024926::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JDialog createTestUI() { + JOptionPane optionPane = new JOptionPane("High resolution icon test"); + optionPane.setMessage("Icons should have high resolutions"); + optionPane.setMessageType(JOptionPane.ERROR_MESSAGE); + JDialog dialog = new JDialog(); + dialog.setContentPane(optionPane); + dialog.pack(); + return dialog; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JPopupMenu/7160604/bug7160604.html openjdk-21-21.0.9+10/test/jdk/javax/swing/JPopupMenu/7160604/bug7160604.html --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JPopupMenu/7160604/bug7160604.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JPopupMenu/7160604/bug7160604.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ - - - - - -Click on the top-bar and combo-box more than once. -Make sure popup menu and drop-down list have a border and their items are drawn properly. - - diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JPopupMenu/7160604/bug7160604.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JPopupMenu/7160604/bug7160604.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JPopupMenu/7160604/bug7160604.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JPopupMenu/7160604/bug7160604.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* @test - @bug 7160604 - @summary Using non-opaque windows - popups are initially not painted correctly - @author Oleg Pekhovskiy - @run applet/manual=yesno bug7160604.html -*/ - -import javax.swing.AbstractAction; -import javax.swing.BorderFactory; -import javax.swing.JApplet; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JWindow; -import javax.swing.SwingUtilities; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import static java.awt.GraphicsDevice.WindowTranslucency.*; - -public class bug7160604 extends JApplet { - - public void init() { - SwingUtilities.invokeLater(() -> { - if (!GraphicsEnvironment - .getLocalGraphicsEnvironment() - .getDefaultScreenDevice() - .isWindowTranslucencySupported(PERPIXEL_TRANSLUCENT)) { - // Tested translucency is not supported. Test passed - return; - } - - final JWindow window = new JWindow(); - window.setLocation(200, 200); - window.setSize(300, 300); - - final JLabel label = new JLabel("...click to invoke JPopupMenu"); - label.setOpaque(true); - final JPanel contentPane = new JPanel(new BorderLayout()); - contentPane.setBorder(BorderFactory.createLineBorder(Color.RED)); - window.setContentPane(contentPane); - contentPane.add(label, BorderLayout.NORTH); - - final JComboBox comboBox = new JComboBox(new Object[]{"1", "2", "3", "4"}); - contentPane.add(comboBox, BorderLayout.SOUTH); - - final JPopupMenu jPopupMenu = new JPopupMenu(); - - jPopupMenu.add("string"); - jPopupMenu.add(new AbstractAction("action") { - @Override - public void actionPerformed(final ActionEvent e) { - } - }); - jPopupMenu.add(new JLabel("label")); - jPopupMenu.add(new JMenuItem("MenuItem")); - label.addMouseListener(new MouseAdapter() { - @Override - public void mouseReleased(final MouseEvent e) { - jPopupMenu.show(label, 0, 0); - } - }); - - window.setBackground(new Color(0, 0, 0, 0)); - - window.setVisible(true); - }); - } -} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JPopupMenu/bug7160604.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JPopupMenu/bug7160604.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JPopupMenu/bug7160604.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JPopupMenu/bug7160604.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7160604 + * @summary Using non-opaque windows - popups are initially not painted correctly + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug7160604 +*/ +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.GraphicsEnvironment; +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import static java.awt.GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT; +import javax.swing.AbstractAction; +import javax.swing.BorderFactory; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JWindow; +import javax.swing.SwingUtilities; + +public class bug7160604 { + + private static final String INSTRUCTIONS = """ + Click on the top-bar and combo-box at the bottom more than once. + Check top-bar popup menu and combo-box drop-down list have a border + and their items are drawn properly. + If yes, Click Pass else click Fail."""; + + public static void main(String[] args) throws Exception { + if (!GraphicsEnvironment + .getLocalGraphicsEnvironment() + .getDefaultScreenDevice() + .isWindowTranslucencySupported(PERPIXEL_TRANSLUCENT)) { + // Tested translucency is not supported. Test passed + return; + } + PassFailJFrame.builder() + .title("PopupMenu Instructions") + .instructions(INSTRUCTIONS) + .rows(5) + .columns(35) + .testUI(bug7160604::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JWindow createTestUI() { + + final JWindow window = new JWindow(); + window.setLocation(200, 200); + window.setSize(300, 300); + + final JLabel label = new JLabel("...click to invoke JPopupMenu"); + label.setOpaque(true); + final JPanel contentPane = new JPanel(new BorderLayout()); + contentPane.setBorder(BorderFactory.createLineBorder(Color.RED)); + window.setContentPane(contentPane); + contentPane.add(label, BorderLayout.NORTH); + + final JComboBox comboBox = new JComboBox(new Object[]{"1", "2", "3", "4"}); + contentPane.add(comboBox, BorderLayout.SOUTH); + + final JPopupMenu jPopupMenu = new JPopupMenu(); + + jPopupMenu.add("string"); + jPopupMenu.add(new AbstractAction("action") { + @Override + public void actionPerformed(final ActionEvent e) { + } + }); + jPopupMenu.add(new JLabel("label")); + jPopupMenu.add(new JMenuItem("MenuItem")); + label.addMouseListener(new MouseAdapter() { + @Override + public void mouseReleased(final MouseEvent e) { + jPopupMenu.show(label, 0, 0); + } + }); + + window.setBackground(new Color(0, 0, 0, 0)); + + return window; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JRadioButton/8033699/bug8033699.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JRadioButton/8033699/bug8033699.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JRadioButton/8033699/bug8033699.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JRadioButton/8033699/bug8033699.java 2025-10-13 07:49:24.000000000 +0000 @@ -35,17 +35,16 @@ import java.awt.event.KeyEvent; import javax.swing.BorderFactory; -import javax.swing.BoxLayout; +import javax.swing.Box; import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JFrame; -import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.SwingUtilities; import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; public class bug8033699 { - private static JFrame mainFrame; private static Robot robot; private static JButton btnStart; @@ -55,77 +54,101 @@ private static JRadioButton radioBtn2; private static JRadioButton radioBtn3; private static JRadioButton radioBtnSingle; + private static KeyboardFocusManager focusManager; public static void main(String[] args) throws Throwable { - SwingUtilities.invokeAndWait(() -> { - changeLAF(); - createAndShowGUI(); - }); - robot = new Robot(); - robot.waitForIdle(); - robot.delay(1000); - // tab key test grouped radio button - runTest1(); - robot.delay(100); - - // tab key test non-grouped radio button - runTest2(); - robot.delay(100); - - // shift tab key test grouped and non-grouped radio button - runTest3(); - robot.delay(100); - - // left/up key test in grouped radio button - runTest4(); - robot.delay(100); - - // down/right key test in grouped radio button - runTest5(); - robot.delay(100); - - // tab from radio button in group to next component in the middle of button group layout - runTest6(); - robot.delay(100); - - // tab to radio button in group from component in the middle of button group layout - runTest7(); - robot.delay(100); - - // down key circle back to first button in grouped radio button - runTest8(); - robot.delay(100); - - // Verify that ActionListener is called when a RadioButton is selected using arrow key. - runTest9(); - robot.delay(100); - - SwingUtilities.invokeAndWait(() -> mainFrame.dispose()); - } - - private static void changeLAF() { - String currentLAF = UIManager.getLookAndFeel().toString(); - System.out.println(currentLAF); - currentLAF = currentLAF.toLowerCase(); - if (currentLAF.contains("nimbus")) { - try { - UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); - } catch (Exception ex) { - ex.printStackTrace(); - } + SwingUtilities.invokeAndWait(() -> + focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager()); + + UIManager.LookAndFeelInfo[] lafs = UIManager.getInstalledLookAndFeels(); + for (UIManager.LookAndFeelInfo laf : lafs) { + testLaF(laf); + } + } + + private static void testLaF(UIManager.LookAndFeelInfo laf) throws Exception { + try { + System.out.println("Testing LaF: " + laf.getName()); + SwingUtilities.invokeAndWait(() -> { + setLookAndFeel(laf); + createAndShowGUI(); + }); + + robot.waitForIdle(); + robot.delay(1000); + + // tab key test grouped radio button + runTest1(); + robot.delay(100); + + // tab key test non-grouped radio button + runTest2(); + robot.delay(100); + + // shift tab key test grouped and non-grouped radio button + runTest3(); + robot.delay(100); + + // left/up key test in grouped radio button + runTest4(); + robot.delay(100); + + // down/right key test in grouped radio button + runTest5(); + robot.delay(100); + + // tab from radio button in group to next component in the middle of + // button group layout + runTest6(); + robot.delay(100); + + // tab to radio button in group from component in the middle of + // button group layout + runTest7(); + robot.delay(100); + + // down key circle back to first button in grouped radio button + runTest8(); + robot.delay(100); + + // Verify that ActionListener is called when a RadioButton is + // selected using arrow key + runTest9(); + robot.delay(100); + } catch (Exception e) { + Throwable cause = e.getCause(); + throw new RuntimeException("Error testing LaF: " + laf.getName() + + (cause != null ? " - " + cause.getMessage() : ""), + e); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (mainFrame != null) { + mainFrame.dispose(); + mainFrame = null; + } + }); + } + } + + private static void setLookAndFeel(UIManager.LookAndFeelInfo laf) { + try { + UIManager.setLookAndFeel(laf.getClassName()); + } catch (ClassNotFoundException | InstantiationException | + IllegalAccessException | UnsupportedLookAndFeelException e) { + System.err.println("Error setting LaF: " + laf.getName()); + throw new RuntimeException("Failed to set look and feel", e); } } private static void createAndShowGUI() { - mainFrame = new JFrame("Bug 8033699 - 8 Tests for Grouped/Non Group Radio Buttons"); + mainFrame = new JFrame("Radio Button Focus Tests"); btnStart = new JButton("Start"); btnEnd = new JButton("End"); btnMiddle = new JButton("Middle"); - JPanel box = new JPanel(); - box.setLayout(new BoxLayout(box, BoxLayout.Y_AXIS)); + Box box = Box.createVerticalBox(); box.setBorder(BorderFactory.createTitledBorder("Grouped Radio Buttons")); radioBtn1 = new JRadioButton("A"); radioBtn2 = new JRadioButton("B"); @@ -145,16 +168,17 @@ radioBtnSingle = new JRadioButton("Not Grouped"); radioBtnSingle.setSelected(true); - mainFrame.getContentPane().add(btnStart); - mainFrame.getContentPane().add(box); - mainFrame.getContentPane().add(radioBtnSingle); - mainFrame.getContentPane().add(btnEnd); + Box mainBox = Box.createVerticalBox(); + mainBox.add(btnStart); + mainBox.add(box); + mainBox.add(radioBtnSingle); + mainBox.add(btnEnd); + mainFrame.add(mainBox); mainFrame.getRootPane().setDefaultButton(btnStart); btnStart.requestFocus(); mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - mainFrame.setLayout(new BoxLayout(mainFrame.getContentPane(), BoxLayout.Y_AXIS)); mainFrame.setSize(300, 300); mainFrame.setLocationRelativeTo(null); @@ -169,33 +193,41 @@ hitKey(KeyEvent.VK_TAB); SwingUtilities.invokeAndWait(() -> { - if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtnSingle) { - System.out.println("Radio Button Group Go To Next Component through Tab Key failed"); - throw new RuntimeException("Focus is not on Radio Button Single as Expected"); + if (focusManager.getFocusOwner() != radioBtnSingle) { + System.out.println("Radio Button Group Go To " + + "Next Component through Tab Key failed"); + throw new RuntimeException("Focus is not on " + + "Radio Button Single as Expected"); } }); } - // Non-Grouped Radio button as a single component when traversing through tab key + // Non-Grouped Radio button as a single component when traversing through + // tab key private static void runTest2() throws Exception { hitKey(KeyEvent.VK_TAB); SwingUtilities.invokeAndWait(() -> { - if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != btnEnd) { - System.out.println("Non Grouped Radio Button Go To Next Component through Tab Key failed"); - throw new RuntimeException("Focus is not on Button End as Expected"); + if (focusManager.getFocusOwner() != btnEnd) { + System.out.println("Non Grouped Radio Button Go To " + + "Next Component through Tab Key failed"); + throw new RuntimeException("Focus is not on Button End " + + "as Expected"); } }); } - // Non-Grouped Radio button and Group Radio button as a single component when traversing through shift-tab key + // Non-Grouped Radio button and Group Radio button as a single component + // when traversing through shift-tab key private static void runTest3() throws Exception { hitKey(KeyEvent.VK_SHIFT, KeyEvent.VK_TAB); hitKey(KeyEvent.VK_SHIFT, KeyEvent.VK_TAB); hitKey(KeyEvent.VK_SHIFT, KeyEvent.VK_TAB); SwingUtilities.invokeAndWait(() -> { - if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtn1) { - System.out.println("Radio button Group/Non Grouped Radio Button SHIFT-Tab Key Test failed"); - throw new RuntimeException("Focus is not on Radio Button A as Expected"); + if (focusManager.getFocusOwner() != radioBtn1) { + System.out.println("Radio button Group/Non Grouped " + + "Radio Button SHIFT-Tab Key Test failed"); + throw new RuntimeException("Focus is not on Radio Button A " + + "as Expected"); } }); } @@ -205,9 +237,11 @@ hitKey(KeyEvent.VK_DOWN); hitKey(KeyEvent.VK_RIGHT); SwingUtilities.invokeAndWait(() -> { - if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtn3) { - System.out.println("Radio button Group UP/LEFT Arrow Key Move Focus Failed"); - throw new RuntimeException("Focus is not on Radio Button C as Expected"); + if (focusManager.getFocusOwner() != radioBtn3) { + System.out.println("Radio button Group UP/LEFT Arrow Key " + + "Move Focus Failed"); + throw new RuntimeException("Focus is not on Radio Button C " + + "as Expected"); } }); } @@ -216,9 +250,11 @@ hitKey(KeyEvent.VK_UP); hitKey(KeyEvent.VK_LEFT); SwingUtilities.invokeAndWait(() -> { - if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtn1) { - System.out.println("Radio button Group Left/Up Arrow Key Move Focus Failed"); - throw new RuntimeException("Focus is not on Radio Button A as Expected"); + if (focusManager.getFocusOwner() != radioBtn1) { + System.out.println("Radio button Group Left/Up Arrow Key " + + "Move Focus Failed"); + throw new RuntimeException("Focus is not on Radio Button A " + + "as Expected"); } }); } @@ -227,9 +263,11 @@ hitKey(KeyEvent.VK_UP); hitKey(KeyEvent.VK_UP); SwingUtilities.invokeAndWait(() -> { - if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtn2) { - System.out.println("Radio button Group Circle Back To First Button Test"); - throw new RuntimeException("Focus is not on Radio Button B as Expected"); + if (focusManager.getFocusOwner() != radioBtn2) { + System.out.println("Radio button Group Circle Back To " + + "First Button Test"); + throw new RuntimeException("Focus is not on Radio Button B " + + "as Expected"); } }); } @@ -237,9 +275,11 @@ private static void runTest7() throws Exception { hitKey(KeyEvent.VK_TAB); SwingUtilities.invokeAndWait(() -> { - if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != btnMiddle) { - System.out.println("Separate Component added in button group layout"); - throw new RuntimeException("Focus is not on Middle Button as Expected"); + if (focusManager.getFocusOwner() != btnMiddle) { + System.out.println("Separate Component added in" + + " button group layout"); + throw new RuntimeException("Focus is not on Middle Button" + + " as Expected"); } }); } @@ -247,18 +287,21 @@ private static void runTest8() throws Exception { hitKey(KeyEvent.VK_TAB); SwingUtilities.invokeAndWait(() -> { - if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtnSingle) { - System.out.println("Separate Component added in button group layout"); - throw new RuntimeException("Focus is not on Radio Button Single as Expected"); + if (focusManager.getFocusOwner() != radioBtnSingle) { + System.out.println("Separate Component added in" + + " button group layout"); + throw new RuntimeException("Focus is not on Radio Button Single" + + " as Expected"); } }); } - private static boolean actRB1 = false; - private static boolean actRB2 = false; - private static boolean actRB3 = false; + private static volatile boolean actRB1 = false; + private static volatile boolean actRB2 = false; + private static volatile boolean actRB3 = false; - // JDK-8226892: Verify that ActionListener is called when a RadioButton is selected using arrow key. + // JDK-8226892: Verify that ActionListener is called when a RadioButton + // is selected using arrow key private static void runTest9() throws Exception { SwingUtilities.invokeAndWait(() -> { radioBtn1.setSelected(true); @@ -269,15 +312,19 @@ ActionListener actLrRB2 = e -> actRB2 = true; ActionListener actLrRB3 = e -> actRB3 = true; - radioBtn1.addActionListener(actLrRB1); - radioBtn2.addActionListener(actLrRB2); - radioBtn3.addActionListener(actLrRB3); + // Adding Action Listeners + SwingUtilities.invokeAndWait(() -> { + radioBtn1.addActionListener(actLrRB1); + radioBtn2.addActionListener(actLrRB2); + radioBtn3.addActionListener(actLrRB3); + }); hitKey(KeyEvent.VK_DOWN); hitKey(KeyEvent.VK_DOWN); hitKey(KeyEvent.VK_DOWN); - String failMessage = "ActionListener not invoked when selected using arrow key."; + String failMessage = "ActionListener not invoked when selected using " + + "arrow key."; if (!actRB2) { throw new RuntimeException("RadioButton 2: " + failMessage); } @@ -288,9 +335,12 @@ throw new RuntimeException("RadioButton 1: " + failMessage); } - radioBtn1.removeActionListener(actLrRB1); - radioBtn2.removeActionListener(actLrRB2); - radioBtn3.removeActionListener(actLrRB3); + // Removing Action Listeners + SwingUtilities.invokeAndWait(() -> { + radioBtn1.removeActionListener(actLrRB1); + radioBtn2.removeActionListener(actLrRB2); + radioBtn3.removeActionListener(actLrRB3); + }); } private static void hitKey(int keycode) { diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JScrollBar/8039464/Test8039464.html openjdk-21-21.0.9+10/test/jdk/javax/swing/JScrollBar/8039464/Test8039464.html --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JScrollBar/8039464/Test8039464.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JScrollBar/8039464/Test8039464.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ - - - - -Choose the variable applet size and try to resize the applet. -The test passes the thumb is painted correctly. - - - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JScrollBar/8039464/Test8039464.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JScrollBar/8039464/Test8039464.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JScrollBar/8039464/Test8039464.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JScrollBar/8039464/Test8039464.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2014, 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.Container; -import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; - -import javax.swing.JApplet; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JScrollBar; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; - -/* - * @test - * @bug 8039464 - * @summary Tests enabling/disabling of titled border's caption - * @author Sergey Malenkov - * @run applet/manual=yesno Test8039464.html - */ - -public class Test8039464 extends JApplet { - static { - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } catch (Exception exception) { - throw new Error("unexpected", exception); - } - } - - @Override - public void init() { - init(this); - } - - private static void init(Container container) { - container.setLayout(new GridBagLayout()); - GridBagConstraints gbc = new GridBagConstraints(); - gbc.fill = GridBagConstraints.BOTH; - gbc.gridx = 0; - gbc.gridy = 1; - JLabel label = new JLabel(); - Dimension size = new Dimension(111, 0); - label.setPreferredSize(size); - label.setMinimumSize(size); - container.add(label, gbc); - gbc.gridx = 1; - gbc.weightx = 1; - container.add(new JScrollBar(JScrollBar.HORIZONTAL, 1, 111, 1, 1111), gbc); - gbc.gridx = 2; - gbc.gridy = 0; - gbc.weightx = 0; - gbc.weighty = 1; - container.add(new JScrollBar(JScrollBar.VERTICAL, 1, 111, 1, 1111), gbc); - } - - public static void main(String[] args) throws Exception { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - JFrame frame = new JFrame("8039464"); - init(frame); - frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - frame.pack(); - frame.setLocationRelativeTo(null); - frame.setVisible(true); - } - }); - } -} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JScrollBar/Test8039464.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JScrollBar/Test8039464.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JScrollBar/Test8039464.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JScrollBar/Test8039464.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Container; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; + +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JScrollBar; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +/* + * @test + * @bug 8039464 + * @summary Tests enabling/disabling of titled border's caption + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual Test8039464 + */ + +public class Test8039464 { + private static final String INSTRUCTIONS = """ + If the scrollbar thumb is painted correctly in system lookandfeel + click Pass else click Fail. """; + + static { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception exception) { + throw new Error("unexpected", exception); + } + } + + private static void init(Container container) { + container.setLayout(new GridBagLayout()); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.fill = GridBagConstraints.BOTH; + gbc.gridx = 0; + gbc.gridy = 1; + JLabel label = new JLabel(); + Dimension size = new Dimension(111, 0); + label.setPreferredSize(size); + label.setMinimumSize(size); + container.add(label, gbc); + gbc.gridx = 1; + gbc.weightx = 1; + container.add(new JScrollBar(JScrollBar.HORIZONTAL, 1, 111, 1, 1111), gbc); + gbc.gridx = 2; + gbc.gridy = 0; + gbc.weightx = 0; + gbc.weighty = 1; + container.add(new JScrollBar(JScrollBar.VERTICAL, 1, 111, 1, 1111), gbc); + } + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("JScrollBar Instructions") + .instructions(INSTRUCTIONS) + .rows(5) + .columns(35) + .testUI(Test8039464::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI() { + JFrame frame = new JFrame("8039464"); + init(frame); + frame.pack(); + return frame; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JSlider/4987336/bug4987336.html openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/4987336/bug4987336.html --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JSlider/4987336/bug4987336.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/4987336/bug4987336.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ - - - - - -There are four Sliders. Each of them has a label with animated gif (a waving duke) -and a label with static image. - -Check that for every LAF animation works for all Sliders. - - diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JSlider/4987336/bug4987336.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/4987336/bug4987336.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JSlider/4987336/bug4987336.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/4987336/bug4987336.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,25 +21,58 @@ * questions. */ -/* @test - @bug 4987336 - @summary JSlider doesn't show label's animated icon. - @author Pavel Porvatov - @run applet/manual=done bug4987336.html +/* + * @test + * @bug 4987336 + * @summary JSlider doesn't show label's animated icon. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4987336 */ - -import javax.swing.*; -import javax.swing.border.TitledBorder; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import javax.swing.ButtonGroup; +import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JScrollPane; +import javax.swing.JSlider; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.border.TitledBorder; import java.util.Hashtable; -public class bug4987336 extends JApplet { +public class bug4987336 { + private static final String INSTRUCTIONS = """ + There are four Sliders. + Each of them has a label with animated gif (a waving duke) + and a label with static image. + If it is rendered correctly, click Pass else click Fail."""; + private static final String IMAGE_RES = "box.gif"; private static final String ANIM_IMAGE_RES = "duke.gif"; + private static JFrame frame; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("Slider rendering Instructions") + .instructions(INSTRUCTIONS) + .rows(5) + .columns(35) + .testUI(bug4987336::createTestUI) + .position(PassFailJFrame.Position.TOP_LEFT_CORNER) + .build() + .awaitAndCheck(); + } - public void init() { + private static JFrame createTestUI() { + frame = new JFrame("bug4987336"); JPanel pnLafs = new JPanel(); pnLafs.setLayout(new BoxLayout(pnLafs, BoxLayout.Y_AXIS)); @@ -64,7 +97,9 @@ pnContent.add(createSlider(true, ANIM_IMAGE_RES, null, IMAGE_RES, IMAGE_RES)); pnContent.add(createSlider(false, ANIM_IMAGE_RES, null, IMAGE_RES, IMAGE_RES)); - getContentPane().add(new JScrollPane(pnContent)); + frame.getContentPane().add(new JScrollPane(pnContent)); + frame.pack(); + return frame; } private static JSlider createSlider(boolean enabled, @@ -99,7 +134,7 @@ return result; } - private class LafRadioButton extends JRadioButton { + private static class LafRadioButton extends JRadioButton { public LafRadioButton(final UIManager.LookAndFeelInfo lafInfo) { super(lafInfo.getName(), lafInfo.getName().equals(UIManager.getLookAndFeel().getName())); @@ -108,7 +143,7 @@ try { UIManager.setLookAndFeel(lafInfo.getClassName()); - SwingUtilities.updateComponentTreeUI(bug4987336.this); + SwingUtilities.updateComponentTreeUI(frame); } catch (Exception ex) { // Ignore such errors System.out.println("Cannot set LAF " + lafInfo.getName()); diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JSlider/6587742/bug6587742.html openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/6587742/bug6587742.html --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JSlider/6587742/bug6587742.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/6587742/bug6587742.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ - - - - - -Select every theme and check that all sliders looks good. -Note that every slider has a tooltip text with information about -slider configuration. -There is a small difference in sliders with property "filled = null" (it's -default behaviour when property JSlider.isFilled is not setted) -for themes: -1. OceanTheme - sliders look like filled -2. DefaultMetalTheme - sliders look like NOT filled - - diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JSlider/6587742/bug6587742.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/6587742/bug6587742.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JSlider/6587742/bug6587742.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/6587742/bug6587742.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* @test - * @bug 6587742 - * @summary filling half of a JSlider's track is no longer optional - * @author Pavel Porvatov - * @run applet/manual=done bug6587742.html - */ - -import javax.swing.*; -import javax.swing.plaf.metal.DefaultMetalTheme; -import javax.swing.plaf.metal.MetalLookAndFeel; -import javax.swing.plaf.metal.MetalTheme; -import javax.swing.plaf.metal.OceanTheme; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; - -public class bug6587742 extends JApplet { - public void init() { - TestPanel panel = new TestPanel(); - - setContentPane(panel); - } - - private class TestPanel extends JPanel { - private final JComboBox cbThemes = new JComboBox(); - - private TestPanel() { - // Fill cbThemes - cbThemes.addItem(new OceanTheme()); - cbThemes.addItem(new DefaultMetalTheme()); - - cbThemes.addItemListener(new ItemListener() { - public void itemStateChanged(ItemEvent e) { - MetalTheme theme = (MetalTheme) cbThemes.getSelectedItem(); - - if (theme != null) { - MetalLookAndFeel.setCurrentTheme(theme); - - // re-install the Metal Look and Feel - try { - UIManager.setLookAndFeel(new MetalLookAndFeel()); - } catch (UnsupportedLookAndFeelException e1) { - JOptionPane.showMessageDialog(TestPanel.this, "Can't change theme: " + e1.getMessage(), - "Error", JOptionPane.ERROR_MESSAGE); - - return; - } - - SwingUtilities.updateComponentTreeUI(bug6587742.this); - } - } - }); - - JPanel pnVertical = new JPanel(); - - pnVertical.setLayout(new BoxLayout(pnVertical, BoxLayout.Y_AXIS)); - - for (int i = 0; i < 12; i++) { - int filled = i >> 2; - - pnVertical.add(createSlider(false, filled > 1 ? null : Boolean.valueOf(filled == 1), (i & 2) == 0, - (i & 1) != 0)); - } - - JPanel pnHorizontal = new JPanel(); - - pnHorizontal.setLayout(new BoxLayout(pnHorizontal, BoxLayout.X_AXIS)); - - for (int i = 0; i < 12; i++) { - int filled = i >> 2; - - pnHorizontal.add(createSlider(true, filled > 1 ? null : Boolean.valueOf(filled == 1), (i & 2) == 0, - (i & 1) != 0)); - } - - JTabbedPane tpSliders = new JTabbedPane(); - - tpSliders.add("Vertical sliders", pnVertical); - tpSliders.add("Horizontal sliders", pnHorizontal); - - setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); - - add(new JLabel("Select theme:")); - add(cbThemes); - add(tpSliders); - } - } - - private static JSlider createSlider(boolean vertical, Boolean filled, boolean enabled, boolean inverted) { - JSlider result = new JSlider(vertical ? SwingConstants.VERTICAL : SwingConstants.HORIZONTAL, 0, 100, 50); - - result.setMajorTickSpacing(20); - result.setMinorTickSpacing(5); - result.setPaintTicks(true); - result.setPaintLabels(true); - result.setEnabled(enabled); - - if (filled != null) { - result.putClientProperty("JSlider.isFilled", filled); - } - - result.setInverted(inverted); - result.setToolTipText("vertical = " + vertical + "
enabled = " + enabled + "
filled = " + filled + - "
inverted = " + inverted + ""); - - return result; - } -} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JSlider/6742358/bug6742358.html openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/6742358/bug6742358.html --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JSlider/6742358/bug6742358.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/6742358/bug6742358.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ - - - - - -Check that all sliders look good. - - diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JSlider/6742358/bug6742358.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/6742358/bug6742358.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JSlider/6742358/bug6742358.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/6742358/bug6742358.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* @test - * @bug 6742358 - * @summary MetalSliderUI paint wrong vertical disabled filled JSlider for DefaultMetalTheme - * @author Pavel Porvatov - * @run applet/manual=done bug6742358.html - */ - -import javax.swing.*; -import javax.swing.plaf.metal.DefaultMetalTheme; -import javax.swing.plaf.metal.MetalLookAndFeel; - -public class bug6742358 extends JApplet { - public static void main(String[] args) { - MetalLookAndFeel.setCurrentTheme(new DefaultMetalTheme()); - - JFrame frame = new JFrame(); - - frame.setContentPane(new TestPanel()); - frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - frame.pack(); - frame.setLocationRelativeTo(null); - - frame.setVisible(true); - } - - public void init() { - MetalLookAndFeel.setCurrentTheme(new DefaultMetalTheme()); - - TestPanel panel = new TestPanel(); - - setContentPane(panel); - } - - private static class TestPanel extends JPanel { - - private TestPanel() { - JPanel pnVertical = new JPanel(); - - pnVertical.setLayout(new BoxLayout(pnVertical, BoxLayout.Y_AXIS)); - - for (int i = 0; i < 8; i++) { - pnVertical.add(createSlider(false, (i & 4) == 0, (i & 2) == 0, (i & 1) == 0)); - } - - JPanel pnHorizontal = new JPanel(); - - pnHorizontal.setLayout(new BoxLayout(pnHorizontal, BoxLayout.X_AXIS)); - - for (int i = 0; i < 8; i++) { - pnHorizontal.add(createSlider(true, (i & 4) == 0, (i & 2) == 0, (i & 1) == 0)); - } - - add(pnHorizontal); - add(pnVertical); - } - } - - private static JSlider createSlider(boolean vertical, boolean enabled, boolean filled, boolean inverted) { - JSlider result = new JSlider(vertical ? SwingConstants.VERTICAL : SwingConstants.HORIZONTAL, 0, 10, 5); - - result.setEnabled(enabled); - result.putClientProperty("JSlider.isFilled", filled); - result.setInverted(inverted); - result.setToolTipText("vertical = " + vertical + "
enabled = " + enabled + "
filled = " + filled + - "
inverted = " + inverted + ""); - - return result; - } -} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JSlider/bug6587742.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/bug6587742.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JSlider/bug6587742.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/bug6587742.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.BoxLayout; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JSlider; +import javax.swing.JTabbedPane; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.plaf.metal.DefaultMetalTheme; +import javax.swing.plaf.metal.MetalLookAndFeel; +import javax.swing.plaf.metal.MetalTheme; +import javax.swing.plaf.metal.OceanTheme; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +/* @test + * @bug 6587742 + * @summary filling half of a JSlider's track is no longer optional + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug6587742 + */ + +public class bug6587742 { + private static final String INSTRUCTIONS = """ + Select every theme and check that all sliders looks good. + Note that every slider has a tooltip text with information about + slider configuration. + There is a small difference in sliders with property "filled = null" (it's + default behaviour when property JSlider.isFilled is not setted) + for themes: + 1. OceanTheme - sliders look like filled + 2. DefaultMetalTheme - sliders look like NOT filled\s"""; + private static JFrame frame; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("JSlider Instructions") + .instructions(INSTRUCTIONS) + .rows(10) + .columns(40) + .testUI(bug6587742::createAndShowUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createAndShowUI() { + frame = new JFrame("Test Sliders"); + TestPanel panel = new TestPanel(); + frame.setSize(800, 600); + frame.getContentPane().add(panel); + return frame; + } + + private static class TestPanel extends JPanel { + private final JComboBox cbThemes = new JComboBox(); + + private TestPanel() { + // Fill cbThemes + cbThemes.addItem(new OceanTheme()); + cbThemes.addItem(new DefaultMetalTheme()); + + cbThemes.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + MetalTheme theme = (MetalTheme) cbThemes.getSelectedItem(); + + if (theme != null) { + MetalLookAndFeel.setCurrentTheme(theme); + + // re-install the Metal Look and Feel + try { + UIManager.setLookAndFeel(new MetalLookAndFeel()); + } catch (UnsupportedLookAndFeelException e1) { + JOptionPane.showMessageDialog(TestPanel.this, "Can't change theme: " + e1.getMessage(), + "Error", JOptionPane.ERROR_MESSAGE); + + return; + } + + SwingUtilities.updateComponentTreeUI(frame); + } + } + }); + + JPanel pnVertical = new JPanel(); + + pnVertical.setLayout(new BoxLayout(pnVertical, BoxLayout.X_AXIS)); + + for (int i = 0; i < 12; i++) { + int filled = i >> 2; + + pnVertical.add(createSlider(true, filled > 1 ? null : Boolean.valueOf(filled == 1), (i & 2) == 0, + (i & 1) != 0)); + } + + JPanel pnHorizontal = new JPanel(); + + pnHorizontal.setLayout(new BoxLayout(pnHorizontal, BoxLayout.Y_AXIS)); + + for (int i = 0; i < 12; i++) { + int filled = i >> 2; + + pnHorizontal.add(createSlider(false, filled > 1 ? null : Boolean.valueOf(filled == 1), (i & 2) == 0, + (i & 1) != 0)); + } + + JTabbedPane tpSliders = new JTabbedPane(); + + tpSliders.add("Vertical sliders", pnVertical); + tpSliders.add("Horizontal sliders", pnHorizontal); + + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + + add(new JLabel("Select theme:")); + add(cbThemes); + add(tpSliders); + } + } + + private static JSlider createSlider(boolean vertical, Boolean filled, boolean enabled, boolean inverted) { + JSlider result = new JSlider(vertical ? SwingConstants.VERTICAL : SwingConstants.HORIZONTAL, 0, 100, 50); + + result.setMajorTickSpacing(20); + result.setMinorTickSpacing(5); + result.setPaintTicks(true); + result.setPaintLabels(true); + result.setEnabled(enabled); + + if (filled != null) { + result.putClientProperty("JSlider.isFilled", filled); + } + + result.setInverted(inverted); + result.setToolTipText("vertical = " + vertical + "
enabled = " + enabled + "
filled = " + filled + + "
inverted = " + inverted + ""); + + return result; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JSlider/bug6742358.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/bug6742358.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JSlider/bug6742358.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JSlider/bug6742358.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6742358 + * @summary Verifies that painting a vertical disabled filled JSlider, the + * track will be painted correctly for DefaultMetalTheme. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug6742358 + */ + +import javax.swing.BoxLayout; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JSlider; +import javax.swing.SwingConstants; +import javax.swing.plaf.metal.DefaultMetalTheme; +import javax.swing.plaf.metal.MetalLookAndFeel; + +public class bug6742358 { + private static final String INSTRUCTIONS = """ + Check that all sliders look good."""; + + public static void main(String[] args) throws Exception { + MetalLookAndFeel.setCurrentTheme(new DefaultMetalTheme()); + PassFailJFrame.builder() + .title("JSlider Instructions") + .instructions(INSTRUCTIONS) + .rows(5) + .columns(40) + .testUI(bug6742358::createAndShowUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createAndShowUI() { + JFrame frame = new JFrame("Test Sliders"); + TestPanel panel = new TestPanel(); + frame.setSize(400, 300); + frame.getContentPane().add(panel); + return frame; + } + + private static class TestPanel extends JPanel { + + private TestPanel() { + JPanel pnVertical = new JPanel(); + + pnVertical.setLayout(new BoxLayout(pnVertical, BoxLayout.Y_AXIS)); + + for (int i = 0; i < 8; i++) { + pnVertical.add(createSlider(false, (i & 4) == 0, + (i & 2) == 0, (i & 1) == 0)); + } + + JPanel pnHorizontal = new JPanel(); + + pnHorizontal.setLayout(new BoxLayout(pnHorizontal, BoxLayout.X_AXIS)); + + for (int i = 0; i < 8; i++) { + pnHorizontal.add(createSlider(true, (i & 4) == 0, + (i & 2) == 0, (i & 1) == 0)); + } + + add(pnHorizontal); + add(pnVertical); + } + } + + private static JSlider createSlider(boolean vertical, boolean enabled, + boolean filled, boolean inverted) { + JSlider result = new JSlider(vertical ? SwingConstants.VERTICAL : SwingConstants.HORIZONTAL, + 0, 10, 5); + + result.setEnabled(enabled); + result.putClientProperty("JSlider.isFilled", filled); + result.setInverted(inverted); + result.setToolTipText("vertical = " + vertical + "
enabled = " + + enabled+ "
filled = " + filled + + "
inverted = " + inverted + ""); + + return result; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JSplitPane/4164779/JSplitPaneKeyboardNavigationTest.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JSplitPane/4164779/JSplitPaneKeyboardNavigationTest.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JSplitPane/4164779/JSplitPaneKeyboardNavigationTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JSplitPane/4164779/JSplitPaneKeyboardNavigationTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,7 +64,7 @@ public static void main(String[] s) throws Exception { robot = new Robot(); robot.setAutoWaitForIdle(true); - robot.setAutoDelay(200); + robot.setAutoDelay(100); List lafs = Arrays.stream(getInstalledLookAndFeels()) .map(LookAndFeelInfo::getClassName) .collect(Collectors.toList()); @@ -81,10 +81,13 @@ continue; } robot.waitForIdle(); + robot.delay(1000); // Press Right button 1 and move focus to it. pressButton(rightButton1); hitKeys(KeyEvent.VK_F6); + robot.waitForIdle(); + robot.delay(100); // Verifier1 - Verifies that, F6 transfers focus to the right/bottom side of the splitpane if (isFocusOwner(rightButton2)) { @@ -98,9 +101,12 @@ // Press Right button 2 and move focus to it. pressButton(rightButton2); hitKeys(KeyEvent.VK_F6); + robot.waitForIdle(); + robot.delay(100); // Verifier2 - Verifies that, F6 transfers focus to the left side of the parent splitpane, - // if the right/bottom side of splitpane already has focus, and it is contained within another splitpane + // if the right/bottom side of splitpane already has focus, + // and it is contained within another splitpane if (isFocusOwner(leftButton)) { System.out.println("Verifier 2 passed"); } else { @@ -112,6 +118,9 @@ // Press Left button and move focus to it. pressButton(leftButton); hitKeys(KeyEvent.VK_CONTROL, KeyEvent.VK_TAB); + robot.waitForIdle(); + robot.delay(100); + // Verifier3 - Verifies that, CTRL-TAB navigates forward outside the JSplitPane if (isFocusOwner(bottomButton)) { System.out.println("Verifier 3 passed"); @@ -124,6 +133,8 @@ // Press Left button and move focus to it. pressButton(leftButton); hitKeys(KeyEvent.VK_CONTROL, KeyEvent.VK_SHIFT, KeyEvent.VK_TAB); + robot.waitForIdle(); + robot.delay(100); // Verifier4 - Verifies that, CTRL-SHIFT-TAB navigates backward outside the JSplitPane if (isFocusOwner(topButton)) { @@ -137,7 +148,8 @@ if (failedVerifiers.toString().isEmpty()) { System.out.println("Test passed, All verifiers succeeded for " + laf); } else { - throw new RuntimeException("Test failed, verifiers " + failedVerifiers.toString() + " failed for " + laf); + throw new RuntimeException("Test failed, verifiers " + + failedVerifiers.toString() + " failed for " + laf); } } finally { SwingUtilities.invokeAndWait(JSplitPaneKeyboardNavigationTest::disposeFrame); @@ -159,13 +171,14 @@ loc.set(button.getLocationOnScreen()); }); final Point buttonLoc = loc.get(); - robot.mouseMove(buttonLoc.x + 8, buttonLoc.y + 8); + robot.mouseMove(buttonLoc.x + button.getWidth() / 2, + buttonLoc.y + button.getHeight() / 2); robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); } public static void createUI() { - frame = new JFrame(); + frame = new JFrame("JSplitPaneKeyboardNavigationTest"); panel = new JPanel(); panel.setLayout(new BorderLayout()); leftButton = new JButton("Left Button"); @@ -175,13 +188,14 @@ bottomButton = new JButton("Bottom Button"); panel.add(topButton, BorderLayout.NORTH); panel.add(bottomButton, BorderLayout.SOUTH); - final JSplitPane splitPane2 = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, rightButton1, rightButton2); - final JSplitPane splitPane1 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, leftButton, splitPane2); + final JSplitPane splitPane2 = new JSplitPane(JSplitPane.VERTICAL_SPLIT, + true, rightButton1, rightButton2); + final JSplitPane splitPane1 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, + true, leftButton, splitPane2); panel.add(splitPane1, BorderLayout.CENTER); frame.setContentPane(panel); frame.setSize(200, 200); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - frame.pack(); frame.setAlwaysOnTop(true); frame.setLocationRelativeTo(null); frame.setVisible(true); @@ -213,7 +227,6 @@ private static void disposeFrame() { if (frame != null) { frame.dispose(); - frame = null; } } diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JSplitPane/8132123/bug8132123.html openjdk-21-21.0.9+10/test/jdk/javax/swing/JSplitPane/8132123/bug8132123.html --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JSplitPane/8132123/bug8132123.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JSplitPane/8132123/bug8132123.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ - - - - -Verify that JSplitPane uses high-resolution system icons for the one-touch expanding -buttons on HiDPI displays. - -If the display does not support HiDPI mode press PASS. - -1. Run the test on HiDPI Display. -2. Check that the one-touch expanding buttons on the JSplitPane are painted -correctly. If so, press PASS, else press FAIL. - - - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JSplitPane/8132123/bug8132123.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JSplitPane/8132123/bug8132123.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JSplitPane/8132123/bug8132123.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JSplitPane/8132123/bug8132123.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -import java.awt.Color; -import javax.swing.JApplet; -import javax.swing.JPanel; -import javax.swing.JSplitPane; -import javax.swing.SwingUtilities; - -/* @test - * @bug 8132123 - * @summary MultiResolutionCachedImage unnecessarily creates base image - * to get its size - * @author Alexander Scherbatiy - * @run applet/manual=yesno bug8132123.html - */ -public class bug8132123 extends JApplet { - - @Override - public void init() { - SwingUtilities.invokeLater(() -> { - JPanel left = new JPanel(); - left.setBackground(Color.GRAY); - JPanel right = new JPanel(); - right.setBackground(Color.GRAY); - JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, - left, right); - splitPane.setOneTouchExpandable(true); - getContentPane().add(splitPane); - }); - } -} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JSplitPane/bug8132123.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JSplitPane/bug8132123.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JSplitPane/bug8132123.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JSplitPane/bug8132123.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.BorderLayout; +import java.awt.Color; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JSplitPane; + +/* + * @test + * @bug 8132123 + * @summary MultiResolutionCachedImage unnecessarily creates base image + * to get its size + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual/othervm -Dsun.java2d.uiScale=2 bug8132123 + */ + +public class bug8132123 { + + private static final String INSTRUCTIONS = """ + Verify that JSplitPane uses high-resolution system icons for + the one-touch expanding buttons on HiDPI displays. + + If the display does not support HiDPI mode press PASS. + + 1. Run the test on HiDPI Display. + 2. Check that the one-touch expanding buttons on the JSplitPane are painted + correctly. If so, press PASS, else press FAIL. """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("JSplitPane Instructions") + .instructions(INSTRUCTIONS) + .rows(10) + .columns(40) + .testUI(bug8132123::init) + .build() + .awaitAndCheck(); + } + + public static JFrame init() { + JFrame frame = new JFrame("Test SplitPane"); + JPanel left = new JPanel(); + left.setBackground(Color.GRAY); + JPanel right = new JPanel(); + right.setBackground(Color.GRAY); + JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, + left, right); + splitPane.setOneTouchExpandable(true); + frame.setLayout(new BorderLayout()); + frame.setSize(250, 250); + frame.getContentPane().add(splitPane); + return frame; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JTabbedPane/4666224/bug4666224.html openjdk-21-21.0.9+10/test/jdk/javax/swing/JTabbedPane/4666224/bug4666224.html --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JTabbedPane/4666224/bug4666224.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JTabbedPane/4666224/bug4666224.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ - - - - - - bug4666224 - - - -

bug4666224
Bug ID: 4666224

- -

See the dialog box (usually in upper left corner) for instructions

- - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JTabbedPane/4666224/bug4666224.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JTabbedPane/4666224/bug4666224.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JTabbedPane/4666224/bug4666224.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JTabbedPane/4666224/bug4666224.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,572 +0,0 @@ -/* - * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; -/* - * test - * @bug 4666224 -*/ - -public class bug4666224 extends JApplet { - final static int placements[] = { JTabbedPane.LEFT, JTabbedPane.RIGHT, JTabbedPane.TOP, JTabbedPane.BOTTOM }; - private JTabbedPane tabPane; - private JPanel mainPanel; - - public bug4666224() throws Exception { - java.awt.EventQueue.invokeAndWait( () -> { - tabPane = new JTabbedPane(); - tabPane.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - Point pt = e.getPoint(); - System.out.println("Index at location: " - + tabPane.indexAtLocation(pt.x, pt.y)); - } - }); - InputMap inputMap = createInputMap(); - SwingUtilities.replaceUIInputMap(getRootPane(), JComponent.WHEN_IN_FOCUSED_WINDOW, inputMap); - ActionMap actionMap = createActionMap(); - SwingUtilities.replaceUIActionMap(getRootPane(), actionMap); - - //setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - tabPane.setTabPlacement(JTabbedPane.TOP); - tabPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); - JPanel panel = new JPanel(); - panel.setPreferredSize(new Dimension(200, 300)); - tabPane.addTab("Number Zero", panel); - panel = new JPanel(); - //panel.requestFocus(); - panel.setPreferredSize(new Dimension(200, 300)); - tabPane.addTab("Number One", panel); - panel = new JPanel(); - panel.setPreferredSize(new Dimension(200, 300)); - tabPane.addTab("Number Two", panel); - panel = new JPanel(); - panel.setPreferredSize(new Dimension(200, 300)); - tabPane.addTab("Number Three", new JColorChooser()); - panel = new JPanel(); - panel.setPreferredSize(new Dimension(200, 300)); - tabPane.addTab("Number Four", panel); - panel = new JPanel(); - panel.setPreferredSize(new Dimension(200, 300)); - tabPane.addTab("Number Five", panel); - panel = new JPanel(); - panel.setPreferredSize(new Dimension(200, 300)); - tabPane.addTab("Number Six", panel); - panel = new JPanel(); - panel.setPreferredSize(new Dimension(200, 300)); - tabPane.addTab("Number Seven", panel); - panel = new JPanel(); - panel.setPreferredSize(new Dimension(200, 300)); - tabPane.addTab("Number Eight", panel); - panel = new JPanel(); - panel.setPreferredSize(new Dimension(200, 300)); - tabPane.addTab("Number Nine", panel); - panel = new JPanel(); - panel.setPreferredSize(new Dimension(200, 300)); - tabPane.addTab("Number Ten", panel); - mainPanel = new JPanel(); - mainPanel.add(tabPane); - - getContentPane().add(mainPanel); - tabPane.requestFocus(); - - - //pack(); - //setVisible(true); - }); - } - - public void init() { - String[][] instructionsSet = - { - { - " Note : Incase of Assertion failure,user can enter", - " remarks by pressing 'Assertion Fail Remarks ' button", - " ", - " You would see an applet with JTabbedPane. Keep the size of applet variable.", - " ", - " ON ALL PLATFORMS", - "1. Click on any of the tabs, focus indicator is visible", - "2. Lose focus on the window by clicking on some other window ", - "3. Focus indicator should disappear", - "4. Regain focus on the window the focus indicator should reappear." , - " If focus doesn't behave as above, ", - " press 'Assertion Fail' else press 'Assertion Pass'", - }, - { - " Note : Incase of Assertion failure,user can enter", - " remarks by pressing 'Assertion Fail Remarks ' button", - " ", - " You would see an applet with JTabbedPane. Keep the size of applet variable.", - " ", - " ON ALL PLATFORMS", - "1. type 'C' to change the tab layout to WRAP_TAB_LAYOUT ", - "2. Lose focus on the window by clicking on some other window ", - "3. Focus indicator should disappear", - "4. Regain focus on the window the focus indicator should reappear." , - " If focus doesn't behave as above, ", - " press 'Assertion Fail' else press 'Assertion Pass'", - }, - - { - " Note : Incase of Assertion failure,user can enter", - " remarks by pressing 'Assertion Fail Remarks ' button", - " ", - " You would see an applet with JTabbedPane. Keep the size of applet variable.", - " ", - " ON ALL PLATFORMS", - "1. type 'R' to align the tabs to the right side ", - "2. Lose focus on the window by clicking on some other window ", - "3. Focus indicator should disappear", - "4. Regain focus on the window the focus indicator should reappear." , - " If focus doesn't behave as above, ", - " press 'Assertion Fail' else press 'Assertion Pass'", - }, - - { - " Note : Incase of Assertion failure,user can enter", - " remarks by pressing 'Assertion Fail Remarks ' button", - " ", - " You would see an applet with JTabbedPane. Keep the size of applet variable.", - " ", - " ON ALL PLATFORMS", - "1. type 'B' to align the tabs to the bottom side ", - "2. Lose focus on the window by clicking on some other window ", - "3. Focus indicator should disappear", - "4. Regain focus on the window the focus indicator should reappear." , - " If focus doesn't behave as above, ", - " press 'Assertion Fail' else press 'Assertion Pass'", - }, - - { - " Note : Incase of Assertion failure,user can enter", - " remarks by pressing 'Assertion Fail Remarks ' button", - " ", - " You would see an applet with JTabbedPane. Keep the size of applet variable.", - " ", - " ON ALL PLATFORMS", - "1. type 'L' to align the tabs to the left side ", - "2. Lose focus on the window by clicking on some other window ", - "3. Focus indicator should disappear", - "4. Regain focus on the window the focus indicator should reappear." , - " If focus doesn't behave as above, ", - " press 'Assertion Fail' else press 'Assertion Pass'", - }, - - - { - " Note : Incase of Assertion failure,user can enter", - " remarks by pressing 'Assertion Fail Remarks ' button", - " ", - " You would see an applet with JTabbedPane. Keep the size of applet variable.", - " ", - " ON ALL PLATFORMS", - "1. type 'T' to align the tabs to the top side ", - "2. Lose focus on the window by clicking on some other window ", - "3. Focus indicator should disappear", - "4. Regain focus on the window the focus indicator should reappear." , - " If focus doesn't behave as above, ", - " press 'Assertion Fail' else press 'Assertion Pass'", - }, - - { - " Note : Incase of Assertion failure,user can enter", - " remarks by pressing 'Assertion Fail Remarks ' button", - " ", - " You would see an applet with JTabbedPane. Keep the size of applet variable.", - " ", - " ON ALL PLATFORMS", - "1. type 'B' to align the tabs to the bottom side ", - "2. Lose focus on the window by clicking on some other window ", - "3. Focus indicator should disappear", - "4. Regain focus on the window the focus indicator should reappear." , - " If focus doesn't behave as above, ", - " press 'Assertion Fail' else press 'Assertion Pass'", - }, - - { - " Note : Incase of Assertion failure,user can enter", - " remarks by pressing 'Assertion Fail Remarks ' button", - " ", - " You would see an applet with JTabbedPane. Keep the size of applet variable.", - " ", - " ON ALL PLATFORMS", - "1. type 'R' to align the tabs to the right side ", - "2. Lose focus on the window by clicking on some other window ", - "3. Focus indicator should disappear", - "4. Regain focus on the window the focus indicator should reappear." , - " If focus doesn't behave as above, ", - " press 'Assertion Fail' else press 'Assertion Pass'", - } - }; - - String[] exceptionsSet = - { - "Focus painted incorrectly in tabbed pane(SCROLL_TAB_LAYOUT) when tabs aligned to the TOP of the window", - "Focus painted incorrectly in tabbed pane(SCROLL_TAB_LAYOUT) when tabs aligned to the RIGHT of the window", - "Focus painted incorrectly in tabbed pane(SCROLL_TAB_LAYOUT) when tabs aligned to the BOTTOM of the window", - "Focus painted incorrectly in tabbed pane(SCROLL_TAB_LAYOUT) when tabs aligned to the LEFT of the window", - "Focus painted incorrectly in tabbed pane(WRAP_TAB_LAYOUT) when tabs aligned to the LEFT of the window", - "Focus painted incorrectly in tabbed pane(WRAP_TAB_LAYOUT) when tabs aligned to the TOP of the window", - "Focus painted incorrectly in tabbed pane(WRAP_TAB_LAYOUT) when tabs aligned to the BOTTOM of the window", - "Focus painted incorrectly in tabbed pane(WRAP_TAB_LAYOUT) when tabs aligned to the RIGHT of the window" - }; - - Sysout.setInstructionsWithExceptions(instructionsSet,exceptionsSet); - - } - - public void start (){} - - public void destroy(){ - if(Sysout.failStatus()) { - String failMsg = Sysout.getFailureMessages(); - failMsg = failMsg.replace('\n',' '); - throw new RuntimeException(failMsg); - }// End destroy - } - - protected InputMap createInputMap() { - return LookAndFeel.makeComponentInputMap(getRootPane(), new Object[] { - "R", "right", - "L", "left", - "T", "top", - "B", "bottom", - "C", "changeLayout", - "D", "dump" - }); - } - - protected ActionMap createActionMap() { - ActionMap map = new ActionMap(); - map.put("right", new RotateAction(JTabbedPane.RIGHT)); - map.put("left", new RotateAction(JTabbedPane.LEFT)); - map.put("top", new RotateAction(JTabbedPane.TOP)); - map.put("bottom", new RotateAction(JTabbedPane.BOTTOM)); - map.put("changeLayout", new ChangeLayoutAction()); - map.put("dump", new DumpAction()); - return map; - } - - private class RotateAction extends AbstractAction { - private int placement; - public RotateAction(int placement) { - this.placement = placement; - } - - public void actionPerformed(ActionEvent e) { - tabPane.setTabPlacement(placement); - } - } - - private class ChangeLayoutAction extends AbstractAction { - private boolean a = true; - public void actionPerformed(ActionEvent e) { - if (a) { - tabPane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT); - a = false; - } else { - tabPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); - a = true; - } - } - } - - private class DumpAction extends AbstractAction { - public void actionPerformed(ActionEvent e) { - for (int i = 0; i < tabPane.getTabCount(); i++) { - System.out.println("Tab: " + i + " " - + tabPane.getUI().getTabBounds(tabPane, i)); - } - } - } -} - - -/**************************************************** - Standard Test Machinery - DO NOT modify anything below -- it's a standard - chunk of code whose purpose is to make user - interaction uniform, and thereby make it simpler - to read and understand someone else's test. - ****************************************************/ - -/** - This is part of the standard test machinery. - It creates a dialog (with the instructions), and is the interface - for sending text messages to the user. - To print the instructions, send an array of strings to Sysout.createDialog - WithInstructions method. Put one line of instructions per array entry. - To display a message for the tester to see, simply call Sysout.println - with the string to be displayed. - This mimics System.out.println but works within the test harness as well - as standalone. - */ - -class Sysout - { - private static TestDialog dialog; - - public static void createDialogWithInstructions( String[] instructions ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - dialog.printInstructions( instructions ); - dialog.show(); - println( "Any messages for the tester will display here." ); - } - - public static void createDialog( ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - String[] defInstr = { "Instructions will appear here. ", "" } ; - dialog.printInstructions( defInstr ); - dialog.show(); - println( "Any messages for the tester will display here." ); - } - - - public static void printInstructions( String[] instructions ) - { - dialog.printInstructions( instructions ); - } - - - public static void println( String messageIn ) - { - dialog.displayMessage( messageIn ); - } - - public static void setInstructionsWithExceptions(String instructionsSet[][], - String exceptionsSet[]) { - createDialogWithInstructions(instructionsSet[0]); - dialog.setInstructions(instructionsSet); - dialog.setExceptionMessages(exceptionsSet); - } - - public static String getFailureMessages() { - return dialog.failureMessages; - } - - public static boolean failStatus() { - return dialog.failStatus; - } - - }// Sysout class - -/** - This is part of the standard test machinery. It provides a place for the - test instructions to be displayed, and a place for interactive messages - to the user to be displayed. - To have the test instructions displayed, see Sysout. - To have a message to the user be displayed, see Sysout. - Do not call anything in this dialog directly. - */ -class TestDialog extends Dialog - { - - TextArea instructionsText; - TextArea messageText; - int maxStringLength = 70; - - Panel assertPanel; - Button assertPass,assertFail,remarks; - HandleAssert handleAssert; - boolean failStatus=false; - int instructionCounter=0; - String instructions[][]; - int exceptionCounter=0; - String exceptionMessages[]; - String failureMessages="
"; - String remarksMessage=null; - RemarksDialog remarksDialog; - - //DO NOT call this directly, go through Sysout - public TestDialog( Frame frame, String name ) - { - super( frame, name ); - int scrollBoth = TextArea.SCROLLBARS_BOTH; - instructionsText = new TextArea( "", 14, maxStringLength, scrollBoth ); - add( "North", instructionsText ); - - messageText = new TextArea( "", 3, maxStringLength, scrollBoth ); - add("Center", messageText); - - assertPanel = new Panel(new FlowLayout()); - assertPass=new Button("Assertion Pass"); - assertPass.setName("Assertion Pass"); - assertFail=new Button("Assertion Fail"); - assertFail.setName("Assertion Fail"); - remarks = new Button("Assertion Fail Remarks"); - remarks.setEnabled(false); - remarks.setName("Assertion Remarks"); - assertPanel.add(assertPass); - assertPanel.add(assertFail); - assertPanel.add(remarks); - handleAssert = new HandleAssert(); - assertPass.addActionListener(handleAssert); - assertFail.addActionListener(handleAssert); - remarks.addActionListener(handleAssert); - add("South",assertPanel); - pack(); - - show(); - }// TestDialog() - - //DO NOT call this directly, go through Sysout - public void printInstructions( String[] instructions ) - { - //Clear out any current instructions - instructionsText.setText( "" ); - - //Go down array of instruction strings - - String printStr, remainingStr; - for( int i=0; i < instructions.length; i++ ) - { - //chop up each into pieces maxSringLength long - remainingStr = instructions[ i ]; - while( remainingStr.length() > 0 ) - { - //if longer than max then chop off first max chars to print - if( remainingStr.length() >= maxStringLength ) - { - //Try to chop on a word boundary - int posOfSpace = remainingStr. - lastIndexOf( ' ', maxStringLength - 1 ); - - if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; - - printStr = remainingStr.substring( 0, posOfSpace + 1 ); - remainingStr = remainingStr.substring( posOfSpace + 1 ); - } - //else just print - else - { - printStr = remainingStr; - remainingStr = ""; - } - - instructionsText.append( printStr + "\n" ); - - }// while - - }// for - - }//printInstructions() - - //DO NOT call this directly, go through Sysout - public void displayMessage( String messageIn ) - { - messageText.append( messageIn + "\n" ); - } - - public void emptyMessage() { - messageText.setText(""); - } - - public void setInstructions(String insStr[][]) { - instructions=insStr; - } - - public void setExceptionMessages(String exceptionMessages[]) { - this.exceptionMessages=exceptionMessages; - } - - class HandleAssert implements ActionListener { - public void actionPerformed(ActionEvent ae) { - if(ae.getSource()==remarks) { - remarksDialog = new RemarksDialog(TestDialog.this, - "Assertion Remarks Dialog",true); - remarks.setEnabled(false); - if(remarksMessage!=null) - failureMessages+=". User Remarks : "+remarksMessage; - } - else { - if(instructionCounter"+ - exceptionMessages[exceptionCounter]; - } - } - exceptionCounter++; - } - } - } - - class RemarksDialog extends Dialog implements ActionListener{ - Panel rootPanel,remarksPanel; - TextArea textarea; - Button addRemarks,cancelRemarks; - public RemarksDialog(Dialog owner,String title,boolean modal) { - super(owner,title,modal); - rootPanel = new Panel(new BorderLayout()); - remarksPanel = new Panel(new FlowLayout()); - textarea = new TextArea(5,30); - addRemarks=new Button("Add Remarks"); - addRemarks.addActionListener(this); - cancelRemarks = new Button("Cancel Remarks"); - cancelRemarks.addActionListener(this); - remarksPanel.add(addRemarks); - remarksPanel.add(cancelRemarks); - rootPanel.add(textarea,"Center"); - rootPanel.add(remarksPanel,"South"); - add(rootPanel); - setBounds(150,150,400,200); - setVisible(true); - } - - public void actionPerformed(ActionEvent ae) { - remarksMessage=null; - if(ae.getSource()==addRemarks) { - String msg = textarea.getText().trim(); - if (msg.length()>0) - remarksMessage=msg; - } - dispose(); - } - - } - -}// TestDialog class diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JTabbedPane/bug4499556.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JTabbedPane/bug4499556.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JTabbedPane/bug4499556.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JTabbedPane/bug4499556.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,280 @@ +/* + Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 4499556 + * @summary Use arbitrary (J)Components as JTabbedPane tab labels. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4499556 +*/ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.BorderFactory; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JTabbedPane; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public class bug4499556 { + + static final String INSTRUCTIONS = """ + The test window contains a tabbedPane with 4 tabs. + + Tab #0 without any tabComponent, just a title. + Tab #1 with a JLabel and a little JButton wrapped into JPanel + Tab #2 with a JButton (Delete #1) as a tabComponent + Tab #3 with a JTextField as a tabComponent + + Check that tabbedPane and all tabComponents are shown properly + for different tabLayout and tabPlacement policies, + (you can change them with help of settings in the right panel), + and for different looks and feels (you can change L&F by using the L&F menu) + + Remove tab #1 by clicking the Button labeled Delete #1 and then re-insert it + by clicking "Insert #1". Check that it works - ie Delete #1 is restored. + + If everything displays and behaves as described, the test PASSES, otherwise it FAILS. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4499556::createUI) + .build() + .awaitAndCheck(); + } + + static volatile JTabbedPane pane; + + static JFrame createUI() { + JFrame frame = new JFrame("bug4499556"); + pane = getTabbedPane(); + frame.add(pane); + frame.add(getRightPanel(), BorderLayout.EAST); + JMenu menu = new JMenu("L&F Menu"); + JMenuItem platformItem = new JMenuItem("Platform L&F"); + JMenuItem nimbusItem = new JMenuItem("Nimbus L&F"); + JMenuItem metalItem = new JMenuItem("Metal L&F"); + menu.add(platformItem); + menu.add(nimbusItem); + menu.add(metalItem); + JMenuBar menuBar = new JMenuBar(); + menuBar.add(menu); + frame.setJMenuBar(menuBar); + platformItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setPlatformLAF(); + } + }); + metalItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setMetalLAF(); + } + }); + + nimbusItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setNimbusLAF(); + } + }); + frame.setSize(500, 500); + return frame; + } + + static JTabbedPane getTabbedPane() { + final JTabbedPane pane = new JTabbedPane(); + + pane.add("Title", new JLabel("")); + + addCompoundTab(pane); + + pane.add("Title", new JLabel("")); + pane.add("Title", new JLabel("")); + + final JButton button = new JButton("Delete #1"); + pane.setTabComponentAt(2, button); + button.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (pane.getTabCount() == 4) { + pane.remove(1); + button.setText("Insert #1"); + } else { + addCompoundTab(pane); + button.setText("Delete #1"); + } + } + }); + + JTextField tf = new JTextField("JTextField", 7); + pane.setTabComponentAt(3, tf); + + return pane; + } + + static JComponent getRightPanel() { + JComponent ret = new Box(BoxLayout.Y_AXIS); + ret.setBorder(BorderFactory.createTitledBorder("Properties")); + ret.setPreferredSize(new Dimension(100, 0)); + final JCheckBox checkBox = new JCheckBox(); + JPanel temp = new JPanel(); + temp.add(new JLabel("Scrollable")); + temp.add(checkBox); + pane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT); + checkBox.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + if (checkBox.isSelected()) { + pane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); + } else { + pane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT); + } + } + }); + checkBox.doClick(); + ret.add(temp); + ButtonGroup group = new ButtonGroup(); + temp = new JPanel(); + JRadioButton topRadio = new JRadioButton("Top"); + temp.add(topRadio); + topRadio.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + pane.setTabPlacement(JTabbedPane.TOP); + } + }); + ret.add(temp); + temp = new JPanel(); + JRadioButton bottomRadio = new JRadioButton("Bottom"); + temp.add(bottomRadio); + bottomRadio.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + pane.setTabPlacement(JTabbedPane.BOTTOM); + } + }); + ret.add(temp); + temp = new JPanel(); + JRadioButton leftRadio = new JRadioButton("Left"); + temp.add(leftRadio); + leftRadio.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + pane.setTabPlacement(JTabbedPane.LEFT); + } + }); + ret.add(temp); + temp = new JPanel(); + JRadioButton rightRadio = new JRadioButton("Right"); + temp.add(rightRadio); + rightRadio.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + pane.setTabPlacement(JTabbedPane.RIGHT); + } + }); + ret.add(temp); + group.add(topRadio); + group.add(bottomRadio); + group.add(leftRadio); + group.add(rightRadio); + return ret; + } + + + + static void addCompoundTab(final JTabbedPane pane) { + JLabel label = new JLabel("JLabel"); + label.setOpaque(true); + JPanel testPanel = new JPanel(); + JLabel comp = new JLabel("JLabel"); + testPanel.add(comp); + JButton closeButton = new CloseButton(); + closeButton.setPreferredSize(new Dimension(10, 10)); + testPanel.add(closeButton); + testPanel.setOpaque(false); + pane.insertTab("Test", null, new JLabel(""), "", 1); + pane.setTabComponentAt(1, testPanel); + } + + static class CloseButton extends JButton { + public CloseButton() { + final Object[] options = {"Fine"}; + addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JOptionPane.showOptionDialog(null, + "How are you ?", "Hello !", JOptionPane.YES_OPTION, + JOptionPane.QUESTION_MESSAGE, null, options, null); + } + }); + } + + protected void paintComponent(Graphics g) { + super.paintComponent(g); + g.setColor(Color.black); + g.drawLine(0, 0, getWidth()-1, getHeight()-1); + g.drawLine(0, getHeight()-1, getWidth()-1, 0); + } + } + + static boolean setLAF(String laf) { + try { + UIManager.setLookAndFeel(laf); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + SwingUtilities.updateComponentTreeUI(pane); + return true; + } + + static final boolean setPlatformLAF() { + return setLAF(UIManager.getSystemLookAndFeelClassName()); + } + + static final boolean setNimbusLAF() { + return setLAF("javax.swing.plaf.nimbus.NimbusLookAndFeel"); + } + + static final boolean setMetalLAF() { + return setLAF("javax.swing.plaf.metal.MetalLookAndFeel"); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JTabbedPane/bug4666224.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JTabbedPane/bug4666224.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JTabbedPane/bug4666224.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JTabbedPane/bug4666224.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.Dimension; +import java.awt.Point; +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.AbstractAction; +import javax.swing.ActionMap; +import javax.swing.InputMap; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.LookAndFeel; +import javax.swing.SwingUtilities; + +/* @test + * @bug 4666224 + * @summary Tests that focus indicator is painted properly in JTabbedPane + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4666224 + */ + +public class bug4666224 { + private static JTabbedPane tabPane; + private static JFrame frame; + + private static final String INSTRUCTIONS = """ + ON ALL PLATFORMS except macos where pt.6 is not applicable + 1. Click on any of the tabs, focus indicator is visible. + 2. Lose focus on the window by clicking on some other window. + 3. Focus indicator should disappear + 4. Regain focus on the window by pressing the tab, + the focus indicator should reappear. + 5. If focus doesn't behave as above, + press 'Fail' else press 'Pass'. + 6. Type 'C' to change the tab layout to WRAP_TAB_LAYOUT + and repeat from step 1 to 5. + 7. Type 'R' to align the tabs to the right side and repeat + from step 1 to 5. + 8. Type 'B' to align the tabs to the bottom side and repeat + from step 1 to 5. + 9. Type 'L' to align the tabs to the left side and repeat + from step 1 to 5. + 10. Type 'T' to align the tabs to the top side and repeat + from step 1 to 5."""; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("JTabbedPane Instructions") + .instructions(INSTRUCTIONS) + .rows(20) + .columns(40) + .testUI(bug4666224::createAndShowUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createAndShowUI() { + frame = new JFrame("Test JTabbedPane"); + tabPane = new JTabbedPane(); + tabPane.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + Point pt = e.getPoint(); + System.out.println("Index at location: " + + tabPane.indexAtLocation(pt.x, pt.y)); + } + }); + InputMap inputMap = createInputMap(); + SwingUtilities.replaceUIInputMap(frame.getRootPane(), JComponent.WHEN_IN_FOCUSED_WINDOW, inputMap); + ActionMap actionMap = createActionMap(); + SwingUtilities.replaceUIActionMap(frame.getRootPane(), actionMap); + + tabPane.setTabPlacement(JTabbedPane.TOP); + tabPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); + + for (int i = 0; i <= 10; i++) { + JPanel panel = new JPanel(); + panel.setPreferredSize(new Dimension(500, 200)); + tabPane.addTab("Tab " + i, panel); + } + JPanel mainPanel = new JPanel(); + mainPanel.add(tabPane); + + frame.setSize(600, 300); + frame.getContentPane().add(mainPanel); + tabPane.requestFocus(); + return frame; + } + + protected static InputMap createInputMap() { + return LookAndFeel.makeComponentInputMap(frame.getRootPane(), new Object[] { + "R", "right", + "L", "left", + "T", "top", + "B", "bottom", + "C", "changeLayout", + "D", "dump" + }); + } + + protected static ActionMap createActionMap() { + ActionMap map = new ActionMap(); + map.put("right", new RotateAction(JTabbedPane.RIGHT)); + map.put("left", new RotateAction(JTabbedPane.LEFT)); + map.put("top", new RotateAction(JTabbedPane.TOP)); + map.put("bottom", new RotateAction(JTabbedPane.BOTTOM)); + map.put("changeLayout", new ChangeLayoutAction()); + map.put("dump", new DumpAction()); + return map; + } + + private static class RotateAction extends AbstractAction { + private int placement; + public RotateAction(int placement) { + this.placement = placement; + } + + public void actionPerformed(ActionEvent e) { + tabPane.setTabPlacement(placement); + } + } + + private static class ChangeLayoutAction extends AbstractAction { + private boolean a = true; + public void actionPerformed(ActionEvent e) { + if (a) { + tabPane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT); + a = false; + } else { + tabPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); + a = true; + } + } + } + + private static class DumpAction extends AbstractAction { + public void actionPerformed(ActionEvent e) { + for (int i = 0; i < tabPane.getTabCount(); i++) { + System.out.println("Tab: " + i + " " + + tabPane.getUI().getTabBounds(tabPane, i)); + } + } + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JTabbedPane/bug6259533.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JTabbedPane/bug6259533.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JTabbedPane/bug6259533.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JTabbedPane/bug6259533.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6259533 + * @requires (os.family == "windows") + * @summary Win L&F : JTabbedPane should move upwards the tabComponent of the selected tab. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug6259533 +*/ + +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTabbedPane; +import javax.swing.UIManager; + +public class bug6259533 { + + static final String INSTRUCTIONS = """ + This test is for the Windows LaF only. + + You should see a JTabbedPane with two tabs. + The first tab uses a string and the second tab has a JLabel as a tabComponent + + Select each tab and notice that on selection the tab title + is moved upwards slightly in comparison with the unselected tab + + If that is the observed behaviour, press PASS, press FAIL otherwise. + + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug6259533::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + try { + UIManager.setLookAndFeel( + "com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel"); + } catch (Exception e) { + throw new RuntimeException(e); + } + + JFrame frame = new JFrame("bug6259533"); + JTabbedPane pane = new JTabbedPane(); + pane.add("String Tab", null); + pane.add("Tab 2", null); + JLabel label = new JLabel("JLabel Tab"); + pane.setTabComponentAt(1, label); + frame.add(pane); + frame.setSize(400, 200); + return frame; + } + +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JTable/4222153/bug4222153.html openjdk-21-21.0.9+10/test/jdk/javax/swing/JTable/4222153/bug4222153.html --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JTable/4222153/bug4222153.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JTable/4222153/bug4222153.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ - - - - -Click in the upper-left cell and then press TAB two times. -If table cell selection is not on the left cell of the second row -then test fails. - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JTable/4222153/bug4222153.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JTable/4222153/bug4222153.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JTable/4222153/bug4222153.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JTable/4222153/bug4222153.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -/* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import javax.swing.JApplet; -import javax.swing.JTable; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; - -/** - * @test - * @bug 4222153 - * @author Konstantin Eremin - * @run applet/manual=yesno bug4222153.html - */ -public class bug4222153 extends JApplet { - - public void init() { - SwingUtilities.invokeLater(() -> { - try { - UIManager.setLookAndFeel( - "javax.swing.plaf.metal.MetalLookAndFeel"); - } catch (Exception e) { - throw new RuntimeException(e); - } - getContentPane().add(new JTable(2, 2)); - }); - } -} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JTable/TAB/TAB.html openjdk-21-21.0.9+10/test/jdk/javax/swing/JTable/TAB/TAB.html --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JTable/TAB/TAB.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JTable/TAB/TAB.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ - - - - - - Tabbing test - - - -

Tabbing test

- - - -

- Select a cell by double clicking it, press tab. Check that the focus moves to the next cell. - If it does, press "pass", otherwise press "fail". -


-
Philip Milne
- - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JTable/TAB/TAB.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JTable/TAB/TAB.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JTable/TAB/TAB.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JTable/TAB/TAB.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,169 +0,0 @@ -/* - * Copyright (c) 1999, 2014, 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.Color; -import java.awt.Container; -import java.awt.Dimension; - -import javax.swing.DefaultCellEditor; -import javax.swing.JApplet; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; -import javax.swing.border.BevelBorder; -import javax.swing.table.AbstractTableModel; -import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.TableCellRenderer; -import javax.swing.table.TableColumn; -import javax.swing.table.TableModel; - -/** - * @test - * @bug 4128521 - * @summary - * Tabbing test - * @author milne - * @run applet/manual=yesno TAB.html - */ -public class TAB extends JApplet -{ - static void initTest(Container contentPane) - { - // Take the dummy data from SwingSet. - final String[] names = {"First Name", "Last Name", "Favorite Color", - "Favorite Number", "Vegetarian"}; - final Object[][] data = { - {"Mark", "Andrews", "Red", new Integer(2), new Boolean(true)}, - {"Tom", "Ball", "Blue", new Integer(99), new Boolean(false)}, - {"Alan", "Chung", "Green", new Integer(838), new Boolean(false)}, - {"Jeff", "Dinkins", "Turquois", new Integer(8), new Boolean(true)}, - {"Amy", "Fowler", "Yellow", new Integer(3), new Boolean(false)}, - {"Brian", "Gerhold", "Green", new Integer(0), new Boolean(false)}, - {"James", "Gosling", "Pink", new Integer(21), new Boolean(false)}, - {"David", "Karlton", "Red", new Integer(1), new Boolean(false)}, - {"Dave", "Kloba", "Yellow", new Integer(14), new Boolean(false)}, - {"Peter", "Korn", "Purple", new Integer(12), new Boolean(false)}, - {"Phil", "Milne", "Purple", new Integer(3), new Boolean(false)}, - {"Dave", "Moore", "Green", new Integer(88), new Boolean(false)}, - {"Hans", "Muller", "Maroon", new Integer(5), new Boolean(false)}, - {"Rick", "Levenson", "Blue", new Integer(2), new Boolean(false)}, - {"Tim", "Prinzing", "Blue", new Integer(22), new Boolean(false)}, - {"Chester", "Rose", "Black", new Integer(0), new Boolean(false)}, - {"Ray", "Ryan", "Gray", new Integer(77), new Boolean(false)}, - {"Georges", "Saab", "Red", new Integer(4), new Boolean(false)}, - {"Willie", "Walker", "Phthalo Blue", new Integer(4), new Boolean(false)}, - {"Kathy", "Walrath", "Blue", new Integer(8), new Boolean(false)}, - {"Arnaud", "Weber", "Green", new Integer(44), new Boolean(false)} - }; - - // Create a model of the data. - TableModel dataModel = new AbstractTableModel() { - // These methods always need to be implemented. - public int getColumnCount() { return names.length; } - public int getRowCount() { return data.length;} - public Object getValueAt(int row, int col) {return data[row][col];} - - // The default implementations of these methods in - // AbstractTableModel would work, but we can refine them. - public String getColumnName(int column) {return names[column];} - public Class getColumnClass(int c) {return getValueAt(0, c).getClass();} - public boolean isCellEditable(int row, int col) {return true;} - public void setValueAt(Object aValue, int row, int column) { - System.out.println("Setting value to: " + aValue); - data[row][column] = aValue; - } - }; - - // Create the table - JTable tableView = new JTable(dataModel); - // Turn off auto-resizing so that we can set column sizes programmatically. - // In this mode, all columns will get their preferred widths, as set blow. - tableView.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); - - // Create a combo box to show that you can use one in a table. - JComboBox comboBox = new JComboBox(); - comboBox.addItem("Red"); - comboBox.addItem("Orange"); - comboBox.addItem("Yellow"); - comboBox.addItem("Green"); - comboBox.addItem("Blue"); - comboBox.addItem("Indigo"); - comboBox.addItem("Violet"); - - TableColumn colorColumn = tableView.getColumn("Favorite Color"); - // Use the combo box as the editor in the "Favorite Color" column. - colorColumn.setCellEditor(new DefaultCellEditor(comboBox)); - - // Set a pink background and tooltip for the Color column renderer. - DefaultTableCellRenderer colorColumnRenderer = new DefaultTableCellRenderer(); - colorColumnRenderer.setBackground(Color.pink); - colorColumnRenderer.setToolTipText("Click for combo box"); - colorColumn.setCellRenderer(colorColumnRenderer); - - // Set a tooltip for the header of the colors column. - TableCellRenderer headerRenderer = colorColumn.getHeaderRenderer(); - if (headerRenderer instanceof DefaultTableCellRenderer) - ((DefaultTableCellRenderer)headerRenderer).setToolTipText("Hi Mom!"); - - // Set the width of the "Vegetarian" column. - TableColumn vegetarianColumn = tableView.getColumn("Vegetarian"); - vegetarianColumn.setPreferredWidth(100); - - // Show the values in the "Favorite Number" column in different colors. - TableColumn numbersColumn = tableView.getColumn("Favorite Number"); - DefaultTableCellRenderer numberColumnRenderer = new DefaultTableCellRenderer() { - public void setValue(Object value) { - int cellValue = (value instanceof Number) ? ((Number)value).intValue() : 0; - setForeground((cellValue > 30) ? Color.black : Color.red); - setText((value == null) ? "" : value.toString()); - } - }; - numberColumnRenderer.setHorizontalAlignment(JLabel.RIGHT); - numbersColumn.setCellRenderer(numberColumnRenderer); - numbersColumn.setPreferredWidth(110); - - // Finish setting up the table. - JScrollPane scrollpane = new JScrollPane(tableView); - scrollpane.setBorder(new BevelBorder(BevelBorder.LOWERED)); - scrollpane.setPreferredSize(new Dimension(430, 200)); - - contentPane.add(scrollpane); - } - - - public void init() { - SwingUtilities.invokeLater(() -> { - try { - UIManager.setLookAndFeel( - "javax.swing.plaf.metal.MetalLookAndFeel"); - } catch (Exception e) { - throw new RuntimeException(e); - } - - initTest(getContentPane()); - }); - } -} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JTable/Tab.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JTable/Tab.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JTable/Tab.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JTable/Tab.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,225 @@ +/* + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; + +import javax.swing.DefaultCellEditor; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.border.BevelBorder; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableModel; + +/* + * @test + * @bug 4128521 + * @key headful + * @summary Verify focus changes correctly when tab is pressed while editing + * a JTextField in a JTable + * @run main Tab + */ + +public class Tab { + private static Robot robot; + private static JFrame frame; + private static JTable tableView; + private static volatile Point tableLoc; + private static volatile Rectangle cellRect; + private static volatile int selectedRowBeforeTabPress; + private static volatile int selectedColumnBeforeTabPress; + private static volatile int selectedRowAfterTabPress; + private static volatile int selectedColumnAfterTabPress; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + robot = new Robot(); + robot.setAutoDelay(50); + try { + SwingUtilities.invokeAndWait(Tab::createAndShowUI); + robot.waitForIdle(); + robot.delay(1000); + + SwingUtilities.invokeAndWait(() -> { + tableLoc = tableView.getLocationOnScreen(); + cellRect = tableView.getCellRect(2, 1, true); + }); + + robot.mouseMove(tableLoc.x + cellRect.x + cellRect.width / 2, + tableLoc.y + cellRect.y + cellRect.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(20); + + SwingUtilities.invokeAndWait(() -> { + selectedRowBeforeTabPress = tableView.getSelectedRow(); + selectedColumnBeforeTabPress = tableView.getSelectedColumn(); + }); + + robot.keyPress(KeyEvent.VK_TAB); + robot.keyRelease(KeyEvent.VK_TAB); + robot.waitForIdle(); + robot.delay(20); + + SwingUtilities.invokeAndWait(() -> { + selectedRowAfterTabPress = tableView.getSelectedRow(); + selectedColumnAfterTabPress = tableView.getSelectedColumn(); + }); + + if (selectedRowAfterTabPress != selectedRowBeforeTabPress + && selectedColumnAfterTabPress != (selectedColumnBeforeTabPress + 1)) { + throw new RuntimeException("JTable's cell focus didn't move to next" + + " cell on TAB press"); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + static void createAndShowUI() { + frame = new JFrame("Test JTable's Focus Component"); + // Take the dummy data from SwingSet. + final String[] names = {"First Name", "Last Name", "Favorite Color", + "Favorite Number", "Vegetarian"}; + final Object[][] data = { + {"Mark", "Andrews", "Red", 2, true}, + {"Tom", "Ball", "Blue", 99, false}, + {"Alan", "Chung", "Green", 838, false}, + {"Jeff", "Dinkins", "Turquois", 8, true}, + {"Amy", "Fowler", "Yellow", 3, false}, + {"Brian", "Gerhold", "Green", 0, false}, + {"James", "Gosling", "Pink", 21, false}, + {"David", "Karlton", "Red", 1, false}, + {"Dave", "Kloba", "Yellow", 14, false}, + {"Peter", "Korn", "Purple", 12, false}, + {"Phil", "Milne", "Purple", 3, false}, + {"Dave", "Moore", "Green", 88, false}, + {"Hans", "Muller", "Maroon", 5, false}, + {"Rick", "Levenson", "Blue", 2, false}, + {"Tim", "Prinzing", "Blue", 22, false}, + {"Chester", "Rose", "Black", 0, false}, + {"Ray", "Ryan", "Gray", 77, false}, + {"Georges", "Saab", "Red", 4, false}, + {"Willie", "Walker", "Phthalo Blue", 4, false}, + {"Kathy", "Walrath", "Blue", 8, false}, + {"Arnaud", "Weber", "Green", 44, false} + }; + + // Create a model of the data. + TableModel dataModel = new AbstractTableModel() { + // These methods always need to be implemented. + public int getColumnCount() { return names.length; } + public int getRowCount() { return data.length;} + public Object getValueAt(int row, int col) {return data[row][col];} + + // The default implementations of these methods in + // AbstractTableModel would work, but we can refine them. + public String getColumnName(int column) {return names[column];} + public Class getColumnClass(int c) {return getValueAt(0, c).getClass();} + public boolean isCellEditable(int row, int col) {return true;} + public void setValueAt(Object aValue, int row, int column) { + System.out.println("Setting value to: " + aValue); + data[row][column] = aValue; + } + }; + + // Create the table + tableView = new JTable(dataModel); + // Turn off auto-resizing so that we can set column sizes programmatically. + // In this mode, all columns will get their preferred widths, as set blow. + tableView.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + + // Create a combo box to show that you can use one in a table. + JComboBox comboBox = new JComboBox(); + comboBox.addItem("Red"); + comboBox.addItem("Orange"); + comboBox.addItem("Yellow"); + comboBox.addItem("Green"); + comboBox.addItem("Blue"); + comboBox.addItem("Indigo"); + comboBox.addItem("Violet"); + + TableColumn colorColumn = tableView.getColumn("Favorite Color"); + // Use the combo box as the editor in the "Favorite Color" column. + colorColumn.setCellEditor(new DefaultCellEditor(comboBox)); + + // Set a pink background and tooltip for the Color column renderer. + DefaultTableCellRenderer colorColumnRenderer = new DefaultTableCellRenderer(); + colorColumnRenderer.setBackground(Color.pink); + colorColumnRenderer.setToolTipText("Click for combo box"); + colorColumn.setCellRenderer(colorColumnRenderer); + + // Set a tooltip for the header of the colors column. + TableCellRenderer headerRenderer = colorColumn.getHeaderRenderer(); + if (headerRenderer instanceof DefaultTableCellRenderer) + ((DefaultTableCellRenderer)headerRenderer).setToolTipText("Hi Mom!"); + + // Set the width of the "Vegetarian" column. + TableColumn vegetarianColumn = tableView.getColumn("Vegetarian"); + vegetarianColumn.setPreferredWidth(100); + + // Show the values in the "Favorite Number" column in different colors. + TableColumn numbersColumn = tableView.getColumn("Favorite Number"); + DefaultTableCellRenderer numberColumnRenderer = new DefaultTableCellRenderer() { + public void setValue(Object value) { + int cellValue = (value instanceof Number) ? ((Number)value).intValue() : 0; + setForeground((cellValue > 30) ? Color.black : Color.red); + setText((value == null) ? "" : value.toString()); + } + }; + numberColumnRenderer.setHorizontalAlignment(JLabel.RIGHT); + numbersColumn.setCellRenderer(numberColumnRenderer); + numbersColumn.setPreferredWidth(110); + + // Finish setting up the table. + JScrollPane scrollpane = new JScrollPane(tableView); + scrollpane.setBorder(new BevelBorder(BevelBorder.LOWERED)); + scrollpane.setPreferredSize(new Dimension(430, 200)); + + frame.getContentPane().add(scrollpane); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JTable/bug4222153.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JTable/bug4222153.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JTable/bug4222153.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JTable/bug4222153.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,117 @@ +/* + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; + +import javax.swing.JFrame; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +/* + * @test + * @bug 4222153 + * @key headful + * @summary Verify that when tab is pressed, the focus shift to next row first cell, + * if the current selected cell is the last cell in that row. + * @run main bug4222153 + */ + +public class bug4222153 { + private static JFrame frame; + private static JTable table; + private static volatile Point tableLoc; + private static volatile Rectangle cellRect; + private static volatile int selectedRowBeforeTabPress; + private static volatile int selectedColumnBeforeTabPress; + private static volatile int selectedRowAfterTabPress; + private static volatile int selectedColumnAfterTabPress; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + Robot robot = new Robot(); + robot.setAutoDelay(50); + try { + SwingUtilities.invokeAndWait(bug4222153::createAndShowUI); + robot.waitForIdle(); + robot.delay(1000); + + SwingUtilities.invokeAndWait(() -> { + tableLoc = table.getLocationOnScreen(); + cellRect = table.getCellRect(0, 0, true); + }); + + robot.mouseMove(tableLoc.x + cellRect.x + cellRect.width / 2, + tableLoc.y + cellRect.y + cellRect.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(20); + + SwingUtilities.invokeAndWait(() -> { + selectedRowBeforeTabPress = table.getSelectedRow(); + selectedColumnBeforeTabPress = table.getSelectedColumn(); + }); + + robot.keyPress(KeyEvent.VK_TAB); + robot.keyRelease(KeyEvent.VK_TAB); + robot.waitForIdle(); + robot.delay(20); + robot.keyPress(KeyEvent.VK_TAB); + robot.keyRelease(KeyEvent.VK_TAB); + robot.waitForIdle(); + robot.delay(20); + + SwingUtilities.invokeAndWait(() -> { + selectedRowAfterTabPress = table.getSelectedRow(); + selectedColumnAfterTabPress = table.getSelectedColumn(); + }); + + if (selectedRowAfterTabPress != (selectedRowBeforeTabPress + 1) + && selectedColumnAfterTabPress != selectedColumnBeforeTabPress) { + throw new RuntimeException("JTable's cell focus didn't shift to next" + + " row first cell on TAB press"); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void createAndShowUI() { + frame = new JFrame("Test JTable Tab Press"); + table = new JTable(2, 2); + frame.getContentPane().add(table); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JTextArea/bug4265784.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JTextArea/bug4265784.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JTextArea/bug4265784.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JTextArea/bug4265784.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,7 @@ try { SwingUtilities.invokeAndWait(() -> { frame = new JFrame("bug4265784"); - ta = new JTextArea(); + ta = new JTextArea("some text", 50, 50); frame.getContentPane().add(ta); frame.pack(); frame.setLocationRelativeTo(null); diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JToolTip/4644444/bug4644444.html openjdk-21-21.0.9+10/test/jdk/javax/swing/JToolTip/4644444/bug4644444.html --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JToolTip/4644444/bug4644444.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JToolTip/4644444/bug4644444.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ - - - - - - - bug4644444 - - - -

bug4644444
Bug ID: 4644444

- -

See the dialog box (usually in upper left corner) for instructions

- - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JToolTip/4644444/bug4644444.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JToolTip/4644444/bug4644444.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JToolTip/4644444/bug4644444.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JToolTip/4644444/bug4644444.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,354 +0,0 @@ -/* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.awt.*; -import javax.swing.*; -import java.awt.event.*; - -/* - * test - * @bug 4644444 8076246 -*/ - -public class bug4644444 extends JApplet { - - JPanel panel; - JButton button; - - public bug4644444() throws Exception { - java.awt.EventQueue.invokeLater( () -> { - panel = new JPanel(); - button = new JButton("whooo"); - button.setToolTipText("Somthing really long 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890"); - panel.add(button); - getContentPane().add(panel); - }); - } - - public void init() { - String[][] instructionsSet = - { - { - " Note : Incase of Assertion failure,user can enter", - " remarks by pressing 'Assertion Fail Remarks ' button", - " ", - " You would see a testframe with a Button", - " ", - " ON ALL PLATFORMS", - "1. Move the mouse on the button, ", - " so that the tooltip attached to it comes up ", - "2. Tool tip should get adjusted it-self to show ", - " its full length of text. ", - "3. If tooltip text gets cut, ", - " press 'Assertion Fail' else press 'Assertion Pass'", - "4. Similarly, move the applet to different locations of the screen, ", - " & see if tooltip works properly everywhere. " - } - }; - - String[] exceptionsSet = - { - "JToolTip is shown partially when placed very close to screen boundaries", - }; - - Sysout.setInstructionsWithExceptions(instructionsSet,exceptionsSet); - - } - - public void start (){} - - public void destroy(){ - if(Sysout.failStatus()) { - String failMsg = Sysout.getFailureMessages(); - failMsg = failMsg.replace('\n',' '); - throw new RuntimeException(failMsg); - }// End destroy - } -} - - -/**************************************************** - Standard Test Machinery - DO NOT modify anything below -- it's a standard - chunk of code whose purpose is to make user - interaction uniform, and thereby make it simpler - to read and understand someone else's test. - ****************************************************/ - -/** - This is part of the standard test machinery. - It creates a dialog (with the instructions), and is the interface - for sending text messages to the user. - To print the instructions, send an array of strings to Sysout.createDialog - WithInstructions method. Put one line of instructions per array entry. - To display a message for the tester to see, simply call Sysout.println - with the string to be displayed. - This mimics System.out.println but works within the test harness as well - as standalone. - */ - -class Sysout - { - private static TestDialog dialog; - - public static void createDialogWithInstructions( String[] instructions ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - dialog.printInstructions( instructions ); - dialog.show(); - println( "Any messages for the tester will display here." ); - } - - public static void createDialog( ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - String[] defInstr = { "Instructions will appear here. ", "" } ; - dialog.printInstructions( defInstr ); - dialog.show(); - println( "Any messages for the tester will display here." ); - } - - - public static void printInstructions( String[] instructions ) - { - dialog.printInstructions( instructions ); - } - - - public static void println( String messageIn ) - { - dialog.displayMessage( messageIn ); - } - - public static void setInstructionsWithExceptions(String instructionsSet[][], - String exceptionsSet[]) { - createDialogWithInstructions(instructionsSet[0]); - dialog.setInstructions(instructionsSet); - dialog.setExceptionMessages(exceptionsSet); - } - - public static String getFailureMessages() { - return dialog.failureMessages; - } - - public static boolean failStatus() { - return dialog.failStatus; - } - - }// Sysout class - -/** - This is part of the standard test machinery. It provides a place for the - test instructions to be displayed, and a place for interactive messages - to the user to be displayed. - To have the test instructions displayed, see Sysout. - To have a message to the user be displayed, see Sysout. - Do not call anything in this dialog directly. - */ -class TestDialog extends Dialog - { - - TextArea instructionsText; - TextArea messageText; - int maxStringLength = 70; - - Panel assertPanel; - Button assertPass,assertFail,remarks; - HandleAssert handleAssert; - boolean failStatus=false; - int instructionCounter=0; - String instructions[][]; - int exceptionCounter=0; - String exceptionMessages[]; - String failureMessages="
"; - String remarksMessage=null; - RemarksDialog remarksDialog; - - //DO NOT call this directly, go through Sysout - public TestDialog( Frame frame, String name ) - { - super( frame, name ); - int scrollBoth = TextArea.SCROLLBARS_BOTH; - instructionsText = new TextArea( "", 14, maxStringLength, scrollBoth ); - add( "North", instructionsText ); - - messageText = new TextArea( "", 3, maxStringLength, scrollBoth ); - add("Center", messageText); - - assertPanel = new Panel(new FlowLayout()); - assertPass=new Button("Assertion Pass"); - assertPass.setName("Assertion Pass"); - assertFail=new Button("Assertion Fail"); - assertFail.setName("Assertion Fail"); - remarks = new Button("Assertion Fail Remarks"); - remarks.setEnabled(false); - remarks.setName("Assertion Remarks"); - assertPanel.add(assertPass); - assertPanel.add(assertFail); - assertPanel.add(remarks); - handleAssert = new HandleAssert(); - assertPass.addActionListener(handleAssert); - assertFail.addActionListener(handleAssert); - remarks.addActionListener(handleAssert); - add("South",assertPanel); - pack(); - - show(); - }// TestDialog() - - //DO NOT call this directly, go through Sysout - public void printInstructions( String[] instructions ) - { - //Clear out any current instructions - instructionsText.setText( "" ); - - //Go down array of instruction strings - - String printStr, remainingStr; - for( int i=0; i < instructions.length; i++ ) - { - //chop up each into pieces maxSringLength long - remainingStr = instructions[ i ]; - while( remainingStr.length() > 0 ) - { - //if longer than max then chop off first max chars to print - if( remainingStr.length() >= maxStringLength ) - { - //Try to chop on a word boundary - int posOfSpace = remainingStr. - lastIndexOf( ' ', maxStringLength - 1 ); - - if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; - - printStr = remainingStr.substring( 0, posOfSpace + 1 ); - remainingStr = remainingStr.substring( posOfSpace + 1 ); - } - //else just print - else - { - printStr = remainingStr; - remainingStr = ""; - } - - instructionsText.append( printStr + "\n" ); - - }// while - - }// for - - }//printInstructions() - - //DO NOT call this directly, go through Sysout - public void displayMessage( String messageIn ) - { - messageText.append( messageIn + "\n" ); - } - - public void emptyMessage() { - messageText.setText(""); - } - - public void setInstructions(String insStr[][]) { - instructions=insStr; - } - - public void setExceptionMessages(String exceptionMessages[]) { - this.exceptionMessages=exceptionMessages; - } - - class HandleAssert implements ActionListener { - public void actionPerformed(ActionEvent ae) { - if(ae.getSource()==remarks) { - remarksDialog = new RemarksDialog(TestDialog.this, - "Assertion Remarks Dialog",true); - remarks.setEnabled(false); - if(remarksMessage!=null) - failureMessages+=". User Remarks : "+remarksMessage; - } - else { - if(instructionCounter"+ - exceptionMessages[exceptionCounter]; - } - } - exceptionCounter++; - } - } - } - - class RemarksDialog extends Dialog implements ActionListener{ - Panel rootPanel,remarksPanel; - TextArea textarea; - Button addRemarks,cancelRemarks; - public RemarksDialog(Dialog owner,String title,boolean modal) { - super(owner,title,modal); - rootPanel = new Panel(new BorderLayout()); - remarksPanel = new Panel(new FlowLayout()); - textarea = new TextArea(5,30); - addRemarks=new Button("Add Remarks"); - addRemarks.addActionListener(this); - cancelRemarks = new Button("Cancel Remarks"); - cancelRemarks.addActionListener(this); - remarksPanel.add(addRemarks); - remarksPanel.add(cancelRemarks); - rootPanel.add(textarea,"Center"); - rootPanel.add(remarksPanel,"South"); - add(rootPanel); - setBounds(150,150,400,200); - setVisible(true); - } - - public void actionPerformed(ActionEvent ae) { - remarksMessage=null; - if(ae.getSource()==addRemarks) { - String msg = textarea.getText().trim(); - if (msg.length()>0) - remarksMessage=msg; - } - dispose(); - } - - } - -}// TestDialog class diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JToolTip/bug4644444.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JToolTip/bug4644444.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JToolTip/bug4644444.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JToolTip/bug4644444.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.JButton; +import javax.swing.JFrame; + +/* + * @test + * @bug 4644444 8076246 + * @summary JToolTip is shown improperly when placed very close to screen boundaries + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4644444 + */ + +public class bug4644444 { + + private static final String INSTRUCTIONS = """ + 1. Move the mouse on the button, so that the tooltip is visible. + 2. Tooltip should get adjusted itself to show its full length of text. + 3. Similarly, move the frame to different locations of the screen + & see if tooltip works properly everywhere. + 4. Press 'Pass' if tooltip text is fully visible else press 'Fail'. """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("JToolTip Instructions") + .instructions(INSTRUCTIONS) + .testUI(bug4644444::createUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createUI() { + JFrame frame = new JFrame("bug4644444"); + JButton button = new JButton("Button"); + button.setToolTipText("Something really long 1234567890 1234567890 " + + "1234567890 1234567890 1234567890 1234567890 1234567890 1234567890"); + frame.getContentPane().add(button); + frame.setSize(200, 80); + return frame; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JTree/4314199/bug4314199.html openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/4314199/bug4314199.html --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JTree/4314199/bug4314199.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/4314199/bug4314199.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ - - - - -Select the last tree node (marked "Here") and click on the menu. -Look at the vertical line connecting nodes "Bug" and "Here". If -this line disappears when the menu drops down, test fails. - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JTree/4314199/bug4314199.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/4314199/bug4314199.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JTree/4314199/bug4314199.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/4314199/bug4314199.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/* - * @test - * @bug 4314199 - * @summary Tests that JTree repaints correctly in a container with a JMenu - * @author Peter Zhelezniakov - * @run applet/manual=yesno bug4314199.html - */ - -import javax.swing.*; -import javax.swing.tree.*; - -public class bug4314199 extends JApplet { - - public void init() { - - try { - UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); - SwingUtilities.invokeAndWait(new Runnable() { - - public void run() { - createAndShowGUI(); - } - }); - } catch (final Exception e) { - SwingUtilities.invokeLater(new Runnable() { - - public void run() { - createAndShowMessage("Test fails because of exception: " - + e.getMessage()); - } - }); - } - - } - - private void createAndShowMessage(String message) { - getContentPane().add(new JLabel(message)); - } - - private void createAndShowGUI() { - JMenuBar mb = new JMenuBar(); - - // needed to exactly align left edge of menu and angled line of tree - mb.add(Box.createHorizontalStrut(27)); - - JMenu mn = new JMenu("Menu"); - JMenuItem mi = new JMenuItem("MenuItem"); - mn.add(mi); - mb.add(mn); - setJMenuBar(mb); - - DefaultMutableTreeNode n1 = new DefaultMutableTreeNode("Root"); - DefaultMutableTreeNode n2 = new DefaultMutableTreeNode("Duke"); - n1.add(n2); - DefaultMutableTreeNode n3 = new DefaultMutableTreeNode("Bug"); - n2.add(n3); - n3.add(new DefaultMutableTreeNode("Blah")); - n3.add(new DefaultMutableTreeNode("Blah")); - n3.add(new DefaultMutableTreeNode("Blah")); - DefaultMutableTreeNode n4 = new DefaultMutableTreeNode("Here"); - n2.add(n4); - - JTree tree = new JTree(new DefaultTreeModel(n1)); - tree.putClientProperty("JTree.lineStyle", "Angled"); - tree.expandPath(new TreePath(new Object[]{n1, n2, n3})); - setContentPane(tree); - } -} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JTree/NodeChangedTest.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/NodeChangedTest.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JTree/NodeChangedTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/NodeChangedTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4199472 + * @summary Tests that node changed for the root of the tree update the + * structure. + * @run main NodeChangedTest + */ + +import javax.swing.JTree; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; + +public class NodeChangedTest { + public static void main(String[] args) { + // Create 3 nodes + final DefaultMutableTreeNode root = new DefaultMutableTreeNode("root", + true); + final DefaultMutableTreeNode child = new DefaultMutableTreeNode("child", + true); + final DefaultMutableTreeNode leaf = new DefaultMutableTreeNode("leaf", + false); + root.add(child); + child.add(leaf); + + final JTree tree = new JTree(root); + + // Change the root node + root.setUserObject("New root"); + ((DefaultTreeModel) tree.getModel()).nodeChanged(root); + + // Check + if (!root.getUserObject().toString().equals("New root")) { + throw new RuntimeException("Failed changing root node for default model."); + } + + // Change to large model + tree.setLargeModel(true); + tree.setRowHeight(20); + root.setUserObject("root"); + tree.setModel(new DefaultTreeModel(root)); + root.setUserObject("New root"); + ((DefaultTreeModel) tree.getModel()).nodeChanged(root); + + // Check again + if (!root.getUserObject().toString().equals("New root")) { + throw new RuntimeException("Failed changing root node for large model."); + } + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JTree/bug4118860.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/bug4118860.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JTree/bug4118860.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/bug4118860.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4118860 + * @summary setToggleClickCount/getToggleClickCount have been added. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4118860 + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.GridLayout; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTree; + +public class bug4118860 { + static final String INSTRUCTIONS = """ + Push the "Single Click" button and try expanding/contracting + branch nodes of the tree with one left mouse button click + on the label part of the node (not the icon or handles). + + Then push the "Double Click" button and try doing the same using + left mouse button double click. Single click shouldn't cause + expanding/contracting. A double click should now be required + to expand/contract nodes. + + If it works then the test PASSES, else the test FAILS. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4118860 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4118860::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame f = new JFrame("ToggleClickCount Test"); + JTree tr = new JTree(); + JPanel p = new JPanel(); + p.setBackground(Color.red); + p.setLayout(new GridLayout(1, 1)); + tr.setOpaque(false); + p.add(tr); + f.add(p, BorderLayout.CENTER); + JPanel bp = new JPanel(); + JButton bt1 = new JButton("Single Click"); + bt1.addActionListener(e -> { + tr.setToggleClickCount(1); + if (tr.getToggleClickCount() != 1) { + throw new RuntimeException("ToggleClickCount doesn't set..."); + } + }); + JButton bt2 = new JButton("Double Click"); + bt2.addActionListener(e -> { + tr.setToggleClickCount(2); + if (tr.getToggleClickCount() != 2) { + throw new RuntimeException("ToggleClickCount doesn't set..."); + } + }); + bp.setLayout(new GridLayout(1, 2)); + bp.add(bt1); + bp.add(bt2); + f.add(bp, BorderLayout.SOUTH); + f.setSize(300, 200); + return f; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JTree/bug4169215.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/bug4169215.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JTree/bug4169215.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/bug4169215.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4169215 + * @summary Accessibility hierarchy JTree node test. + * @run main bug4169215 + */ + +import javax.accessibility.AccessibleContext; +import javax.swing.JTree; +import javax.swing.tree.DefaultMutableTreeNode; + +public class bug4169215 { + public static void main(String[] args) { + // create the tree + DefaultMutableTreeNode root = new DefaultMutableTreeNode("top"); + DefaultMutableTreeNode nodeA = new DefaultMutableTreeNode("A"); + DefaultMutableTreeNode nodeB = new DefaultMutableTreeNode("B"); + root.add(nodeA); + root.add(nodeB); + JTree tree = new JTree(root); + + // find the AccessibleContext of the tree + AccessibleContext actree = tree.getAccessibleContext(); + + // find the AccessibleContext of top node of the tree + AccessibleContext act = actree.getAccessibleChild(0).getAccessibleContext(); + + // find the AccessibleContext of the first child of the table -> + // the AccessibleContext of nodeA + AccessibleContext accA = act.getAccessibleChild(0).getAccessibleContext(); + + // find the AccessibleContext of the next sibling of nodeA, by getting + // child+1 of the parent (the table) + AccessibleContext accB = act.getAccessibleChild( + accA.getAccessibleIndexInParent()+1).getAccessibleContext(); + + // look to see who the sibling is. + if (accB.getAccessibleName().compareTo("B") != 0) { + throw new RuntimeException("Parent node is a sibling instead!"); + } + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JTree/bug4196987.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/bug4196987.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JTree/bug4196987.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/bug4196987.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4196987 + * @summary Test Metal L&F JTree expander icons transparency. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4196987 + */ + +import java.awt.Color; +import java.awt.GridLayout; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTree; +import javax.swing.UIManager; + +public class bug4196987 { + static final String INSTRUCTIONS = """ + If the background of tree icons are red, the test PASSES. + Otherwise the test FAILS. + """; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + PassFailJFrame.builder() + .title("bug4196987 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4196987::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame f = new JFrame("JTree Icon Transparency Test"); + JPanel p = new JPanel(); + p.setBackground(Color.red); + p.setLayout(new GridLayout(1, 1)); + JTree t = new JTree(); + t.setOpaque(false); + p.add(t); + f.add(p); + f.setSize(200, 200); + return f; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JTree/bug4270654.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/bug4270654.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JTree/bug4270654.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/bug4270654.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4270654 + * @summary Tests that selection change in JTree does not cause unnecessary + scrolling. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4270654 + */ + +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTree; +import javax.swing.tree.DefaultMutableTreeNode; + +public class bug4270654 { + static final String INSTRUCTIONS = """ + Select the "dan" node and scroll to the right a little using the + scrollbar. Then press down arrow key. If the tree unscrolls back + to the left, the test FAILS. Otherwise, the test PASSES. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4270654 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4270654::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame f = new JFrame("JTree Scroll Back Test"); + DefaultMutableTreeNode root = new DefaultMutableTreeNode("root"); + String[] lev1 = {"foo", "bar", "dan"}; + String[][] lev2 = { + {}, + {"small", "a nice big node for testing"}, + {"xyz", "pqd", "a really really big node for testing"}}; + for (int i = 0; i < lev1.length; i++) { + DefaultMutableTreeNode child = new DefaultMutableTreeNode(lev1[i]); + root.add(child); + for (int j = 0; j < lev2[i].length; j++) + child.add(new DefaultMutableTreeNode(lev2[i][j])); + } + final JTree tree = new JTree(root); + tree.expandRow(3); + f.add(new JScrollPane(tree)); + f.setSize(200, 200); + return f; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JTree/bug4314199.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/bug4314199.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JTree/bug4314199.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/bug4314199.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * @test + * @bug 4314199 + * @summary Tests that JTree repaints correctly in a container with a JMenu + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4314199 + */ + +import java.awt.BorderLayout; +import javax.swing.Box; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JTree; +import javax.swing.UIManager; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreePath; + +public class bug4314199 { + + private static final String INSTRUCTIONS = """ + Select the last tree node (marked "Here") and click on the "Menu". + Look at the vertical line connecting nodes "Bug" and "Here". + If the connecting line does not disappear when the "Menu" drops down, + press 'Pass' else 'Fail'. """; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + + PassFailJFrame.builder() + .title("JTree Instructions") + .instructions(INSTRUCTIONS) + .rows(6) + .splitUI(bug4314199::createAndShowGUI) + .build() + .awaitAndCheck(); + } + + private static JPanel createAndShowGUI() { + JMenuBar mb = new JMenuBar(); + + // needed to exactly align left edge of menu and angled line of tree + mb.add(Box.createHorizontalStrut(27)); + + JMenu mn = new JMenu("Menu"); + JMenuItem mi = new JMenuItem("MenuItem"); + mn.add(mi); + mb.add(mn); + + DefaultMutableTreeNode n1 = new DefaultMutableTreeNode("Root"); + DefaultMutableTreeNode n2 = new DefaultMutableTreeNode("Duke"); + n1.add(n2); + DefaultMutableTreeNode n3 = new DefaultMutableTreeNode("Bug"); + n2.add(n3); + n3.add(new DefaultMutableTreeNode("Blah")); + n3.add(new DefaultMutableTreeNode("Blah")); + n3.add(new DefaultMutableTreeNode("Blah")); + DefaultMutableTreeNode n4 = new DefaultMutableTreeNode("Here"); + n2.add(n4); + + JTree tree = new JTree(new DefaultTreeModel(n1)); + tree.putClientProperty("JTree.lineStyle", "Angled"); + tree.expandPath(new TreePath(new Object[]{n1, n2, n3})); + + JPanel p = new JPanel(); + p.setLayout(new BorderLayout()); + p.setSize(200, 200); + p.add(mb, BorderLayout.NORTH); + p.add(tree); + return p; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JTree/bug4618767.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/bug4618767.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JTree/bug4618767.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JTree/bug4618767.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4618767 + * @summary First letter navigation in JTree interferes with mnemonics + * @key headful + * @run main bug4618767 + */ + +import java.awt.Robot; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.KeyEvent; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JTree; +import javax.swing.SwingUtilities; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; + +public class bug4618767 { + private static JFrame f; + private static final JTree tree = new + JTree(new String[] {"one", "two", "three", "four"}); + private static boolean menuSelected; + private static CountDownLatch listGainedFocusLatch = new CountDownLatch(1); + + public static void main(String[] args) throws Exception { + try { + SwingUtilities.invokeAndWait(() -> { + f = new JFrame("bug4618767 Test"); + JMenu menu = new JMenu("File"); + menu.setMnemonic('F'); + JMenuItem menuItem = new JMenuItem("item"); + menu.add(menuItem); + JMenuBar menuBar = new JMenuBar(); + menuBar.add(menu); + f.setJMenuBar(menuBar); + + menu.addMenuListener(new MenuListener() { + public void menuCanceled(MenuEvent e) {} + public void menuDeselected(MenuEvent e) {} + public void menuSelected(MenuEvent e) { + menuSelected = true; + } + }); + + tree.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + listGainedFocusLatch.countDown(); + } + }); + f.add(tree); + f.pack(); + f.setLocationRelativeTo(null); + f.setAlwaysOnTop(true); + f.setVisible(true); + }); + runTest(); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (f != null) { + f.dispose(); + } + }); + } + } + + private static void runTest() throws Exception { + if (!listGainedFocusLatch.await(3, TimeUnit.SECONDS)) { + throw new RuntimeException("Waited too long, but can't gain" + + " focus for list"); + } + Robot robot = new Robot(); + robot.setAutoDelay(200); + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_O); + robot.keyRelease(KeyEvent.VK_O); + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_ALT); + robot.keyPress(KeyEvent.VK_F); + robot.keyRelease(KeyEvent.VK_F); + robot.keyRelease(KeyEvent.VK_ALT); + + SwingUtilities.invokeAndWait(() -> { + if (menuSelected && !tree.getSelectionPath() + .getLastPathComponent().toString().equals("one")) { + throw new RuntimeException("Mnemonics interferes with JTree" + + " item selection using KeyEvent"); + } + }); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JViewport/bug4137282.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JViewport/bug4137282.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JViewport/bug4137282.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JViewport/bug4137282.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4137282 + * @summary Tests that scrollbars appear automatically when the enclosed + * component is enlarged + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4137282 + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class bug4137282 { + + private static final String INSTRUCTIONS = """ + Press the "resize" button. Two scrollbars should appear. + Press Pass if they appear and Fail otherwise."""; + + static volatile JPanel pane; + + public static void main(String[] args) throws Exception { + + PassFailJFrame.builder() + .title("JViewport Instructions") + .instructions(INSTRUCTIONS) + .rows(5) + .columns(30) + .testUI(bug4137282::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI() { + pane = new JPanel(); + + pane.setBackground(Color.blue); + setPaneSize(100, 100); + JFrame frame = new JFrame("bug4137282"); + JScrollPane sp = new JScrollPane(pane); + + JButton b = new JButton("resize"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + setPaneSize(300, 300); + } + }); + + frame.add(b, BorderLayout.NORTH); + frame.add(sp, BorderLayout.CENTER); + frame.pack(); + return frame; + } + + static void setPaneSize(int w, int h) { + pane.setPreferredSize(new Dimension(w, h)); + pane.setSize(w, h); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JViewport/bug4217252.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JViewport/bug4217252.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JViewport/bug4217252.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JViewport/bug4217252.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4217252 + * @summary Tests + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4217252 + */ + +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.Rectangle; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.AbstractTableModel; + +public class bug4217252 { + + private static final String INSTRUCTIONS = """ + Click on the 'Scroll' button and then click it again. + If you see row 98 and 99 twice, then test failed, otherwise it passed."""; + + static class TestModel extends AbstractTableModel { + + public String getColumnName(int column) { + return Integer.toString(column); + } + + public int getRowCount() { + return 100; + } + + public int getColumnCount() { + return 5; + } + + public Object getValueAt(int row, int col) { + return row + " x " + col; + } + + public boolean isCellEditable(int row, int column) { return false; } + + public void setValueAt(Object value, int row, int col) { } + } + + public static void main(String[] args) throws Exception { + + PassFailJFrame.builder() + .title("JViewport Instructions") + .instructions(INSTRUCTIONS) + .rows(5) + .columns(30) + .testUI(bug4217252::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI(){ + JFrame frame = new JFrame("bug4217252"); + final JTable table = new JTable(new TestModel()); + JButton scrollButton = new JButton("Scroll"); + scrollButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ae) { + Rectangle bounds = table.getBounds(); + bounds.y = bounds.height + table.getRowHeight(); + bounds.height = table.getRowHeight(); + table.scrollRectToVisible(bounds); + } + }); + frame.getContentPane().add(new JScrollPane(table), + BorderLayout.CENTER); + frame.getContentPane().add(scrollButton, BorderLayout.SOUTH); + frame.pack(); + return frame; + } + +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JViewport/bug4237176.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JViewport/bug4237176.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JViewport/bug4237176.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JViewport/bug4237176.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4237176 + * @summary Tests that background color is set properly for JViewport + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4237176 + */ + +import java.awt.Color; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JViewport; + +public class bug4237176 { + + private static final String INSTRUCTIONS = """ + Look at the empty space below the table. It should be blue. + If it is, test passes, otherwise it fails."""; + + public static void main(String[] args) throws Exception { + + PassFailJFrame.builder() + .title("JViewport Instructions") + .instructions(INSTRUCTIONS) + .rows(5) + .columns(30) + .testUI(bug4237176::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI() { + JFrame frame = new JFrame("Color Demo"); + JTable table = new JTable(new Object[][]{{"one", "two"}}, new Object[]{"A", "B"}); + JScrollPane sp = new JScrollPane(table); + JViewport vp = sp.getViewport(); + vp.setBackground(Color.blue); + vp.setOpaque(true); + + frame.getContentPane().add(sp); + frame.pack(); + return frame; + } + +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JViewport/bug4243479.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JViewport/bug4243479.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JViewport/bug4243479.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JViewport/bug4243479.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,96 @@ +/* + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4243479 + * @summary Tests that JViewport do not blit when not visible + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4243479 + */ + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.FlowLayout; +import java.awt.Point; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTabbedPane; +import javax.swing.JTextArea; +import javax.swing.JViewport; + +public class bug4243479 { + private static final String INSTRUCTIONS = """ + The tabbed pane contains two tabs: "button" and "scrollpane". + The second contains some text inserted into a scrollpane. + Press the "Press here" button. + If a piece of scrollpane appears, press Fail else press Pass."""; + + private static JFrame createTestUI() { + char[] text = new char[20000]; + for (int counter = 0; counter < text.length; counter++) { + if (counter % 80 == 0) { + text[counter] = '\n'; + } + else { + text[counter] = 'a'; + } + } + JScrollPane sp = new JScrollPane(new JTextArea + (new String(text))); + final JViewport vp = sp.getViewport(); + vp.putClientProperty("EnableWindowBlit", Boolean.TRUE); + JTabbedPane tp = new JTabbedPane(); + JPanel panel = new JPanel(new FlowLayout()); + JButton button = new JButton("Press here"); + button.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ae) { + Point location = vp.getViewPosition(); + location.y += 100; + vp.setViewPosition(location); + } + }); + panel.add(button); + tp.add("button", panel); + tp.add("scrollpane", sp); + JFrame frame = new JFrame("4243479 Test"); + frame.getContentPane().add(tp); + frame.pack(); + return frame; + } + + public static void main(String[] argv) throws Exception { + PassFailJFrame.builder() + .title("JViewport Instructions") + .instructions(INSTRUCTIONS) + .rows(5) + .columns(30) + .position(PassFailJFrame.Position.TOP_LEFT_CORNER) + .testUI(bug4243479::createTestUI) + .build() + .awaitAndCheck(); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/JViewport/bug4750421.java openjdk-21-21.0.9+10/test/jdk/javax/swing/JViewport/bug4750421.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/JViewport/bug4750421.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/JViewport/bug4750421.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4750421 + * @summary 4143833 - regression in 1.4.x + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4750421 + */ + +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JViewport; + +public class bug4750421 { + + private static final String INSTRUCTIONS = """ + A table will be shown. + Select the third row of the table. + Then press down arrow button of vertical scrollbar to scroll down. + (in macos drag the vertical scrollbar down via mouse just enough + to scroll by 1 unit as there is no arrow button in scrollbar) + If the selection disappears press Fail else press Pass."""; + + private static JFrame createTestUI() { + JFrame frame = new JFrame("bug4750421"); + JTable table = new JTable(30, 10); + table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + JScrollPane pane = new JScrollPane(table); + frame.getContentPane().add(pane); + pane.getViewport().setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE); + frame.pack(); + return frame; + } + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("JViewport Instructions") + .instructions(INSTRUCTIONS) + .rows(7) + .columns(35) + .testUI(bug4750421::createTestUI) + .build() + .awaitAndCheck(); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/ProgressMonitor/bug4401480.java openjdk-21-21.0.9+10/test/jdk/javax/swing/ProgressMonitor/bug4401480.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/ProgressMonitor/bug4401480.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/ProgressMonitor/bug4401480.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4401480 + * @summary Tests that closing ProgressMonitor dialog cancels it + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4401480 + */ + +import java.lang.reflect.InvocationTargetException; +import javax.swing.JButton; +import javax.swing.JPanel; +import javax.swing.ProgressMonitor; +import javax.swing.SwingUtilities; + +public class bug4401480 { + private static ProgressMonitor monitor; + private static volatile boolean cancelled = false; + + private static final String INSTRUCTIONS = """ + This is a semi-automated test which automatically + passes if closing the JProgressBar dialog cancels it. + Read the following test instructions and when ready + click on the Start button below. + + After clicking on Start button wait for few seconds for + progress monitor (a dialog with progress bar) to appear. + Close it by clicking on the window close button. + DO NOT click on Cancel button. + + NOTE: + Ensure to click on the window close button before + progress bar reaches its max limit. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("JProgress Monitor Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .splitUIBottom(bug4401480::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JPanel createTestUI() { + JPanel panel = new JPanel(); + JButton startButton = new JButton("Start"); + startButton.addActionListener(e -> { + monitor = new ProgressMonitor(null, "Progress", "Running ...", 0, 10); + monitor.setProgress(0); + + new Thread(() -> { + for (int i = 0; i < 10; i++) { + int count = i; + try { + SwingUtilities.invokeAndWait(() -> + monitor.setProgress(count)); + Thread.sleep(2000); + SwingUtilities.invokeAndWait(() -> + cancelled = monitor.isCanceled()); + } catch (InterruptedException + | InvocationTargetException ex) { + throw new RuntimeException(ex); + } + if (cancelled) { + break; + } + } + + if (cancelled) { + PassFailJFrame.forcePass(); + } else { + PassFailJFrame.forceFail("Test Failed! JProgress Monitor" + + " was not cancelled"); + } + }).start(); + }); + panel.add(startButton); + return panel; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/border/Test4243289.html openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4243289.html --- openjdk-21-21.0.8+9/test/jdk/javax/swing/border/Test4243289.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4243289.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ - - - - -When applet starts, you'll see a panel with a TitledBorder with title "Panel Title". -If this title is overstriken with the border line, test fails, otherwise it passes. - - - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/border/Test4243289.java openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4243289.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/border/Test4243289.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4243289.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,32 +21,55 @@ * questions. */ +import java.awt.Dimension; +import java.awt.Font; +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.border.TitledBorder; + /* * @test * @bug 4243289 * @summary Tests that TitledBorder do not draw line through its caption - * @author Peter Zhelezniakov - * @run applet/manual=yesno Test4243289.html + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual Test4243289 */ -import java.awt.Font; -import javax.swing.BorderFactory; -import javax.swing.JApplet; -import javax.swing.JPanel; -import javax.swing.border.TitledBorder; +public class Test4243289 { + public static void main(String[] args) throws Exception { + String testInstructions = """ + If TitledBorder with title "Panel Title" is overstruck with + the border line, test fails, otherwise it passes. + """; + + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(testInstructions) + .rows(3) + .columns(35) + .splitUI(Test4243289::init) + .build() + .awaitAndCheck(); + } -public class Test4243289 extends JApplet { - public void init() { - Font font = new Font("Dialog", Font.PLAIN, 12); // NON-NLS: the font name + public static JComponent init() { + Font font = new Font(Font.DIALOG, Font.PLAIN, 12); TitledBorder border = BorderFactory.createTitledBorder( BorderFactory.createEtchedBorder(), - "Panel Title", // NON-NLS: the title of the border + "Panel Title", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, font); JPanel panel = new JPanel(); panel.setBorder(border); - getContentPane().add(panel); + panel.setPreferredSize(new Dimension(100, 100)); + Box main = Box.createVerticalBox(); + main.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); + main.add(panel); + return main; } } diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/border/Test4247606.html openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4247606.html --- openjdk-21-21.0.8+9/test/jdk/javax/swing/border/Test4247606.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4247606.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ - - - - -If the button do not fit into the titled border bounds -and cover the bottom border's line then test fails. -Otherwise test passes. - - - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/border/Test4247606.java openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4247606.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/border/Test4247606.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4247606.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,36 +21,55 @@ * questions. */ -/* - * @test - * @bug 4247606 - * @summary BorderedPane appears wrong with Title Position Below Bottom - * @author Andrey Pikalev - * @run applet/manual=yesno Test4247606.html - */ - import java.awt.BorderLayout; import java.awt.Color; +import java.awt.Dimension; import javax.swing.BorderFactory; -import javax.swing.JApplet; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.border.Border; import javax.swing.border.TitledBorder; -public class Test4247606 extends JApplet { - public void init() { - JButton button = new JButton("Button"); // NON-NLS: the button text +/* + * @test + * @bug 4247606 + * @summary BorderedPane appears wrong with title position below bottom + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual Test4247606 + */ + +public class Test4247606 { + public static void main(String[] args) throws Exception { + String testInstructions = """ + If the button does not fit into the titled border bounds + and cover the bottom border's line then test fails. + Otherwise test passes + """; + + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(testInstructions) + .rows(4) + .columns(35) + .splitUI(Test4247606::initializeTest) + .build() + .awaitAndCheck(); + } + + public static JComponent initializeTest() { + JButton button = new JButton("Button"); button.setBorder(BorderFactory.createLineBorder(Color.red, 1)); - TitledBorder border = new TitledBorder("Bordered Pane"); // NON-NLS: the panel title + TitledBorder border = new TitledBorder("Bordered Pane"); border.setTitlePosition(TitledBorder.BELOW_BOTTOM); JPanel panel = create(button, border); panel.setBackground(Color.green); + panel.setPreferredSize(new Dimension(200, 150)); - getContentPane().add(create(panel, BorderFactory.createEmptyBorder(10, 10, 10, 10))); + return create(panel, BorderFactory.createEmptyBorder(10, 10, 10, 10)); } private static JPanel create(JComponent component, Border border) { diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/border/Test4252164.html openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4252164.html --- openjdk-21-21.0.8+9/test/jdk/javax/swing/border/Test4252164.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4252164.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ - - - - -Please, ensure that rounded border is filled completely. -It should not contain white points inside. -Use Mouse Wheel to change thickness of the border. - - - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/border/Test4252164.java openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4252164.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/border/Test4252164.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4252164.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,53 +21,56 @@ * questions. */ -/* - * @test - * @bug 4252164 8041917 - * @summary Tests rounded LineBorder for components - * @author Sergey Malenkov - * @run applet/manual=yesno Test4252164.html - */ - import java.awt.Color; -import java.awt.event.MouseWheelEvent; -import java.awt.event.MouseWheelListener; -import javax.swing.JApplet; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.border.LineBorder; -public class Test4252164 extends JApplet implements MouseWheelListener { - private int thickness; - private JLabel rounded; - private JLabel straight; - - public void mouseWheelMoved(MouseWheelEvent event) { - update(event.getWheelRotation()); - } +/* + * @test + * @bug 4252164 8041917 + * @summary Tests rounded LineBorder for components + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual Test4252164 + */ - public void init() { - add(createUI()); - addMouseWheelListener(this); +public class Test4252164 { + private static int thickness; + private static JLabel rounded; + private static JLabel straight; + + public static void main(String[] args) throws Exception { + String testInstructions = """ + Please, ensure that rounded border is filled completely. + It should not contain white points inside. + Use Mouse Wheel to change thickness of the border. + """; + + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(testInstructions) + .rows(4) + .columns(35) + .splitUI(Test4252164::createUI) + .build() + .awaitAndCheck(); } - private JPanel createUI() { - this.rounded = new JLabel("ROUNDED"); // NON-NLS: the label for rounded border - this.straight = new JLabel("STRAIGHT"); // NON-NLS: the label for straight border - + private static JPanel createUI() { + rounded = new JLabel("ROUNDED"); // NON-NLS: the label for rounded border + straight = new JLabel("STRAIGHT"); // NON-NLS: the label for straight border JPanel panel = new JPanel(); - panel.add(this.rounded); - panel.add(this.straight); - + panel.add(rounded); + panel.add(straight); update(10); - + panel.addMouseWheelListener(e -> update(e.getWheelRotation())); return panel; } - private void update(int thickness) { - this.thickness += thickness; - - this.rounded.setBorder(new LineBorder(Color.RED, this.thickness, true)); - this.straight.setBorder(new LineBorder(Color.RED, this.thickness, false)); + private static void update(int thicknessValue) { + thickness += thicknessValue; + rounded.setBorder(new LineBorder(Color.RED, thickness, true)); + straight.setBorder(new LineBorder(Color.RED, thickness, false)); } } diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/border/Test4760089.html openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4760089.html --- openjdk-21-21.0.8+9/test/jdk/javax/swing/border/Test4760089.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4760089.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ - - - - -When applet starts, you'll see a panel with a compound titled border. -If one of its titles is overstriken with the border's line then test fails. -Otherwise test passes. - - - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/border/Test4760089.java openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4760089.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/border/Test4760089.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test4760089.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,29 +21,52 @@ * questions. */ +import java.awt.Dimension; +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.border.Border; +import javax.swing.border.EtchedBorder; +import javax.swing.border.TitledBorder; + /* * @test * @bug 4760089 * @summary Tests that titled border do not paint inner titled border over its caption - * @author Sergey Malenkov - * @run applet/manual=yesno Test4760089.html + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual Test4760089 */ -import javax.swing.JApplet; -import javax.swing.JPanel; -import javax.swing.border.Border; -import javax.swing.border.EtchedBorder; -import javax.swing.border.TitledBorder; +public class Test4760089 { + public static void main(String[] args) throws Exception { + String testInstructions = """ + When test starts, a panel with a compound titled border is seen. + If one of its titles is overstruck with the border's + line then test fails. Otherwise test passes."""; + + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(testInstructions) + .rows(4) + .columns(35) + .splitUI(Test4760089::init) + .build() + .awaitAndCheck(); + } -public class Test4760089 extends JApplet { - @Override - public void init() { + public static JComponent init() { Border border = new EtchedBorder(); - border = new TitledBorder(border, "LEFT", TitledBorder.LEFT, TitledBorder.TOP); + border = new TitledBorder(border, "LEFT", TitledBorder.LEFT, TitledBorder.TOP); border = new TitledBorder(border, "RIGHT", TitledBorder.RIGHT, TitledBorder.TOP); JPanel panel = new JPanel(); panel.setBorder(border); - getContentPane().add(panel); + panel.setPreferredSize(new Dimension(200, 100)); + Box main = Box.createVerticalBox(); + main.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); + main.add(panel); + return main; } } diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/border/Test6910490.html openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test6910490.html --- openjdk-21-21.0.8+9/test/jdk/javax/swing/border/Test6910490.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test6910490.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ - - - - -If the border is painted over scroll bars then test fails. -Otherwise test passes. - - - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/border/Test6910490.java openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test6910490.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/border/Test6910490.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/border/Test6910490.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,8 @@ import java.awt.Graphics; import java.awt.Insets; import javax.swing.Icon; -import javax.swing.JApplet; import javax.swing.JButton; +import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.border.MatteBorder; @@ -37,22 +37,40 @@ * @test * @bug 6910490 * @summary Tests a matte border around a component inside a scroll pane. - * @author Sergey Malenkov - * @run applet/manual=yesno Test6910490.html + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual Test6910490 */ -public class Test6910490 extends JApplet implements Icon { +public class Test6910490 implements Icon { + public static void main(String[] args) throws Exception { + String testInstructions = """ + If the border is painted over scroll bars then test fails. + Otherwise test passes."""; + Test6910490 obj = new Test6910490(); + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(testInstructions) + .rows(3) + .columns(35) + .testUI(obj.initializeTest()) + .build() + .awaitAndCheck(); + } - @Override - public void init() { + public JFrame initializeTest() { Insets insets = new Insets(10, 10, 10, 10); - Dimension size = new Dimension(getWidth() / 2, getHeight()); + JFrame frame = new JFrame("Matte Border Test"); + frame.setSize(600, 300); + Dimension size = new Dimension(frame.getWidth() / 2, frame.getHeight()); JSplitPane pane = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, create("Color", size, new MatteBorder(insets, RED)), create("Icon", size, new MatteBorder(insets, this))); + pane.setDividerLocation(size.width - pane.getDividerSize() / 2); - add(pane); + frame.add(pane); + return frame; } private JScrollPane create(String name, Dimension size, MatteBorder border) { diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/basic/BasicGraphicsUtils/DrawEtchedRectTest.java openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicGraphicsUtils/DrawEtchedRectTest.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/basic/BasicGraphicsUtils/DrawEtchedRectTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicGraphicsUtils/DrawEtchedRectTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4198822 + * @summary Tests that the bottom line drawn by + * BasicGraphicsUtils.drawEtchedRect extends to the end. + * @run main DrawEtchedRectTest + */ + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.File; + +import javax.imageio.ImageIO; +import javax.swing.plaf.basic.BasicGraphicsUtils; + +import static java.awt.image.BufferedImage.TYPE_INT_ARGB; + +public class DrawEtchedRectTest { + private static final int WIDTH = 200; + private static final int HEIGHT = 200; + private static final int RANGE = 10; + + public static void main(String[] args) throws Exception { + // Draw etched rectangle to a BufferedImage + BufferedImage image = new BufferedImage(WIDTH, HEIGHT, TYPE_INT_ARGB); + Graphics2D g2d = image.createGraphics(); + Component sq = new Component() { + public void paint(Graphics g) { + g.setColor(Color.WHITE); + g.fillRect(0, 0, WIDTH, HEIGHT); + BasicGraphicsUtils.drawEtchedRect(g, 0, 0, WIDTH, HEIGHT, + Color.black, Color.black, + Color.black, Color.black); + } + }; + sq.paint(g2d); + g2d.dispose(); + + // Check if connected at bottom-right corner + int c1; + int c2; + for (int i = 1; i < RANGE; i++) { + c1 = image.getRGB(WIDTH - i, HEIGHT - 1); + c2 = image.getRGB(WIDTH - 1, HEIGHT - i); + if (c1 == Color.WHITE.getRGB() || c2 == Color.WHITE.getRGB()) { + ImageIO.write(image, "png", new File("failImage.png")); + throw new RuntimeException("Bottom line is not connected!"); + } + } + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/basic/BasicHTML/4228104/bug4228104.java openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicHTML/4228104/bug4228104.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/basic/BasicHTML/4228104/bug4228104.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicHTML/4228104/bug4228104.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4228104 + * @summary Tests work of BODY BACKGROUND tag in HTML renderer + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4228104 + */ + +import java.awt.BorderLayout; + +import javax.swing.JFrame; +import javax.swing.JLabel; + +public class bug4228104 { + static final String INSTRUCTIONS = """ + There should be an image displaying dukes under the rows of digits. + If you can see it, the test PASSES. Otherwise, the test FAILS. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4228104 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4228104::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame f = new JFrame("Background HTML Text Test"); + String dir = System.getProperty("test.src", + System.getProperty("user.dir")); + String htmlText1 = + "\n" + + "
111111111111111111" + + "
111111111111111111" + + "
111111111111111111" + + "
111111111111111111" + + "
111111111111111111" + + "
111111111111111111" + + "
111111111111111111" + + "
111111111111111111" + + "
111111111111111111"; + JLabel button1 = new JLabel(htmlText1); + f.add(button1, BorderLayout.NORTH); + f.setSize(200, 200); + return f; + } +} Binary files /srv/release.debian.org/tmp/USNPHwmYvu/openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/basic/BasicHTML/4228104/duke.gif and /srv/release.debian.org/tmp/emfaCnEiU2/openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicHTML/4228104/duke.gif differ diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/basic/BasicInternalFrameTitlePane/bug4331515.java openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicInternalFrameTitlePane/bug4331515.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/basic/BasicInternalFrameTitlePane/bug4331515.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicInternalFrameTitlePane/bug4331515.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4331515 + * @requires (os.family == "windows") + * @summary System menu of an internal frame shouldn't have duplicated items in Win L&F + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4331515 + */ + +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.UIManager; + +public class bug4331515 { + static final String INSTRUCTIONS = """ + Open the system menu of internal frame "JIF" placed in the frame "Test". + If this menu contains duplicates of some items then test FAILS, else + test PASSES. + """; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + PassFailJFrame.builder() + .title("bug4331515 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4331515::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame fr = new JFrame("System Menu in JIF Test"); + JDesktopPane dp = new JDesktopPane(); + fr.setContentPane(dp); + JInternalFrame jif = new JInternalFrame("JIF", true, true, true, true); + dp.add(jif); + jif.setBounds(20, 20, 120, 100); + jif.setVisible(true); + fr.setSize(200, 200); + return fr; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/basic/BasicSliderUI/bug4220108.java openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicSliderUI/bug4220108.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/basic/BasicSliderUI/bug4220108.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicSliderUI/bug4220108.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4220108 + * @summary JSlider in JInternalFrame should be painted correctly + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4220108 + */ + +import java.awt.BorderLayout; +import java.awt.FlowLayout; + +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.JLabel; +import javax.swing.JSlider; + +public class bug4220108 { + static final String INSTRUCTIONS = """ + If you see a slider in the internal frame, then the test PASSES. + Otherwise the test FAILS. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4220108 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4220108::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame f = new JFrame("Internal Frame Slider Test"); + f.setLayout(new FlowLayout()); + JDesktopPane desktop = new JDesktopPane(); + f.setContentPane(desktop); + + JInternalFrame iFrame = + new JInternalFrame("Slider Frame", true, true, true, true); + JSlider sl = new JSlider(); + iFrame.add(sl); + iFrame.add(new JLabel("Label"), BorderLayout.SOUTH); + desktop.add(iFrame); + iFrame.pack(); + iFrame.setVisible(true); + f.setSize(300, 200); + return f; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/basic/BasicSplitPaneDivider/AddMouseListenerTest.java openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicSplitPaneDivider/AddMouseListenerTest.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/basic/BasicSplitPaneDivider/AddMouseListenerTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicSplitPaneDivider/AddMouseListenerTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4165874 + * @summary Adds a MouseListener to the splitpane divider. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual AddMouseListenerTest + */ + +import java.awt.Component; +import java.awt.event.MouseAdapter; + +import javax.swing.JFrame; +import javax.swing.JSplitPane; + +public class AddMouseListenerTest { + static final String INSTRUCTIONS = """ + Try dragging the split pane divider, if you can, click PASS, + else click FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("AddMouseListenerTest Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(AddMouseListenerTest::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame f = new JFrame("JSplitPane With ActionListener Test"); + JSplitPane sp = new JSplitPane(); + + sp.setContinuousLayout(true); + Component[] children = sp.getComponents(); + for (int counter = children.length - 1; counter >= 0; counter--) { + children[counter].addMouseListener(new MouseAdapter() {}); + } + f.getContentPane().add(sp); + f.setSize(400, 400); + return f; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/basic/BasicSplitPaneUI/NegativeSizeTest.java openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicSplitPaneUI/NegativeSizeTest.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/basic/BasicSplitPaneUI/NegativeSizeTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicSplitPaneUI/NegativeSizeTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4199666 + * @summary Makes sure initial negative size of a component does not confuse + * JSplitPane. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual NegativeSizeTest + */ + +import java.awt.BorderLayout; +import java.awt.CardLayout; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JSplitPane; + +public class NegativeSizeTest { + static final String INSTRUCTIONS = """ + Click on the 'Show JSplitPane' button. If two buttons appear, + click PASS, otherwise click FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("NegativeSizeTest Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(NegativeSizeTest::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame f = new JFrame("Negative Size Test"); + CardLayout cardLayout = new CardLayout(); + JPanel mainPanel = new JPanel(cardLayout); + + JSplitPane splitPane = new JSplitPane(); + splitPane.setContinuousLayout(true); + JPanel splitContainer = new JPanel(new BorderLayout()); + splitContainer.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + splitContainer.add(splitPane, BorderLayout.CENTER); + + if (false) { + mainPanel.add(splitContainer, "split"); + mainPanel.add(new JPanel(), "blank"); + } + else { + mainPanel.add(new JPanel(), "blank"); + mainPanel.add(splitContainer, "split"); + } + + f.add(mainPanel, BorderLayout.CENTER); + + JButton button = new JButton("Show JSplitPane"); + button.addActionListener(e -> cardLayout.show(mainPanel, "split")); + f.add(button, BorderLayout.SOUTH); + f.setSize(400, 300); + return f; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/basic/BasicSplitPaneUI/PreferredSizeLayoutTest.java openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicSplitPaneUI/PreferredSizeLayoutTest.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/basic/BasicSplitPaneUI/PreferredSizeLayoutTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicSplitPaneUI/PreferredSizeLayoutTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4208549 + * @summary Makes sure preferred size returned by layout managers used by + * JSplitPane is correct. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual PreferredSizeLayoutTest + */ + +import java.awt.Container; +import java.awt.FlowLayout; + +import javax.swing.JFrame; +import javax.swing.JSplitPane; + +public class PreferredSizeLayoutTest { + static final String INSTRUCTIONS = """ + If the buttons in the JSplitpanes do not have '...' in them, + click PASS, otherwise click FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("PreferredSizeLayoutTest Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(PreferredSizeLayoutTest::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame f = new JFrame("Preferred Size Layout Test"); + Container parent = f.getContentPane(); + JSplitPane sp = new JSplitPane(); + + parent.setLayout(new FlowLayout()); + + sp.setOrientation(JSplitPane.HORIZONTAL_SPLIT); + parent.add(sp); + sp = new JSplitPane(); + sp.setOrientation(JSplitPane.VERTICAL_SPLIT); + parent.add(sp); + f.setSize(400, 300); + return f; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/basic/BasicToolBarUI/bug4305622.java openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicToolBarUI/bug4305622.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/basic/BasicToolBarUI/bug4305622.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicToolBarUI/bug4305622.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4305622 + * @summary MetalToolBarUI.installUI invokeLater causes flickering + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4305622 + */ + +import java.awt.BorderLayout; +import java.awt.Color; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JToolBar; +import javax.swing.UIManager; +import javax.swing.border.LineBorder; + + +public class bug4305622 { + private static JFrame fr; + static final String INSTRUCTIONS = """ + Press button "Create ToolBar" at frame "Create ToolBar Test". + If you see any flickering during creating of toolbar + then the test FAILS, otherwise the test PASSES. + """; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + PassFailJFrame.builder() + .title("bug4305622 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4305622::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + fr = new JFrame("Create ToolBar Test"); + JButton button = new JButton("Create ToolBar"); + button.addActionListener(ae -> addToolBar()); + fr.add(button, BorderLayout.SOUTH); + fr.setSize(400, 400); + return fr; + } + + static void addToolBar() { + fr.repaint(); + fr.revalidate(); + JToolBar toolbar = new JToolBar(); + + JButton btn = new JButton("Button 1"); + btn.setBorder(new LineBorder(Color.red, 30)); + toolbar.add(btn); + + btn = new JButton("Button 2"); + btn.setBorder(new LineBorder(Color.red, 30)); + toolbar.add(btn); + + toolbar.updateUI(); + fr.add(toolbar, BorderLayout.NORTH); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/basic/BasicToolBarUI/bug4331392.java openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicToolBarUI/bug4331392.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/basic/BasicToolBarUI/bug4331392.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/basic/BasicToolBarUI/bug4331392.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4331392 + * @summary Tests if BasicToolBarUI has bogus logic that prevents vertical + * toolbars from docking + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4331392 + */ + +import java.awt.BorderLayout; +import java.awt.Container; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JToolBar; + +public class bug4331392 { + static final String INSTRUCTIONS = """ + Try to dock the toolbar across all the edges of frame. If you succeed, + then the test PASSES. Otherwise, it FAILS. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4331392 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4331392::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("JToolBar Docking Test"); + Container c = frame.getContentPane(); + + JToolBar tbar = new JToolBar(JToolBar.VERTICAL); + + tbar.add(new JButton("A")); + tbar.add(new JButton("B")); + tbar.add(new JButton("C")); + + JButton b = new JButton("Hello"); + c.add(b, BorderLayout.CENTER); + c.add(tbar, BorderLayout.EAST); + frame.setSize(300, 300); + return frame; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/metal/MenuItemUI/JavaLAFMenuAcceleratorDelimiter.java openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/metal/MenuItemUI/JavaLAFMenuAcceleratorDelimiter.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/metal/MenuItemUI/JavaLAFMenuAcceleratorDelimiter.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/metal/MenuItemUI/JavaLAFMenuAcceleratorDelimiter.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4210461 + * @summary Confirm Metal Look & Feel's MenuItem Accelerator Delimiter + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual JavaLAFMenuAcceleratorDelimiter + */ + +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; + +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.KeyStroke; +import javax.swing.UIManager; + +public class JavaLAFMenuAcceleratorDelimiter { + static final String INSTRUCTIONS = """ + A simple check. The visual design specification for JLF/Metal asks for + a "-" to delimit the other two entities in a menu item's accelerator. + The test passes if the delimiter for the accelerator is correct when + opening the example menu. Otherwise, the test fails. + """; + + public static void main(String[] args) throws Exception { + // Set Metal L&F + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + PassFailJFrame.builder() + .title("JavaLAFMenuAcceleratorDelimiter Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(JavaLAFMenuAcceleratorDelimiter::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("Metal L&F Accelerator Delimiter Test"); + JPanel menuPanel = new JPanel(); + JMenuBar menuBar = new JMenuBar(); + menuBar.setOpaque(true); + JMenu exampleMenu = new JMenu("Example"); + JMenuItem hiMenuItem = new JMenuItem("Hi There!"); + hiMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H, + ActionEvent.CTRL_MASK)); + exampleMenu.add(hiMenuItem); + menuBar.add(exampleMenu); + menuPanel.add(menuBar); + + frame.getContentPane().setLayout(new BorderLayout()); + frame.getContentPane().add(menuPanel, BorderLayout.CENTER); + frame.setSize(250, 150); + return frame; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/metal/MetalIconFactory/bug4952462.java openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/metal/MetalIconFactory/bug4952462.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/metal/MetalIconFactory/bug4952462.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/metal/MetalIconFactory/bug4952462.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4952462 + * @summary Ocean: Tests that disabled selected JRadioButton dot is NOT + * painted with the foreground color + * @modules java.desktop/sun.awt + * @library /test/lib + * @key headful + * @run main bug4952462 + */ + +import java.awt.Color; +import java.awt.FlowLayout; +import java.awt.Point; +import java.awt.Robot; + +import javax.swing.JFrame; +import javax.swing.JRadioButton; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.plaf.metal.MetalTheme; + +import jtreg.SkippedException; +import sun.awt.AppContext; + +public class bug4952462 { + private static JFrame frame; + private static JRadioButton rb; + + public static void main(String[] args) throws Exception { + try { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + + MetalTheme theme = (MetalTheme) AppContext.getAppContext().get("currentMetalTheme"); + if (theme == null || !"Ocean".equals(theme.getName())) { + throw new SkippedException("Current theme is not Ocean. Test is " + + "only for Metal's Ocean theme. Skipping test."); + } else { + Robot r = new Robot(); + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame("Metal JRadioButton Foreground Color Test"); + frame.getContentPane().setLayout(new FlowLayout()); + rb = new JRadioButton("RadioButton", true); + rb.setEnabled(false); + rb.setForeground(Color.RED); + frame.getContentPane().add(rb); + frame.setSize(250, 100); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + + r.waitForIdle(); + r.delay(500); + + SwingUtilities.invokeAndWait(() -> { + Point p = rb.getLocationOnScreen(); + for (int i = 0; i < 50; i++) { + Color c = r.getPixelColor(p.x + 10 + i, p.y + (rb.getHeight() / 2)); + System.out.println(c); + if (c.getRed() > 200 && c.getBlue() < 200 && c.getGreen() < 200) { + throw new RuntimeException("Test failed. Radiobutton is red " + + "and not grey."); + } + } + }); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/bug4186347.java openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/bug4186347.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/bug4186347.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/bug4186347.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4186347 + * @summary Tests changing Slider.horizontalThumbIcon UIResource + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4186347 + */ + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JFrame; +import javax.swing.JSlider; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.IconUIResource; + +public class bug4186347 { + static final String INSTRUCTIONS = """ + If the slider's thumb icon is painted correctly + (that is centered vertically relative to slider + channel) then test passed, otherwise it failed. + """; + + public static void main(String[] args) throws Exception { + // Set Metal L&F + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + PassFailJFrame.builder() + .title("bug4186347 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4186347::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("Metal JSlider Icon Test"); + String a = System.getProperty("test.src", ".") + + System.getProperty("file.separator") + + "duke.gif"; + Icon icon = new ImageIcon(a); + IconUIResource iconResource = new IconUIResource(icon); + UIDefaults defaults = UIManager.getDefaults(); + defaults.put("Slider.horizontalThumbIcon", iconResource); + JSlider s = new JSlider(); + frame.getContentPane().add(s); + frame.setSize(250, 150); + return frame; + } +} Binary files /srv/release.debian.org/tmp/USNPHwmYvu/openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/duke.gif and /srv/release.debian.org/tmp/emfaCnEiU2/openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/duke.gif differ diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/bug4969419.java openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/bug4969419.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/bug4969419.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/bug4969419.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4969419 + * @summary Tests that generated disabled icons have same look with Ocean + * and are updated when theme is switched + * @modules java.desktop/sun.awt + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @key headful + * @run main/manual bug4969419 + */ + +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.FlowLayout; + +import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.JToggleButton; +import javax.swing.LookAndFeel; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.plaf.metal.DefaultMetalTheme; +import javax.swing.plaf.metal.MetalLookAndFeel; +import javax.swing.plaf.metal.MetalTheme; + +import sun.awt.AppContext; + +public class bug4969419 { + static final String INSTRUCTIONS = """ + When the test starts you'll see several components with icons. + Use the bottom combo box and the "Set" button to switch between + the Ocean theme and DefaultMetalTheme. + + 1. Set the Ocean theme. Ensure all the icons are the same + Note that they all are of the same brightness: none of them + can be brighter or darker than the others. + + 2. Switch to DefaultMetalTheme. Ensure all the icons changed + (became slightly darker). + + 3. Switch back to Ocean. Ensure all the icons changed + (became brighter). + """; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + PassFailJFrame.builder() + .title("bug4969419 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4969419::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("Metal Themes Icon Test"); + Container pane = frame.getContentPane(); + + LFSwitch lfswitch = new LFSwitch(pane); + if (!lfswitch.obtainOceanTheme()) { + throw new RuntimeException("No Ocean theme available"); + } + + pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS)); + + String prefix = System.getProperty("test.src", + System.getProperty("user.dir")) + System.getProperty("file.separator"); + ImageIcon icon = new ImageIcon(prefix + "duke.gif"); + + JPanel panel = new JPanel(); + JButton b = new JButton(icon); + b.setEnabled(false); + + JLabel label = new JLabel(icon, SwingConstants.LEFT); + label.setEnabled(false); + + JTabbedPane tp = new JTabbedPane(); + tp.addTab("", icon, new JPanel()); + tp.addTab("", icon, new JPanel()); + tp.setEnabledAt(0, false); + tp.setEnabledAt(1, false); + + JButton sb = new JButton(icon); + sb.setSelectedIcon(icon); + sb.setSelected(true); + sb.setEnabled(false); + + JToggleButton tb = new JToggleButton(icon); + tb.setEnabled(false); + + JToggleButton stb = new JToggleButton(icon); + stb.setSelectedIcon(icon); + stb.setSelected(true); + stb.setEnabled(false); + + pane.setBackground(Color.white); + panel.setBackground(Color.white); + b.setBackground(Color.white); + label.setBackground(Color.white); + tp.setBackground(Color.white); + sb.setBackground(Color.white); + tb.setBackground(Color.white); + stb.setBackground(Color.white); + + panel.add(b); + panel.add(label); + panel.add(tp); + panel.add(sb); + panel.add(tb); + panel.add(stb); + + pane.add(panel); + pane.add(lfswitch); + frame.setSize(400, 400); + return frame; + } + + static class LFSwitch extends JPanel { + private Component target; + static MetalTheme oceanTheme; + JComboBox lfcombo; + + public LFSwitch(Component target) { + this.target = target; + setLayout(new FlowLayout()); + lfcombo = new JComboBox(lookAndFeels); + add(lfcombo); + JButton setLfBut = new JButton("Set"); + add(setLfBut); + setLfBut.addActionListener(e -> setLf(lfcombo.getSelectedIndex(), + LFSwitch.this.target)); + } + + boolean obtainOceanTheme() { + if (oceanTheme != null) { + return true; + } + try { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + SwingUtilities.updateComponentTreeUI(this); + } catch (Exception e) { + JOptionPane.showMessageDialog(this, + "Unexpected error: couldn't set Metal", "Error", + JOptionPane.ERROR_MESSAGE); + return false; + } + MetalTheme theme = (MetalTheme) AppContext.getAppContext(). + get("currentMetalTheme"); + if (theme == null || theme.getName() != "Ocean") { + JOptionPane.showMessageDialog(this, + "The Ocean theme is not the default Metal theme,\n" + + "but this test requires it to be default.\n" + + "Therefore simply click PASS"); + return false; + } + oceanTheme = theme; + return true; + } + + void setLf(int idx, final Component root) { + try { + UIManager.setLookAndFeel((LookAndFeel) lfs[idx]); + if (root != null) { + SwingUtilities.updateComponentTreeUI(root); + } + } catch (UnsupportedLookAndFeelException e) { + JOptionPane.showMessageDialog(root, + "The selected look and feel is unsupported on this platform", + "Error", JOptionPane.ERROR_MESSAGE); + } catch (Exception exc) { + JOptionPane.showMessageDialog(root, + "Error setting the selected look and feel", "Error", + JOptionPane.ERROR_MESSAGE); + } + } + + static Object[] lookAndFeels = { + "Metal (Ocean)", "Metal (DefaultMetalTheme)", + }; + static Object[] lfs = { + new MetalLookAndFeel() { + protected void createDefaultTheme() { + setCurrentTheme(oceanTheme); + } + }, + new MetalLookAndFeel() { + protected void createDefaultTheme() { + MetalTheme dt = new DefaultMetalTheme(); + setCurrentTheme(dt); + } + }, + }; + } +} Binary files /srv/release.debian.org/tmp/USNPHwmYvu/openjdk-21-21.0.8+9/test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/duke.gif and /srv/release.debian.org/tmp/emfaCnEiU2/openjdk-21-21.0.9+10/test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/duke.gif differ diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/text/BoxView/bug6494356.java openjdk-21-21.0.9+10/test/jdk/javax/swing/text/BoxView/bug6494356.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/text/BoxView/bug6494356.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/text/BoxView/bug6494356.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 6494356 + * @key headful + * @summary Test that BoxView.layout() is not called with negative arguments + * @run main bug6494356 + */ + +import java.awt.Dimension; +import java.awt.Toolkit; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.Writer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.concurrent.CountDownLatch; +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import javax.swing.text.Element; +import javax.swing.text.StyleConstants; +import javax.swing.text.View; +import javax.swing.text.ViewFactory; +import javax.swing.text.html.HTML; +import javax.swing.text.html.HTMLEditorKit; +import javax.swing.text.html.ParagraphView; + +public class bug6494356 { + static JEditorPane ep; + private static final CountDownLatch latch = new CountDownLatch(1); + + public static void main(final String[] args) throws Exception { + final Path file = Path.of("bug6494356.html"); + try (Writer writer = Files.newBufferedWriter(file)) { + writer.write("

Paragraph

"); + } + try { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + ep = new JEditorPane(); + ep.setEditorKitForContentType("text/html", new MyEditorKit()); + ep.addPropertyChangeListener("page", new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent pce) { + if (pce.getPropertyName().equals("page")) { + latch.countDown(); + } + } + }); + JFrame f = new JFrame(); + f.setTitle("6494356"); + f.setSize(new Dimension( + Toolkit.getDefaultToolkit().getScreenSize().width, 600)); + f.setContentPane(ep); + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + f.setVisible(true); + try { + ep.setPage("file:" + file); + } catch (Exception ex) { + testPassed = false; + throw new RuntimeException(ex); + } + } + }); + + latch.await(); + if (!testPassed) { + throw new RuntimeException("test failed."); + } + } finally { + Files.delete(file); + } + System.out.println("6494356 OK"); + } + + static volatile boolean testPassed = true; + + static class MyEditorKit extends HTMLEditorKit { + static class MyViewFactory extends HTMLFactory { + public View create(Element elem) { + HTML.Tag tag = (HTML.Tag) elem.getAttributes().getAttribute( + StyleConstants.NameAttribute); + if ((tag != null) && (tag == HTML.Tag.P)) { + return new MyParagraphView(elem); + } else { + return super.create(elem); + } + } + + static class MyParagraphView extends ParagraphView { + MyParagraphView(Element elem) { + super(elem); + } + + protected void layout(int width, int height) { + if ((width < 0) || (height < 0)) { + testPassed = false; + throw new RuntimeException("w=" + width + " h=" + height); + } + super.layout(width, height); + } + } + + } + + final ViewFactory viewFactory = new MyViewFactory(); + + public ViewFactory getViewFactory() { + return viewFactory; + } + } + +} + diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/text/GlyphView/4984669/bug4984669.html openjdk-21-21.0.9+10/test/jdk/javax/swing/text/GlyphView/4984669/bug4984669.html --- openjdk-21-21.0.8+9/test/jdk/javax/swing/text/GlyphView/4984669/bug4984669.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/text/GlyphView/4984669/bug4984669.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ - - - - -The four lines printed above in a bold typeface should all be underlined. -It is a bug if any of these lines is underlined only partially. -The very first line should not be underlined at all. - - diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/text/GlyphView/4984669/bug4984669.java openjdk-21-21.0.9+10/test/jdk/javax/swing/text/GlyphView/4984669/bug4984669.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/text/GlyphView/4984669/bug4984669.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/text/GlyphView/4984669/bug4984669.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* @test - @bug 4984669 8002148 - @summary Tests HTML underlining - @author Peter Zhelezniakov - @run applet/manual=yesno bug4984669.html -*/ -import javax.swing.*; -import javax.swing.text.*; - -public class bug4984669 extends JApplet -{ - public void init() { - JEditorPane pane = new JEditorPane(); - this.getContentPane().add(new JScrollPane(pane)); - pane.setEditorKit(new StyledEditorKit()); - - try { - pane.getDocument().insertString(0,"12 \n",null); - MutableAttributeSet attrs = new SimpleAttributeSet(); - - StyleConstants.setFontSize(attrs, 36); - StyleConstants.setBold(attrs, true); - StyleConstants.setUnderline(attrs, true); - pane.getDocument().insertString(6, "aa\n", attrs); - pane.getDocument().insertString(9, "bbb\n", attrs); - pane.getDocument().insertString(13, "cccc\n", attrs); - pane.getDocument().insertString(18, "ddddd\n", attrs); - } catch (Exception e) { - throw new Error("Failed: Unexpected Exception", e); - } - } -} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/text/GlyphView/htmlUnderliningTest.java openjdk-21-21.0.9+10/test/jdk/javax/swing/text/GlyphView/htmlUnderliningTest.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/text/GlyphView/htmlUnderliningTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/text/GlyphView/htmlUnderliningTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.JEditorPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.text.MutableAttributeSet; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledEditorKit; + +/* @test + * @bug 4984669 8002148 + * @summary Tests HTML underlining + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual htmlUnderliningTest + */ + +public class htmlUnderliningTest { + public static void main(String[] args) throws Exception { + String testInstructions = """ + The four lines printed in a bold typeface should all be underlined. + It is a bug if any of these lines is underlined only partially. + The very first line should not be underlined at all. + """; + + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(testInstructions) + .rows(4) + .columns(35) + .splitUI(htmlUnderliningTest::initializeTest) + .build() + .awaitAndCheck(); + } + + public static JPanel initializeTest() { + JPanel panel = new JPanel(); + JEditorPane pane = new JEditorPane(); + panel.add(new JScrollPane(pane)); + pane.setEditorKit(new StyledEditorKit()); + + try { + pane.getDocument().insertString(0, "12 \n", null); + MutableAttributeSet attrs = new SimpleAttributeSet(); + + StyleConstants.setFontSize(attrs, 36); + StyleConstants.setBold(attrs, true); + StyleConstants.setUnderline(attrs, true); + pane.getDocument().insertString(6, "aa\n", attrs); + pane.getDocument().insertString(9, "bbb\n", attrs); + pane.getDocument().insertString(13, "cccc\n", attrs); + pane.getDocument().insertString(18, "ddddd\n", attrs); + } catch (Exception e) { + throw new Error("Failed: Unexpected Exception", e); + } + return panel; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/text/html/TableView/7030332/bug7030332.html openjdk-21-21.0.9+10/test/jdk/javax/swing/text/html/TableView/7030332/bug7030332.html --- openjdk-21-21.0.8+9/test/jdk/javax/swing/text/html/TableView/7030332/bug7030332.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/text/html/TableView/7030332/bug7030332.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ - - - - - - -Compare Golden Images with rendered JEditorPane. -They should looks simalar in each line. Pay attention to: - -1. Border width around tables -2. Border width around cells - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/swing/text/html/TableView/7030332/bug7030332.java openjdk-21-21.0.9+10/test/jdk/javax/swing/text/html/TableView/7030332/bug7030332.java --- openjdk-21-21.0.8+9/test/jdk/javax/swing/text/html/TableView/7030332/bug7030332.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/swing/text/html/TableView/7030332/bug7030332.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,18 +21,49 @@ * questions. */ -/* @test - @bug 7030332 - @summary Default borders in tables looks incorrect JEditorPane - @author Pavel Porvatov - * @run applet/manual=yesno bug7030332.html -*/ +import java.awt.GridLayout; +import javax.swing.JComponent; +import javax.swing.JEditorPane; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.ImageIcon; +import javax.swing.SwingConstants; -import javax.swing.*; -import java.awt.*; import java.net.URL; -public class bug7030332 extends JApplet { +/* @test + * @bug 7030332 + * @summary Default borders in tables looks incorrect + * when rendered using JEditorPane + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual/othervm -Dsun.java2d.uiScale=1 bug7030332 + */ + +public class bug7030332 { + public static void main(String[] args) throws Exception { + String testInstructions = """ + Compare Golden Images with rendered JEditorPane. + They should look similar in each line. + Pay attention to: + 1. Border width around tables + 2. Border width around cells + Note: The test was written before there was hidpi. + Hence we are considering the border width being + "similar enough" with 1.0 scaling. + """; + + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(testInstructions) + .rows(9) + .columns(35) + .splitUI(bug7030332::createContentPane) + .build() + .awaitAndCheck(); + } + public static final String[] HTML_SAMPLES = new String[]{ "
Column1Column2
", "
Column1Column2
", @@ -40,35 +71,7 @@ "
Column1Column2
", }; - public static void main(String[] args) throws Exception { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - JFrame frame = new JFrame(); - - frame.setContentPane(createContentPane()); - frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - frame.setSize(600, 400); - frame.setLocationRelativeTo(null); - - frame.setVisible(true); - - } - }); - } - - public void init() { - try { - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - setContentPane(createContentPane()); - } - }); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private static Container createContentPane() { + private static JComponent createContentPane() { JPanel result = new JPanel(new GridLayout(HTML_SAMPLES.length + 1, 3, 10, 10)); result.add(new JLabel("Html code")); @@ -77,22 +80,16 @@ for (int i = 0; i < HTML_SAMPLES.length; i++) { String htmlSample = HTML_SAMPLES[i]; - JTextArea textArea = new JTextArea(htmlSample); - textArea.setLineWrap(true); - result.add(textArea); String imageName = "sample" + i + ".png"; URL resource = bug7030332.class.getResource(imageName); - result.add(resource == null ? new JLabel(imageName + " not found") : new JLabel(new ImageIcon(resource), SwingConstants.LEFT)); - result.add(new JEditorPane("text/html", htmlSample)); } - return result; } } diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/xml/crypto/dsig/GenerationTests.java openjdk-21-21.0.9+10/test/jdk/javax/xml/crypto/dsig/GenerationTests.java --- openjdk-21-21.0.8+9/test/jdk/javax/xml/crypto/dsig/GenerationTests.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/xml/crypto/dsig/GenerationTests.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /** * @test * @bug 4635230 6283345 6303830 6824440 6867348 7094155 8038184 8038349 8046949 - * 8046724 8079693 8177334 8205507 8210736 8217878 8241306 8305972 + * 8046724 8079693 8177334 8205507 8210736 8217878 8241306 8305972 8344137 * @summary Basic unit tests for generating XML Signatures with JSR 105 * @modules java.base/sun.security.util * java.base/sun.security.x509 @@ -99,6 +99,7 @@ private static SignatureMethod dsaSha1, dsaSha256, rsaSha1, rsaSha224, rsaSha256, rsaSha384, rsaSha512, ecdsaSha1, ecdsaSha224, ecdsaSha256, ecdsaSha384, ecdsaSha512, + ecdsaSha3_224, ecdsaSha3_256, ecdsaSha3_384, ecdsaSha3_512, hmacSha1, hmacSha224, hmacSha256, hmacSha384, hmacSha512, rsaSha1mgf1, rsaSha224mgf1, rsaSha256mgf1, rsaSha384mgf1, rsaSha512mgf1, rsaSha3_224mgf1, rsaSha3_256mgf1, rsaSha3_384mgf1, rsaSha3_512mgf1, @@ -305,6 +306,10 @@ test_create_signature_enveloping_p256_sha256(); test_create_signature_enveloping_p256_sha384(); test_create_signature_enveloping_p256_sha512(); + test_create_signature_enveloping_p256_sha3_224(); + test_create_signature_enveloping_p256_sha3_256(); + test_create_signature_enveloping_p256_sha3_384(); + test_create_signature_enveloping_p256_sha3_512(); test_create_signature_enveloping_p384_sha1(); test_create_signature_enveloping_p521_sha1(); test_create_signature_enveloping_ed25519(); @@ -559,6 +564,10 @@ ecdsaSha256 = fac.newSignatureMethod(SignatureMethod.ECDSA_SHA256, null); ecdsaSha384 = fac.newSignatureMethod(SignatureMethod.ECDSA_SHA384, null); ecdsaSha512 = fac.newSignatureMethod(SignatureMethod.ECDSA_SHA512, null); + ecdsaSha3_224 = fac.newSignatureMethod("http://www.w3.org/2021/04/xmldsig-more#ecdsa-sha3-224", null); + ecdsaSha3_256 = fac.newSignatureMethod("http://www.w3.org/2021/04/xmldsig-more#ecdsa-sha3-256", null); + ecdsaSha3_384 = fac.newSignatureMethod("http://www.w3.org/2021/04/xmldsig-more#ecdsa-sha3-384", null); + ecdsaSha3_512 = fac.newSignatureMethod("http://www.w3.org/2021/04/xmldsig-more#ecdsa-sha3-512", null); ed25519 = fac.newSignatureMethod(SignatureMethod.ED25519, null); ed448 = fac.newSignatureMethod(SignatureMethod.ED448, null); @@ -891,6 +900,34 @@ getECPrivateKey("P256"), kvks, false, true); System.out.println(); } + + static void test_create_signature_enveloping_p256_sha3_224() throws Exception { + System.out.println("* Generating signature-enveloping-p256-sha3_224.xml"); + test_create_signature_enveloping(sha1, ecdsaSha3_224, p256ki, + getECPrivateKey("P256"), kvks, false, true); + System.out.println(); + } + + static void test_create_signature_enveloping_p256_sha3_256() throws Exception { + System.out.println("* Generating signature-enveloping-p256-sha3_256.xml"); + test_create_signature_enveloping(sha1, ecdsaSha3_256, p256ki, + getECPrivateKey("P256"), kvks, false, true); + System.out.println(); + } + + static void test_create_signature_enveloping_p256_sha3_384() throws Exception { + System.out.println("* Generating signature-enveloping-p256-sha3_384.xml"); + test_create_signature_enveloping(sha1, ecdsaSha3_384, p256ki, + getECPrivateKey("P256"), kvks, false, true); + System.out.println(); + } + + static void test_create_signature_enveloping_p256_sha3_512() throws Exception { + System.out.println("* Generating signature-enveloping-p256-sha3_512.xml"); + test_create_signature_enveloping(sha1, ecdsaSha3_512, p256ki, + getECPrivateKey("P256"), kvks, false, true); + System.out.println(); + } static void test_create_signature_enveloping_p384_sha1() throws Exception { System.out.println("* Generating signature-enveloping-p384-sha1.xml"); diff -Nru openjdk-21-21.0.8+9/test/jdk/javax/xml/crypto/dsig/PSS.java openjdk-21-21.0.9+10/test/jdk/javax/xml/crypto/dsig/PSS.java --- openjdk-21-21.0.8+9/test/jdk/javax/xml/crypto/dsig/PSS.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/javax/xml/crypto/dsig/PSS.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import jdk.test.lib.Asserts; +import jdk.test.lib.security.XMLUtils; + +import javax.xml.crypto.dsig.DigestMethod; +import javax.xml.crypto.dsig.SignatureMethod; +import javax.xml.crypto.dsig.spec.RSAPSSParameterSpec; +import java.security.KeyPairGenerator; +import java.security.spec.MGF1ParameterSpec; +import java.security.spec.PSSParameterSpec; + +/** + * @test + * @bug 8344137 + * @summary check RSASSA-PSS key + * @library /test/lib + * @modules java.xml.crypto + */ +public class PSS { + + public static void main(String[] args) throws Exception { + + var doc = XMLUtils.string2doc("TextRaw"); + var kpg = KeyPairGenerator.getInstance("RSASSA-PSS"); + kpg.initialize(2048); + var keyPair = kpg.generateKeyPair(); + + var pspec = new PSSParameterSpec("SHA-384", "MGF1", + MGF1ParameterSpec.SHA512, 48, + PSSParameterSpec.TRAILER_FIELD_BC); + + var signed = XMLUtils.signer(keyPair.getPrivate(), keyPair.getPublic()) + .dm(DigestMethod.SHA384) + .sm(SignatureMethod.RSA_PSS, new RSAPSSParameterSpec(pspec)) + .sign(doc); + + Asserts.assertTrue(XMLUtils.validator().validate(signed)); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/jdk/internal/platform/cgroup/TestSystemSettings.java openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/cgroup/TestSystemSettings.java --- openjdk-21-21.0.8+9/test/jdk/jdk/internal/platform/cgroup/TestSystemSettings.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/cgroup/TestSystemSettings.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024, Red Hat, Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 cgroups + * @requires (os.family == "linux" & !vm.musl) + * @requires vm.flagless + * @library /test/lib + * @build TestSystemSettings + * @run main/othervm TestSystemSettings + */ + +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; + +public class TestSystemSettings { + + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XshowSettings:system", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + output.shouldContain("System not containerized."); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java --- openjdk-21-21.0.8+9/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java 2025-10-13 07:49:24.000000000 +0000 @@ -27,6 +27,7 @@ * @summary Verify that -XshowSettings:system works * @key cgroups * @requires docker.support + * @requires !vm.asan * @library /test/lib * @run main/timeout=360 TestDockerBasic */ diff -Nru openjdk-21-21.0.8+9/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java --- openjdk-21-21.0.8+9/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java 2025-10-13 07:49:24.000000000 +0000 @@ -35,6 +35,7 @@ * @key cgroups * @summary Test JDK Metrics class when running inside docker container * @requires docker.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform * @build MetricsCpuTester diff -Nru openjdk-21-21.0.8+9/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java --- openjdk-21-21.0.8+9/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java 2025-10-13 07:49:24.000000000 +0000 @@ -33,6 +33,7 @@ * @key cgroups * @summary Test JDK Metrics class when running inside docker container * @requires docker.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform * @build MetricsMemoryTester diff -Nru openjdk-21-21.0.8+9/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java --- openjdk-21-21.0.8+9/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java 2025-10-13 07:49:24.000000000 +0000 @@ -26,6 +26,7 @@ * @key cgroups * @bug 8242480 * @requires docker.support + * @requires !vm.asan * @library /test/lib * @build GetFreeSwapSpaceSize * @run driver TestGetFreeSwapSpaceSize diff -Nru openjdk-21-21.0.8+9/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java --- openjdk-21-21.0.8+9/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java 2025-10-13 07:49:24.000000000 +0000 @@ -29,6 +29,7 @@ * @key cgroups * @summary Test container limits updating as they get updated at runtime without restart * @requires docker.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform * @build LimitUpdateChecker diff -Nru openjdk-21-21.0.8+9/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java --- openjdk-21-21.0.8+9/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java 2025-10-13 07:49:24.000000000 +0000 @@ -28,6 +28,7 @@ * @summary Test JDK Metrics class when running inside a docker container with limited pids * @bug 8266490 * @requires docker.support + * @requires !vm.asan * @library /test/lib * @build TestPidsLimit * @run driver TestPidsLimit diff -Nru openjdk-21-21.0.8+9/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java --- openjdk-21-21.0.8+9/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java 2025-10-13 07:49:24.000000000 +0000 @@ -26,6 +26,7 @@ * @key cgroups * @summary Test JDK Metrics class when running inside docker container * @requires docker.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform * @run main TestSystemMetrics diff -Nru openjdk-21-21.0.8+9/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java --- openjdk-21-21.0.8+9/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java 2025-10-13 07:49:24.000000000 +0000 @@ -25,6 +25,7 @@ * @test * @summary UseContainerSupport flag should reflect Metrics being available * @requires docker.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform * @build CheckUseContainerSupport diff -Nru openjdk-21-21.0.8+9/test/jdk/jdk/jfr/api/metadata/annotations/TestPeriod.java openjdk-21-21.0.9+10/test/jdk/jdk/jfr/api/metadata/annotations/TestPeriod.java --- openjdk-21-21.0.8+9/test/jdk/jdk/jfr/api/metadata/annotations/TestPeriod.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/jdk/jfr/api/metadata/annotations/TestPeriod.java 2025-10-13 07:49:24.000000000 +0000 @@ -26,6 +26,7 @@ import jdk.jfr.Event; import jdk.jfr.EventType; import jdk.jfr.Period; +import jdk.jfr.FlightRecorder; import jdk.test.lib.Asserts; import jdk.test.lib.jfr.Events; @@ -34,7 +35,7 @@ * @key jfr * @requires vm.hasJFR * @library /test/lib - * @run main/othervm jdk.jfr.api.metadata.annotations.TestLabel + * @run main/othervm jdk.jfr.api.metadata.annotations.TestPeriod */ public class TestPeriod { @@ -44,6 +45,7 @@ public static void main(String[] args) throws Exception { EventType periodicEvent = EventType.getEventType(PeriodicEvent.class); + FlightRecorder.addPeriodicEvent(PeriodicEvent.class, () -> {}); String defaultValue = Events.getSetting(periodicEvent, Period.NAME).getDefaultValue(); Asserts.assertEQ(defaultValue, "47 s", "Incorrect default value for period"); } diff -Nru openjdk-21-21.0.8+9/test/jdk/jdk/jfr/api/metadata/settingdescriptor/TestGetContentType.java openjdk-21-21.0.9+10/test/jdk/jdk/jfr/api/metadata/settingdescriptor/TestGetContentType.java --- openjdk-21-21.0.8+9/test/jdk/jdk/jfr/api/metadata/settingdescriptor/TestGetContentType.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/jdk/jfr/api/metadata/settingdescriptor/TestGetContentType.java 2025-10-13 07:49:24.000000000 +0000 @@ -38,7 +38,7 @@ * @key jfr * @requires vm.hasJFR * @library /test/lib /test/jdk - * @run main/othervm jdk.jfr.api.metadata.settingdescriptor.TestGetDescription + * @run main/othervm jdk.jfr.api.metadata.settingdescriptor.TestGetContentType */ public class TestGetContentType { @@ -49,7 +49,7 @@ Asserts.assertNull(plain.getContentType()); SettingDescriptor annotatedType = Events.getSetting(type, "annotatedType"); - Asserts.assertNull(annotatedType.getContentType(), Timestamp.class.getName()); + Asserts.assertEquals(annotatedType.getContentType(), Timestamp.class.getName()); SettingDescriptor newName = Events.getSetting(type, "newName"); Asserts.assertEquals(newName.getContentType(), Timespan.class.getName()); @@ -58,7 +58,7 @@ Asserts.assertNull(overridden.getContentType()); SettingDescriptor protectedBase = Events.getSetting(type, "protectedBase"); - Asserts.assertEquals(protectedBase.getContentType(), Frequency.class); + Asserts.assertEquals(protectedBase.getContentType(), Frequency.class.getName()); SettingDescriptor publicBase = Events.getSetting(type, "publicBase"); Asserts.assertEquals(publicBase.getContentType(), Timestamp.class.getName()); diff -Nru openjdk-21-21.0.8+9/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java openjdk-21-21.0.9+10/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java --- openjdk-21-21.0.8+9/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java 2025-10-13 07:49:24.000000000 +0000 @@ -417,50 +417,6 @@ */ /* - * @test id=affirmtrustcommercialca - * @bug 8040012 - * @summary Interoperability tests with AffirmTrust Commercial CA - * @library /test/lib - * @build jtreg.SkippedException ValidatePathWithURL CAInterop - * @run main/othervm/manual -Djava.security.debug=certpath,ocsp CAInterop affirmtrustcommercialca OCSP - * @run main/othervm/manual -Djava.security.debug=certpath,ocsp -Dcom.sun.security.ocsp.useget=false CAInterop affirmtrustcommercialca OCSP - * @run main/othervm/manual -Djava.security.debug=certpath CAInterop affirmtrustcommercialca CRL - */ - -/* - * @test id=affirmtrustnetworkingca - * @bug 8040012 - * @summary Interoperability tests with AffirmTrust Networking CA - * @library /test/lib - * @build jtreg.SkippedException ValidatePathWithURL CAInterop - * @run main/othervm/manual -Djava.security.debug=certpath,ocsp CAInterop affirmtrustnetworkingca OCSP - * @run main/othervm/manual -Djava.security.debug=certpath,ocsp -Dcom.sun.security.ocsp.useget=false CAInterop affirmtrustnetworkingca OCSP - * @run main/othervm/manual -Djava.security.debug=certpath CAInterop affirmtrustnetworkingca CRL - */ - -/* - * @test id=affirmtrustpremiumca - * @bug 8040012 - * @summary Interoperability tests with AffirmTrust Premium CA - * @library /test/lib - * @build jtreg.SkippedException ValidatePathWithURL CAInterop - * @run main/othervm/manual -Djava.security.debug=certpath,ocsp CAInterop affirmtrustpremiumca OCSP - * @run main/othervm/manual -Djava.security.debug=certpath,ocsp -Dcom.sun.security.ocsp.useget=false CAInterop affirmtrustpremiumca OCSP - * @run main/othervm/manual -Djava.security.debug=certpath CAInterop affirmtrustpremiumca CRL - */ - -/* - * @test id=affirmtrustpremiumeccca - * @bug 8040012 - * @summary Interoperability tests with AffirmTrust Premium ECC CA - * @library /test/lib - * @build jtreg.SkippedException ValidatePathWithURL CAInterop - * @run main/othervm/manual -Djava.security.debug=certpath,ocsp CAInterop affirmtrustpremiumeccca OCSP - * @run main/othervm/manual -Djava.security.debug=certpath,ocsp -Dcom.sun.security.ocsp.useget=false CAInterop affirmtrustpremiumeccca OCSP - * @run main/othervm/manual -Djava.security.debug=certpath CAInterop affirmtrustpremiumeccca CRL - */ - -/* * @test id=teliarootcav2 * @bug 8317373 * @summary Interoperability tests with Telia Root CA V2 @@ -726,20 +682,6 @@ new CATestURLs("https://valid.servicesca.dhimyotis.com", "https://revoked.servicesca.dhimyotis.com"); - // These are listed at https://www.affirmtrust.com/resources/ - case "affirmtrustcommercialca" -> - new CATestURLs("https://validcommercial.affirmtrust.com", - "https://revokedcommercial.affirmtrust.com"); - case "affirmtrustnetworkingca" -> - new CATestURLs("https://validnetworking.affirmtrust.com", - "https://revokednetworking.affirmtrust.com"); - case "affirmtrustpremiumca" -> - new CATestURLs("https://validpremium.affirmtrust.com", - "https://revokedpremium.affirmtrust.com"); - case "affirmtrustpremiumeccca" -> - new CATestURLs("https://validpremiumecc.affirmtrust.com", - "https://revokedpremiumecc.affirmtrust.com"); - case "teliarootcav2" -> new CATestURLs("https://juolukka.cover.telia.fi:10600", "https://juolukka.cover.telia.fi:10601"); diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/java2d/Disposer/TestDisposerRace.java openjdk-21-21.0.9+10/test/jdk/sun/java2d/Disposer/TestDisposerRace.java --- openjdk-21-21.0.8+9/test/jdk/sun/java2d/Disposer/TestDisposerRace.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/java2d/Disposer/TestDisposerRace.java 2025-10-13 07:49:24.000000000 +0000 @@ -23,6 +23,7 @@ import java.util.LinkedList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Supplier; import javax.swing.SwingUtilities; import sun.java2d.Disposer; @@ -39,16 +40,23 @@ private static final AtomicInteger recordsCount = new AtomicInteger(); private static volatile boolean disposerDone = false; + private static final String KO_OVERFLOW = "Some records have not been disposed!"; + private static final String KO_UNDERFLOW = "Disposed more records than were added!"; + public static void main(String[] args) throws Exception { - TestDisposerRace test = new TestDisposerRace(); - test.run(); + new TestDisposerRace().run(); checkRecordsCountIsSane(); if (recordsCount.get() > 0) { + System.err.println(KO_OVERFLOW); // In case the next line fails to allocate due to OOME throw new RuntimeException("Some records (" + recordsCount + ") have not been disposed"); } } + interface ThrowingRunnable { + void run() throws E; + } + TestDisposerRace() { addRecordsToDisposer(30_000); } @@ -56,14 +64,14 @@ void run() throws Exception { generateOOME(); for (int i = 0; i < 1000; ++i) { - SwingUtilities.invokeAndWait(Disposer::pollRemove); - if (i % 10 == 0) { - // Adding records will race with the diposer trying to remove them + retryOnOOME(() -> SwingUtilities.invokeAndWait(Disposer::pollRemove)); + + // Adding records will race with the diposer trying to remove them + if (i % 10 == 0) addRecordsToDisposer(1000); - } } - Disposer.addObjectRecord(new Object(), new FinalDisposerRecord()); + retryOnOOME(() -> Disposer.addObjectRecord(new Object(), new FinalDisposerRecord())); while (!disposerDone) { generateOOME(); @@ -72,18 +80,45 @@ private static void checkRecordsCountIsSane() { if (recordsCount.get() < 0) { - throw new RuntimeException("Disposed more records than were added"); + throw new RuntimeException(KO_UNDERFLOW); + } + } + + private static T retryOnOOME(Supplier allocator) { + for(;;) { + try { + return allocator.get(); + } catch (OutOfMemoryError ignored1) { + try { + Thread.sleep(1); // Give GC a little chance to run + } catch (InterruptedException ignored2) {} + } + } + } + + private static void retryOnOOME(ThrowingRunnable tr) throws E { + for(;;) { + try { + tr.run(); + break; + } catch (OutOfMemoryError ignored1) { + try { + Thread.sleep(1); // Give GC a little chance to run + } catch (InterruptedException ignored2) {} + } } } private void addRecordsToDisposer(int count) { checkRecordsCountIsSane(); - recordsCount.addAndGet(count); + MyDisposerRecord disposerRecord = retryOnOOME(MyDisposerRecord::new); - MyDisposerRecord disposerRecord = new MyDisposerRecord(); - for (int i = 0; i < count; i++) { - Disposer.addObjectRecord(new Object(), disposerRecord); + while(count > 0) { + recordsCount.incrementAndGet(); // pre-add to make sure it doesn't go negative + var o = retryOnOOME(Object::new); + retryOnOOME(() -> Disposer.addObjectRecord(o, disposerRecord)); + --count; } } @@ -106,8 +141,8 @@ } private static void generateOOME() throws Exception { - final List leak = new LinkedList<>(); try { + final List leak = new LinkedList<>(); while (true) { leak.add(new byte[1024 * 1024]); } diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/java2d/loops/CopyAreaSpeed.html openjdk-21-21.0.9+10/test/jdk/sun/java2d/loops/CopyAreaSpeed.html --- openjdk-21-21.0.8+9/test/jdk/sun/java2d/loops/CopyAreaSpeed.html 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/java2d/loops/CopyAreaSpeed.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ - - - - - CopyAreaSpeed - - - -

CopyAreaSpeed

-
-
Thanh Nguyen
- - -Last modified: Tue Jan 19 16:18:37 PST 1999 - - - - diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/java2d/loops/CopyAreaSpeed.java openjdk-21-21.0.9+10/test/jdk/sun/java2d/loops/CopyAreaSpeed.java --- openjdk-21-21.0.8+9/test/jdk/sun/java2d/loops/CopyAreaSpeed.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/java2d/loops/CopyAreaSpeed.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -20,6 +20,17 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Rectangle; +import javax.swing.JFrame; +import javax.swing.JOptionPane; + +import java.util.Date; + /* * @test * @bug 4189070 @@ -27,46 +38,54 @@ * copyArea calls to be completed. Because the performance measurement is * relative, this code only provides a benchmark to run with different releases * to compare the outcomes. - * @run applet/manual=done CopyAreaSpeed.html + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual CopyAreaSpeed */ -import java.applet.Applet; -import java.awt.*; -import java.awt.event.*; -import java.util.*; +public class CopyAreaSpeed { + public static void main(String args[]) throws Exception { + String instructions = """ + This test prints out the time it takes for a certain amount + of copyArea calls to be completed. Because the performance + measurement is relative, this code only provides a benchmark + to run with different releases to compare the outcomes. + """; + + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(instructions) + .rows(5) + .columns(35) + .testUI(CopyAreaSpeed::initialize) + .build() + .awaitAndCheck(); + } + + public static JFrame initialize() { + JFrame frame = new JFrame("Copy Area Test"); + frame.add(new CopyAreaSpeedTest()); + frame.setSize(300, 320); + frame.setVisible(true); + return frame; + } +} -public class CopyAreaSpeed extends Applet implements Runnable { +class CopyAreaSpeedTest extends Container implements Runnable { int top = 0; + public static String result; - public void init() { - } - - public CopyAreaSpeed() - { + public CopyAreaSpeedTest() { super(); - String[] instructions = - { - "This test prints out the time it takes for a certain amount ", - "of copyArea calls to be completed. Because the performance ", - "measurement is relative, this code only provides a benchmark ", - "to run with different releases to compare the outcomes." - }; - Sysout.createDialogWithInstructions( instructions ); (new Thread(this)).start(); - Button bt = new Button("Hello"); - bt.setBounds(50, 10, 50, 22); - bt.setVisible(false); - add(bt); } - public void update(Graphics g) - { + public void update(Graphics g) { paint(g); } - public void paint(Graphics g) - { - synchronized(this) { + public void paint(Graphics g) { + synchronized (this) { Rectangle rct = g.getClipBounds(); g.setColor(Color.white); g.fillRect(rct.x, rct.y, rct.width, rct.height); @@ -78,19 +97,18 @@ if (y > rct.y) { int z = y / 20 + top; g.drawString("" + z, 10, y); - } /* endif */ - } // endfor + } + } } } static long millsec(Date s, Date e) { long ts = s.getTime(); long te = e.getTime(); - return te-ts; + return te - ts; } - public void run() - { + public void run() { int count = 1000; int loops = count; Date start; @@ -100,7 +118,7 @@ while (count-- > 0) { Dimension dm = getSize(); if (dm != null && dm.width != 0 && dm.height != 0) { - synchronized(this) { + synchronized (this) { top++; Graphics g = getGraphics(); g.copyArea(0, 20, dm.width, dm.height - 20, 0, -20); @@ -111,158 +129,15 @@ } try { Thread.sleep(1); - } catch(Exception ex) { + } catch (Exception ex) { ex.printStackTrace(); } } end = new Date(); - Sysout.println("copyArea X "+loops+" = "+ millsec(start, end) + " msec"); - } - - public static void main(String args[]) { - Frame frm = new Frame("CopyAreaSpeed"); - frm.add(new CopyAreaSpeed()); - frm.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent ev) { - System.exit(0); - } - }); - frm.setSize(500, 500); - frm.show(); + Graphics g = getGraphics(); + g.setFont(getFont()); + g.setColor(Color.black); + result = "copyArea X " + loops + " = " + millsec(start, end) + " msec"; + JOptionPane.showMessageDialog(null, result); } } -/**************************************************** - Standard Test Machinery - DO NOT modify anything below -- it's a standard - chunk of code whose purpose is to make user - interaction uniform, and thereby make it simpler - to read and understand someone else's test. - ****************************************************/ - -/** - This is part of the standard test machinery. - It creates a dialog (with the instructions), and is the interface - for sending text messages to the user. - To print the instructions, send an array of strings to Sysout.createDialog - WithInstructions method. Put one line of instructions per array entry. - To display a message for the tester to see, simply call Sysout.println - with the string to be displayed. - This mimics System.out.println but works within the test harness as well - as standalone. - */ -class Sysout -{ - private static TestDialog dialog; - - public static void createDialogWithInstructions( String[] instructions ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - dialog.printInstructions( instructions ); - dialog.show(); - println( "Any messages for the tester will display here." ); - } - - public static void createDialog( ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - String[] defInstr = { "Instructions will appear here. ", "" } ; - dialog.printInstructions( defInstr ); - dialog.show(); - println( "Any messages for the tester will display here." ); - } - - - public static void printInstructions( String[] instructions ) - { - dialog.printInstructions( instructions ); - } - - - public static void println( String messageIn ) - { - dialog.displayMessage( messageIn ); - } - -}// Sysout class - -/** - This is part of the standard test machinery. It provides a place for the - test instructions to be displayed, and a place for interactive messages - to the user to be displayed. - To have the test instructions displayed, see Sysout. - To have a message to the user be displayed, see Sysout. - Do not call anything in this dialog directly. - */ -class TestDialog extends Dialog -{ - - TextArea instructionsText; - TextArea messageText; - int maxStringLength = 80; - - //DO NOT call this directly, go through Sysout - public TestDialog( Frame frame, String name ) - { - super( frame, name ); - int scrollBoth = TextArea.SCROLLBARS_BOTH; - instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); - add( "North", instructionsText ); - - messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); - add("South", messageText); - - pack(); - - show(); - }// TestDialog() - - //DO NOT call this directly, go through Sysout - public void printInstructions( String[] instructions ) - { - //Clear out any current instructions - instructionsText.setText( "" ); - - //Go down array of instruction strings - - String printStr, remainingStr; - for( int i=0; i < instructions.length; i++ ) - { - //chop up each into pieces maxSringLength long - remainingStr = instructions[ i ]; - while( remainingStr.length() > 0 ) - { - //if longer than max then chop off first max chars to print - if( remainingStr.length() >= maxStringLength ) - { - //Try to chop on a word boundary - int posOfSpace = remainingStr. - lastIndexOf( ' ', maxStringLength - 1 ); - - if( posOfSpace <= 0 ) { - posOfSpace = maxStringLength - 1; - } - - printStr = remainingStr.substring( 0, posOfSpace + 1 ); - remainingStr = remainingStr.substring( posOfSpace + 1 ); - } - else //else just print - { - printStr = remainingStr; - remainingStr = ""; - } - - instructionsText.append( printStr + "\n" ); - - }// while - - }// for - - }//printInstructions() - - //DO NOT call this directly, go through Sysout - public void displayMessage( String messageIn ) - { - messageText.append( messageIn + "\n" ); - } - -}// TestDialog class diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/net/www/protocol/file/NonLocalFtpFallback.java openjdk-21-21.0.9+10/test/jdk/sun/net/www/protocol/file/NonLocalFtpFallback.java --- openjdk-21-21.0.8+9/test/jdk/sun/net/www/protocol/file/NonLocalFtpFallback.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/net/www/protocol/file/NonLocalFtpFallback.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashSet; +import java.util.Random; +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * @test + * @bug 8353662 + * @summary Verify long-standing behavior of resolving non-local file URLs using FTP. + * @run junit NonLocalFtpFallback + */ + +public class NonLocalFtpFallback { + + // Port 21 may not be available, use an HTTP proxy with an ephemeral port + private HttpServer proxyServer; + + // The file requested in this test + private Path file; + + // FTP URIs requested by the proxy client + private Set uris = new HashSet<>(); + + /** + * Set up the HTTP proxy used for serving FTP in this test + * + * @throws IOException if an unexpected IO error occurs + */ + @BeforeEach + public void setup() throws IOException { + // Create a file with some random data + byte[] data = new byte[512]; + new Random().nextBytes(data); + file = Files.write(Path.of("ftp-file.txt"), data); + + // Set up an HTTP proxy server + proxyServer = HttpServer.create(); + // Bind to the loopback address with an ephemeral port + InetAddress loopbackAddress = InetAddress.getLoopbackAddress(); + proxyServer.bind(new InetSocketAddress(loopbackAddress, 0), 0); + // Handler for the FTP proxy request + proxyServer.createContext("/", new HttpHandler() { + @Override + public void handle(HttpExchange exchange) throws IOException { + // Record the URI requested + uris.add(exchange.getRequestURI()); + // Send the data + exchange.sendResponseHeaders(200, Files.size(file)); + try (OutputStream out = exchange.getResponseBody()) { + Files.copy(file, out); + } + // Complete the exchange + exchange.close(); + } + }); + // Start the proxy server + proxyServer.start(); + } + + /** + * Shut down proxy server and clean up files created + * + * @throws IOException if an unexpected IO error occurs + */ + @AfterEach + public void destroy() throws IOException { + proxyServer.stop(2); + Files.delete(file); + } + + /** + * Verifies the long-standing and unspecified FTP fallback feature where the file + * URL scheme handler attempts an FTP connection for non-local files. + * + * The non-local file URL used here is of the form file://127.0.0.1/path. Since the + * host component here is not equal to "localhost", this is considered a non-local + * URL. + * + * @throws Exception + */ + @Test + public void verifyNonLocalFtpFallback() throws Exception { + URL localURL = file.toUri().toURL(); + // We can use a fake host name here, no actual FTP request will be made + String hostname = "remotehost"; + URL nonLocalURL = new URL("file", hostname, localURL.getFile()); + + // Open the non-local file: URL connection using a proxy + Proxy proxy = new Proxy(Proxy.Type.HTTP, + new InetSocketAddress(proxyServer.getAddress().getAddress(), + proxyServer.getAddress().getPort())); + URLConnection con = nonLocalURL.openConnection(proxy); + + // Assert that the expected file content is retrieved + try (InputStream in = con.getInputStream()) { + byte[] retrived = in.readAllBytes(); + assertArrayEquals(Files.readAllBytes(file), retrived); + } + + // Assert that the expected FTP URI was requested in the HTTP proxy + assertEquals(1, uris.size()); + URL ftpURL = new URL("ftp", hostname, localURL.getFile()); + assertEquals(ftpURL.toURI(), uris.iterator().next()); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/net/www/protocol/http/UserCookie.java openjdk-21-21.0.9+10/test/jdk/sun/net/www/protocol/http/UserCookie.java --- openjdk-21-21.0.8+9/test/jdk/sun/net/www/protocol/http/UserCookie.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/net/www/protocol/http/UserCookie.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,9 @@ /* * @test * @bug 6439651 - * @modules jdk.httpserver - * @run main/othervm UserAuth * @summary Sending "Cookie" header with JRE 1.5.0_07 doesn't work anymore + * @modules jdk.httpserver + * @run main/othervm UserCookie */ import java.net.*; diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/DNSIdentities.java openjdk-21-21.0.9+10/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/DNSIdentities.java --- openjdk-21-21.0.8+9/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/DNSIdentities.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/DNSIdentities.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -893,7 +893,7 @@ TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); tmf.init(ks); - SSLContext ctx = SSLContext.getInstance("TLS"); + SSLContext ctx = SSLContext.getInstance("TLSv1.2"); if (keyCertStr != null) { KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPAddressIPIdentities.java openjdk-21-21.0.9+10/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPAddressIPIdentities.java --- openjdk-21-21.0.8+9/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPAddressIPIdentities.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPAddressIPIdentities.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -901,7 +901,7 @@ TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); tmf.init(ks); - SSLContext ctx = SSLContext.getInstance("TLS"); + SSLContext ctx = SSLContext.getInstance("TLSv1.2"); if (keyCertStr != null) { KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java openjdk-21-21.0.9+10/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java --- openjdk-21-21.0.8+9/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -900,7 +900,7 @@ TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); tmf.init(ks); - SSLContext ctx = SSLContext.getInstance("TLS"); + SSLContext ctx = SSLContext.getInstance("TLSv1.2"); if (keyCertStr != null) { KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/Identities.java openjdk-21-21.0.9+10/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/Identities.java --- openjdk-21-21.0.8+9/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/Identities.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/Identities.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -893,7 +893,7 @@ TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); tmf.init(ks); - SSLContext ctx = SSLContext.getInstance("TLS"); + SSLContext ctx = SSLContext.getInstance("TLSv1.2"); if (keyCertStr != null) { KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/krb5/auto/TEST.properties openjdk-21-21.0.9+10/test/jdk/sun/security/krb5/auto/TEST.properties --- openjdk-21-21.0.8+9/test/jdk/sun/security/krb5/auto/TEST.properties 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/krb5/auto/TEST.properties 2025-10-13 07:49:24.000000000 +0000 @@ -1,12 +1,12 @@ -modules java.base/jdk.internal.misc \ - java.base/sun.security.util \ - java.security.jgss/sun.security.jgss \ - java.security.jgss/sun.security.jgss.krb5 \ - java.security.jgss/sun.security.krb5:+open \ - java.security.jgss/sun.security.krb5.internal:+open \ - java.security.jgss/sun.security.krb5.internal.ccache \ - java.security.jgss/sun.security.krb5.internal.rcache \ - java.security.jgss/sun.security.krb5.internal.crypto \ - java.security.jgss/sun.security.krb5.internal.ktab \ - jdk.security.auth \ - jdk.security.jgss +modules = java.base/jdk.internal.misc \ + java.base/sun.security.util \ + java.security.jgss/sun.security.jgss \ + java.security.jgss/sun.security.jgss.krb5 \ + java.security.jgss/sun.security.krb5:+open \ + java.security.jgss/sun.security.krb5.internal:+open \ + java.security.jgss/sun.security.krb5.internal.ccache \ + java.security.jgss/sun.security.krb5.internal.rcache \ + java.security.jgss/sun.security.krb5.internal.crypto \ + java.security.jgss/sun.security.krb5.internal.ktab \ + jdk.security.auth \ + jdk.security.jgss diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java openjdk-21-21.0.9+10/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java 2025-10-13 07:49:24.000000000 +0000 @@ -28,7 +28,7 @@ * 8223499 8225392 8232019 8234245 8233223 8225068 8225069 8243321 8243320 * 8243559 8225072 8258630 8259312 8256421 8225081 8225082 8225083 8245654 * 8305975 8304760 8307134 8295894 8314960 8317373 8317374 8318759 8319187 - * 8321408 8316138 8341057 8303770 8350498 8359170 + * 8321408 8316138 8341057 8303770 8350498 8359170 8361212 * @summary Check root CA entries in cacerts file */ import java.io.ByteArrayInputStream; @@ -47,12 +47,12 @@ + File.separator + "security" + File.separator + "cacerts"; // The numbers of certs now. - private static final int COUNT = 113; + private static final int COUNT = 109; // SHA-256 of cacerts, can be generated with // shasum -a 256 cacerts | sed -e 's/../&:/g' | tr '[:lower:]' '[:upper:]' | cut -c1-95 private static final String CHECKSUM - = "18:36:49:15:B6:71:85:FF:F1:8E:C0:10:BE:0A:41:52:5B:DC:F7:B3:1F:51:7A:45:7D:7A:14:10:3A:59:42:4C"; + = "70:73:12:D3:E8:01:89:28:F5:3D:10:8E:45:34:F6:28:CB:BF:AD:18:19:6D:F1:A2:E7:28:84:30:0B:E1:A6:9F"; // Hex formatter to upper case with ":" delimiter private static final HexFormat HEX = HexFormat.ofDelimiter(":").withUpperCase(); @@ -193,14 +193,6 @@ "43:DF:57:74:B0:3E:7F:EF:5F:E4:0D:93:1A:7B:ED:F1:BB:2E:6B:42:73:8C:4E:6D:38:41:10:3D:3A:A7:F3:39"); put("entrustevca [jdk]", "73:C1:76:43:4F:1B:C6:D5:AD:F4:5B:0E:76:E7:27:28:7C:8D:E5:76:16:C1:E6:E6:14:1A:2B:2C:BC:7D:8E:4C"); - put("affirmtrustnetworkingca [jdk]", - "0A:81:EC:5A:92:97:77:F1:45:90:4A:F3:8D:5D:50:9F:66:B5:E2:C5:8F:CD:B5:31:05:8B:0E:17:F3:F0:B4:1B"); - put("affirmtrustpremiumca [jdk]", - "70:A7:3F:7F:37:6B:60:07:42:48:90:45:34:B1:14:82:D5:BF:0E:69:8E:CC:49:8D:F5:25:77:EB:F2:E9:3B:9A"); - put("affirmtrustcommercialca [jdk]", - "03:76:AB:1D:54:C5:F9:80:3C:E4:B2:E2:01:A0:EE:7E:EF:7B:57:B6:36:E8:A9:3C:9B:8D:48:60:C9:6F:5F:A7"); - put("affirmtrustpremiumeccca [jdk]", - "BD:71:FD:F6:DA:97:E4:CF:62:D1:64:7A:DD:25:81:B0:7D:79:AD:F8:39:7E:B4:EC:BA:9C:5E:84:88:82:14:23"); put("ttelesecglobalrootclass3ca [jdk]", "FD:73:DA:D3:1C:64:4F:F1:B4:3B:EF:0C:CD:DA:96:71:0B:9C:D9:87:5E:CA:7E:31:70:7A:F3:E9:6D:52:2B:BD"); put("ttelesecglobalrootclass2ca [jdk]", diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/mscapi/AllTypes.java openjdk-21-21.0.9+10/test/jdk/sun/security/mscapi/AllTypes.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/mscapi/AllTypes.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/mscapi/AllTypes.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,33 +45,12 @@ var nr = test("windows-root"); var nmu = test("windows-my-currentuser"); var nru = test("windows-root-currentuser"); - var hasAdminPrivileges = detectIfRunningWithAdminPrivileges(); - var nmm = adminTest("windows-my-localmachine", hasAdminPrivileges); - var nrm = adminTest("windows-root-localmachine", hasAdminPrivileges); + var nmm = test("windows-my-localmachine"); + var nrm = test("windows-root-localmachine"); Asserts.assertEQ(nm, nmu); Asserts.assertEQ(nr, nru); } - private static boolean detectIfRunningWithAdminPrivileges() { - try { - Process p = Runtime.getRuntime().exec("reg query \"HKU\\S-1-5-19\""); - p.waitFor(); - return (p.exitValue() == 0); - } - catch (Exception ex) { - System.out.println("Warning: unable to detect admin privileges, assuming none"); - return false; - } - } - - private static List adminTest(String type, boolean hasAdminPrivileges) throws Exception { - if (hasAdminPrivileges) { - return test(type); - } - System.out.println("Ignoring: " + type + " as it requires admin privileges"); - return null; - } - private static List test(String type) throws Exception { var stdType = "Windows-" + type.substring(8).toUpperCase(Locale.ROOT); SecurityTools.keytool("-storetype " + type + " -list") diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/pkcs11/PKCS11Test.java openjdk-21-21.0.9+10/test/jdk/sun/security/pkcs11/PKCS11Test.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/pkcs11/PKCS11Test.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/pkcs11/PKCS11Test.java 2025-10-13 07:49:24.000000000 +0000 @@ -31,7 +31,6 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.security.AlgorithmParameters; import java.security.InvalidAlgorithmParameterException; @@ -64,7 +63,6 @@ import jdk.test.lib.Utils; import jdk.test.lib.artifacts.Artifact; import jdk.test.lib.artifacts.ArtifactResolver; -import jdk.test.lib.artifacts.ArtifactResolverException; import jtreg.SkippedException; public abstract class PKCS11Test { @@ -245,10 +243,6 @@ static String getNSSLibDir(String library) throws Exception { Path libPath = getNSSLibPath(library); - if (libPath == null) { - return null; - } - String libDir = String.valueOf(libPath.getParent()) + File.separatorChar; System.out.println("nssLibDir: " + libDir); System.setProperty("pkcs11test.nss.libdir", libDir); @@ -262,12 +256,7 @@ static Path getNSSLibPath(String library) throws Exception { String osid = getOsId(); Path libraryName = Path.of(System.mapLibraryName(library)); - Path nssLibPath = fetchNssLib(osid, libraryName); - if (nssLibPath == null) { - throw new SkippedException("Warning: unsupported OS: " + osid - + ", please initialize NSS library location, skipping test"); - } - return nssLibPath; + return fetchNssLib(osid, libraryName); } private static String getOsId() { @@ -728,7 +717,7 @@ return data; } - private static Path fetchNssLib(String osId, Path libraryName) { + private static Path fetchNssLib(String osId, Path libraryName) throws IOException { switch (osId) { case "Windows-amd64-64": return fetchNssLib(WINDOWS_X64.class, libraryName); @@ -753,28 +742,13 @@ return fetchNssLib(LINUX_AARCH64.class, libraryName); } default: - return null; + throw new SkippedException("Unsupported OS: " + osId); } } - private static Path fetchNssLib(Class clazz, Path libraryName) { - Path path = null; - try { - Path p = ArtifactResolver.resolve(clazz).entrySet().stream() - .findAny().get().getValue(); - path = findNSSLibrary(p, libraryName); - } catch (ArtifactResolverException | IOException e) { - Throwable cause = e.getCause(); - if (cause == null) { - System.out.println("Cannot resolve artifact, " - + "please check if JIB jar is present in classpath."); - } else { - throw new RuntimeException("Fetch artifact failed: " + clazz - + "\nPlease make sure the artifact is available.", e); - } - } - Policy.setPolicy(null); // Clear the policy created by JIB if any - return path; + private static Path fetchNssLib(Class clazz, Path libraryName) throws IOException { + Path p = ArtifactResolver.fetchOne(clazz); + return findNSSLibrary(p, libraryName); } private static Path findNSSLibrary(Path path, Path libraryName) throws IOException { diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/pkcs11/SecmodTest.java openjdk-21-21.0.9+10/test/jdk/sun/security/pkcs11/SecmodTest.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/pkcs11/SecmodTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/pkcs11/SecmodTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,7 @@ useNSS(); LIBPATH = getNSSLibDir(); // load all the libraries except libnss3 into memory - if ((LIBPATH == null) || (!loadNSPR(LIBPATH))) { + if (!loadNSPR(LIBPATH)) { throw new SkippedException("Failed to load NSS libraries"); } diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/pkcs11/tls/TestKeyMaterialMisuse.java openjdk-21-21.0.9+10/test/jdk/sun/security/pkcs11/tls/TestKeyMaterialMisuse.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/pkcs11/tls/TestKeyMaterialMisuse.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/pkcs11/tls/TestKeyMaterialMisuse.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8349849 + * @summary Verify that SunTlsKeyMaterial doesn't crash on TLS 1.2 parameters + * @library /test/lib .. + * @modules java.base/sun.security.internal.spec + * @run main/othervm TestKeyMaterialMisuse + */ + +import sun.security.internal.spec.TlsKeyMaterialParameterSpec; +import sun.security.internal.spec.TlsKeyMaterialSpec; + +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +import java.security.Provider; +import java.security.ProviderException; +import java.util.Arrays; +import java.util.List; + +public class TestKeyMaterialMisuse extends PKCS11Test { + + public static void main(String[] args) throws Exception { + System.out.println("NSS Version: " + getNSSVersion()); + main(new TestKeyMaterialMisuse(), args); + } + + @Override + public void main(Provider provider) throws Exception { + byte[] keyBytes = new byte[48]; + Arrays.fill(keyBytes, (byte)1); + SecretKey master = new SecretKeySpec(keyBytes, "TlsMasterSecret"); + byte[] cr = "clientRandom".getBytes(); + byte[] sr = "serverRandom".getBytes(); + for (int minor : List.of(1, 3)) { + try { + // the algorithms below are deliberately reversed: + // - SunTls12KeyMaterial is used with TLS 1.0, + // - SunTlsKeyMaterial is used with TLS 1.2 + String algorithm = minor != 3 ? + "SunTls12KeyMaterial" : + "SunTlsKeyMaterial"; + System.out.println("Generating key material for version: " + + minor + " using algorithm: " + algorithm); + + KeyGenerator g = KeyGenerator.getInstance(algorithm, provider); + TlsKeyMaterialParameterSpec spec = + new TlsKeyMaterialParameterSpec( + master, 3, minor, cr, sr, + "AES", 32, 0, + 12, 32, + "SHA-256", 32, 128); + g.init(spec); + // generateKey crashed the JVM: + TlsKeyMaterialSpec km = (TlsKeyMaterialSpec) g.generateKey(); + System.out.println("Success!"); + } catch (ProviderException e) { + System.out.println("Got exception, not crash:"); + e.printStackTrace(); + } + } + } + +} diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java openjdk-21-21.0.9+10/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -56,7 +56,6 @@ import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.security.OpensslArtifactFetcher; -import jtreg.SkippedException; import java.io.File; import java.io.FileInputStream; @@ -82,19 +81,9 @@ boolean generatePKCS12 = Boolean.parseBoolean(args[0]); if (generatePKCS12) { String opensslPath = OpensslArtifactFetcher.getOpensslPath(); - if (opensslPath != null) { - // if the current version of openssl is available, perform all - // keytool <-> openssl interop tests - generateInitialKeystores(opensslPath); - testWithJavaCommands(); - testWithOpensslCommands(opensslPath); - } else { - String exMsg = "Can't find the version: " - + OpensslArtifactFetcher.getTestOpensslBundleVersion() - + " of openssl binary on this machine, please install" - + " and set openssl path with property 'test.openssl.path'"; - throw new SkippedException(exMsg); - } + generateInitialKeystores(opensslPath); + testWithJavaCommands(); + testWithOpensslCommands(opensslPath); } else { // since this scenario is using preexisting PKCS12, skip all // openssl command dependent tests diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/CipherSuite/AbstractDisableCipherSuites.java openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/CipherSuite/AbstractDisableCipherSuites.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/CipherSuite/AbstractDisableCipherSuites.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/CipherSuite/AbstractDisableCipherSuites.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.nio.ByteBuffer; +import java.security.GeneralSecurityException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLEngineResult; +import javax.net.ssl.SSLEngineResult.HandshakeStatus; +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.SSLSession; + +/** + * This is not a test. Actual tests are implemented by concrete subclasses. + * The abstract class AbstractDisableCipherSuites provides a base framework + * for testing cipher suite disablement. + */ +public abstract class AbstractDisableCipherSuites { + + private static final byte RECTYPE_HS = 0x16; + private static final byte HSMSG_CLIHELLO = 0x01; + private static final ByteBuffer CLIOUTBUF = + ByteBuffer.wrap("Client Side".getBytes()); + + /** + * Create an engine with the default set of cipher suites enabled and make + * sure none of the disabled suites are present in the client hello. + * + * @param disabledSuiteIds the {@code List} of disabled cipher suite IDs + * to be checked for. + * + * @return true if the test passed (No disabled suites), false otherwise + */ + protected boolean testDefaultCase(List disabledSuiteIds) + throws Exception { + System.err.println("\nTest: Default SSLEngine suite set"); + SSLEngine ssle = makeEngine(); + if (getDebug()) { + listCiphers("Suite set upon creation", ssle); + } + SSLEngineResult clientResult; + ByteBuffer cTOs = makeClientBuf(ssle); + clientResult = ssle.wrap(CLIOUTBUF, cTOs); + if (getDebug()) { + dumpResult("ClientHello: ", clientResult); + } + cTOs.flip(); + boolean foundSuite = areSuitesPresentCH(cTOs, disabledSuiteIds); + if (foundSuite) { + System.err.println("FAIL: Found disabled suites!"); + return false; + } else { + System.err.println("PASS: No disabled suites found."); + return true; + } + } + + /** + * Create an engine and set only disabled cipher suites. + * The engine should not create the client hello message since the only + * available suites to assert in the client hello are disabled ones. + * + * @param disabledSuiteNames an array of cipher suite names that + * should be disabled cipher suites. + * + * @return true if the engine throws SSLHandshakeException during client + * hello creation, false otherwise. + */ + protected boolean testEngOnlyDisabled(String[] disabledSuiteNames) + throws Exception { + System.err.println( + "\nTest: SSLEngine configured with only disabled suites"); + try { + SSLEngine ssle = makeEngine(); + ssle.setEnabledCipherSuites(disabledSuiteNames); + if (getDebug()) { + listCiphers("Suite set upon creation", ssle); + } + SSLEngineResult clientResult; + ByteBuffer cTOs = makeClientBuf(ssle); + clientResult = ssle.wrap(CLIOUTBUF, cTOs); + if (getDebug()) { + dumpResult("ClientHello: ", clientResult); + } + cTOs.flip(); + } catch (SSLHandshakeException shse) { + System.err.println("PASS: Caught expected exception: " + shse); + return true; + } + System.err.println("FAIL: Expected SSLHandshakeException not thrown"); + return false; + } + + /** + * Create an engine and add some disabled suites to the default + * set of cipher suites. Make sure none of the disabled suites show up + * in the client hello even though they were explicitly added. + * + * @param disabledNames an array of cipher suite names that + * should be disabled cipher suites. + * @param disabledIds the {@code List} of disabled cipher suite IDs + * to be checked for. + * + * @return true if the test passed (No disabled suites), false otherwise + */ + protected boolean testEngAddDisabled(String[] disabledNames, + List disabledIds) throws Exception { + System.err.println("\nTest: SSLEngine with disabled suites added"); + SSLEngine ssle = makeEngine(); + + // Add disabled suites to the existing engine's set of enabled suites + String[] initialSuites = ssle.getEnabledCipherSuites(); + String[] plusDisSuites = Arrays.copyOf(initialSuites, + initialSuites.length + disabledNames.length); + System.arraycopy(disabledNames, 0, plusDisSuites, + initialSuites.length, disabledNames.length); + ssle.setEnabledCipherSuites(plusDisSuites); + + if (getDebug()) { + listCiphers("Suite set upon creation", ssle); + } + SSLEngineResult clientResult; + ByteBuffer cTOs = makeClientBuf(ssle); + clientResult = ssle.wrap(CLIOUTBUF, cTOs); + if (getDebug()) { + dumpResult("ClientHello: ", clientResult); + } + cTOs.flip(); + boolean foundDisabled = areSuitesPresentCH(cTOs, disabledIds); + if (foundDisabled) { + System.err.println("FAIL: Found disabled suites!"); + return false; + } else { + System.err.println("PASS: No disabled suites found."); + return true; + } + } + + protected String getProtocol() { + return "TLSv1.2"; + } + + private SSLEngine makeEngine() throws GeneralSecurityException { + SSLContext ctx = SSLContext.getInstance(getProtocol()); + ctx.init(null, null, null); + return ctx.createSSLEngine(); + } + + private static ByteBuffer makeClientBuf(SSLEngine ssle) { + ssle.setUseClientMode(true); + ssle.setNeedClientAuth(false); + SSLSession sess = ssle.getSession(); + ByteBuffer cTOs = ByteBuffer.allocateDirect(sess.getPacketBufferSize()); + return cTOs; + } + + private static void listCiphers(String prefix, SSLEngine ssle) { + System.err.println(prefix + "\n---------------"); + String[] suites = ssle.getEnabledCipherSuites(); + for (String suite : suites) { + System.err.println(suite); + } + System.err.println("---------------"); + } + + /** + * Walk a TLS 1.2 or earlier ClientHello looking for any of the suites + * in the suiteIdList. + * + * @param clientHello a ByteBuffer containing the ClientHello message as + * a complete TLS record. The position of the buffer should be + * at the first byte of the TLS record header. + * @param suiteIdList a List of integer values corresponding to + * TLS cipher suite identifiers. + * + * @return true if at least one of the suites in {@code suiteIdList} + * is found in the ClientHello's cipher suite list + * + * @throws IOException if the data in the {@code clientHello} + * buffer is not a TLS handshake message or is not a client hello. + */ + private boolean areSuitesPresentCH(ByteBuffer clientHello, + List suiteIdList) throws IOException { + byte val; + + // Process the TLS Record + val = clientHello.get(); + if (val != RECTYPE_HS) { + throw new IOException( + "Not a handshake record, type = " + val); + } + + // Just skip over the version and length + clientHello.position(clientHello.position() + 4); + + // Check the handshake message type + val = clientHello.get(); + if (val != HSMSG_CLIHELLO) { + throw new IOException( + "Not a ClientHello handshake message, type = " + val); + } + + // Skip over the length + clientHello.position(clientHello.position() + 3); + + // Skip over the protocol version (2) and random (32); + clientHello.position(clientHello.position() + 34); + + // Skip past the session ID (variable length <= 32) + int len = Byte.toUnsignedInt(clientHello.get()); + if (len > 32) { + throw new IOException("Session ID is too large, len = " + len); + } + clientHello.position(clientHello.position() + len); + + // Finally, we are at the cipher suites. Walk the list and place them + // into a List. + int csLen = Short.toUnsignedInt(clientHello.getShort()); + if (csLen % 2 != 0) { + throw new IOException("CipherSuite length is invalid, len = " + + csLen); + } + int csCount = csLen / 2; + List csSuiteList = new ArrayList<>(csCount); + log("Found following suite IDs in hello:"); + for (int i = 0; i < csCount; i++) { + int curSuite = Short.toUnsignedInt(clientHello.getShort()); + log(String.format("Suite ID: 0x%04x", curSuite)); + csSuiteList.add(curSuite); + } + + // Now check to see if any of the suites passed in match what is in + // the suite list. + boolean foundMatch = false; + for (Integer cs : suiteIdList) { + if (csSuiteList.contains(cs)) { + System.err.format("Found match for suite ID 0x%04x\n", cs); + foundMatch = true; + break; + } + } + + // We don't care about the rest of the ClientHello message. + // Rewind and return whether we found a match or not. + clientHello.rewind(); + return foundMatch; + } + + private static void dumpResult(String str, SSLEngineResult result) { + System.err.println("The format of the SSLEngineResult is: \n" + + "\t\"getStatus() / getHandshakeStatus()\" +\n" + + "\t\"bytesConsumed() / bytesProduced()\"\n"); + HandshakeStatus hsStatus = result.getHandshakeStatus(); + System.err.println(str + result.getStatus() + "/" + hsStatus + ", " + + result.bytesConsumed() + "/" + result.bytesProduced() + " bytes"); + if (hsStatus == HandshakeStatus.FINISHED) { + System.err.println("\t...ready for application data"); + } + } + + private void log(String str) { + if (getDebug()) { + System.err.println(str); + } + } + + protected boolean getDebug() { + return false; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/CipherSuite/NoDesRC4DesEdeCiphSuite.java openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/CipherSuite/NoDesRC4DesEdeCiphSuite.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/CipherSuite/NoDesRC4DesEdeCiphSuite.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/CipherSuite/NoDesRC4DesEdeCiphSuite.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,21 +34,11 @@ */ import java.security.Security; -import javax.net.ssl.*; -import javax.net.ssl.SSLEngineResult.HandshakeStatus; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.security.GeneralSecurityException; -import java.util.List; -import java.util.ArrayList; import java.util.Arrays; +import java.util.List; -public class NoDesRC4DesEdeCiphSuite { - - private static final boolean DEBUG = false; +public class NoDesRC4DesEdeCiphSuite extends AbstractDisableCipherSuites { - private static final byte RECTYPE_HS = 0x16; - private static final byte HSMSG_CLIHELLO = 0x01; // These are some groups of Cipher Suites by names and IDs private static final List DES_CS_LIST = Arrays.asList( @@ -93,28 +83,27 @@ "SSL_RSA_WITH_3DES_EDE_CBC_SHA" }; - private static final ByteBuffer CLIOUTBUF = - ByteBuffer.wrap("Client Side".getBytes()); public static void main(String[] args) throws Exception { boolean allGood = true; String disAlg = Security.getProperty("jdk.tls.disabledAlgorithms"); System.err.println("Disabled Algs: " + disAlg); + NoDesRC4DesEdeCiphSuite test = new NoDesRC4DesEdeCiphSuite(); // Disabled DES tests - allGood &= testDefaultCase(DES_CS_LIST); - allGood &= testEngAddDisabled(DES_CS_LIST_NAMES, DES_CS_LIST); - allGood &= testEngOnlyDisabled(DES_CS_LIST_NAMES); + allGood &= test.testDefaultCase(DES_CS_LIST); + allGood &= test.testEngAddDisabled(DES_CS_LIST_NAMES, DES_CS_LIST); + allGood &= test.testEngOnlyDisabled(DES_CS_LIST_NAMES); // Disabled RC4 tests - allGood &= testDefaultCase(RC4_CS_LIST); - allGood &= testEngAddDisabled(RC4_CS_LIST_NAMES, RC4_CS_LIST); - allGood &= testEngOnlyDisabled(RC4_CS_LIST_NAMES); + allGood &= test.testDefaultCase(RC4_CS_LIST); + allGood &= test.testEngAddDisabled(RC4_CS_LIST_NAMES, RC4_CS_LIST); + allGood &= test.testEngOnlyDisabled(RC4_CS_LIST_NAMES); // Disabled 3DES tests - allGood &= testDefaultCase(DESEDE_CS_LIST); - allGood &= testEngAddDisabled(DESEDE_CS_LIST_NAMES, DESEDE_CS_LIST); - allGood &= testEngOnlyDisabled(DESEDE_CS_LIST_NAMES); + allGood &= test.testDefaultCase(DESEDE_CS_LIST); + allGood &= test.testEngAddDisabled(DESEDE_CS_LIST_NAMES, DESEDE_CS_LIST); + allGood &= test.testEngOnlyDisabled(DESEDE_CS_LIST_NAMES); if (allGood) { System.err.println("All tests passed"); @@ -122,242 +111,4 @@ throw new RuntimeException("One or more tests failed"); } } - - /** - * Create an engine with the default set of cipher suites enabled and make - * sure none of the disabled suites are present in the client hello. - * - * @param disabledSuiteIds the {@code List} of disabled cipher suite IDs - * to be checked for. - * - * @return true if the test passed (No disabled suites), false otherwise - */ - private static boolean testDefaultCase(List disabledSuiteIds) - throws Exception { - System.err.println("\nTest: Default SSLEngine suite set"); - SSLEngine ssle = makeEngine(); - if (DEBUG) { - listCiphers("Suite set upon creation", ssle); - } - SSLEngineResult clientResult; - ByteBuffer cTOs = makeClientBuf(ssle); - clientResult = ssle.wrap(CLIOUTBUF, cTOs); - if (DEBUG) { - dumpResult("ClientHello: ", clientResult); - } - cTOs.flip(); - boolean foundSuite = areSuitesPresentCH(cTOs, disabledSuiteIds); - if (foundSuite) { - System.err.println("FAIL: Found disabled suites!"); - return false; - } else { - System.err.println("PASS: No disabled suites found."); - return true; - } - } - - /** - * Create an engine and set only disabled cipher suites. - * The engine should not create the client hello message since the only - * available suites to assert in the client hello are disabled ones. - * - * @param disabledSuiteNames an array of cipher suite names that - * should be disabled cipher suites. - * - * @return true if the engine throws SSLHandshakeException during client - * hello creation, false otherwise. - */ - private static boolean testEngOnlyDisabled(String[] disabledSuiteNames) - throws Exception { - System.err.println( - "\nTest: SSLEngine configured with only disabled suites"); - try { - SSLEngine ssle = makeEngine(); - ssle.setEnabledCipherSuites(disabledSuiteNames); - if (DEBUG) { - listCiphers("Suite set upon creation", ssle); - } - SSLEngineResult clientResult; - ByteBuffer cTOs = makeClientBuf(ssle); - clientResult = ssle.wrap(CLIOUTBUF, cTOs); - if (DEBUG) { - dumpResult("ClientHello: ", clientResult); - } - cTOs.flip(); - } catch (SSLHandshakeException shse) { - System.err.println("PASS: Caught expected exception: " + shse); - return true; - } - System.err.println("FAIL: Expected SSLHandshakeException not thrown"); - return false; - } - - /** - * Create an engine and add some disabled suites to the default - * set of cipher suites. Make sure none of the disabled suites show up - * in the client hello even though they were explicitly added. - * - * @param disabledSuiteNames an array of cipher suite names that - * should be disabled cipher suites. - * @param disabledIds the {@code List} of disabled cipher suite IDs - * to be checked for. - * - * @return true if the test passed (No disabled suites), false otherwise - */ - private static boolean testEngAddDisabled(String[] disabledNames, - List disabledIds) throws Exception { - System.err.println("\nTest: SSLEngine with disabled suites added"); - SSLEngine ssle = makeEngine(); - - // Add disabled suites to the existing engine's set of enabled suites - String[] initialSuites = ssle.getEnabledCipherSuites(); - String[] plusDisSuites = Arrays.copyOf(initialSuites, - initialSuites.length + disabledNames.length); - System.arraycopy(disabledNames, 0, plusDisSuites, - initialSuites.length, disabledNames.length); - ssle.setEnabledCipherSuites(plusDisSuites); - - if (DEBUG) { - listCiphers("Suite set upon creation", ssle); - } - SSLEngineResult clientResult; - ByteBuffer cTOs = makeClientBuf(ssle); - clientResult = ssle.wrap(CLIOUTBUF, cTOs); - if (DEBUG) { - dumpResult("ClientHello: ", clientResult); - } - cTOs.flip(); - boolean foundDisabled = areSuitesPresentCH(cTOs, disabledIds); - if (foundDisabled) { - System.err.println("FAIL: Found disabled suites!"); - return false; - } else { - System.err.println("PASS: No disabled suites found."); - return true; - } - } - - private static SSLEngine makeEngine() throws GeneralSecurityException { - SSLContext ctx = SSLContext.getInstance("TLSv1.2"); - ctx.init(null, null, null); - return ctx.createSSLEngine(); - } - - private static ByteBuffer makeClientBuf(SSLEngine ssle) { - ssle.setUseClientMode(true); - ssle.setNeedClientAuth(false); - SSLSession sess = ssle.getSession(); - ByteBuffer cTOs = ByteBuffer.allocateDirect(sess.getPacketBufferSize()); - return cTOs; - } - - private static void listCiphers(String prefix, SSLEngine ssle) { - System.err.println(prefix + "\n---------------"); - String[] suites = ssle.getEnabledCipherSuites(); - for (String suite : suites) { - System.err.println(suite); - } - System.err.println("---------------"); - } - - /** - * Walk a TLS 1.2 or earlier ClientHello looking for any of the suites - * in the suiteIdList. - * - * @param clientHello a ByteBuffer containing the ClientHello message as - * a complete TLS record. The position of the buffer should be - * at the first byte of the TLS record header. - * @param suiteIdList a List of integer values corresponding to - * TLS cipher suite identifiers. - * - * @return true if at least one of the suites in {@code suiteIdList} - * is found in the ClientHello's cipher suite list - * - * @throws IOException if the data in the {@code clientHello} - * buffer is not a TLS handshake message or is not a client hello. - */ - private static boolean areSuitesPresentCH(ByteBuffer clientHello, - List suiteIdList) throws IOException { - byte val; - - // Process the TLS Record - val = clientHello.get(); - if (val != RECTYPE_HS) { - throw new IOException( - "Not a handshake record, type = " + val); - } - - // Just skip over the version and length - clientHello.position(clientHello.position() + 4); - - // Check the handshake message type - val = clientHello.get(); - if (val != HSMSG_CLIHELLO) { - throw new IOException( - "Not a ClientHello handshake message, type = " + val); - } - - // Skip over the length - clientHello.position(clientHello.position() + 3); - - // Skip over the protocol version (2) and random (32); - clientHello.position(clientHello.position() + 34); - - // Skip past the session ID (variable length <= 32) - int len = Byte.toUnsignedInt(clientHello.get()); - if (len > 32) { - throw new IOException("Session ID is too large, len = " + len); - } - clientHello.position(clientHello.position() + len); - - // Finally, we are at the cipher suites. Walk the list and place them - // into a List. - int csLen = Short.toUnsignedInt(clientHello.getShort()); - if (csLen % 2 != 0) { - throw new IOException("CipherSuite length is invalid, len = " + - csLen); - } - int csCount = csLen / 2; - List csSuiteList = new ArrayList<>(csCount); - log("Found following suite IDs in hello:"); - for (int i = 0; i < csCount; i++) { - int curSuite = Short.toUnsignedInt(clientHello.getShort()); - log(String.format("Suite ID: 0x%04x", curSuite)); - csSuiteList.add(curSuite); - } - - // Now check to see if any of the suites passed in match what is in - // the suite list. - boolean foundMatch = false; - for (Integer cs : suiteIdList) { - if (csSuiteList.contains(cs)) { - System.err.format("Found match for suite ID 0x%04x\n", cs); - foundMatch = true; - break; - } - } - - // We don't care about the rest of the ClientHello message. - // Rewind and return whether we found a match or not. - clientHello.rewind(); - return foundMatch; - } - - private static void dumpResult(String str, SSLEngineResult result) { - System.err.println("The format of the SSLEngineResult is: \n" + - "\t\"getStatus() / getHandshakeStatus()\" +\n" + - "\t\"bytesConsumed() / bytesProduced()\"\n"); - HandshakeStatus hsStatus = result.getHandshakeStatus(); - System.err.println(str + result.getStatus() + "/" + hsStatus + ", " + - result.bytesConsumed() + "/" + result.bytesProduced() + " bytes"); - if (hsStatus == HandshakeStatus.FINISHED) { - System.err.println("\t...ready for application data"); - } - } - - private static void log(String str) { - if (DEBUG) { - System.err.println(str); - } - } } diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/CipherSuite/TLSCipherSuiteWildCardMatchingDisablePartsOfCipherSuite.java openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/CipherSuite/TLSCipherSuiteWildCardMatchingDisablePartsOfCipherSuite.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/CipherSuite/TLSCipherSuiteWildCardMatchingDisablePartsOfCipherSuite.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/CipherSuite/TLSCipherSuiteWildCardMatchingDisablePartsOfCipherSuite.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8341964 + * @summary Add mechanism to disable different parts of TLS cipher suite + * @run testng/othervm TLSCipherSuiteWildCardMatchingDisablePartsOfCipherSuite + */ + +import static org.testng.AssertJUnit.assertTrue; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import java.security.Security; +import java.util.List; + +public class TLSCipherSuiteWildCardMatchingDisablePartsOfCipherSuite extends + AbstractDisableCipherSuites { + + private static final String SECURITY_PROPERTY = "jdk.tls.disabledAlgorithms"; + private static final String TEST_ALGORITHMS = + "TLS_RSA_*," + + " TLS_ECDH*WITH_AES_256_GCM_*," + + " TLS_*_anon_WITH_AES_*_SHA," + + " TLS_.*"; // This pattern should not disable anything + private static final String[] CIPHER_SUITES = new String[] { + "TLS_RSA_WITH_AES_256_GCM_SHA384", + "TLS_RSA_WITH_AES_128_GCM_SHA256", + "TLS_RSA_WITH_AES_256_CBC_SHA256", + "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", + "TLS_DH_anon_WITH_AES_128_CBC_SHA", + "TLS_ECDH_anon_WITH_AES_256_CBC_SHA" + }; + static final List CIPHER_SUITES_IDS = List.of( + 0x009D, + 0x009C, + 0x003D, + 0xC02E, + 0xC02C, + 0x0034, + 0xC018 + ); + + @BeforeTest + void setUp() throws Exception { + Security.setProperty(SECURITY_PROPERTY, TEST_ALGORITHMS); + } + + @Test + public void testDefault() throws Exception { + assertTrue(testDefaultCase(CIPHER_SUITES_IDS)); + } + + @Test + public void testAddDisabled() throws Exception { + assertTrue(testEngAddDisabled(CIPHER_SUITES, CIPHER_SUITES_IDS)); + } + + @Test + public void testOnlyDisabled() throws Exception { + assertTrue(testEngOnlyDisabled(CIPHER_SUITES)); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/CipherSuite/TLSCipherSuiteWildCardMatchingIllegalArgument.java openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/CipherSuite/TLSCipherSuiteWildCardMatchingIllegalArgument.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/CipherSuite/TLSCipherSuiteWildCardMatchingIllegalArgument.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/CipherSuite/TLSCipherSuiteWildCardMatchingIllegalArgument.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8341964 + * @summary Add mechanism to disable different parts of TLS cipher suite + * @run testng/othervm TLSCipherSuiteWildCardMatchingIllegalArgument + */ + +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.fail; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import java.security.Security; + +import javax.net.ssl.SSLContext; + +/** + * SSLContext loads "jdk.tls.disabledAlgorithms" system property statically + * when it's being loaded into memory, so we can't call + * Security.setProperty("jdk.tls.disabledAlgorithms") more than once per test + * class. Thus, we need a separate test class each time we need to modify + * "jdk.tls.disabledAlgorithms" config value for testing. + */ +public class TLSCipherSuiteWildCardMatchingIllegalArgument { + + private static final String SECURITY_PROPERTY = + "jdk.tls.disabledAlgorithms"; + private static final String TEST_ALGORITHMS = "ECDHE_*_WITH_AES_256_GCM_*"; + + @BeforeTest + void setUp() throws Exception { + Security.setProperty(SECURITY_PROPERTY, TEST_ALGORITHMS); + } + + @Test + public void testChainedBefore() throws Exception { + try { + SSLContext.getInstance("TLS"); + fail("No IllegalArgumentException was thrown"); + } catch (ExceptionInInitializerError e) { + assertEquals(IllegalArgumentException.class, + e.getCause().getClass()); + assertEquals("Wildcard pattern must start with \"TLS_\"", + e.getCause().getMessage()); + } + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/DHKeyExchange/LegacyDHEKeyExchange.java openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/DHKeyExchange/LegacyDHEKeyExchange.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/DHKeyExchange/LegacyDHEKeyExchange.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/DHKeyExchange/LegacyDHEKeyExchange.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,7 @@ throw new Exception("Legacy DH keys (< 1024) should be restricted"); } catch (SSLHandshakeException she) { String expectedExMsg = "Received fatal alert: insufficient_security"; - if (!expectedExMsg.equals(she.getMessage())) { + if (!she.getMessage().endsWith(expectedExMsg)) { throw she; } System.out.println("Expected exception thrown in server"); @@ -77,7 +77,7 @@ } catch (SSLHandshakeException she) { String expectedExMsg = "DH ServerKeyExchange does not comply to" + " algorithm constraints"; - if (!expectedExMsg.equals(she.getMessage())) { + if (!she.getMessage().endsWith(expectedExMsg)) { throw she; } System.out.println("Expected exception thrown in client"); diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SSLLogger/DebugPropertyValuesTest.java openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SSLLogger/DebugPropertyValuesTest.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SSLLogger/DebugPropertyValuesTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SSLLogger/DebugPropertyValuesTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8350582 + * @library /test/lib /javax/net/ssl/templates + * @summary Correct the parsing of the ssl value in javax.net.debug + * @run junit DebugPropertyValuesTest + */ + +// A test to verify debug output for different javax.net.debug scenarios + +import jdk.test.lib.process.ProcessTools; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.stream.Stream; + +import jdk.test.lib.process.OutputAnalyzer; + +public class DebugPropertyValuesTest extends SSLSocketTemplate { + + private static final Path LOG_FILE = Path.of("logging.conf"); + private static final HashMap> debugMessages = new HashMap<>(); + + static { + debugMessages.put("handshake", + List.of("Produced ClientHello handshake message", + "supported_versions")); + debugMessages.put("keymanager", List.of("choosing key:")); + debugMessages.put("packet", List.of("Raw write")); + debugMessages.put("plaintext", List.of("Plaintext before ENCRYPTION")); + debugMessages.put("record", List.of("handshake, length =", "WRITE:")); + debugMessages.put("session", List.of("Session initialized:")); + debugMessages.put("sslctx", List.of("trigger seeding of SecureRandom")); + debugMessages.put("ssl", List.of("jdk.tls.keyLimits:")); + debugMessages.put("trustmanager", List.of("adding as trusted certificates")); + debugMessages.put("verbose", List.of("Ignore unsupported cipher suite:")); + debugMessages.put("handshake-expand", + List.of("\"logger\".*: \"javax.net.ssl\",", + "\"message\".*: \"Produced ClientHello handshake message")); + debugMessages.put("record-expand", + List.of("\"logger\".*: \"javax.net.ssl\",", + "\"message\".*: \"READ: TLSv1.2 application_data")); + debugMessages.put("help", + List.of("print the help messages", + "debugging can be widened with:")); + debugMessages.put("javax.net.debug", + List.of("properties: Initial security property:", + "certpath: Cert path validation succeeded")); + debugMessages.put("logger", + List.of("FINE: adding as trusted certificates", + "FINE: WRITE: TLSv1.3 application_data")); + } + + @BeforeAll + static void setup() throws Exception { + Files.writeString(LOG_FILE, ".level = ALL\n" + + "handlers= java.util.logging.ConsoleHandler\n" + + "java.util.logging.ConsoleHandler.level = ALL\n"); + } + + private static Stream patternMatches() { + return Stream.of( + // all should print everything + Arguments.of(List.of("-Djavax.net.debug=all"), + List.of("handshake", "keymanager", "packet", + "plaintext", "record", "session", "ssl", + "sslctx", "trustmanager", "verbose")), + // ssl should print most details except verbose details + Arguments.of(List.of("-Djavax.net.debug=ssl"), + List.of("handshake", "keymanager", + "record", "session", "ssl", + "sslctx", "trustmanager", "verbose")), + // allow expand option for more verbose output + Arguments.of(List.of("-Djavax.net.debug=ssl,handshake,expand"), + List.of("handshake", "handshake-expand", "keymanager", + "record", "session", "record-expand", "ssl", + "sslctx", "trustmanager", "verbose")), + // filtering on record option, with expand + Arguments.of(List.of("-Djavax.net.debug=ssl:record,expand"), + List.of("handshake", "handshake-expand", "keymanager", + "record", "record-expand", "session", "ssl", + "sslctx", "trustmanager", "verbose")), + // this test is equivalent to ssl:record mode + Arguments.of(List.of("-Djavax.net.debug=ssl,record"), + List.of("handshake", "keymanager", "record", + "session", "ssl", "sslctx", + "trustmanager", "verbose")), + // example of test where no "ssl" value is passed + // handshake debugging with verbose mode + // only verbose gets printed. Needs fixing (JDK-8044609) + Arguments.of(List.of("-Djavax.net.debug=handshake:verbose"), + List.of("verbose")), + // another example of test where no "ssl" value is passed + Arguments.of(List.of("-Djavax.net.debug=record"), + List.of("record")), + // ignore bad sub-option. treat like "ssl" + Arguments.of(List.of("-Djavax.net.debug=ssl,typo"), + List.of("handshake", "keymanager", + "record", "session", "ssl", + "sslctx", "trustmanager", "verbose")), + // ssltypo contains "ssl". Treat like "ssl" + Arguments.of(List.of("-Djavax.net.debug=ssltypo"), + List.of("handshake", "keymanager", + "record", "session", "ssl", + "sslctx", "trustmanager", "verbose")), + // plaintext is valid for record option + Arguments.of(List.of("-Djavax.net.debug=ssl:record:plaintext"), + List.of("handshake", "keymanager", "plaintext", + "record", "session", "ssl", + "sslctx", "trustmanager", "verbose")), + Arguments.of(List.of("-Djavax.net.debug=ssl:trustmanager"), + List.of("handshake", "keymanager", "record", "session", + "ssl", "sslctx", "trustmanager", "verbose")), + Arguments.of(List.of("-Djavax.net.debug=ssl:sslctx"), + List.of("handshake", "keymanager", "record", "session", + "ssl", "sslctx", "trustmanager", "verbose")), + // help message test. Should exit without running test + Arguments.of(List.of("-Djavax.net.debug=help"), + List.of("help")), + // add in javax.net.debug sanity test + Arguments.of(List.of("-Djavax.net.debug=ssl:trustmanager", + "-Djava.security.debug=all"), + List.of("handshake", "javax.net.debug", "keymanager", + "record", "session", "ssl", "sslctx", + "trustmanager", "verbose")), + // empty invokes System.Logger use + Arguments.of(List.of("-Djavax.net.debug", + "-Djava.util.logging.config.file=" + LOG_FILE), + List.of("handshake", "keymanager", "logger", "packet", + "plaintext", "record", "session", "ssl", + "sslctx", "trustmanager", "verbose")) + ); + } + + @ParameterizedTest + @MethodSource("patternMatches") + public void checkDebugOutput(List params, + List expected) throws Exception { + + List args = new ArrayList<>(params); + args.add("DebugPropertyValuesTest"); + OutputAnalyzer outputAnalyzer = ProcessTools.executeTestJava(args); + outputAnalyzer.shouldHaveExitValue(0); + for (String s : debugMessages.keySet()) { + for (String output : debugMessages.get(s)) { + if (expected.contains(s)) { + outputAnalyzer.shouldMatch(output); + } else { + outputAnalyzer.shouldNotMatch(output); + } + } + } + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SSLSessionImpl/NoInvalidateSocketException.java openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SSLSessionImpl/NoInvalidateSocketException.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SSLSessionImpl/NoInvalidateSocketException.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SSLSessionImpl/NoInvalidateSocketException.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ /* * @test - * @bug 8274736 8277970 + * @bug 8274736 8277970 8355262 * @summary Concurrent read/close of SSLSockets causes SSLSessions to be * invalidated unnecessarily * @library /javax/net/ssl/templates @@ -285,7 +285,7 @@ // Signal the client, the server is ready to accept connection. serverCondition.countDown(); - // Try to accept a connection in 5 seconds. + // Try to accept a connection in 10 seconds. // We will do this in a loop until the client flips the // finished variable to true SSLSocket sslSocket; @@ -351,7 +351,7 @@ public void configureServerSocket(SSLServerSocket socket) { try { socket.setReuseAddress(true); - socket.setSoTimeout(5000); + socket.setSoTimeout(10000); } catch (SocketException se) { // Rethrow as unchecked to satisfy the override signature throw new RuntimeException(se); diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeClientTLS12withSNI.java openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeClientTLS12withSNI.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeClientTLS12withSNI.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeClientTLS12withSNI.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8350830 + * @summary TLS 1.2 Client session resumption having ServerNameIndication + * @modules java.base/sun.security.tools.keytool + * @run main/othervm -Djavax.net.debug=all ResumeClientTLS12withSNI + */ + +import javax.net.ssl.*; +import javax.net.ssl.SSLEngineResult.HandshakeStatus; +import java.io.*; +import java.nio.ByteBuffer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.util.*; + +public class ResumeClientTLS12withSNI { + + /* + * Enables logging of the SSLEngine operations. + */ + private static final boolean logging = true; + + private static SSLContext sslc; + + private SSLEngine clientEngine; // client Engine + private ByteBuffer clientOut; // write side of clientEngine + private ByteBuffer clientIn; // read side of clientEngine + + private SSLEngine serverEngine; // server Engine + private ByteBuffer serverOut; // write side of serverEngine + private ByteBuffer serverIn; // read side of serverEngine + + /* + * For data transport, this example uses local ByteBuffers. + */ + private ByteBuffer cTOs; // "reliable" transport client->server + private ByteBuffer sTOc; // "reliable" transport server->client + + /* + * The following is to set up the keystores. + */ + private static final String keyFilename = "ks_san.p12"; + private static final String trustFilename = "ks_san.p12"; + private static final char[] passphrase = "123456".toCharArray(); + + private static final String HOST_NAME = "arf.yak.foo.localhost123456.localhost123456.localhost123456.localhost123456.localhost123456.localhost123456." + + "localhost123456.localhost123456.localhost123456.localhost123456.localhost123456.localhost123456"; + private static final SNIMatcher SNI_MATCHER = SNIHostName.createSNIMatcher("arf\\.yak\\.foo.*"); + + /* + * Main entry point for this test. + */ + public static void main(String args[]) throws Exception { + Files.deleteIfExists(Path.of(keyFilename)); + + sun.security.tools.keytool.Main.main( + ("-keystore " + keyFilename + " -storepass 123456 -keypass 123456 -dname" + + " CN=test" + " -alias ks_san -genkeypair -keyalg rsa -ext " + + "san=dns:localhost123.localhost123.localhost123.localhost123." + + "localhost123.localhost123.localhost123.localhost123.localhost123." + + "localhost123.localhost123.localhost123.localhost123.localhost123." + + "localhost123.localhost123.localhost123.localhost123.localhost123.com," + + "dns:localhost456").split(" ")); + final ResumeClientTLS12withSNI clientSession = new ResumeClientTLS12withSNI("TLSv1.2"); + for (int i = 0; i < 2; i++) { + clientSession.runTest(); + } + + Files.deleteIfExists(Path.of(keyFilename)); + } + + public ResumeClientTLS12withSNI(final String sslProtocol) throws Exception { + + KeyManagerFactory kmf = makeKeyManagerFactory(keyFilename, + passphrase); + TrustManagerFactory tmf = makeTrustManagerFactory(trustFilename, + passphrase); + + SSLContext sslCtx = SSLContext.getInstance(sslProtocol); + + sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + + sslc = sslCtx; + } + + private static KeyManagerFactory makeKeyManagerFactory(String ksPath, + char[] pass) throws GeneralSecurityException, IOException { + KeyManagerFactory kmf; + KeyStore ks = KeyStore.getInstance("PKCS12"); + + try (FileInputStream fsIn = new FileInputStream(ksPath)) { + ks.load(fsIn, pass); + kmf = KeyManagerFactory.getInstance("SunX509"); + kmf.init(ks, pass); + } + return kmf; + } + + private static TrustManagerFactory makeTrustManagerFactory(String tsPath, + char[] pass) throws GeneralSecurityException, IOException { + TrustManagerFactory tmf; + KeyStore ts = KeyStore.getInstance("JKS"); + + try (FileInputStream fsIn = new FileInputStream(tsPath)) { + ts.load(fsIn, pass); + tmf = TrustManagerFactory.getInstance("SunX509"); + tmf.init(ts); + } + return tmf; + } + + /* + * Run the test. + * + * Sit in a tight loop, both engines calling wrap/unwrap regardless + * of whether data is available or not. We do this until both engines + * report back they are closed. + * + * The main loop handles all of the I/O phases of the SSLEngine's + * lifetime: + * + * initial handshaking + * application data transfer + * engine closing + * + */ + private void runTest() throws Exception { + boolean dataDone = false; + + createSSLEngines(); + createBuffers(); + + SSLEngineResult clientResult; // results from client's last operation + SSLEngineResult serverResult; // results from server's last operation + + /* + * Examining the SSLEngineResults could be much more involved, + * and may alter the overall flow of the application. + * + * For example, if we received a BUFFER_OVERFLOW when trying + * to write to the output pipe, we could reallocate a larger + * pipe, but instead we wait for the peer to drain it. + */ + while (!isEngineClosed(clientEngine) || + !isEngineClosed(serverEngine)) { + + log("================"); + + clientResult = clientEngine.wrap(clientOut, cTOs); + log("client wrap: ", clientResult); + runDelegatedTasks(clientResult, clientEngine); + + serverResult = serverEngine.wrap(serverOut, sTOc); + log("server wrap: ", serverResult); + runDelegatedTasks(serverResult, serverEngine); + + cTOs.flip(); + sTOc.flip(); + + log("-------"); + + clientResult = clientEngine.unwrap(sTOc, clientIn); + log("client unwrap: ", clientResult); + runDelegatedTasks(clientResult, clientEngine); + + serverResult = serverEngine.unwrap(cTOs, serverIn); + log("server unwrap: ", serverResult); + runDelegatedTasks(serverResult, serverEngine); + + cTOs.compact(); + sTOc.compact(); + + /* + * After we've transfered all application data between the client + * and server, we close the clientEngine's outbound stream. + * This generates a close_notify handshake message, which the + * server engine receives and responds by closing itself. + * + * In normal operation, each SSLEngine should call + * closeOutbound(). To protect against truncation attacks, + * SSLEngine.closeInbound() should be called whenever it has + * determined that no more input data will ever be + * available (say a closed input stream). + */ + if (!dataDone && (clientOut.limit() == serverIn.position()) && + (serverOut.limit() == clientIn.position())) { + + /* + * A sanity check to ensure we got what was sent. + */ + checkTransfer(serverOut, clientIn); + checkTransfer(clientOut, serverIn); + + log("\tClosing clientEngine's *OUTBOUND*..."); + clientEngine.closeOutbound(); + // serverEngine.closeOutbound(); + dataDone = true; + } + } + } + + /* + * Using the SSLContext created during object creation, + * create/configure the SSLEngines we'll use for this test. + */ + private void createSSLEngines() throws Exception { + /* + * Configure the serverEngine to act as a server in the SSL/TLS + * handshake. + */ + serverEngine = sslc.createSSLEngine(); + serverEngine.setUseClientMode(false); + serverEngine.setNeedClientAuth(false); + SSLParameters servSSLParams = serverEngine.getSSLParameters(); + servSSLParams.setSNIMatchers(List.of(SNI_MATCHER)); + serverEngine.setSSLParameters(servSSLParams); + + /* + * Similar to above, but using client mode instead. + */ + clientEngine = sslc.createSSLEngine(HOST_NAME, 80); + clientEngine.setUseClientMode(true); + SSLParameters cliSSLParams = clientEngine.getSSLParameters(); + clientEngine.setSSLParameters(cliSSLParams); + } + + /* + * Create and size the buffers appropriately. + */ + private void createBuffers() { + + /* + * We'll assume the buffer sizes are the same + * between client and server. + */ + SSLSession session = clientEngine.getSession(); + int appBufferMax = session.getApplicationBufferSize(); + int netBufferMax = session.getPacketBufferSize(); + + /* + * We'll make the input buffers a bit bigger than the max needed + * size, so that unwrap()s following a successful data transfer + * won't generate BUFFER_OVERFLOWS. + * + * We'll use a mix of direct and indirect ByteBuffers for + * tutorial purposes only. In reality, only use direct + * ByteBuffers when they give a clear performance enhancement. + */ + clientIn = ByteBuffer.allocate(appBufferMax + 50); + serverIn = ByteBuffer.allocate(appBufferMax + 50); + + cTOs = ByteBuffer.allocateDirect(netBufferMax); + sTOc = ByteBuffer.allocateDirect(netBufferMax); + + clientOut = ByteBuffer.wrap("Hi Server, I'm Client".getBytes()); + serverOut = ByteBuffer.wrap("Hello Client, I'm Server".getBytes()); + } + + /* + * If the result indicates that we have outstanding tasks to do, + * go ahead and run them in this thread. + */ + private static void runDelegatedTasks(SSLEngineResult result, + SSLEngine engine) throws Exception { + + if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { + Runnable runnable; + while ((runnable = engine.getDelegatedTask()) != null) { + log("\trunning delegated task..."); + runnable.run(); + } + HandshakeStatus hsStatus = engine.getHandshakeStatus(); + if (hsStatus == HandshakeStatus.NEED_TASK) { + throw new Exception( + "handshake shouldn't need additional tasks"); + } + log("\tnew HandshakeStatus: " + hsStatus); + } + } + + private static boolean isEngineClosed(SSLEngine engine) { + return (engine.isOutboundDone() && engine.isInboundDone()); + } + + /* + * Simple check to make sure everything came across as expected. + */ + private static void checkTransfer(ByteBuffer a, ByteBuffer b) + throws Exception { + a.flip(); + b.flip(); + + if (!a.equals(b)) { + throw new Exception("Data didn't transfer cleanly"); + } else { + log("\tData transferred cleanly"); + } + + a.position(a.limit()); + b.position(b.limit()); + a.limit(a.capacity()); + b.limit(b.capacity()); + } + + /* + * Logging code + */ + private static boolean resultOnce = true; + + private static void log(String str, SSLEngineResult result) { + if (!logging) { + return; + } + if (resultOnce) { + resultOnce = false; + System.out.println("The format of the SSLEngineResult is: \n" + + "\t\"getStatus() / getHandshakeStatus()\" +\n" + + "\t\"bytesConsumed() / bytesProduced()\"\n"); + } + HandshakeStatus hsStatus = result.getHandshakeStatus(); + log(str + + result.getStatus() + "/" + hsStatus + ", " + + result.bytesConsumed() + "/" + result.bytesProduced() + + " bytes"); + if (hsStatus == HandshakeStatus.FINISHED) { + log("\t...ready for application data"); + } + } + + private static void log(String str) { + if (logging) { + System.out.println(str); + } + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SSLSocketImpl/NonAutoClose.java openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SSLSocketImpl/NonAutoClose.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SSLSocketImpl/NonAutoClose.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SSLSocketImpl/NonAutoClose.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,229 +29,144 @@ /* * @test * @bug 4404399 - * @ignore this test does not work any more as the TLS spec changes the - * behaviors of close_notify. + * @comment this test does not work in TLSv1.3 as the spec changes the + * behaviors of close_notify. * @summary When a layered SSL socket is closed, it should wait for close_notify - * @run main/othervm NonAutoClose + * @library /test/lib /javax/net/ssl/templates + * @run main/othervm NonAutoClose TLSv1 + * @run main/othervm NonAutoClose TLSv1.1 + * @run main/othervm NonAutoClose TLSv1.2 * @author Brad Wetmore */ import java.io.*; +import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; +import java.util.concurrent.CountDownLatch; import javax.net.ssl.*; -import java.security.cert.X509Certificate; -import java.security.cert.CertificateException; +import jdk.test.lib.security.SecurityUtils; -public class NonAutoClose { - /* - * ============================================================= - * Set the various variables needed for the tests, then - * specify what tests to run on each side. - */ - - /* - * Should we run the client or server in a separate thread? - * Both sides can throw exceptions, but do you have a preference - * as to which side should be the main thread. - */ - private static boolean separateServerThread = true; +import static jdk.test.lib.Asserts.assertEquals; - /* - * Where do we find the keystores? - */ - private final static String pathToStores = "../../../../javax/net/ssl/etc"; - private final static String keyStoreFile = "keystore"; - private final static String trustStoreFile = "truststore"; - private final static String passwd = "passphrase"; - private final static char[] cpasswd = "passphrase".toCharArray(); +public class NonAutoClose extends SSLContextTemplate { /* * Is the server ready to serve? */ - volatile static boolean serverReady = false; + private static final CountDownLatch SERVER_READY = new CountDownLatch(1); /* * Turn on SSL debugging? */ - private final static boolean DEBUG = false; - private final static boolean VERBOSE = true; - private final static int NUM_ITERATIONS = 10; + private final static boolean DEBUG = Boolean.getBoolean("test.debug"); + private final static int NUM_ITERATIONS = 10; private final static int PLAIN_SERVER_VAL = 1; private final static int PLAIN_CLIENT_VAL = 2; private final static int TLS_SERVER_VAL = 3; private final static int TLS_CLIENT_VAL = 4; /* - * If the client or server is doing some kind of object creation - * that the other side depends on, and that thread prematurely - * exits, you may experience a hang. The test harness will - * terminate all hung threads after its timeout has expired, - * currently 3 minutes by default, but you might try to be - * smart about it.... - */ - - void expectValue(int got, int expected, String msg) throws IOException { - if (VERBOSE) { - System.err.println(msg + ": read (" + got + ")"); - } - if (got != expected) { - throw new IOException(msg + ": read (" + got - + ") but expecting(" + expected + ")"); - } - } - - - /* * Define the server side of the test. - * - * If the server prematurely exits, serverReady will be set to true - * to avoid infinite hangs. */ + private void doServerSide() throws Exception { + System.out.println("Starting server"); + SSLSocketFactory sslsf = createServerSSLContext().getSocketFactory(); + + try (ServerSocket serverSocket = new ServerSocket(SERVER_PORT)) { + SERVER_PORT = serverSocket.getLocalPort(); + + /* + * Signal Client, we're ready for his connect. + */ + System.out.println("Signal server ready"); + SERVER_READY.countDown(); + + try (Socket plainSocket = serverSocket.accept(); + InputStream is = plainSocket.getInputStream(); + OutputStream os = plainSocket.getOutputStream()) { + + assertEquals(PLAIN_CLIENT_VAL, is.read()); + + os.write(PLAIN_SERVER_VAL); + os.flush(); + + for (int i = 1; i <= NUM_ITERATIONS; i++) { + if (DEBUG) { + System.out.println("================================="); + System.out.println("Server Iteration #" + i); + } - void doServerSide() throws Exception { - if (VERBOSE) { - System.err.println("Starting server"); - } - - /* - * Setup the SSL stuff - */ - SSLSocketFactory sslsf = - (SSLSocketFactory) SSLSocketFactory.getDefault(); - - ServerSocket serverSocket = new ServerSocket(SERVER_PORT); - - SERVER_PORT = serverSocket.getLocalPort(); - - /* - * Signal Client, we're ready for his connect. - */ - serverReady = true; - - Socket plainSocket = serverSocket.accept(); - InputStream is = plainSocket.getInputStream(); - OutputStream os = plainSocket.getOutputStream(); - - expectValue(is.read(), PLAIN_CLIENT_VAL, "Server"); - - os.write(PLAIN_SERVER_VAL); - os.flush(); - - for (int i = 1; i <= NUM_ITERATIONS; i++) { - if (VERBOSE) { - System.err.println("================================="); - System.err.println("Server Iteration #" + i); - } - - SSLSocket ssls = (SSLSocket) sslsf.createSocket(plainSocket, - SERVER_NAME, plainSocket.getPort(), false); - - ssls.setUseClientMode(false); - InputStream sslis = ssls.getInputStream(); - OutputStream sslos = ssls.getOutputStream(); - - expectValue(sslis.read(), TLS_CLIENT_VAL, "Server"); - - sslos.write(TLS_SERVER_VAL); - sslos.flush(); + try (SSLSocket ssls = (SSLSocket) sslsf.createSocket(plainSocket, + plainSocket.getInetAddress().getHostName(), + plainSocket.getPort(), false)) { + + ssls.setEnabledProtocols(new String[]{protocol}); + ssls.setUseClientMode(false); + try (InputStream sslis = ssls.getInputStream(); + OutputStream sslos = ssls.getOutputStream()) { + + assertEquals(TLS_CLIENT_VAL, sslis.read()); + + sslos.write(TLS_SERVER_VAL); + sslos.flush(); + } + } + } - sslis.close(); - sslos.close(); - ssls.close(); + assertEquals(PLAIN_CLIENT_VAL, is.read()); - if (VERBOSE) { - System.err.println("TLS socket is closed"); + os.write(PLAIN_SERVER_VAL); + os.flush(); } } - - expectValue(is.read(), PLAIN_CLIENT_VAL, "Server"); - - os.write(PLAIN_SERVER_VAL); - os.flush(); - - is.close(); - os.close(); - plainSocket.close(); - - if (VERBOSE) { - System.err.println("Server plain socket is closed"); - } } /* * Define the client side of the test. - * - * If the server prematurely exits, serverReady will be set to true - * to avoid infinite hangs. */ private void doClientSide() throws Exception { /* * Wait for server to get started. */ - while (!serverReady) { - Thread.sleep(50); - } - - if (VERBOSE) { - System.err.println("Starting client"); - } + System.out.println("Waiting for server ready"); + SERVER_READY.await(); - /* - * Setup the SSL stuff - */ - SSLSocketFactory sslsf = - (SSLSocketFactory) SSLSocketFactory.getDefault(); + SSLSocketFactory sslsf = createClientSSLContext().getSocketFactory(); - Socket plainSocket = new Socket(SERVER_NAME, SERVER_PORT); - InputStream is = plainSocket.getInputStream(); - OutputStream os = plainSocket.getOutputStream(); + try (Socket plainSocket = new Socket(InetAddress.getLocalHost(), SERVER_PORT); + InputStream is = plainSocket.getInputStream(); + OutputStream os = plainSocket.getOutputStream()) { - os.write(PLAIN_CLIENT_VAL); - os.flush(); + os.write(PLAIN_CLIENT_VAL); + os.flush(); - expectValue(is.read(), PLAIN_SERVER_VAL, "Client"); + assertEquals(PLAIN_SERVER_VAL, is.read()); - for (int i = 1; i <= NUM_ITERATIONS; i++) { - if (VERBOSE) { - System.err.println("==================================="); - System.err.println("Client Iteration #" + i); - } - - SSLSocket ssls = (SSLSocket) sslsf.createSocket(plainSocket, - SERVER_NAME, plainSocket.getPort(), false); - - ssls.setUseClientMode(true); - - InputStream sslis = ssls.getInputStream(); - OutputStream sslos = ssls.getOutputStream(); - - sslos.write(TLS_CLIENT_VAL); - sslos.flush(); + for (int i = 1; i <= NUM_ITERATIONS; i++) { + if (DEBUG) { + System.out.println("==================================="); + System.out.println("Client Iteration #" + i); + } + try (SSLSocket ssls = (SSLSocket) sslsf.createSocket(plainSocket, + plainSocket.getInetAddress().getHostName(), + plainSocket.getPort(), false); + InputStream sslis = ssls.getInputStream(); + OutputStream sslos = ssls.getOutputStream()) { - expectValue(sslis.read(), TLS_SERVER_VAL, "Client"); + ssls.setUseClientMode(true); - sslis.close(); - sslos.close(); - ssls.close(); + sslos.write(TLS_CLIENT_VAL); + sslos.flush(); - if (VERBOSE) { - System.err.println("Client TLS socket is closed"); + assertEquals(TLS_SERVER_VAL, sslis.read()); + } } - } - - os.write(PLAIN_CLIENT_VAL); - os.flush(); - - expectValue(is.read(), PLAIN_SERVER_VAL, "Client"); - is.close(); - os.close(); - plainSocket.close(); - - if (VERBOSE) { - System.err.println("Client plain socket is closed"); + os.write(PLAIN_CLIENT_VAL); + os.flush(); + assertEquals(PLAIN_SERVER_VAL, is.read()); } } @@ -261,25 +176,13 @@ */ private volatile int SERVER_PORT = 0; - private final static String SERVER_NAME = "localhost"; - - private volatile Exception serverException = null; private volatile Exception clientException = null; - private final static String keyFilename = - System.getProperty("test.src", ".") + "/" + pathToStores + - "/" + keyStoreFile; - private final static String trustFilename = - System.getProperty("test.src", ".") + "/" + pathToStores + - "/" + trustStoreFile; - - - // Used for running test standalone public static void main(String[] args) throws Exception { - System.setProperty("javax.net.ssl.keyStore", keyFilename); - System.setProperty("javax.net.ssl.keyStorePassword", passwd); - System.setProperty("javax.net.ssl.trustStore", trustFilename); - System.setProperty("javax.net.ssl.trustStorePassword", passwd); + String protocol = args[0]; + if ("TLSv1".equals(protocol) || "TLSv1.1".equals(protocol)) { + SecurityUtils.removeFromDisabledTlsAlgs(protocol); + } if (DEBUG) System.setProperty("javax.net.debug", "all"); @@ -287,94 +190,45 @@ /* * Start the tests. */ - new NonAutoClose(); + new NonAutoClose(protocol); } private Thread clientThread = null; - private Thread serverThread = null; + private final String protocol; /* * Primary constructor, used to drive remainder of the test. * * Fork off the other side, then do your work. */ - NonAutoClose() throws Exception { - if (separateServerThread) { - startServer(true); - startClient(false); - } else { - startClient(true); - startServer(false); - } + NonAutoClose(String protocol) throws Exception { + this.protocol = protocol; + startClient(); + doServerSide(); /* * Wait for other side to close down. */ - if (separateServerThread) { - serverThread.join(); - } else { - clientThread.join(); - } + clientThread.join(); - /* - * When we get here, the test is pretty much over. - * - * If the main thread excepted, that propagates back - * immediately. If the other thread threw an exception, we - * should report back. - */ - if (serverException != null) { - System.err.print("Server Exception:"); - throw serverException; - } if (clientException != null) { System.err.print("Client Exception:"); throw clientException; } } - private void startServer(boolean newThread) throws Exception { - if (newThread) { - serverThread = new Thread() { - public void run() { - try { - doServerSide(); - } catch (Exception e) { - /* - * Our server thread just died. - * - * Release the client, if not active already... - */ - System.err.println("Server died..."); - serverReady = true; - serverException = e; - } - } - }; - serverThread.start(); - } else { - doServerSide(); - } - } - - private void startClient(boolean newThread) throws Exception { - if (newThread) { - clientThread = new Thread() { - public void run() { - try { - doClientSide(); - } catch (Exception e) { - /* - * Our client thread just died. - */ - System.err.println("Client died..."); - clientException = e; - } - } - }; - clientThread.start(); - } else { - doClientSide(); - } + private void startClient() { + clientThread = new Thread(() -> { + try { + doClientSide(); + } catch (Exception e) { + /* + * Our client thread just died. + */ + System.err.println("Client died..."); + clientException = e; + } + }); + clientThread.start(); } } diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SSLSocketImpl/SetClientMode.java openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SSLSocketImpl/SetClientMode.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SSLSocketImpl/SetClientMode.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SSLSocketImpl/SetClientMode.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,11 +27,13 @@ /* * @test * @bug 6223624 - * @ignore this test does not grant to work. The handshake may have completed - * when getSession() return. Please update or remove this test case. + * @library /test/lib /javax/net/ssl/templates * @summary SSLSocket.setUseClientMode() fails to throw expected * IllegalArgumentException - * @run main/othervm SetClientMode + * @run main/othervm SetClientMode TLSv1 + * @run main/othervm SetClientMode TLSv1.1 + * @run main/othervm SetClientMode TLSv1.2 + * @run main/othervm SetClientMode TLSv1.3 */ /* @@ -47,143 +49,82 @@ * occasionally on the very first iteration. */ -import java.io.*; import java.lang.*; import java.net.*; +import java.util.concurrent.CountDownLatch; import javax.net.ssl.*; -import java.security.*; -import java.security.cert.*; +import jdk.test.lib.security.SecurityUtils; -public class SetClientMode { - private static String[] algorithms = {"TLS", "SSL", "SSLv3", "TLS"}; - volatile int serverPort = 0; - - /* - * Where do we find the keystores? - */ - static String pathToStores = "../../../../javax/net/ssl/etc"; - static String keyStoreFile = "keystore"; - static String trustStoreFile = "truststore"; - static String passwd = "passphrase"; +import static jdk.test.lib.Asserts.assertThrows; - - public SetClientMode() { - // trivial constructor - } +public class SetClientMode extends SSLContextTemplate { + private volatile int serverPort = 0; + private static final CountDownLatch HANDSHAKE_COMPLETE = new CountDownLatch(1); public static void main(String[] args) throws Exception { - String keyFilename = - System.getProperty("test.src", "./") + "/" + pathToStores + - "/" + keyStoreFile; - String trustFilename = - System.getProperty("test.src", "./") + "/" + pathToStores + - "/" + trustStoreFile; - - System.setProperty("javax.net.ssl.keyStore", keyFilename); - System.setProperty("javax.net.ssl.keyStorePassword", passwd); - System.setProperty("javax.net.ssl.trustStore", trustFilename); - System.setProperty("javax.net.ssl.trustStorePassword", passwd); + String protocol = args[0]; - new SetClientMode().run(); - } - - public void run() throws Exception { - for (int i = 0; i < algorithms.length; i++) { - testCombo( algorithms[i] ); + if ("TLSv1".equals(protocol) || "TLSv1.1".equals(protocol)) { + SecurityUtils.removeFromDisabledTlsAlgs(protocol); } - } - public void testCombo(String algorithm) throws Exception { - Exception modeException = null ; + new SetClientMode().run(protocol); + } + public void run(String protocol) throws Exception { // Create a server socket - SSLServerSocketFactory ssf = - (SSLServerSocketFactory)SSLServerSocketFactory.getDefault(); - SSLServerSocket serverSocket = - (SSLServerSocket)ssf.createServerSocket(serverPort); - serverPort = serverSocket.getLocalPort(); - - // Create a client socket - SSLSocketFactory sf = (SSLSocketFactory)SSLSocketFactory.getDefault(); - SSLSocket clientSocket = (SSLSocket)sf.createSocket( - InetAddress.getLocalHost(), - serverPort ); - - // Create a client which will use the SSLSocket to talk to the server - SocketClient client = new SocketClient(clientSocket); - - // Start the client and then accept any connection - client.start(); - - SSLSocket connectedSocket = (SSLSocket)serverSocket.accept(); - - // force handshaking to complete - connectedSocket.getSession(); - - try { - // Now try invoking setClientMode() on one - // or the other of our two sockets. We expect - // to see an IllegalArgumentException because - // handshaking has begun. - clientSocket.setUseClientMode(false); - - modeException = new Exception("no IllegalArgumentException"); - } catch (IllegalArgumentException iae) { - System.out.println("succeeded, we can't set the client mode"); - } catch (Exception e) { - modeException = e; - } finally { - // Shut down. - connectedSocket.close(); - serverSocket.close(); + SSLServerSocketFactory ssf = createServerSSLContext().getServerSocketFactory(); + + try (SSLServerSocket serverSocket = + (SSLServerSocket) ssf.createServerSocket(serverPort)) { + serverSocket.setEnabledProtocols(new String[]{ protocol }); + serverPort = serverSocket.getLocalPort(); + + // Create a client socket + SSLSocketFactory sf = createClientSSLContext().getSocketFactory(); + + try (SSLSocket clientSocket = (SSLSocket) sf.createSocket( + InetAddress.getLocalHost(), + serverPort)) { + + // Create a client which will use the SSLSocket to talk to the server + Client client = new Client(clientSocket); - if (modeException != null) { - throw modeException; + // Start the client and then accept any connection + client.start(); + + SSLSocket connectedSocket = (SSLSocket) serverSocket.accept(); + + // force handshaking to complete + connectedSocket.getSession(); + + HANDSHAKE_COMPLETE.await(); + + // Now try invoking setClientMode() on the client socket. + // We expect to see an IllegalArgumentException because + // handshaking has begun. + assertThrows(IllegalArgumentException.class, + () -> clientSocket.setUseClientMode(false)); } } - - return; } // A thread-based client which does nothing except // start handshaking on the socket it's given. - class SocketClient extends Thread { - SSLSocket clientsideSocket; - Exception clientException = null; - boolean done = false; + static class Client extends Thread { + private final SSLSocket socket; - public SocketClient( SSLSocket s ) { - clientsideSocket = s; + public Client(SSLSocket s) { + socket = s; } public void run() { try { - clientsideSocket.startHandshake(); - - // If we were to invoke setUseClientMode() - // here, the expected exception will happen. - //clientsideSocket.getSession(); - //clientsideSocket.setUseClientMode( false ); - } catch ( Exception e ) { + socket.startHandshake(); + HANDSHAKE_COMPLETE.countDown(); + } catch (Exception e) { e.printStackTrace(); - clientException = e; - } finally { - done = true; - try { - clientsideSocket.close(); - } catch ( IOException e ) { - // eat it - } } - return; - } - - boolean isDone() { - return done; - } - - Exception getException() { - return clientException; } } } diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SignatureScheme/AbstractCheckSignatureSchemes.java openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/AbstractCheckSignatureSchemes.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SignatureScheme/AbstractCheckSignatureSchemes.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/AbstractCheckSignatureSchemes.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.nio.ByteBuffer; +import java.util.AbstractMap.SimpleImmutableEntry; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLException; + +/** + * This is not a test. Actual tests are implemented by concrete subclasses. + * The abstract class AbstractCheckSignatureSchemes provides a base framework + * for checking TLS signature schemes. + */ + +public abstract class AbstractCheckSignatureSchemes extends SSLEngineTemplate { + + // Helper map to correlate integral SignatureScheme identifiers to + // their IANA string name counterparts. + protected static final Map sigSchemeMap = Map.ofEntries( + new SimpleImmutableEntry(0x0401, "rsa_pkcs1_sha256"), + new SimpleImmutableEntry(0x0501, "rsa_pkcs1_sha384"), + new SimpleImmutableEntry(0x0601, "rsa_pkcs1_sha512"), + new SimpleImmutableEntry(0x0403, "ecdsa_secp256r1_sha256"), + new SimpleImmutableEntry(0x0503, "ecdsa_secp384r1_sha384"), + new SimpleImmutableEntry(0x0603, "ecdsa_secp521r1_sha512"), + new SimpleImmutableEntry(0x0804, "rsa_pss_rsae_sha256"), + new SimpleImmutableEntry(0x0805, "rsa_pss_rsae_sha384"), + new SimpleImmutableEntry(0x0806, "rsa_pss_rsae_sha512"), + new SimpleImmutableEntry(0x0807, "ed25519"), + new SimpleImmutableEntry(0x0808, "ed448"), + new SimpleImmutableEntry(0x0809, "rsa_pss_pss_sha256"), + new SimpleImmutableEntry(0x080a, "rsa_pss_pss_sha384"), + new SimpleImmutableEntry(0x080b, "rsa_pss_pss_sha512"), + new SimpleImmutableEntry(0x0101, "rsa_md5"), + new SimpleImmutableEntry(0x0201, "rsa_pkcs1_sha1"), + new SimpleImmutableEntry(0x0202, "dsa_sha1"), + new SimpleImmutableEntry(0x0203, "ecdsa_sha1"), + new SimpleImmutableEntry(0x0301, "rsa_sha224"), + new SimpleImmutableEntry(0x0302, "dsa_sha224"), + new SimpleImmutableEntry(0x0303, "ecdsa_sha224"), + new SimpleImmutableEntry(0x0402, "rsa_pkcs1_sha256")); + + // Other useful TLS definitions for these tests + protected static final int TLS_HS_CLI_HELLO = 1; + protected static final int TLS_HS_CERT_REQ = 13; + protected static final int SIG_ALGS_EXT = 13; + protected static final int SIG_ALGS_CERT_EXT = 50; + + protected AbstractCheckSignatureSchemes() throws Exception { + super(); + } + + // Returns the protocol for test to use. + abstract String getProtocol(); + + protected boolean isDtls() { + return getProtocol().startsWith("DTLS"); + } + + @Override + protected SSLEngine configureClientEngine(SSLEngine clientEngine) { + clientEngine.setUseClientMode(true); + clientEngine.setEnabledProtocols(new String[]{getProtocol()}); + return clientEngine; + } + + @Override + protected SSLEngine configureServerEngine(SSLEngine serverEngine) { + serverEngine.setUseClientMode(false); + serverEngine.setWantClientAuth(true); + serverEngine.setEnabledProtocols(new String[]{getProtocol()}); + return serverEngine; + } + + @Override + protected ContextParameters getServerContextParameters() { + return new ContextParameters(getProtocol(), "PKIX", "NewSunX509"); + } + + @Override + protected ContextParameters getClientContextParameters() { + return new ContextParameters(getProtocol(), "PKIX", "NewSunX509"); + } + + protected ByteBuffer extractHandshakeMsg(ByteBuffer tlsRecord, int hsMsgId) + throws SSLException { + return extractHandshakeMsg(tlsRecord, hsMsgId, isDtls()); + } + + /** + * Parses the ClientHello message and extracts from it a list of + * SignatureScheme values in string form. It is assumed that the provided + * ByteBuffer has its position set at the first byte of the ClientHello + * message body (AFTER the handshake header) and contains the entire + * hello message. Upon successful completion of this method the ByteBuffer + * will have its position reset to the initial offset in the buffer. + * If an exception is thrown the position at the time of the exception + * will be preserved. + * + * @param data The ByteBuffer containing the ClientHello bytes. + * @param extCode Code of the TLS extension from which to extract + * signature schemes. + * @return A List of the signature schemes in string form. + */ + protected List getSigSchemesCliHello( + ByteBuffer data, int extCode) { + Objects.requireNonNull(data); + data.mark(); + + // Skip over the protocol version and client random + data.position(data.position() + 34); + + // Jump past the session ID (if there is one) + int sessLen = Byte.toUnsignedInt(data.get()); + if (sessLen != 0) { + data.position(data.position() + sessLen); + } + + // Skip DTLS-specific opaque cookie if any + if (isDtls()) { + int cookieLen = Byte.toUnsignedInt(data.get()); + if (cookieLen != 0) { + data.position(data.position() + cookieLen); + } + } + + // Jump past the cipher suites + int csLen = Short.toUnsignedInt(data.getShort()); + if (csLen != 0) { + data.position(data.position() + csLen); + } + + // ...and the compression + int compLen = Byte.toUnsignedInt(data.get()); + if (compLen != 0) { + data.position(data.position() + compLen); + } + + // Now for the fun part. Go through the extensions and look + // for the two status request exts. + List extSigAlgs = getSigSchemesFromExt(data, extCode); + + // We should be at the end of the ClientHello + data.reset(); + return extSigAlgs; + } + + /** + * Parses the CertificateRequest message and extracts from it a list of + * SignatureScheme values in string form. It is assumed that the provided + * ByteBuffer has its position set at the first byte of the + * CertificateRequest message body (AFTER the handshake header) and + * contains the entire CR message. Upon successful completion of this + * method the ByteBuffer will have its position reset to the initial + * offset in the buffer. + * If an exception is thrown the position at the time of the exception + * will be preserved. + * + * @param data The ByteBuffer containing the CertificateRequest bytes + * + * @return A List of the signature schemes in string form. If no + * signature_algorithms extension is present in the CertificateRequest + * then an empty list will be returned. + */ + protected List getSigSchemesCertReq(ByteBuffer data) { + Objects.requireNonNull(data); + data.mark(); + + // Jump past the certificate types + int certTypeLen = Byte.toUnsignedInt(data.get()); + if (certTypeLen != 0) { + data.position(data.position() + certTypeLen); + } + + // Collect the SignatureAndHashAlgorithms + List extSigAlgs = new ArrayList(); + int sigSchemeLen = Short.toUnsignedInt(data.getShort()); + for (int ssOff = 0; ssOff < sigSchemeLen; ssOff += 2) { + String schemeName = sigSchemeMap.get( + Short.toUnsignedInt(data.getShort())); + if (schemeName != null) { + extSigAlgs.add(schemeName); + } + } + + data.reset(); + return extSigAlgs; + } + + /** + * Gets signatures schemes from the given TLS extension. + * The buffer should be positioned at the start of the extension. + */ + protected List getSigSchemesFromExt( + ByteBuffer data, int extCode) { + + List extSigAlgs = new ArrayList<>(); + data.getShort(); // read length + + while (data.hasRemaining()) { + int extType = Short.toUnsignedInt(data.getShort()); + int extLen = Short.toUnsignedInt(data.getShort()); + if (extType == extCode) { + // Start processing signature algorithms + int sigSchemeLen = Short.toUnsignedInt(data.getShort()); + for (int ssOff = 0; ssOff < sigSchemeLen; ssOff += 2) { + String schemeName = sigSchemeMap.get( + Short.toUnsignedInt(data.getShort())); + if (schemeName != null) { + extSigAlgs.add(schemeName); + } + } + } else { + // Not the extension we're looking for. Skip past the + // extension data + data.position(data.position() + extLen); + } + } + + return extSigAlgs; + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SignatureScheme/DisableSignatureSchemePerScopeDTLS12.java openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/DisableSignatureSchemePerScopeDTLS12.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SignatureScheme/DisableSignatureSchemePerScopeDTLS12.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/DisableSignatureSchemePerScopeDTLS12.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8349583 + * @summary Add mechanism to disable signature schemes based on their TLS scope. + * This test only covers DTLS 1.2. + * @library /javax/net/ssl/templates + * /test/lib + * @run main/othervm DisableSignatureSchemePerScopeDTLS12 + */ + +import java.security.Security; + +public class DisableSignatureSchemePerScopeDTLS12 + extends DisableSignatureSchemePerScopeTLS12 { + + protected DisableSignatureSchemePerScopeDTLS12() throws Exception { + super(); + } + + public static void main(String[] args) throws Exception { + Security.setProperty( + "jdk.tls.disabledAlgorithms", DISABLED_CONSTRAINTS); + new DisableSignatureSchemePerScopeDTLS12().run(); + } + + @Override + protected String getProtocol() { + return "DTLSv1.2"; + } + + // No CertificateRequest in DTLS server flight. + @Override + protected void checkCertificateRequest() { + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SignatureScheme/DisableSignatureSchemePerScopeTLS12.java openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/DisableSignatureSchemePerScopeTLS12.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SignatureScheme/DisableSignatureSchemePerScopeTLS12.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/DisableSignatureSchemePerScopeTLS12.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8349583 + * @summary Add mechanism to disable signature schemes based on their TLS scope. + * This test only covers TLS 1.2. + * @library /javax/net/ssl/templates + * /test/lib + * @run main/othervm DisableSignatureSchemePerScopeTLS12 + */ + +import static jdk.test.lib.Asserts.assertFalse; +import static jdk.test.lib.Asserts.assertTrue; + +import java.security.Security; +import java.util.List; + +public class DisableSignatureSchemePerScopeTLS12 extends + AbstractCheckSignatureSchemes { + + // Disabled for Handshake scope. + protected static final String HANDSHAKE_DISABLED_SIG = "rsa_pss_rsae_sha384"; + + // Disabled for Certificate scope. + protected static final String CERTIFICATE_DISABLED_SIG = "ecdsa_secp384r1_sha384"; + + // jdk.tls.disabledAlgorithms value + // We differ from "HandshakeSignature" and "CertificateSignature" specified + // in java.security to check case-insensitive matching. + protected static final String DISABLED_CONSTRAINTS = + HANDSHAKE_DISABLED_SIG + " usage HandShakesignature, " + + CERTIFICATE_DISABLED_SIG + " usage certificateSignature"; + + protected DisableSignatureSchemePerScopeTLS12() throws Exception { + super(); + } + + public static void main(String[] args) throws Exception { + Security.setProperty( + "jdk.tls.disabledAlgorithms", DISABLED_CONSTRAINTS); + new DisableSignatureSchemePerScopeTLS12().run(); + } + + protected String getProtocol() { + return "TLSv1.2"; + } + + // Run things in TLS handshake order. + protected void run() throws Exception { + + // Produce client_hello + clientEngine.wrap(clientOut, cTOs); + cTOs.flip(); + + checkClientHello(); + + // Consume client_hello. + serverEngine.unwrap(cTOs, serverIn); + runDelegatedTasks(serverEngine); + + // Produce server_hello. + serverEngine.wrap(serverOut, sTOc); + sTOc.flip(); + + checkCertificateRequest(); + } + + protected void checkClientHello() throws Exception { + // --- Check signature_algorithms extension --- + + // Get signature_algorithms extension signature schemes. + List sigAlgsSS = getSigSchemesCliHello( + extractHandshakeMsg(cTOs, TLS_HS_CLI_HELLO), + SIG_ALGS_EXT); + + // signature_algorithms extension MUST NOT contain disabled + // handshake signature scheme. + assertFalse(sigAlgsSS.contains(HANDSHAKE_DISABLED_SIG), + "Signature Scheme " + HANDSHAKE_DISABLED_SIG + + " present in ClientHello's signature_algorithms extension"); + + // signature_algorithms extension MUST contain disabled + // certificate signature scheme. + assertTrue(sigAlgsSS.contains(CERTIFICATE_DISABLED_SIG), + "Signature Scheme " + CERTIFICATE_DISABLED_SIG + + " isn't present in ClientHello's" + + " signature_algorithms extension"); + + // --- Check signature_algorithms_cert extension --- + + // Get signature_algorithms_cert extension signature schemes. + List sigAlgsCertSS = getSigSchemesCliHello( + extractHandshakeMsg(cTOs, TLS_HS_CLI_HELLO), + SIG_ALGS_CERT_EXT); + + // signature_algorithms_cert extension MUST contain disabled + // handshake signature scheme. + assertTrue(sigAlgsCertSS.contains(HANDSHAKE_DISABLED_SIG), + "Signature Scheme " + HANDSHAKE_DISABLED_SIG + + " isn't present in ClientHello's" + + " signature_algorithms extension"); + + // signature_algorithms_cert extension MUST NOT contain disabled + // certificate signature scheme. + assertFalse(sigAlgsCertSS.contains(CERTIFICATE_DISABLED_SIG), + "Signature Scheme " + CERTIFICATE_DISABLED_SIG + + " present in ClientHello's signature_algorithms extension"); + } + + protected void checkCertificateRequest() throws Exception { + // Get CertificateRequest message signature schemes. + List sigAlgsCertSS = getSigSchemesCertReq( + extractHandshakeMsg(sTOc, TLS_HS_CERT_REQ)); + + // TLSv1.2 CertificateRequest message MUST NOT contain both: + // disabled handshake signature scheme and disabled + // certificate signature scheme + + assertFalse(sigAlgsCertSS.contains(HANDSHAKE_DISABLED_SIG), + "Signature Scheme " + HANDSHAKE_DISABLED_SIG + + " present in CertificateRequest"); + + assertFalse(sigAlgsCertSS.contains(CERTIFICATE_DISABLED_SIG), + "Signature Scheme " + CERTIFICATE_DISABLED_SIG + + " present in CertificateRequest"); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SignatureScheme/DisableSignatureSchemePerScopeTLS13.java openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/DisableSignatureSchemePerScopeTLS13.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SignatureScheme/DisableSignatureSchemePerScopeTLS13.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/DisableSignatureSchemePerScopeTLS13.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8349583 + * @summary Add mechanism to disable signature schemes based on their TLS scope. + * This test only covers TLS 1.3. + * @library /javax/net/ssl/templates + * /test/lib + * @run main/othervm DisableSignatureSchemePerScopeTLS13 + */ + + +import static jdk.test.lib.Asserts.assertFalse; +import static jdk.test.lib.Asserts.assertTrue; + +import java.security.Security; +import java.util.List; + +public class DisableSignatureSchemePerScopeTLS13 + extends DisableSignatureSchemePerScopeTLS12 { + + // Signature schemes not supported in TLSv1.3 only for the handshake. + // This is regardless of jdk.tls.disabledAlgorithms configuration. + List NOT_SUPPORTED_FOR_HANDSHAKE = List.of( + "rsa_pkcs1_sha1", + "rsa_pkcs1_sha256", + "rsa_pkcs1_sha384", + "rsa_pkcs1_sha512" + ); + + protected DisableSignatureSchemePerScopeTLS13() throws Exception { + super(); + } + + public static void main(String[] args) throws Exception { + Security.setProperty( + "jdk.tls.disabledAlgorithms", DISABLED_CONSTRAINTS); + new DisableSignatureSchemePerScopeTLS13().run(); + } + + @Override + protected String getProtocol() { + return "TLSv1.3"; + } + + @Override + protected void checkClientHello() throws Exception { + super.checkClientHello(); + + // Get signature_algorithms extension signature schemes. + List sigAlgsSS = getSigSchemesCliHello( + extractHandshakeMsg(cTOs, TLS_HS_CLI_HELLO), + SIG_ALGS_EXT); + + // Should not be present in signature_algorithms extension. + NOT_SUPPORTED_FOR_HANDSHAKE.forEach(ss -> + assertFalse(sigAlgsSS.contains(ss), + "Signature Scheme " + ss + + " present in ClientHello's signature_algorithms extension")); + + // Get signature_algorithms_cert extension signature schemes. + List sigAlgsCertSS = getSigSchemesCliHello( + extractHandshakeMsg(cTOs, TLS_HS_CLI_HELLO), + SIG_ALGS_CERT_EXT); + + // Should be present in signature_algorithms_cert extension. + NOT_SUPPORTED_FOR_HANDSHAKE.forEach(ss -> + assertTrue(sigAlgsCertSS.contains(ss), + "Signature Scheme " + ss + + " isn't present in ClientHello's" + + " signature_algorithms extension")); + } + + // TLSv1.3 sends CertificateRequest signature schemes in + // signature_algorithms and signature_algorithms_cert extensions. Same as + // ClientHello, but they are encrypted. So we skip CertificateRequest + // signature schemes verification for TLSv1.3. + @Override + protected void checkCertificateRequest() { + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SignatureScheme/MD5NotAllowedInTLS13CertificateSignature.java openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/MD5NotAllowedInTLS13CertificateSignature.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SignatureScheme/MD5NotAllowedInTLS13CertificateSignature.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/MD5NotAllowedInTLS13CertificateSignature.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8350807 + * @summary Certificates using MD5 algorithm that are disabled by default are + * incorrectly allowed in TLSv1.3 when re-enabled. + * @modules java.base/sun.security.x509 + * java.base/sun.security.util + * @library /javax/net/ssl/templates + * /test/lib + * @run main/othervm MD5NotAllowedInTLS13CertificateSignature + */ + +import static jdk.test.lib.Asserts.assertEquals; +import static jdk.test.lib.Asserts.assertTrue; +import static jdk.test.lib.Utils.runAndCheckException; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Date; +import java.util.List; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.TrustManagerFactory; +import jdk.test.lib.security.CertificateBuilder; +import jdk.test.lib.security.SecurityUtils; +import sun.security.x509.AuthorityKeyIdentifierExtension; +import sun.security.x509.GeneralName; +import sun.security.x509.GeneralNames; +import sun.security.x509.KeyIdentifier; +import sun.security.x509.SerialNumber; +import sun.security.x509.X500Name; + +public class MD5NotAllowedInTLS13CertificateSignature extends + SSLSocketTemplate { + + private final String protocol; + private X509Certificate trustedCert; + private X509Certificate serverCert; + private X509Certificate clientCert; + private KeyPair serverKeys; + private KeyPair clientKeys; + + protected MD5NotAllowedInTLS13CertificateSignature(String protocol) + throws Exception { + super(); + this.protocol = protocol; + setupCertificates(); + } + + public static void main(String[] args) throws Exception { + // MD5 is disabled by default in java.security config file, + // re-enable it for our test. + SecurityUtils.removeFromDisabledAlgs( + "jdk.certpath.disabledAlgorithms", List.of("MD5")); + SecurityUtils.removeFromDisabledAlgs( + "jdk.tls.disabledAlgorithms", List.of("MD5withRSA")); + + // Should fail on TLSv1.3 and up. + runAndCheckException( + // The conditions to reproduce the bug being fixed only met when + // 'TLS' is specified, i.e. when older versions of protocol are + // supported besides TLSv1.3. + () -> new MD5NotAllowedInTLS13CertificateSignature("TLS").run(), + serverEx -> { + Throwable clientEx = serverEx.getSuppressed()[0]; + assertTrue(clientEx instanceof SSLHandshakeException); + assertEquals(clientEx.getMessage(), "(bad_certificate) " + + "PKIX path validation failed: " + + "java.security.cert.CertPathValidatorException: " + + "Algorithm constraints check failed on signature" + + " algorithm: MD5withRSA"); + }); + + // Should run fine on TLSv1.2. + new MD5NotAllowedInTLS13CertificateSignature("TLSv1.2").run(); + } + + @Override + public SSLContext createServerSSLContext() throws Exception { + return getSSLContext( + trustedCert, serverCert, serverKeys.getPrivate(), protocol); + } + + @Override + public SSLContext createClientSSLContext() throws Exception { + return getSSLContext( + trustedCert, clientCert, clientKeys.getPrivate(), protocol); + } + + private static SSLContext getSSLContext( + X509Certificate trustedCertificate, X509Certificate keyCertificate, + PrivateKey privateKey, String protocol) + throws Exception { + + // create a key store + KeyStore ks = KeyStore.getInstance("PKCS12"); + ks.load(null, null); + + // import the trusted cert + ks.setCertificateEntry("TLS Signer", trustedCertificate); + + // generate certificate chain + Certificate[] chain = new Certificate[2]; + chain[0] = keyCertificate; + chain[1] = trustedCertificate; + + // import the key entry. + final char[] passphrase = "passphrase".toCharArray(); + ks.setKeyEntry("Whatever", privateKey, passphrase, chain); + + // Using PKIX TrustManager - this is where MD5 signature check is done. + TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); + tmf.init(ks); + + // create SSL context + SSLContext ctx = SSLContext.getInstance(protocol); + + // Using "SunX509" which doesn't check peer supported signature + // algorithms, so we check against local supported signature + // algorithms which constitutes the fix being tested. + KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); + kmf.init(ks, passphrase); + + ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + + return ctx; + } + + // Certificate-building helper methods. + // Certificates are signed with signature using MD5WithRSA algorithm. + + private void setupCertificates() throws Exception { + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); + kpg.initialize(1024); + KeyPair caKeys = kpg.generateKeyPair(); + this.serverKeys = kpg.generateKeyPair(); + this.clientKeys = kpg.generateKeyPair(); + + this.trustedCert = createTrustedCert(caKeys); + + this.serverCert = customCertificateBuilder( + "O=Some-Org, L=Some-City, ST=Some-State, C=US", + serverKeys.getPublic(), caKeys.getPublic()) + .addBasicConstraintsExt(false, false, -1) + .build(trustedCert, caKeys.getPrivate(), "MD5WithRSA"); + + this.clientCert = customCertificateBuilder( + "CN=localhost, OU=SSL-Client, O=Some-Org, L=Some-City, ST=Some-State, C=US", + clientKeys.getPublic(), caKeys.getPublic()) + .addBasicConstraintsExt(false, false, -1) + .build(trustedCert, caKeys.getPrivate(), "MD5WithRSA"); + } + + private static X509Certificate createTrustedCert(KeyPair caKeys) + throws Exception { + SecureRandom random = new SecureRandom(); + + KeyIdentifier kid = new KeyIdentifier(caKeys.getPublic()); + GeneralNames gns = new GeneralNames(); + GeneralName name = new GeneralName(new X500Name( + "O=Some-Org, L=Some-City, ST=Some-State, C=US")); + gns.add(name); + BigInteger serialNumber = BigInteger.valueOf( + random.nextLong(1000000) + 1); + return customCertificateBuilder( + "O=Some-Org, L=Some-City, ST=Some-State, C=US", + caKeys.getPublic(), caKeys.getPublic()) + .setSerialNumber(serialNumber) + .addExtension(new AuthorityKeyIdentifierExtension(kid, gns, + new SerialNumber(serialNumber))) + .addBasicConstraintsExt(true, true, -1) + .build(null, caKeys.getPrivate(), "MD5WithRSA"); + } + + private static CertificateBuilder customCertificateBuilder( + String subjectName, PublicKey publicKey, PublicKey caKey) + throws CertificateException, IOException { + SecureRandom random = new SecureRandom(); + + CertificateBuilder builder = new CertificateBuilder() + .setSubjectName(subjectName) + .setPublicKey(publicKey) + .setNotBefore( + Date.from(Instant.now().minus(1, ChronoUnit.HOURS))) + .setNotAfter(Date.from(Instant.now().plus(1, ChronoUnit.HOURS))) + .setSerialNumber( + BigInteger.valueOf(random.nextLong(1000000) + 1)) + .addSubjectKeyIdExt(publicKey) + .addAuthorityKeyIdExt(caKey); + builder.addKeyUsageExt( + new boolean[]{true, true, true, true, true, true}); + + return builder; + } + +} diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SignatureScheme/MixingTLSUsageConstraintsWithNonTLS.java openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/MixingTLSUsageConstraintsWithNonTLS.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SignatureScheme/MixingTLSUsageConstraintsWithNonTLS.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/MixingTLSUsageConstraintsWithNonTLS.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8349583 + * @summary Add mechanism to disable signature schemes based on their TLS scope + * @library /javax/net/ssl/templates + * /test/lib + * @run main/othervm MixingTLSUsageConstraintsWithNonTLS + */ + +import static jdk.test.lib.Asserts.assertEquals; +import static jdk.test.lib.Asserts.assertTrue; +import static jdk.test.lib.Utils.runAndCheckException; + +import java.security.Security; + +public class MixingTLSUsageConstraintsWithNonTLS extends SSLSocketTemplate { + + public static void main(String[] args) throws Exception { + Security.setProperty("jdk.tls.disabledAlgorithms", + "rsa_pkcs1_sha1 usage handshakeSignature certificateSignature TLSServer"); + + runAndCheckException( + () -> new MixingTLSUsageConstraintsWithNonTLS().run(), + e -> { + assertTrue(e instanceof ExceptionInInitializerError); + assertTrue( + e.getCause() instanceof IllegalArgumentException); + assertEquals(e.getCause().getMessage(), + "Can't mix TLS protocol specific constraints" + + " with other usage constraints"); + }); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,6 @@ /* - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (C) 2021, 2024 THL A29 Limited, a Tencent company. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -122,7 +123,7 @@ "Expected SSLHandshakeException wasn't thrown"); } } catch (SSLHandshakeException e) { - if (EXPECT_FAIL && e.getMessage().equals( + if (EXPECT_FAIL && e.getMessage().endsWith( "No supported signature algorithm")) { System.out.println("Expected SSLHandshakeException"); } else { diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,4 +1,5 @@ /* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -78,7 +79,7 @@ "Expected SSLHandshakeException wasn't thrown"); } } catch (SSLHandshakeException e) { - if (expectFail && e.getMessage().equals( + if (expectFail && e.getMessage().endsWith( "No supported signature algorithm")) { System.out.println("Expected SSLHandshakeException"); } else { diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SignatureScheme/SigSchemePropOrdering.java openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/SigSchemePropOrdering.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/SignatureScheme/SigSchemePropOrdering.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/SignatureScheme/SigSchemePropOrdering.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,48 +34,14 @@ * @run main/othervm SigSchemePropOrdering */ -import java.nio.ByteBuffer; -import java.util.*; -import java.util.AbstractMap.SimpleImmutableEntry; -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLException; - -public class SigSchemePropOrdering extends SSLEngineTemplate { - - // Helper map to correlate integral SignatureScheme identifiers to - // their IANA string name counterparts. - static final Map sigSchemeMap = Map.ofEntries( - new SimpleImmutableEntry(0x0401, "rsa_pkcs1_sha256"), - new SimpleImmutableEntry(0x0501, "rsa_pkcs1_sha384"), - new SimpleImmutableEntry(0x0601, "rsa_pkcs1_sha512"), - new SimpleImmutableEntry(0x0403, "ecdsa_secp256r1_sha256"), - new SimpleImmutableEntry(0x0503, "ecdsa_secp384r1_sha384"), - new SimpleImmutableEntry(0x0603, "ecdsa_secp521r1_sha512"), - new SimpleImmutableEntry(0x0804, "rsa_pss_rsae_sha256"), - new SimpleImmutableEntry(0x0805, "rsa_pss_rsae_sha384"), - new SimpleImmutableEntry(0x0806, "rsa_pss_rsae_sha512"), - new SimpleImmutableEntry(0x0807, "ed25519"), - new SimpleImmutableEntry(0x0808, "ed448"), - new SimpleImmutableEntry(0x0809, "rsa_pss_pss_sha256"), - new SimpleImmutableEntry(0x080a, "rsa_pss_pss_sha384"), - new SimpleImmutableEntry(0x080b, "rsa_pss_pss_sha512"), - new SimpleImmutableEntry(0x0101, "rsa_md5"), - new SimpleImmutableEntry(0x0201, "rsa_pkcs1_sha1"), - new SimpleImmutableEntry(0x0202, "dsa_sha1"), - new SimpleImmutableEntry(0x0203, "ecdsa_sha1"), - new SimpleImmutableEntry(0x0301, "rsa_sha224"), - new SimpleImmutableEntry(0x0302, "dsa_sha224"), - new SimpleImmutableEntry(0x0303, "ecdsa_sha224"), - new SimpleImmutableEntry(0x0402, "rsa_pkcs1_sha256")); - - // Other useful TLS definitions for these tests - private static final int TLS_HS_CLI_HELLO = 1; - private static final int TLS_HS_CERT_REQ = 13; - private static final int HELLO_EXT_SIG_ALGS = 13; +import java.util.Arrays; +import java.util.List; + +public class SigSchemePropOrdering extends AbstractCheckSignatureSchemes { private static final String SIG_SCHEME_STR = "rsa_pkcs1_sha256,rsa_pss_rsae_sha256,rsa_pss_pss_sha256," + - "ed448,ed25519,ecdsa_secp256r1_sha256"; + "ed448,ed25519,ecdsa_secp256r1_sha256"; SigSchemePropOrdering() throws Exception { super(); @@ -88,18 +54,8 @@ new SigSchemePropOrdering().run(); } - @Override - protected SSLEngine configureClientEngine(SSLEngine clientEngine) { - clientEngine.setUseClientMode(true); - clientEngine.setEnabledProtocols(new String[] { "TLSv1.2" }); - return clientEngine; - } - - @Override - protected SSLEngine configureServerEngine(SSLEngine serverEngine) { - serverEngine.setUseClientMode(false); - serverEngine.setWantClientAuth(true); - return serverEngine; + protected String getProtocol() { + return "TLSv1.2"; } private void run() throws Exception { @@ -112,7 +68,8 @@ cTOs.flip(); List actualSS = getSigSchemesCliHello( - extractHandshakeMsg(cTOs, TLS_HS_CLI_HELLO)); + extractHandshakeMsg(cTOs, TLS_HS_CLI_HELLO), + SIG_ALGS_EXT); // Make sure the ordering is correct if (!expectedSS.equals(actualSS)) { @@ -155,177 +112,4 @@ "FAIL: Expected and Actual values differ."); } } - - /** - * Given a TLS record containing one or more handshake messages, return - * the specific handshake message as a ByteBuffer (a slice of the record) - * - * @param tlsRecord a ByteBuffer containing a TLS record. It is assumed - * that the position of the ByteBuffer is on the first byte of the TLS - * record header. - * @param hsMsgId the message identifier for the handshake message being - * sought. - * - * @return a ByteBuffer containing the TLS handshake message. The position - * of the returned ByteBuffer will be on the first byte of the TLS - * handshake message data, immediately following the handshake header. - * If the message is not found, null will be returned. - * - * @throws SSLException if the incoming ByteBuffer does not contain a - * well-formed TLS message. - */ - private static ByteBuffer extractHandshakeMsg(ByteBuffer tlsRecord, - int hsMsgId) throws SSLException { - Objects.requireNonNull(tlsRecord); - tlsRecord.mark(); - - // Process the TLS record header - int type = Byte.toUnsignedInt(tlsRecord.get()); - int ver_major = Byte.toUnsignedInt(tlsRecord.get()); - int ver_minor = Byte.toUnsignedInt(tlsRecord.get()); - int recLen = Short.toUnsignedInt(tlsRecord.getShort()); - - // Simple sanity checks - if (type != 22) { - throw new SSLException("Not a handshake: Type = " + type); - } else if (recLen > tlsRecord.remaining()) { - throw new SSLException("Incomplete record in buffer: " + - "Record length = " + recLen + ", Remaining = " + - tlsRecord.remaining()); - } - - while (tlsRecord.hasRemaining()) { - // Grab the handshake message header. - int msgHdr = tlsRecord.getInt(); - int msgType = (msgHdr >> 24) & 0x000000FF; - int msgLen = msgHdr & 0x00FFFFFF; - - if (msgType == hsMsgId) { - // Slice the buffer such that it contains the entire - // handshake message (less the handshake header). - ByteBuffer buf = tlsRecord.slice(tlsRecord.position(), msgLen); - tlsRecord.reset(); - return buf; - } else { - // Skip to the next handshake message, if there is one - tlsRecord.position(tlsRecord.position() + msgLen); - } - } - - tlsRecord.reset(); - return null; - } - - - /** - * Parses the ClientHello message and extracts from it a list of - * SignatureScheme values in string form. It is assumed that the provided - * ByteBuffer has its position set at the first byte of the ClientHello - * message body (AFTER the handshake header) and contains the entire - * hello message. Upon successful completion of this method the ByteBuffer - * will have its position reset to the initial offset in the buffer. - * If an exception is thrown the position at the time of the exception - * will be preserved. - * - * @param data the ByteBuffer containing the ClientHello bytes - * - * @return A List of the signature schemes in string form. If no - * signature_algorithms extension is present in the client hello then - * an empty list will be returned. - */ - private static List getSigSchemesCliHello(ByteBuffer data) { - Objects.requireNonNull(data); - data.mark(); - - // Skip over the protocol version and client random - data.position(data.position() + 34); - - // Jump past the session ID (if there is one) - int sessLen = Byte.toUnsignedInt(data.get()); - if (sessLen != 0) { - data.position(data.position() + sessLen); - } - - // Jump past the cipher suites - int csLen = Short.toUnsignedInt(data.getShort()); - if (csLen != 0) { - data.position(data.position() + csLen); - } - - // ...and the compression - int compLen = Byte.toUnsignedInt(data.get()); - if (compLen != 0) { - data.position(data.position() + compLen); - } - - // Now for the fun part. Go through the extensions and look - // for the two status request exts. - List extSigAlgs = new ArrayList(); - int extsLen = Short.toUnsignedInt(data.getShort()); - while (data.hasRemaining()) { - int extType = Short.toUnsignedInt(data.getShort()); - int extLen = Short.toUnsignedInt(data.getShort()); - if (extType == HELLO_EXT_SIG_ALGS) { - // Start processing signature algorithms - int sigSchemeLen = Short.toUnsignedInt(data.getShort()); - for (int ssOff = 0; ssOff < sigSchemeLen; ssOff += 2) { - String schemeName = sigSchemeMap.get( - Short.toUnsignedInt(data.getShort())); - if (schemeName != null) { - extSigAlgs.add(schemeName); - } - } - } else { - // Not the extension we're looking for. Skip past the - // extension data - data.position(data.position() + extLen); - } - } - - // We should be at the end of the ClientHello - data.reset(); - return extSigAlgs; - } - - /** - * Parses the CertificateRequest message and extracts from it a list of - * SignatureScheme values in string form. It is assumed that the provided - * ByteBuffer has its position set at the first byte of the - * CertificateRequest message body (AFTER the handshake header) and - * contains the entire CR message. Upon successful completion of this - * method the ByteBuffer will have its position reset to the initial - * offset in the buffer. - * If an exception is thrown the position at the time of the exception - * will be preserved. - * - * @param data the ByteBuffer containing the CertificateRequest bytes - * - * @return A List of the signature schemes in string form. If no - * signature_algorithms extension is present in the CertificateRequest - * then an empty list will be returned. - */ - private static List getSigSchemesCertReq(ByteBuffer data) { - Objects.requireNonNull(data); - data.mark(); - - // Jump past the certificate types - int certTypeLen = Byte.toUnsignedInt(data.get()); - if (certTypeLen != 0) { - data.position(data.position() + certTypeLen); - } - - // Collect the SignatureAndHashAlgorithms - List extSigAlgs = new ArrayList(); - int sigSchemeLen = Short.toUnsignedInt(data.getShort()); - for (int ssOff = 0; ssOff < sigSchemeLen; ssOff += 2) { - String schemeName = sigSchemeMap.get( - Short.toUnsignedInt(data.getShort())); - if (schemeName != null) { - extSigAlgs.add(schemeName); - } - } - - data.reset(); - return extSigAlgs; - } } diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Entrust.java openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Entrust.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Entrust.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Entrust.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ /** * @test - * @bug 8337664 8341059 + * @bug 8337664 8341059 8361212 * @summary Check that TLS Server certificates chaining back to distrusted * Entrust roots are invalid * @library /test/lib @@ -41,14 +41,13 @@ public class Entrust { - private static final String certPath = "chains" + File.separator + "entrust"; + private static final String CERT_PATH = "chains" + File.separator + "entrust"; // Each of the roots have a test certificate chain stored in a file // named "-chain.pem". - private static String[] rootsToTest = new String[]{ - "entrustevca", "entrustrootcaec1", "entrustrootcag2", "entrustrootcag4", - "entrust2048ca", "affirmtrustcommercialca", "affirmtrustnetworkingca", - "affirmtrustpremiumca", "affirmtrustpremiumeccca"}; + private static final String[] ROOTS_TO_TEST = new String[]{ + "entrustevca", "entrustrootcaec1", "entrustrootcag2", + "entrustrootcag4", "entrust2048ca"}; // Date when the restrictions take effect private static final ZonedDateTime DISTRUST_DATE = @@ -63,6 +62,6 @@ }; Date notBefore = distrust.getNotBefore(DISTRUST_DATE); - distrust.testCertificateChain(certPath, notBefore, tms, rootsToTest); + distrust.testCertificateChain(CERT_PATH, notBefore, tms, ROOTS_TO_TEST); } } diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustcommercialca-chain.pem openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustcommercialca-chain.pem --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustcommercialca-chain.pem 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustcommercialca-chain.pem 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ -Root Certificate: - Version: 3 (0x2) - Serial Number: 8608355977964138876 (0x7777062726a9b17c) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=US, O=AffirmTrust, CN=AffirmTrust Commercial - Validity - Not Before: Jan 29 14:06:06 2010 GMT - Not After : Dec 31 14:06:06 2030 GMT - ------BEGIN CERTIFICATE----- -MIIHHjCCBgagAwIBAgIQAWZjFOyCvT00u/gtkCvS2TANBgkqhkiG9w0BAQsFADCB -gzELMAkGA1UEBhMCQ0ExFDASBgNVBAoTC0FmZmlybVRydXN0MSswKQYDVQQLEyJT -ZWUgd3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MTEwLwYDVQQDEyhBZmZp -cm1UcnVzdCBFeHRlbmRlZCBWYWxpZGF0aW9uIENBIC0gRVYxMB4XDTI0MDYyODIx -MzgwNVoXDTI1MDcyODIxMzgwNFowgdgxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdP -bnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEzARBgsrBgEEAYI3PAIBAxMCQ0ExGDAW -BgsrBgEEAYI3PAIBAhMHT250YXJpbzEcMBoGA1UEChMTQWZmaXJtdHJ1c3QgTGlt -aXRlZDEdMBsGA1UEDxMUUHJpdmF0ZSBPcmdhbml6YXRpb24xEDAOBgNVBAUTBzI1 -NDA1NDcxKDAmBgNVBAMTH3ZhbGlkY29tbWVyY2lhbC5hZmZpcm10cnVzdC5jb20w -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDeIT2XO0hJ5wDSbIiIcMvs -P3NpQc7O7v5DqldpME6+Qn2sF5b9hc6j72hgTXREa77uUcP5u1JcMWCSWwYQHMpJ -kFzmIzijhS60wW1epb5QyTgM3ZYh1WKvttFCbHUcrTtd+LoPFYsjw9ZK//K9tPp+ -ddn06/ivWvUO5y5vn0wrCaB9tuLdDn4RCQzK2XoZdDuqhPlBBogJX0vM6lsXjgLy -EbvE+/sKYps/In6VtRvCoYavg3OqaIMeaA7gTiYTb1ZGFOAiltnq7fcp6SZUohK3 -QNihv1DadVc+n8LnEUKKDkgG2YgWEFczaE3qwG3ef6L3MzLGrkgVY+qGHyyv2IE7 -AgMBAAGjggM1MIIDMTAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBT4ARNL47hAsOpa -96VMgKEY3sLIAjAfBgNVHSMEGDAWgBTb72U3C+VHyzXRkB8DwbyIx6fqgDBsBggr -BgEFBQcBAQRgMF4wJwYIKwYBBQUHMAGGG2h0dHA6Ly9vY3NwLmFmZmlybXRydXN0 -LmNvbTAzBggrBgEFBQcwAoYnaHR0cDovL2FpYS5hZmZpcm10cnVzdC5jb20vYWZ0 -ZXYxY2EuY3J0MDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuYWZmaXJtdHJ1 -c3QuY29tL2NybC9hZnRldjFjYS5jcmwwKgYDVR0RBCMwIYIfdmFsaWRjb21tZXJj -aWFsLmFmZmlybXRydXN0LmNvbTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYI -KwYBBQUHAwEGCCsGAQUFBwMCMFYGA1UdIARPME0wBwYFZ4EMAQEwQgYKKwYBBAGC -jwkCATA0MDIGCCsGAQUFBwIBFiZodHRwczovL3d3dy5hZmZpcm10cnVzdC5jb20v -cmVwb3NpdG9yeTCCAYAGCisGAQQB1nkCBAIEggFwBIIBbAFqAHcAEvFONL1TckyE -BhnDjz96E/jntWKHiJxtMAWE6+WGJjoAAAGQYMi3wQAABAMASDBGAiEAjvdsU4G2 -o4BZSOOjaH6gOp7zhKtXQByQUvfHfsi2ePcCIQDnnIO2qlHBm+sskUDlXfR0lCUW -yFPVr9nFZ0L9YPpozgB2AA3h8jAr0w3BQGISCepVLvxHdHyx1+kw7w5CHrR+Tqo0 -AAABkGDIt9MAAAQDAEcwRQIhANh1zS3Qeo9yKF+j3G52JhmDRYBS+1TM0wykoXCY -llpxAiAG+LAlKSbwwgrboUSTDDXWNeoRYZ7fKbU72kKfHrpZvwB3ABoE/0nQVB1A -r/agw7/x2MRnL07s7iNAaJhrF0Au3Il9AAABkGDIt9sAAAQDAEgwRgIhAN8OoC4I -zw8bFJy8ACgK40c9ZfsIfFhePTc9CyrL5uDsAiEA4Jn/IqBB9L5DeTgqw9hBaYag -FmY/2gWDip36ga0WUsAwDQYJKoZIhvcNAQELBQADggEBABywPLJP097Emz6LNeFU -/HvfhaUKv2pgIHf/Kvjs5x78RK9G605THPEHr/TeUjNZ4PBd48WBNVWzyd/8FuOt -r+FsYkRJb9CnrOhZHuCwlcdWXvuY8PiuBmT+xB16BWR5yhYbbiGe4hea0Pf6CfHh -jJoGJw4dQKfgneZOV7IcaWnNTKYawlcZOgxvEwFvj+iZM31WphEPKRAV+N+Tp+ZR -nxlEdjmdbOjqBydlYIEzuFIgxgtnPdK5wqCOWb+z2cARUAO/AkiWrOLTPDc7ydQK -GcfDrSqffHOlwaee08C6STFaJWIcpqxZdXE6Jc+8/85bfPEAG1UepgfnBTqW9RGT -Q3s= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEqDCCA5CgAwIBAgIQFylVHtaOf7Ht9XMA811/1TANBgkqhkiG9w0BAQsFADBE -MQswCQYDVQQGEwJVUzEUMBIGA1UECgwLQWZmaXJtVHJ1c3QxHzAdBgNVBAMMFkFm -ZmlybVRydXN0IENvbW1lcmNpYWwwHhcNMTkwMzIxMjAyNzU0WhcNMzAxMjAyMDQw -MDAwWjCBgzELMAkGA1UEBhMCQ0ExFDASBgNVBAoTC0FmZmlybVRydXN0MSswKQYD -VQQLEyJTZWUgd3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MTEwLwYDVQQD -EyhBZmZpcm1UcnVzdCBFeHRlbmRlZCBWYWxpZGF0aW9uIENBIC0gRVYxMIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuPBMIa9VuXJGAw0MHvieGciPFA11 -b9T49YJ7T+zVpoMMQO+ueUKVHb2l26oeCiwIhXMQ5LquOVcx+rofouzcKXY3wKDZ -zHIOnAkU+23Ucn/3dRH7aHJULsBufZq+NvwgYSgJJEDKfqvIV/c5HiRyZ2H+nAI5 -10Q2xC0UxgSBsufccQ+Fwkg6BAGDlTXrvi8wi75UaGue6jv/qcKLybeVUrgqKE64 -d9oa9PG5/g89QwSdsIQEdVSFzFvFpOG9YhJbJ177Zg6DGCxU0lWwFrVpyH/2vnXl -jhMQScn8UxzCJdDg3EDqjgaV0JH2yoLug+QVYgURPu5BEb5ut9vAdP7cLwIDAQAB -o4IBVDCCAVAwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8vb2Nz -cC5hZmZpcm10cnVzdC5jb20wHQYDVR0OBBYEFNvvZTcL5UfLNdGQHwPBvIjHp+qA -MBIGA1UdEwEB/wQIMAYBAf8CAQAwHwYDVR0jBBgwFoAUnZPGU4teyq8/nx4P5ZmV -vCT2lI8wRwYDVR0gBEAwPjA8BgRVHSAAMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8v -d3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MEkGA1UdHwRCMEAwPqA8oDqG -OGh0dHA6Ly9jcmwuYWZmaXJtdHJ1c3QuY29tL2NybC9BZmZpcm1UcnVzdENvbW1l -cmNpYWwuY3JsMA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYI -KwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAATH11fMrINGmQGQqQW0ATteVnUG -LrmRSN2OlmRm+dkUwKXhcQQEfYYlEggPqgvxSUpw13fXSOqVHqAcj3BIqF957kh+ -m3DmC0RX9KaEKD165pf77P5nZcRmZpBl9cctvzIxN19uzcminchusYwLyeWhBtTZ -xpER9LbrfMNaQ7GnrgalMx54QvdjOhw/GJs9/SqEzYmPshL+DzgZX/oAzY63rQIh -rBblf6/2talZqci96oFzNst8rGfPy/xQ7lgkki1hwIYbORMfloBhP+vAZJo0mxdM -ipu3Z0ToK+KU2iqnBxXVr2/kod+CpkHnjUHa1wnQuSaefng3XwZ/vqtSL9c= ------END CERTIFICATE----- diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustnetworkingca-chain.pem openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustnetworkingca-chain.pem --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustnetworkingca-chain.pem 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustnetworkingca-chain.pem 1970-01-01 00:00:00.000000000 +0000 @@ -1,76 +0,0 @@ -Root Certificate: - Version: 3 (0x2) - Serial Number: 8957382827206547757 (0x7c4f04391cd4992d) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=US, O=AffirmTrust, CN=AffirmTrust Networking - Validity - Not Before: Jan 29 14:08:24 2010 GMT - Not After : Dec 31 14:08:24 2030 GMT - ------BEGIN CERTIFICATE----- -MIIHGjCCBgKgAwIBAgIQX2vGPaCJ1tS0ncp2OlBMFjANBgkqhkiG9w0BAQsFADCB -gzELMAkGA1UEBhMCQ0ExFDASBgNVBAoTC0FmZmlybVRydXN0MSswKQYDVQQLEyJT -ZWUgd3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MTEwLwYDVQQDEyhBZmZp -cm1UcnVzdCBFeHRlbmRlZCBWYWxpZGF0aW9uIENBIC0gRVYzMB4XDTI0MDYyODIx -NDU0OVoXDTI1MDcyODIxNDU0OFowgdgxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdP -bnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEzARBgsrBgEEAYI3PAIBAxMCQ0ExGDAW -BgsrBgEEAYI3PAIBAhMHT250YXJpbzEcMBoGA1UEChMTQWZmaXJtdHJ1c3QgTGlt -aXRlZDEdMBsGA1UEDxMUUHJpdmF0ZSBPcmdhbml6YXRpb24xEDAOBgNVBAUTBzI1 -NDA1NDcxKDAmBgNVBAMTH3ZhbGlkbmV0d29ya2luZy5hZmZpcm10cnVzdC5jb20w -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCkGknE8kFr+CaIybQrDPRw -z9OKXq77p4CnrkF1/g9w/HiIs6Ps8YqTjsiTKM3wYLbvPA+TbO9DpCSyCP2bVyLf -AjUE617KZSpfy9RqzvGjn/1qH/cBKohhEliMfDj4ZHfY4x+1WYTZPVK/g0Ny5RAP -wz9lJHR2SsVGLvpqXzWaVoxifJ8HZWD7n5z/75WeYko+Hubx3WvzJZcN2Xjn+q6a -7wkDaXPayrvn5uWGPlOLQHqJ5z7wts21jASMTfJAToFyzH6dGwvqxkP3bVJGJ8AF -vtMfqVjcOcjWgmmOEHMPAAqs5QKrYuSLccH6hFTwFEUCdMwVqfloznt2sNUSBoKj -AgMBAAGjggMxMIIDLTAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTrE0z4fRyx9P9M -0FfA6VgGkJiYVDAfBgNVHSMEGDAWgBR5HrHJF8cerLHHFNfD6H+8uVCbFTBsBggr -BgEFBQcBAQRgMF4wJwYIKwYBBQUHMAGGG2h0dHA6Ly9vY3NwLmFmZmlybXRydXN0 -LmNvbTAzBggrBgEFBQcwAoYnaHR0cDovL2FpYS5hZmZpcm10cnVzdC5jb20vYWZ0 -ZXYzY2EuY3J0MDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuYWZmaXJtdHJ1 -c3QuY29tL2NybC9hZnRldjNjYS5jcmwwKgYDVR0RBCMwIYIfdmFsaWRuZXR3b3Jr -aW5nLmFmZmlybXRydXN0LmNvbTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYI -KwYBBQUHAwEGCCsGAQUFBwMCMFYGA1UdIARPME0wBwYFZ4EMAQEwQgYKKwYBBAGC -jwkCAjA0MDIGCCsGAQUFBwIBFiZodHRwczovL3d3dy5hZmZpcm10cnVzdC5jb20v -cmVwb3NpdG9yeTCCAXwGCisGAQQB1nkCBAIEggFsBIIBaAFmAHYADeHyMCvTDcFA -YhIJ6lUu/Ed0fLHX6TDvDkIetH5OqjQAAAGQYM/MjQAABAMARzBFAiBjnehs1mvh -5Xm3uXZ7Bq8gijwiXThwnLSYROQxnWrnbAIhALbgJG+PRZQfzTBbgM/zAwNsBjhe -F5iENnaajJCxzOhaAHUAEvFONL1TckyEBhnDjz96E/jntWKHiJxtMAWE6+WGJjoA -AAGQYM/MgQAABAMARjBEAiAsWOm1IIjaxQP9uaPI9tQmkiJPUOTrBTsTDO+jkgiG -+QIgVNhND82rsFGjrtAAHzzgCVzLDUM3zaHxnP/z3BNuO4QAdQAaBP9J0FQdQK/2 -oMO/8djEZy9O7O4jQGiYaxdALtyJfQAAAZBgz8zLAAAEAwBGMEQCIBIGxtjk7Lw8 -i+oggK7VrPMNTB632t321cwhEm517BbZAiBws3+uytwh59N6qGJUuSFQnOZNPOPj -eQnH2fSdT1J2sDANBgkqhkiG9w0BAQsFAAOCAQEAcSzitESRKlbcUvxvUB7FjK0I -CaBU1Nyu0xDFCoG2pmp7GASJz34wtPYfsiX5+j4hDh/noMcgk7WlD8pzgWYw15Rk -+5kTv2v4U85y/JFjzMOHbz64KjQdGebqhjvC/E/EXxK+AZf4H574/w7rbyJ30vFL -gNvPF9AxS1MuYIO55jXrHMByKnFoQZgPsmAY/x+n+OzMxWOdR18PupypCB5TyJZ8 -pQzwoxmX7qeZHiXyJ8jQUwe1qoQc2SbwfQxfwSPUPSJuQo90N+5nyQMe7vvPBM0Y -/CXaFpfPqh71D4C0Ey+0hYxSt99gYs4P9twUByjIlP0wTyhaoEpt3zw9DdZypQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEqDCCA5CgAwIBAgIQNCSh7Pjwo1/nRrcBHEPoRDANBgkqhkiG9w0BAQsFADBE -MQswCQYDVQQGEwJVUzEUMBIGA1UECgwLQWZmaXJtVHJ1c3QxHzAdBgNVBAMMFkFm -ZmlybVRydXN0IE5ldHdvcmtpbmcwHhcNMTkwMzIxMjAzODU5WhcNMzAxMjAyMDQw -MDAwWjCBgzELMAkGA1UEBhMCQ0ExFDASBgNVBAoTC0FmZmlybVRydXN0MSswKQYD -VQQLEyJTZWUgd3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MTEwLwYDVQQD -EyhBZmZpcm1UcnVzdCBFeHRlbmRlZCBWYWxpZGF0aW9uIENBIC0gRVYzMIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmHDl/3xr1qiHoe0Rzb3AGLw56e9J -l2a3X59+PAfI5wGBHuK9Dl7XsyoH65X6QIC/rXyVpuNgKbbwIGHB+rCSplyHzGyC -WeM3LXa2q1US7VteeFDS959nxJVRFfwATR9xAK6YTUWQ/yWdw0dZSm0lQNmEMBwS -qi0ufWokiWXZUzWHOu7A6driCohu9sFDwe1INJUPH6uIlovmzGvG3UYbUSymJcjs -Ka0fXXX9zukco8exlOIKWRJSNLxKtSSPDVASrGLQ1xi3qkiLTKci3+jKMNDFf1vw -foZN99HhUcWKXfr2KlWfANdjTMlsTKCfuhfWl1OBVNHGRrACAQCXI/ji0wIDAQAB -o4IBVDCCAVAwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8vb2Nz -cC5hZmZpcm10cnVzdC5jb20wHQYDVR0OBBYEFHkesckXxx6ssccU18Pof7y5UJsV -MBIGA1UdEwEB/wQIMAYBAf8CAQAwHwYDVR0jBBgwFoAUBx/S55zawm6iQLSwelAQ -UHTEyL0wRwYDVR0gBEAwPjA8BgRVHSAAMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8v -d3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MEkGA1UdHwRCMEAwPqA8oDqG -OGh0dHA6Ly9jcmwuYWZmaXJtdHJ1c3QuY29tL2NybC9BZmZpcm1UcnVzdE5ldHdv -cmtpbmcuY3JsMA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYI -KwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAAhmE4I56hNpnWXQ2Si8a/TgQUZr -X5Jlv1LDvl3rkDyfEIHNZ8dth17SakJYJBWHExph/iIYjCJ9YmeyhghV5rPqT+wF -4yyE2ngenIusfnWT2bTpT9u2VZbCNeACE5XnN2UHSA0J9idPjfLuthViWEvSZZUh -DJ53bX+exO366nDY4AI7owIyhz8hdsWyhZ/0ST+eD+kbgd8osd+GdxzRmyKcfl84 -D1K1uff01T9w2dyUaZglQsFljkaO6xmeXZJsPnhwCp/HlMHWzhAneUQ7I9FZSOW+ -WiYbt4RitmBpysadBReikWM4knECzJQ/fMT9vC0k9BLlqUYRwCH9vr0UnZo= ------END CERTIFICATE----- diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustpremiumca-chain.pem openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustpremiumca-chain.pem --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustpremiumca-chain.pem 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustpremiumca-chain.pem 1970-01-01 00:00:00.000000000 +0000 @@ -1,88 +0,0 @@ -Root Certificate: - Version: 3 (0x2) - Serial Number: 7893706540734352110 (0x6d8c1446b1a60aee) - Signature Algorithm: sha384WithRSAEncryption - Issuer: C=US, O=AffirmTrust, CN=AffirmTrust Premium - Validity - Not Before: Jan 29 14:10:36 2010 GMT - Not After : Dec 31 14:10:36 2040 GMT - ------BEGIN CERTIFICATE----- -MIIIFjCCBv6gAwIBAgIQQVOTWr7tEAJXmRDkCSxkajANBgkqhkiG9w0BAQsFADCB -gzELMAkGA1UEBhMCQ0ExFDASBgNVBAoTC0FmZmlybVRydXN0MSswKQYDVQQLEyJT -ZWUgd3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MTEwLwYDVQQDEyhBZmZp -cm1UcnVzdCBFeHRlbmRlZCBWYWxpZGF0aW9uIENBIC0gRVYyMB4XDTI0MDYyODIx -NDgyN1oXDTI1MDcyODIxNDgyNlowgdUxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdP -bnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEzARBgsrBgEEAYI3PAIBAxMCQ0ExGDAW -BgsrBgEEAYI3PAIBAhMHT250YXJpbzEcMBoGA1UEChMTQWZmaXJtdHJ1c3QgTGlt -aXRlZDEdMBsGA1UEDxMUUHJpdmF0ZSBPcmdhbml6YXRpb24xEDAOBgNVBAUTBzI1 -NDA1NDcxJTAjBgNVBAMTHHZhbGlkcHJlbWl1bS5hZmZpcm10cnVzdC5jb20wggIi -MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDVRMzwbDq47ivHOKqJdiEJNL2+ -g9Snj/BRctqcQTrIV99RP0pmAh5fHg7vnhVsHqc9sRLVcQWTJk9NuRJ2VnDKWsBa -Xrp5UWaNjS0vaFA4jzCi1gWzTTZgPTQn3VRG3JP1F5CZb405/mtWDaw/CfWkcUqQ -VSilqFlJRsjcPCzQh7ZaXAo+FmzJxNSwjxdP6JSYMeTDRCUpSb3T8PypVI1CEmLZ -jsxrg5oIZn25591g/pzgLE56N0stNY4d3q4YD1t5x46RsqYAJYSkk8rcTN+kHzsY -VSqaRDyPkGbmuCeJUvW24wJ30yQtXQWA+U0dMYLe7LyglJ7dkOzvWNbqrIcvM8My -hxH/wwVH7e4dL/1E58yr1BHENUk7Mp9rzIXj496eLkF5G1lMkNnuVRQqCAOW0rPY -V0rI8yrCMTK52s4mNjQo2J7JOYdTUvAWZ92MKvEjjhQlMH8eK72Km/+mkxpsgGmr -3c6u+Gom7oI5VaLZ+3p2uWaOsutk1tkzWjhzY4L27hwmIdWujfrWMRx8uxcfoJxX -gQ40d1QiSN51BtCPE5UnpLU/YUxMdzWmtUoGUfYIGVqDVToBnunIFMdmFjC0IrNl -hquDQi/OGMpzuOvxX1FoXb+rRwOhhdrcR0BQqUVRTV0U5LlcsDeNMqmqPE9mzGtJ -W69Fsh7crntng/L72wIDAQABo4IDMDCCAywwDAYDVR0TAQH/BAIwADAdBgNVHQ4E -FgQU3PWyi/4usZghgahc/Tj+Q60QLOcwHwYDVR0jBBgwFoAUc3yaOGg8UXxBCP6h -HyoetGHbzTwwbAYIKwYBBQUHAQEEYDBeMCcGCCsGAQUFBzABhhtodHRwOi8vb2Nz -cC5hZmZpcm10cnVzdC5jb20wMwYIKwYBBQUHMAKGJ2h0dHA6Ly9haWEuYWZmaXJt -dHJ1c3QuY29tL2FmdGV2MmNhLmNydDA8BgNVHR8ENTAzMDGgL6AthitodHRwOi8v -Y3JsLmFmZmlybXRydXN0LmNvbS9jcmwvYWZ0ZXYyY2EuY3JsMCcGA1UdEQQgMB6C -HHZhbGlkcHJlbWl1bS5hZmZpcm10cnVzdC5jb20wDgYDVR0PAQH/BAQDAgWgMB0G -A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBWBgNVHSAETzBNMAcGBWeBDAEB -MEIGCisGAQQBgo8JAgMwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuYWZmaXJt -dHJ1c3QuY29tL3JlcG9zaXRvcnkwggF+BgorBgEEAdZ5AgQCBIIBbgSCAWoBaAB2 -ABoE/0nQVB1Ar/agw7/x2MRnL07s7iNAaJhrF0Au3Il9AAABkGDSN7EAAAQDAEcw -RQIgVDWwhv7yG6RNnkMZnVq1YYA7ypn/GSH0ibUKnESHRpYCIQCY8gyCX7VFONUI -QuR8daz7ra2FCUI9TwylrR3eFfIgGgB3AN3cyjSV1+EWBeeVMvrHn/g9HFDf2wA6 -FBJ2Ciysu8gqAAABkGDSN5cAAAQDAEgwRgIhAM1edsSyFUKU0Dj1WxTGwziE6fCW -g2ByfL8kDrP260YXAiEA6YQOpJf04N13Nn263BxAl+laH9Ar0eo03fArlv743TQA -dQAN4fIwK9MNwUBiEgnqVS78R3R8sdfpMO8OQh60fk6qNAAAAZBg0je+AAAEAwBG -MEQCIExqK4katETAQo+H0+ImuNJCSeFEI9C+9wrjhl6ZnWb9AiBwkC1vpLYOIm/1 -YCLCQIOmTdg2wf8LITlrQNJA8vbBljANBgkqhkiG9w0BAQsFAAOCAQEASOmPu7ot -yl6MoMns19uI6H2KSUjMFh3/fKMcY/ettmEYalgrytexFMrLnD2UniBlD+nJEshp -5/z7o0YDiRoiLhMAs7VqIdX3erNu/ghNh7P2bDnoMWShSoAKxez1XOGL3rRE0NAi -DsWCaNRHH9rnC97275sbGnua7ZYg+8BiF62vpJlqjrxDHjGiej8qAWSjztbB43Af -bwRscpXTxNkMvOBuRFMH+rSxB8CrOV68W+yxmzPuPxVjM7oJH8Qk5BC53NRqFsVz -JhbNfot0+/drj7JT3jlacUVQcD/BzDuC3+qczQlLjLdHgQM2/e4fXsD6C5S6B11d -BDx6ipGpaASofA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFojCCA4qgAwIBAgIQU3HI6weE/VEI5dTz4yPsRjANBgkqhkiG9w0BAQsFADBB -MQswCQYDVQQGEwJVUzEUMBIGA1UECgwLQWZmaXJtVHJ1c3QxHDAaBgNVBAMME0Fm -ZmlybVRydXN0IFByZW1pdW0wHhcNMTkwMzIxMjA0NjM1WhcNMzAxMjAyMDQwMDAw -WjCBgzELMAkGA1UEBhMCQ0ExFDASBgNVBAoTC0FmZmlybVRydXN0MSswKQYDVQQL -EyJTZWUgd3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MTEwLwYDVQQDEyhB -ZmZpcm1UcnVzdCBFeHRlbmRlZCBWYWxpZGF0aW9uIENBIC0gRVYyMIIBIjANBgkq -hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvDDZHfxkB1nAGFKdw0VCgV+B/eBtW1o+ -bXzwRcpeFh5saDI+tv1RAMrYFq+AJkXCCJopgMF2Wqfv5myE3JMgxEHuuKUpJz7H -FprrFckVOGCtJKH8Iy9AWPjBwt8lKmxGJF7EZst+QoVt4hMe0qhL0WEKbATFPe41 -DcM7UsyQv6Bvpn424uePy3/1ATIsVL3YmvAbUNR0aqVxYAJzTefvyIet/761bKGc -NyqdOVWFFeTDtr8iL1TBXToAgl0GJ39bFQZsP19VcCpfk9Zj3YHTPRPq5wZOZuUN -F7jiBUEi6DaVOi3Wy4vdySHtWPeBHRYif1I6fcUfdCNORMc4ee6KewIDAQABo4IB -UTCCAU0wNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8vb2NzcC5h -ZmZpcm10cnVzdC5jb20wHQYDVR0OBBYEFHN8mjhoPFF8QQj+oR8qHrRh2808MBIG -A1UdEwEB/wQIMAYBAf8CAQAwHwYDVR0jBBgwFoAUncBnpgwi2Sb1RaumZVIRJ9hF -rGMwRwYDVR0gBEAwPjA8BgRVHSAAMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3 -LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MEYGA1UdHwQ/MD0wO6A5oDeGNWh0 -dHA6Ly9jcmwuYWZmaXJtdHJ1c3QuY29tL2NybC9BZmZpcm1UcnVzdFByZW1pdW0u -Y3JsMA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUH -AwIwDQYJKoZIhvcNAQELBQADggIBABi64UEwl3l0yIiuSACyVQQIBI60BUmhseac -4BzCAsJrR5tE/2U9QAa2y6JpR1nqm76DJvw1QQgvFcNe+fkwpvoViCaSTbZkGGwD -mQe2xRSYJcDSMQUc/GgzLcX2c1CrexQXE1vwV/q33af1en5s1GzLl915aNS/k1ch -G7EMruJ/D4cuH9j4j2i+b+llmVBzavBwelN5rc693o+Ot9id/1sTWNugwAu3uXGb -VlhETMnjXGIciegOLdWYhWBln0izYlt9IwlDEpjMVaZ0HZlj2JBGaSe4PfEFpJPO -beuPcQpLQGw2XpW2ZMG5JcRYaoKWjixXAGktRA3H9nvVW92jvzx/RX484w2ZM5Rt -E+I1ikAuQLAyWG7clht387e2RuC3NZTtefSyjE3L9gQDOPC+Z9ycwr0WJHRsxFvh -FJQi3JnxgFZf5mc5n2mh3qAgALTNOUHuDiHrerjTOWbpF/1/NJmo/c/YZ63vZIhc -EaER4HuhbBqlpf6z3WOIQdZm1ChwXYHrEcLDgfwm9cXoaVK2HZapkMwQbPffPlT1 -E+AxRFB4YmT1y2WzdaHfhFA9nH6ByUdL5+FfrDoIIUO2e8OLOAcrJsf5+unhAhc0 -v7N48JWdmpstjkXCaCIaidrZLJxS+pikNgHB1dXF/TxokLTiPB9jcYKdGaYs3XHb -YKLdwubu ------END CERTIFICATE----- diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustpremiumeccca-chain.pem openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustpremiumeccca-chain.pem --- openjdk-21-21.0.8+9/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustpremiumeccca-chain.pem 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustpremiumeccca-chain.pem 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -Root Certificate: - Version: 3 (0x2) - Serial Number: 8401224907861490260 (0x7497258ac73f7a54) - Signature Algorithm: ecdsa-with-SHA384 - Issuer: C=US, O=AffirmTrust, CN=AffirmTrust Premium ECC - Validity - Not Before: Jan 29 14:20:24 2010 GMT - Not After : Dec 31 14:20:24 2040 GMT - ------BEGIN CERTIFICATE----- -MIIF0zCCBVmgAwIBAgIQFVwk9nYUM5SYOnBd+IoGtzAKBggqhkjOPQQDAzCBhTEL -MAkGA1UEBhMCQ0ExFDASBgNVBAoTC0FmZmlybVRydXN0MSswKQYDVQQLEyJTZWUg -d3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MTMwMQYDVQQDEypBZmZpcm1U -cnVzdCBFeHRlbmRlZCBWYWxpZGF0aW9uIENBIC0gRVZFQzEwHhcNMjQwNjI4MjE0 -OTUwWhcNMjUwNzI4MjE0OTQ4WjCB2DELMAkGA1UEBhMCQ0ExEDAOBgNVBAgTB09u -dGFyaW8xDzANBgNVBAcTBk90dGF3YTETMBEGCysGAQQBgjc8AgEDEwJDQTEYMBYG -CysGAQQBgjc8AgECEwdPbnRhcmlvMRwwGgYDVQQKExNBZmZpcm10cnVzdCBMaW1p -dGVkMR0wGwYDVQQPExRQcml2YXRlIE9yZ2FuaXphdGlvbjEQMA4GA1UEBRMHMjU0 -MDU0NzEoMCYGA1UEAxMfdmFsaWRwcmVtaXVtZWNjLmFmZmlybXRydXN0LmNvbTB2 -MBAGByqGSM49AgEGBSuBBAAiA2IABEkLBzBYSJPRENKDaA1iBPQz+jZUV+OoM9nJ -sr9sMfmHaqr3nlWxAMM99b9/usVfYyUxqyi+YL2Z3ZSxjX2dpyhwMtPpIQkL1pMW -Iv55XBIcYRyl2NjcADS9B06G+nnix6OCAzcwggMzMAwGA1UdEwEB/wQCMAAwHQYD -VR0OBBYEFP+37ywf2YJJ/4CEVy1GY4ioGm1yMB8GA1UdIwQYMBaAFMaQjAKD113j -vjucLtVlfSoQYO7lMG4GCCsGAQUFBwEBBGIwYDAnBggrBgEFBQcwAYYbaHR0cDov -L29jc3AuYWZmaXJtdHJ1c3QuY29tMDUGCCsGAQUFBzAChilodHRwOi8vYWlhLmFm -ZmlybXRydXN0LmNvbS9hZnRldmVjMWNhLmNydDA+BgNVHR8ENzA1MDOgMaAvhi1o -dHRwOi8vY3JsLmFmZmlybXRydXN0LmNvbS9jcmwvYWZ0ZXZlYzFjYS5jcmwwKgYD -VR0RBCMwIYIfdmFsaWRwcmVtaXVtZWNjLmFmZmlybXRydXN0LmNvbTAOBgNVHQ8B -Af8EBAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMFYGA1UdIARP -ME0wBwYFZ4EMAQEwQgYKKwYBBAGCjwkCBDA0MDIGCCsGAQUFBwIBFiZodHRwczov -L3d3dy5hZmZpcm10cnVzdC5jb20vcmVwb3NpdG9yeTCCAX4GCisGAQQB1nkCBAIE -ggFuBIIBagFoAHUA5tIxY0B3jMEQQQbXcbnOwdJA9paEhvu6hzId/R43jlAAAAGQ -YNN5tQAABAMARjBEAiAnainEoBGI9czVh+c9QLPL30S3Rtov8zrnhlXfeKLzZQIg -UGkntBMux0MqHt9Aj60qMsS/C4ZWF7AihVVaUKcrEVgAdgAN4fIwK9MNwUBiEgnq -VS78R3R8sdfpMO8OQh60fk6qNAAAAZBg03m1AAAEAwBHMEUCIGI9kBByoozH4cfS -ECW/O2N/ElkdATkt7EwQ52kcc4ICAiEA9QTh8JlJTb/ytYC1ECX0vQbrYVexg+fu -dw7dfToF9nAAdwAS8U40vVNyTIQGGcOPP3oT+Oe1YoeInG0wBYTr5YYmOgAAAZBg -03ndAAAEAwBIMEYCIQCox5nSCcVB2AfNYXco77zsJnYP7KAU2I4VA2GNL7I4wQIh -AP6WEzyfBoGpYYqFmNnJUavyhKBmeNiR7eNtaFwpSc+UMAoGCCqGSM49BAMDA2gA -MGUCMAGSNMXAAKDRk0ZOtydN95Rkja97+70TatCIIxEAsJD8Hu7lfj2LHCYFQjVY -oaWTrQIxAKUudx7E/JnjsthuL6sNqKVHfD3iLUJyQNK9wE0SVt1xAm7Cu1JXZORE -M64KMKoQFQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDXDCCAuKgAwIBAgIQAgKlhME0Bk3J8y0gfqNymDAKBggqhkjOPQQDAzBFMQsw -CQYDVQQGEwJVUzEUMBIGA1UECgwLQWZmaXJtVHJ1c3QxIDAeBgNVBAMMF0FmZmly -bVRydXN0IFByZW1pdW0gRUNDMB4XDTE5MDMyMTIwNTUwN1oXDTMwMTIwMjA0MDAw -MFowgYUxCzAJBgNVBAYTAkNBMRQwEgYDVQQKEwtBZmZpcm1UcnVzdDErMCkGA1UE -CxMiU2VlIHd3dy5hZmZpcm10cnVzdC5jb20vcmVwb3NpdG9yeTEzMDEGA1UEAxMq -QWZmaXJtVHJ1c3QgRXh0ZW5kZWQgVmFsaWRhdGlvbiBDQSAtIEVWRUMxMHYwEAYH -KoZIzj0CAQYFK4EEACIDYgAEu9f5NkumdaVlmaNaxpDB+rBk/S6lhqcUU1zTLcRz -4G0dr4290hezjrvZJxGJ/X15aexpdD2V9cwaPD/yuEJcaaz+rg/qDoqQF3+AFqVc -41jw1E0S59+57XVKLtXI7Xh6o4IBVDCCAVAwNwYIKwYBBQUHAQEEKzApMCcGCCsG -AQUFBzABhhtodHRwOi8vb2NzcC5hZmZpcm10cnVzdC5jb20wHQYDVR0OBBYEFMaQ -jAKD113jvjucLtVlfSoQYO7lMBIGA1UdEwEB/wQIMAYBAf8CAQAwHwYDVR0jBBgw -FoAUmq8pesARNTUmUTAAw2r+QNWu1jwwRwYDVR0gBEAwPjA8BgRVHSAAMDQwMgYI -KwYBBQUHAgEWJmh0dHBzOi8vd3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5 -MEkGA1UdHwRCMEAwPqA8oDqGOGh0dHA6Ly9jcmwuYWZmaXJtdHJ1c3QuY29tL2Ny -bC9BZmZpcm1UcnVzdFByZW1pdW1FQ0MuY3JsMA4GA1UdDwEB/wQEAwIBhjAdBgNV -HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwCgYIKoZIzj0EAwMDaAAwZQIwHJ5g -a6sHvQ51DGr0bWq34awuwlWbybC2grHoNp5uYapcXr/qTJusb/6n+dczqFdaAjEA -7VQY06fE9ifMnTgT9824jc3+H6kfhMk4PoIj9ouWdYfc1DyTBS/low9Hb8liQyFr ------END CERTIFICATE----- diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java openjdk-21-21.0.9+10/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java --- openjdk-21-21.0.8+9/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,6 +67,7 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; +import jdk.security.jarsigner.JarSigner; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.util.JarUtils; @@ -1430,7 +1431,9 @@ String expectedDigestAlg() { return digestAlgorithm != null ? digestAlgorithm - : jdkInfo.majorVersion >= 20 ? "SHA-384" : "SHA-256"; + : jdkInfo.majorVersion >= 20 + ? JarSigner.Builder.getDefaultDigestAlgorithm() + : "SHA-256"; } private SignItem tsaDigestAlgorithm(String tsaDigestAlgorithm) { @@ -1439,7 +1442,11 @@ } String expectedTsaDigestAlg() { - return tsaDigestAlgorithm != null ? tsaDigestAlgorithm : "SHA-256"; + return tsaDigestAlgorithm != null + ? tsaDigestAlgorithm + : jdkInfo.majorVersion >= 20 + ? JarSigner.Builder.getDefaultDigestAlgorithm() + : "SHA-256"; } private SignItem tsaIndex(int tsaIndex) { diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatGcCapacityOutput1.sh openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcCapacityOutput1.sh --- openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatGcCapacityOutput1.sh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcCapacityOutput1.sh 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,4 +34,9 @@ JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gccapacity 0 2>&1 | awk -f ${TESTSRC}/gcCapacityOutput1.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gccapacity 0 2>&1 | awk -f ${TESTSRC}/gcCapacityOutput1.awk diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatGcCauseOutput1.sh openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcCauseOutput1.sh --- openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatGcCauseOutput1.sh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcCauseOutput1.sh 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -38,4 +38,9 @@ # The UseParallelGC collector does not currently update the gc cause counters. ${JSTAT} ${COMMON_JSTAT_FLAGS} -gccause 0 2>&1 | awk -f ${TESTSRC}/gcCauseOutput1.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseSerialGC -gccause 0 2>&1 | awk -f ${TESTSRC}/gcCauseOutput1.awk diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatGcMetaCapacityOutput1.sh openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcMetaCapacityOutput1.sh --- openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatGcMetaCapacityOutput1.sh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcMetaCapacityOutput1.sh 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,4 +34,9 @@ JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcmetacapacity 0 2>&1 | awk -f ${TESTSRC}/gcMetaCapacityOutput1.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcmetacapacity 0 2>&1 | awk -f ${TESTSRC}/gcMetaCapacityOutput1.awk diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatGcNewCapacityOutput1.sh openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcNewCapacityOutput1.sh --- openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatGcNewCapacityOutput1.sh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcNewCapacityOutput1.sh 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,4 +34,9 @@ JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcnewcapacity 0 2>&1 | awk -f ${TESTSRC}/gcNewCapacityOutput1.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcnewcapacity 0 2>&1 | awk -f ${TESTSRC}/gcNewCapacityOutput1.awk diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatGcNewOutput1.sh openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcNewOutput1.sh --- openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatGcNewOutput1.sh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcNewOutput1.sh 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,4 +34,9 @@ JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcnew 0 2>&1 | awk -f ${TESTSRC}/gcNewOutput1.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcnew 0 2>&1 | awk -f ${TESTSRC}/gcNewOutput1.awk diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatGcOldCapacityOutput1.sh openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcOldCapacityOutput1.sh --- openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatGcOldCapacityOutput1.sh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcOldCapacityOutput1.sh 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,4 +34,9 @@ JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcoldcapacity 0 2>&1 | awk -f ${TESTSRC}/gcOldCapacityOutput1.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcoldcapacity 0 2>&1 | awk -f ${TESTSRC}/gcOldCapacityOutput1.awk diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatGcOldOutput1.sh openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcOldOutput1.sh --- openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatGcOldOutput1.sh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcOldOutput1.sh 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,4 +34,9 @@ JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcold 0 2>&1 | awk -f ${TESTSRC}/gcOldOutput1.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcold 0 2>&1 | awk -f ${TESTSRC}/gcOldOutput1.awk diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatGcOutput1.sh openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcOutput1.sh --- openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatGcOutput1.sh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatGcOutput1.sh 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,4 +34,9 @@ JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gc 0 2>&1 | awk -f ${TESTSRC}/gcOutput1.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gc 0 2>&1 | awk -f ${TESTSRC}/gcOutput1.awk diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatLineCounts1.sh openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatLineCounts1.sh --- openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatLineCounts1.sh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatLineCounts1.sh 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,4 +34,9 @@ JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcutil 0 250 5 2>&1 | awk -f ${TESTSRC}/lineCounts1.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcutil 0 250 5 2>&1 | awk -f ${TESTSRC}/lineCounts1.awk diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatLineCounts2.sh openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatLineCounts2.sh --- openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatLineCounts2.sh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatLineCounts2.sh 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,4 +34,9 @@ JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcutil 0 2>&1 | awk -f ${TESTSRC}/lineCounts2.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcutil 0 2>&1 | awk -f ${TESTSRC}/lineCounts2.awk diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatLineCounts3.sh openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatLineCounts3.sh --- openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatLineCounts3.sh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatLineCounts3.sh 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,4 +34,9 @@ JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcutil -h 10 0 250 10 2>&1 | awk -f ${TESTSRC}/lineCounts3.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcutil -h 10 0 250 10 2>&1 | awk -f ${TESTSRC}/lineCounts3.awk diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatLineCounts4.sh openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatLineCounts4.sh --- openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/jstatLineCounts4.sh 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/jstatLineCounts4.sh 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,4 +34,9 @@ JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcutil -h 10 0 250 11 2>&1 | awk -f ${TESTSRC}/lineCounts4.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcutil -h 10 0 250 11 2>&1 | awk -f ${TESTSRC}/lineCounts4.awk diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/lineCounts1.awk openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/lineCounts1.awk --- openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/lineCounts1.awk 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/lineCounts1.awk 2025-10-13 07:49:24.000000000 +0000 @@ -29,7 +29,7 @@ headerlines++; } -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+\.[0-9]+$/ { +/^[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+\.[0-9]+$/ { datalines++; } diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/lineCounts2.awk openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/lineCounts2.awk --- openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/lineCounts2.awk 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/lineCounts2.awk 2025-10-13 07:49:24.000000000 +0000 @@ -21,7 +21,7 @@ headerlines++; } -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+\.[0-9]+$/ { +/^[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+\.[0-9]+$/ { datalines++; } diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/lineCounts3.awk openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/lineCounts3.awk --- openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/lineCounts3.awk 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/lineCounts3.awk 2025-10-13 07:49:24.000000000 +0000 @@ -39,7 +39,7 @@ headerlines++; } -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+\.[0-9]+$/ { +/^[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+\.[0-9]+$/ { datalines++; } diff -Nru openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/lineCounts4.awk openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/lineCounts4.awk --- openjdk-21-21.0.8+9/test/jdk/sun/tools/jstat/lineCounts4.awk 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/sun/tools/jstat/lineCounts4.awk 2025-10-13 07:49:24.000000000 +0000 @@ -44,7 +44,7 @@ headerlines++; } -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+\.[0-9]+$/ { +/^[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+\.[0-9]+$/ { if (headerlines == 2) { datalines2++; } diff -Nru openjdk-21-21.0.8+9/test/jdk/tools/jar/JarCreateFileNameTest.java openjdk-21-21.0.9+10/test/jdk/tools/jar/JarCreateFileNameTest.java --- openjdk-21-21.0.8+9/test/jdk/tools/jar/JarCreateFileNameTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/tools/jar/JarCreateFileNameTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.jar.JarFile; +import java.util.spi.ToolProvider; +import java.util.zip.ZipEntry; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +/* + * @test + * @bug 8302293 + * @summary verify that a JAR file creation through "jar --create" operation + * works fine if the JAR file name is less than 3 characters in length + * @run junit JarCreateFileNameTest + */ +public class JarCreateFileNameTest { + + private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() -> + new RuntimeException("jar tool not found") + ); + + /* + * Launches "jar --create --file" with file names of varying lengths and verifies + * that the JAR file was successfully created. + */ + @ParameterizedTest + @ValueSource(strings = {"abcd", "abc", "ab", "a", "d.jar", "ef.jar"}) + void testCreate(final String targetJarFileName) throws Exception { + final Path cwd = Path.of("."); + final Path tmpFile = Files.createTempFile(cwd, "8302293", ".txt"); + final String fileName = tmpFile.getFileName().toString(); + final int exitCode = JAR_TOOL.run(System.out, System.err, + "--create", "--file", targetJarFileName, fileName); + assertEquals(0, exitCode, "jar command failed"); + // verify the JAR file is created and contains the expected entry + try (final JarFile jarFile = new JarFile(new File(targetJarFileName))) { + final ZipEntry entry = jarFile.getEntry(fileName); + assertNotNull(entry, "missing " + fileName + " entry in JAR file " + targetJarFileName); + } + } +} + diff -Nru openjdk-21-21.0.8+9/test/jdk/tools/jimage/JImageToolTest.java openjdk-21-21.0.9+10/test/jdk/tools/jimage/JImageToolTest.java --- openjdk-21-21.0.8+9/test/jdk/tools/jimage/JImageToolTest.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/tools/jimage/JImageToolTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test * @library /test/lib + * @requires vm.flagless * @build jdk.test.lib.process.ProcessTools * @summary Test to check if jimage tool exists and is working * @run main/timeout=360 JImageToolTest diff -Nru openjdk-21-21.0.8+9/test/jdk/tools/jpackage/windows/Win8301247Test.java openjdk-21-21.0.9+10/test/jdk/tools/jpackage/windows/Win8301247Test.java --- openjdk-21-21.0.8+9/test/jdk/tools/jpackage/windows/Win8301247Test.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/tools/jpackage/windows/Win8301247Test.java 2025-10-13 07:49:24.000000000 +0000 @@ -93,34 +93,35 @@ private static Optional findMainAppLauncherPID(JPackageCommand cmd, int expectedCount) { // Get the list of PIDs and PPIDs of app launcher processes. Run setWinRunWithEnglishOutput(true) for JDK-8344275. - // wmic process where (name = "foo.exe") get ProcessID,ParentProcessID - List output = Executor.of("wmic", "process", "where", "(name", - "=", - "\"" + cmd.appLauncherPath().getFileName().toString() + "\"", - ")", "get", "ProcessID,ParentProcessID").dumpOutput(true). - saveOutput().setWinRunWithEnglishOutput(true).executeAndGetOutput(); + // powershell -NoLogo -NoProfile -NonInteractive -Command + // "Get-CimInstance Win32_Process -Filter \"Name = 'foo.exe'\" | select ProcessID,ParentProcessID" + String command = "Get-CimInstance Win32_Process -Filter \\\"Name = '" + + cmd.appLauncherPath().getFileName().toString() + + "'\\\" | select ProcessID,ParentProcessID"; + List output = Executor.of("powershell", "-NoLogo", "-NoProfile", "-NonInteractive", "-Command", command) + .dumpOutput(true).saveOutput().setWinRunWithEnglishOutput(true).executeAndGetOutput(); if (expectedCount == 0) { - TKit.assertEquals("No Instance(s) Available.", output.getFirst(). - trim(), "Check no app launcher processes found running"); - return Optional.empty(); + if (output.size() < 1) { + return Optional.empty(); + } } - String[] headers = Stream.of(output.getFirst().split("\\s+", 2)).map( + String[] headers = Stream.of(output.get(1).split("\\s+", 2)).map( String::trim).map(String::toLowerCase).toArray(String[]::new); Pattern pattern; if (headers[0].equals("parentprocessid") && headers[1].equals( "processid")) { - pattern = Pattern.compile("^(?\\d+)\\s+(?\\d+)\\s+$"); + pattern = Pattern.compile("^\\s+(?\\d+)\\s+(?\\d+)$"); } else if (headers[1].equals("parentprocessid") && headers[0].equals( "processid")) { - pattern = Pattern.compile("^(?\\d+)\\s+(?\\d+)\\s+$"); + pattern = Pattern.compile("^\\s+(?\\d+)\\s+(?\\d+)$"); } else { throw new RuntimeException( - "Unrecognizable output of \'wmic process\' command"); + "Unrecognizable output of \'Get-CimInstance Win32_Process\' command"); } - List processes = output.stream().skip(1).map(line -> { + List processes = output.stream().skip(3).map(line -> { Matcher m = pattern.matcher(line); long[] pids = null; if (m.matches()) { diff -Nru openjdk-21-21.0.8+9/test/jdk/tools/launcher/DisableBestFitMappingTest.java openjdk-21-21.0.9+10/test/jdk/tools/launcher/DisableBestFitMappingTest.java --- openjdk-21-21.0.8+9/test/jdk/tools/launcher/DisableBestFitMappingTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/tools/launcher/DisableBestFitMappingTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8337506 + * @summary Verify Command Line arguments are not mapped with + * "best-fit" mappings on Windows + * @requires (os.family == "windows") + * @library /test/lib + * @run junit DisableBestFitMappingTest + */ +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetEncoder; +import java.util.stream.Stream; +import jdk.test.lib.process.ProcessTools; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assumptions.*; + +public class DisableBestFitMappingTest { + private static final CharsetEncoder NATIVE_ENC = + Charset.forName(System.getProperty("native.encoding")).newEncoder(); + private static final String REPLACEMENT = + NATIVE_ENC.charset().decode(ByteBuffer.wrap(NATIVE_ENC.replacement())).toString(); + private static final int EXIT_SUCCESS = 0; + private static final int EXIT_FAILURE = -1; + + static Stream CMD_ARGS() { + return Stream.of( + Arguments.of("aa\uff02 \uff02bb", "aa" + REPLACEMENT + " " + REPLACEMENT + "bb"), + Arguments.of("aa\uff01bb", "aa" + REPLACEMENT + "bb"), + Arguments.of("aa\u221ebb", "aa" + REPLACEMENT + "bb") + ); + } + + @ParameterizedTest + @MethodSource("CMD_ARGS") + void testDisableBestFitMapping(String arg, String expected) throws Exception { + // Only execute if the arg cannot be encoded + assumeFalse(NATIVE_ENC.canEncode(arg), + "native.encoding (%s) can encode the argument '%s'. Test ignored." + .formatted(NATIVE_ENC.charset(), arg)); + + var result= ProcessTools.executeTestJava( + DisableBestFitMappingTest.class.getSimpleName(), arg, expected); + result.asLines().forEach(System.out::println); + assertEquals(EXIT_SUCCESS, result.getExitValue(), + "Disabling best-fit mapping failed"); + } + + public static void main(String... args) { + System.out.println(args[0]); + System.out.println(args[1]); + System.exit(args[0].equals(args[1]) ? EXIT_SUCCESS : EXIT_FAILURE); + } +} diff -Nru openjdk-21-21.0.8+9/test/jdk/tools/launcher/Settings.java openjdk-21-21.0.9+10/test/jdk/tools/launcher/Settings.java --- openjdk-21-21.0.8+9/test/jdk/tools/launcher/Settings.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jdk/tools/launcher/Settings.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ /* * @test - * @bug 6994753 7123582 8305950 8281658 8310201 + * @bug 6994753 7123582 8305950 8281658 8310201 8343804 * @summary tests -XshowSettings options * @modules jdk.compiler * jdk.zipfs @@ -79,6 +79,7 @@ private static final String BAD_SEC_OPTION_MSG = "Unrecognized security subcommand"; private static final String SYSTEM_SETTINGS = "Operating System Metrics:"; private static final String STACKSIZE_SETTINGS = "Stack Size:"; + private static final String TIMEZONE_SETTINGS = "default timezone"; private static final String TZDATA_SETTINGS = "tzdata version"; static void containsAllOptions(TestResult tr) { @@ -92,6 +93,7 @@ checkContains(tr, SEC_SUMMARY_PROPS_SETTINGS); checkContains(tr, SEC_PROVIDER_SETTINGS); checkContains(tr, SEC_TLS_SETTINGS); + checkContains(tr, TIMEZONE_SETTINGS); checkContains(tr, TZDATA_SETTINGS); if (System.getProperty("os.name").contains("Linux")) { checkContains(tr, SYSTEM_SETTINGS); @@ -160,6 +162,7 @@ checkContains(tr, LOCALE_SETTINGS); checkContains(tr, AVAILABLE_LOCALES); checkNotContains(tr, LOCALE_SUMMARY_SETTINGS); + checkContains(tr, TIMEZONE_SETTINGS); checkContains(tr, TZDATA_SETTINGS); } diff -Nru openjdk-21-21.0.8+9/test/jtreg-ext/requires/VMProps.java openjdk-21-21.0.9+10/test/jtreg-ext/requires/VMProps.java --- openjdk-21-21.0.8+9/test/jtreg-ext/requires/VMProps.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/jtreg-ext/requires/VMProps.java 2025-10-13 07:49:24.000000000 +0000 @@ -129,7 +129,10 @@ map.put("vm.compiler1.enabled", this::isCompiler1Enabled); map.put("vm.compiler2.enabled", this::isCompiler2Enabled); map.put("docker.support", this::dockerSupport); + map.put("systemd.support", this::systemdSupport); map.put("vm.musl", this::isMusl); + map.put("vm.asan", this::isAsanEnabled); + map.put("vm.ubsan", this::isUbsanEnabled); map.put("release.implementor", this::implementor); map.put("jdk.containerized", this::jdkContainerized); map.put("vm.flagless", this::isFlagless); @@ -561,7 +564,7 @@ if (isSupported) { try { - isSupported = checkDockerSupport(); + isSupported = checkProgramSupport("checkDockerSupport()", Container.ENGINE_COMMAND); } catch (Exception e) { isSupported = false; } @@ -571,6 +574,27 @@ return "" + isSupported; } + /** + * A simple check for systemd support + * + * @return true if systemd is supported in a given environment + */ + protected String systemdSupport() { + log("Entering systemdSupport()"); + + boolean isSupported = Platform.isLinux(); + if (isSupported) { + try { + isSupported = checkProgramSupport("checkSystemdSupport()", "systemd-run"); + } catch (Exception e) { + isSupported = false; + } + } + + log("systemdSupport(): returning isSupported = " + isSupported); + return "" + isSupported; + } + // Configures process builder to redirect process stdout and stderr to a file. // Returns file names for stdout and stderr. private Map redirectOutputToLogFile(String msg, ProcessBuilder pb, String fileNameBase) { @@ -605,17 +629,17 @@ }); } - private boolean checkDockerSupport() throws IOException, InterruptedException { - log("checkDockerSupport(): entering"); - ProcessBuilder pb = new ProcessBuilder("which", Container.ENGINE_COMMAND); + private boolean checkProgramSupport(String logString, String cmd) throws IOException, InterruptedException { + log(logString + ": entering"); + ProcessBuilder pb = new ProcessBuilder("which", cmd); Map logFileNames = - redirectOutputToLogFile("checkDockerSupport(): which ", - pb, "which-container"); + redirectOutputToLogFile(logString + ": which " + cmd, + pb, "which-cmd"); Process p = pb.start(); p.waitFor(10, TimeUnit.SECONDS); int exitValue = p.exitValue(); - log(String.format("checkDockerSupport(): exitValue = %s, pid = %s", exitValue, p.pid())); + log(String.format("%s: exitValue = %s, pid = %s", logString, exitValue, p.pid())); if (exitValue != 0) { printLogfileContent(logFileNames); } @@ -632,6 +656,15 @@ return Boolean.toString(WB.getLibcName().contains("musl")); } + // Sanitizer support + protected String isAsanEnabled() { + return "" + WB.isAsanEnabled(); + } + + protected String isUbsanEnabled() { + return "" + WB.isUbsanEnabled(); + } + private String implementor() { try (InputStream in = new BufferedInputStream(new FileInputStream( System.getProperty("java.home") + "/release"))) { diff -Nru openjdk-21-21.0.8+9/test/langtools/jdk/javadoc/doclet/testLinkOption/TestRedirectLinks.java openjdk-21-21.0.9+10/test/langtools/jdk/javadoc/doclet/testLinkOption/TestRedirectLinks.java --- openjdk-21-21.0.8+9/test/langtools/jdk/javadoc/doclet/testLinkOption/TestRedirectLinks.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/langtools/jdk/javadoc/doclet/testLinkOption/TestRedirectLinks.java 2025-10-13 07:49:24.000000000 +0000 @@ -24,6 +24,7 @@ /* * @test * @bug 8190312 + * @key intermittent * @summary test redirected URLs for -link * @library /tools/lib ../../lib * @library /test/lib diff -Nru openjdk-21-21.0.8+9/test/langtools/tools/javac/annotations/typeAnnotations/TypeAnnotationsInConstantInit.java openjdk-21-21.0.9+10/test/langtools/tools/javac/annotations/typeAnnotations/TypeAnnotationsInConstantInit.java --- openjdk-21-21.0.8+9/test/langtools/tools/javac/annotations/typeAnnotations/TypeAnnotationsInConstantInit.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/langtools/tools/javac/annotations/typeAnnotations/TypeAnnotationsInConstantInit.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8346751 + * @summary Verify type annotations inside constant expression field initializers + are handled correctly + * @library /tools/lib + * @modules + * jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.util + * @build toolbox.ToolBox toolbox.JavacTask + * @run main TypeAnnotationsInConstantInit + */ + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import toolbox.JavacTask; +import toolbox.ToolBox; + +public class TypeAnnotationsInConstantInit { + + public static void main(String... args) throws Exception { + new TypeAnnotationsInConstantInit().run(); + } + + ToolBox tb = new ToolBox(); + + void run() throws Exception { + typeAnnotationInConstantExpressionFieldInit(Paths.get(".")); + } + + void typeAnnotationInConstantExpressionFieldInit(Path base) throws Exception { + Path src = base.resolve("src"); + Path classes = base.resolve("classes"); + tb.writeJavaFiles(src, + """ + import java.lang.annotation.*; + + @SuppressWarnings(Decl.VALUE) + public class Decl { + public static final @Nullable String VALUE = (@Nullable String) ""; + } + + @Retention(RetentionPolicy.RUNTIME) + @Target({ ElementType.TYPE_USE }) + @interface Nullable {} + """); + Files.createDirectories(classes); + new JavacTask(tb) + .options("-d", classes.toString()) + .files(tb.findJavaFiles(src)) + .run() + .writeAll(); + } + +} diff -Nru openjdk-21-21.0.8+9/test/langtools/tools/javac/lambda/LambdaExpr02.java openjdk-21-21.0.9+10/test/langtools/tools/javac/lambda/LambdaExpr02.java --- openjdk-21-21.0.8+9/test/langtools/tools/javac/lambda/LambdaExpr02.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/langtools/tools/javac/lambda/LambdaExpr02.java 2025-10-13 07:49:24.000000000 +0000 @@ -28,7 +28,7 @@ * basic test for simple lambda expressions in multiple scopes * @author Brian Goetz * @author Maurizio Cimadamore - * @run main LambdaExpr01 + * @run main LambdaExpr02 */ public class LambdaExpr02 { diff -Nru openjdk-21-21.0.8+9/test/langtools/tools/javac/patterns/SOEDeeplyNestedBlocksTest.java openjdk-21-21.0.9+10/test/langtools/tools/javac/patterns/SOEDeeplyNestedBlocksTest.java --- openjdk-21-21.0.8+9/test/langtools/tools/javac/patterns/SOEDeeplyNestedBlocksTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/langtools/tools/javac/patterns/SOEDeeplyNestedBlocksTest.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,1187 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8322992 + * @summary Javac fails with StackOverflowError when compiling deeply nested synchronized blocks + * @compile SOEDeeplyNestedBlocksTest.java + */ + +public class SOEDeeplyNestedBlocksTest { + + public static void test() { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + synchronized (SOEDeeplyNestedBlocksTest.class) { + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } +} diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/Asserts.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/Asserts.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/Asserts.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/Asserts.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,10 @@ package jdk.test.lib; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Arrays; import java.util.HexFormat; import java.util.Objects; @@ -610,6 +614,28 @@ } /** + * Asserts that contents of two files are equal. + * + * @param f1 The path of the first file to compare + * @param f2 The path of the second file to compare + * @throws RuntimeException on mismatch or I/O failure + */ + public static void assertFileContentsEqual(Path f1, Path f2) { + long mismatchIndex = 0; + try { + mismatchIndex = Files.mismatch(f1, f2); + } catch (IOException exception) { + throw new UncheckedIOException(exception); + } + if (mismatchIndex >= 0) { + String message = String.format( + "Contents of files '%s' and '%s' mismatch at index %d", + f1, f2, mismatchIndex); + fail(message); + } + } + + /** * A functional interface for executing tests in assertThrownException */ @FunctionalInterface @@ -640,7 +666,7 @@ testMethod.execute(); } catch (Throwable exc) { if (expected.isInstance(exc)) { - return (T) exc; + return expected.cast(exc); } else { fail(Objects.toString(msg, "An unexpected exception was thrown.") + " Expected " + expected.getName(), exc); diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/SecurityTools.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/SecurityTools.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/SecurityTools.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/SecurityTools.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -236,13 +236,36 @@ /** * Runs jar. * + * @param args arguments to jar in the list. + * @return an {@link OutputAnalyzer} object + * @throws Exception if there is an error + */ + public static OutputAnalyzer jar(final List args) throws Exception { + return execute(getProcessBuilder("jar", args)); + } + + /** + * Runs jar. + * * @param args arguments to jar in a single string. The string is * converted to be List with makeList. * @return an {@link OutputAnalyzer} object * @throws Exception if there is an error */ - public static OutputAnalyzer jar(String args) throws Exception { - return execute(getProcessBuilder("jar", makeList(args))); + public static OutputAnalyzer jar(final String args) throws Exception { + return jar(makeList(args)); + } + + /** + * Runs jar. + * + * @param args arguments to jar in multiple strings. + * Converted to be a List with List.of. + * @return an {@link OutputAnalyzer} object + * @throws Exception if there is an error + */ + public static OutputAnalyzer jar(final String... args) throws Exception { + return jar(List.of(args)); } /** diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/Utils.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/Utils.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/Utils.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/Utils.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ package jdk.test.lib; import java.io.BufferedReader; +import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; @@ -71,6 +72,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; +import static java.lang.System.lineSeparator; import static jdk.test.lib.Asserts.assertTrue; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; @@ -816,6 +818,62 @@ } /** + * Creates a file in {@code user.dir} and populates it with random ASCII + * characters of given length. + *

+ * If the {@code user.dir} property is not set, {@code .} will be used. + * This choice of parent directory, compared to + * {@link Files#createTempFile(String, String, FileAttribute[])} using the + * {@code java.io.tmpdir} property, doesn't leave files behind in the + * {@code /tmp} directory of the test machine. + *

+ * + * @param prefix the prefix string to be used in generating the file's name; + * may be null + * @param suffix the suffix string to be used in generating the file's name; + * may be null, in which case ".tmp" is used + * @param size the size in bytes of the temporary file to be populated + * @param attrs an optional list of file attributes to set atomically when creating the file + * @return the path to the newly created file that did not exist before this + * method was invoked + * @throws IOException if an I/O error occurs or dir does not exist + * @throws IllegalArgumentException if size is negative + * + * @see #createTempFile(String, String, FileAttribute...) + */ + public static Path createTempFileOfSize(String prefix, String suffix, long size, FileAttribute... attrs) throws IOException { + + // Check arguments + if (size < 0) { + throw new IllegalArgumentException("file size cannot be negative: " + size); + } + + // Entropy ingredients + int prime1 = 2_147_483_647; + int prime2 = 1_047_483_649; + int seed = Long.hashCode(SEED); + + // Create & populate the file + Path path = createTempFile(prefix, suffix, attrs); + try (BufferedWriter writer = Files.newBufferedWriter(path, StandardCharsets.US_ASCII)) { + long remainingSize = size; + for (int rowIndex = 0; remainingSize > 0; rowIndex++) { + for (int colIndex = 0; remainingSize > 0 && colIndex < 80; remainingSize--, colIndex++) { + int r = ((rowIndex ^ seed) * prime1) ^ ((colIndex ^ seed) * prime2); + char c = (char) (0x21 + Math.abs(r) % (0x7e - 0x21)); + writer.append(c); + } + if (remainingSize > lineSeparator().length()) { + writer.write(lineSeparator()); + remainingSize -= lineSeparator().length(); + } + } + } + return path; + + } + + /** * Creates an empty directory in "user.dir" or "." *

* This method is meant as a replacement for {@link Files#createTempDirectory(Path, String, FileAttribute...)} diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/apps/LingeredApp.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/apps/LingeredApp.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/apps/LingeredApp.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/apps/LingeredApp.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -429,7 +429,7 @@ } } - /** + /* * High level interface for test writers */ @@ -592,6 +592,7 @@ * This part is the application itself. First arg is optional "forceCrash". * Following arg is the lock file name. */ + @SuppressWarnings("restricted") public static void main(String args[]) { boolean forceCrash = false; diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/artifacts/ArtifactResolver.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/artifacts/ArtifactResolver.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/artifacts/ArtifactResolver.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/artifacts/ArtifactResolver.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,8 @@ package jdk.test.lib.artifacts; +import jtreg.SkippedException; + import java.nio.file.Path; import java.util.HashMap; import java.util.Map; @@ -33,7 +35,7 @@ try { String managerName = System.getProperty("jdk.test.lib.artifacts.artifactmanager"); if (managerName != null) { - manager = (ArtifactManager) Class.forName(managerName).newInstance(); + manager = (ArtifactManager) Class.forName(managerName).getDeclaredConstructor().newInstance(); } else if (System.getenv().containsKey(JibArtifactManager.JIB_HOME_ENV_NAME)) { manager = JibArtifactManager.newInstance(); } else { @@ -68,6 +70,38 @@ return manager.resolve(name, artifactDescription, unpack); } + /** + * Retrieve an artifact/library/file from a repository or local file system. + *

+ * Artifacts are defined with the {@link jdk.test.lib.artifacts.Artifact} + * annotation. + *

+ * If you have a local version of a dependency that you want to use, you can + * specify that by setting the system property: + * jdk.test.lib.artifacts.ARTIFACT_NAME. Where ARTIFACT_NAME + * is the name field of the Artifact annotation. + *

+ * Generally, tests that use this method should be run with make test. + * However, tests can also be run with jtreg but you must have a + * local copy of the artifact and the system property must be set as specified + * above. + * + * @param klass a class annotated with {@link jdk.test.lib.artifacts.Artifact} + * @return the local path to the artifact. If the artifact is a compressed + * file that gets unpacked, this path will point to the root + * directory of the uncompressed file(s). + * @throws SkippedException thrown if the artifact cannot be found + */ + public static Path fetchOne(Class klass) { + try { + return ArtifactResolver.resolve(klass).entrySet().stream() + .findAny().get().getValue(); + } catch (ArtifactResolverException e) { + Artifact artifact = klass.getAnnotation(Artifact.class); + throw new SkippedException("Cannot find the artifact " + artifact.name(), e); + } + } + private static String artifactName(Artifact artifact) { // Format of the artifact name is .-(-) String name = String.format("%s.%s-%s", artifact.organization(), artifact.name(), artifact.revision()); diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/artifacts/ArtifactResolverException.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/artifacts/ArtifactResolverException.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/artifacts/ArtifactResolverException.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/artifacts/ArtifactResolverException.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,10 +23,14 @@ package jdk.test.lib.artifacts; +import java.io.Serial; + /** * Thrown by the ArtifactResolver when failing to resolve an Artifact. */ public class ArtifactResolverException extends Exception { + @Serial + private static final long serialVersionUID = 8341884506180926911L; public ArtifactResolverException(String message) { super(message); diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/artifacts/JibArtifactManager.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/artifacts/JibArtifactManager.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/artifacts/JibArtifactManager.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/artifacts/JibArtifactManager.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,7 +75,7 @@ ClassLoader oldContextLoader = currentThread.getContextClassLoader(); currentThread.setContextClassLoader(classLoader); - Class jibServiceFactory = classLoader.loadClass(JIB_SERVICE_FACTORY); + Class jibServiceFactory = classLoader.loadClass(JIB_SERVICE_FACTORY); try { Object jibArtifactInstaller = jibServiceFactory.getMethod("createJibArtifactInstaller").invoke(null); return new JibArtifactManager(jibArtifactInstaller, classLoader); diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/classloader/ClassUnloadCommon.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/classloader/ClassUnloadCommon.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/classloader/ClassUnloadCommon.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/classloader/ClassUnloadCommon.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,16 +32,23 @@ import jdk.test.whitebox.WhiteBox; import java.io.File; +import java.io.Serial; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import java.util.stream.Stream; public class ClassUnloadCommon { public static class TestFailure extends RuntimeException { + @Serial + private static final long serialVersionUID = -8108935949624559549L; + TestFailure(String msg) { super(msg); } @@ -68,6 +75,41 @@ } /** + * Calls triggerUnloading() in a retry loop for 2 seconds or until WhiteBox.isClassAlive + * determines that no classes named in classNames are alive. + * + * This variant of triggerUnloading() accommodates the inherent raciness + * of class unloading. For example, it's possible for a JIT compilation to hold + * strong roots to types (e.g. in virtual call or instanceof profiles) that + * are not released or converted to weak roots until the compilation completes. + * + * @param classNames the set of classes that are expected to be unloaded + * @return the set of classes that have not been unloaded after exiting the retry loop + */ + public static Set triggerUnloading(List classNames) { + WhiteBox wb = WhiteBox.getWhiteBox(); + Set aliveClasses = new HashSet<>(classNames); + int attempt = 0; + while (!aliveClasses.isEmpty() && attempt < 20) { + ClassUnloadCommon.triggerUnloading(); + for (String className : classNames) { + if (aliveClasses.contains(className)) { + if (wb.isClassAlive(className)) { + try { + Thread.sleep(100); + } catch (InterruptedException ex) { + } + } else { + aliveClasses.remove(className); + } + } + } + attempt++; + } + return aliveClasses; + } + + /** * Creates a class loader that loads classes from {@code ${test.class.path}} * before delegating to the system class loader. */ diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/classloader/GeneratingClassLoader.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/classloader/GeneratingClassLoader.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/classloader/GeneratingClassLoader.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/classloader/GeneratingClassLoader.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,13 +38,13 @@ public class GeneratingClassLoader extends ClassLoader { - public synchronized Class loadClass(String name) throws ClassNotFoundException { + public synchronized Class loadClass(String name) throws ClassNotFoundException { return loadClass(name, false); } - public synchronized Class loadClass(String name, boolean resolve) + public synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - Class c = findLoadedClass(name); + Class c = findLoadedClass(name); if (c != null) { return c; } @@ -129,7 +129,7 @@ throw new RuntimeException("Class name not found in template class file"); } } - return (byte[]) bytecode.clone(); + return bytecode.clone(); } private void readByteCode() throws ClassNotFoundException { diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/classloader/GeneratingCompilingClassLoader.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/classloader/GeneratingCompilingClassLoader.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/classloader/GeneratingCompilingClassLoader.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/classloader/GeneratingCompilingClassLoader.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -202,7 +202,7 @@ */ public Class[] getGeneratedClasses(int sizeFactor, int numClasses) throws IOException { GeneratedClass[] gc = getGeneratedClass(sizeFactor, numClasses); - Class[] classes = new Class[numClasses]; + Class[] classes = new Class[numClasses]; for (int i = 0; i < numClasses; ++i) { classes[i] = defineClass(gc[i].name, gc[i].bytes, 0 , gc[i].bytes.length); } diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java 2025-10-13 07:49:24.000000000 +0000 @@ -69,6 +69,16 @@ tester.testMemoryUsage(); } tester.testMisc(); + testContainerized(m, inContainer); + } + + private void testContainerized(Metrics m, boolean inContainer) { + if (m.isContainerized() != inContainer) { + throw new RuntimeException("containerized test failed. " + + "Expected isContainerized()==" + inContainer + + " but got '" + m.isContainerized() + "'"); + } + System.out.println("testContainerized() PASSED!"); } public static void main(String[] args) throws Exception { diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/containers/systemd/SystemdRunOptions.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/containers/systemd/SystemdRunOptions.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/containers/systemd/SystemdRunOptions.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/containers/systemd/SystemdRunOptions.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2024, Red Hat, Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.containers.systemd; + +import static jdk.test.lib.Asserts.assertNotNull; + +import java.util.ArrayList; +import java.util.Collections; + + +// This class represents options for running java inside systemd slices +// in test environment. +public class SystemdRunOptions { + public ArrayList javaOpts = new ArrayList<>(); + public String classToRun; // class or "-version" + public ArrayList classParams = new ArrayList<>(); + public String memoryLimit; // used in slice for MemoryLimit property + public String cpuLimit; // used in slice for CPUQuota property + public String sliceName; // name of the slice (nests CPU in memory) + public String sliceDMemoryLimit; // used in jdk_internal.slice.d + public String sliceDCpuLimit; // used in jdk_internal.slice.d + + /** + * Convenience constructor for most common use cases in testing. + * @param classToRun a class to run, or "-version" + * @param javaOpts java options to use + * + * @return Default docker run options + */ + public SystemdRunOptions(String classToRun, String... javaOpts) { + this.classToRun = classToRun; + Collections.addAll(this.javaOpts, javaOpts); + this.sliceName = defaultSliceName(); + } + + private static String defaultSliceName() { + // Create a unique name for a systemd slice + // jtreg guarantees that test.name is unique among all concurrently executing + // tests. For example, if you have two test roots: + // + // $ find test -type f + // test/foo/TEST.ROOT + // test/foo/my/TestCase.java + // test/bar/TEST.ROOT + // test/bar/my/TestCase.java + // $ jtreg -concur:2 test/foo test/bar + // + // jtreg will first run all the tests under test/foo. When they are all finished, then + // jtreg will run all the tests under test/bar. So you will never have two concurrent + // test cases whose test.name is "my/TestCase.java" + String testname = System.getProperty("test.name"); + assertNotNull(testname, "must be set by jtreg"); + testname = testname.replace(".java", ""); + testname = testname.replace("/", "_"); + testname = testname.replace("\\", "_"); + testname = testname.replace("-", "_"); + + // Example: + // Memory: "test_containers_systemd_TestMemoryAwareness" + // CPU: "test_containers_systemd_TestMemoryAwareness-cpu" => derived + return testname; + } + + /** + * The memory limit set with a .slice file in the systemd + * config directory. + * + * @param memLimit The memory limit to set (e.g. 1000M). + * @return The run options. + */ + public SystemdRunOptions memoryLimit(String memLimit) { + this.memoryLimit = memLimit; + return this; + } + + /** + * The memory limit to set in the top-level jdk_internal.slice.d + * systemd config directory. + * + * @param memoryLimit The memory limit to set. + * @return The run options. + */ + public SystemdRunOptions sliceDMemoryLimit(String memoryLimit) { + this.sliceDMemoryLimit = memoryLimit; + return this; + } + + /** + * The CPU limit set with a .slice file in the systemd + * config directory. + * + * @param cpuLimit + * @return The run options. + */ + public SystemdRunOptions cpuLimit(String cpuLimit) { + this.cpuLimit = cpuLimit; + return this; + } + + /** + * The Cpu limit set in the top-level jdk_internal.slice.d + * systemd config directory. + * + * @param cpuLimit The CPU limit to set to. + * @return The run options. + */ + public SystemdRunOptions sliceDCpuLimit(String cpuLimit) { + this.sliceDCpuLimit = cpuLimit; + return this; + } + + public SystemdRunOptions sliceName(String name) { + this.sliceName = name; + return this; + } + + public SystemdRunOptions addJavaOpts(String... opts) { + Collections.addAll(javaOpts, opts); + return this; + } + + public SystemdRunOptions addClassOptions(String... opts) { + Collections.addAll(classParams,opts); + return this; + } + + public boolean hasSliceDLimit() { + return this.sliceDMemoryLimit != null || + this.sliceDCpuLimit != null; + } +} diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/containers/systemd/SystemdTestUtils.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/containers/systemd/SystemdTestUtils.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/containers/systemd/SystemdTestUtils.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/containers/systemd/SystemdTestUtils.java 2025-10-13 07:49:24.000000000 +0000 @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2024, Red Hat, Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.containers.systemd; + +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import jdk.internal.platform.Metrics; +import jdk.test.lib.Platform; +import jdk.test.lib.Utils; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.util.FileUtils; +import jtreg.SkippedException; + +public class SystemdTestUtils { + + private static final String CGROUPS_PROVIDER = Metrics.systemMetrics().getProvider(); + private static boolean CGROUPS_V2 = "cgroupv2".equals(CGROUPS_PROVIDER); + public static boolean RUN_AS_USER = !Platform.isRoot() && CGROUPS_V2; + private static final String SLICE_NAMESPACE_PREFIX = "jdk_internal"; + private static final String SLICE_D_MEM_CONFIG_FILE = "memory-limit.conf"; + private static final String SLICE_D_CPU_CONFIG_FILE = "cpu-limit.conf"; + private static final String USER_HOME = System.getProperty("user.home"); + private static final Path SYSTEMD_CONFIG_HOME_ROOT = Path.of("/", "etc", "systemd", "system"); + private static final Path SYSTEMD_CONFIG_HOME_USER = Path.of(USER_HOME, ".config", "systemd", "user"); + private static final Path SYSTEMD_CONFIG_HOME = Platform.isRoot() ? SYSTEMD_CONFIG_HOME_ROOT : SYSTEMD_CONFIG_HOME_USER; + + // Specifies how many lines to copy from child STDOUT to main test output. + // Having too many lines in the main test output will result + // in JT harness trimming the output, and can lead to loss of useful + // diagnostic information. + private static final int MAX_LINES_TO_COPY_FOR_CHILD_STDOUT = 100; + + public record ResultFiles(Path memory, Path cpu, Path sliceDotDDir) {} + + /** + * Create commonly used options with the class to be launched inside the + * systemd slice + * + * @param testClass The test class or {@code -version} + * @return The basic options. + */ + public static SystemdRunOptions newOpts(String testClass) { + return new SystemdRunOptions(testClass, + "-Xlog:os+container=trace", + "-cp", + Utils.TEST_CLASSES); + } + + /** + * Run Java inside a systemd slice with specified parameters and options. + * + * @param opts The systemd slice options when running java + * @return An OutputAnalyzer of the output of the command than ran. + * @throws Exception If something went wrong. + * @throws SkippedException If the test cannot be run (i.e. non-root user + * on cgroups v1). + */ + public static OutputAnalyzer buildAndRunSystemdJava(SystemdRunOptions opts) throws Exception, SkippedException { + if (!Platform.isRoot() && !CGROUPS_V2) { + throw new SkippedException("Systemd tests require root on cgroup v1. Test skipped!"); + } + ResultFiles files = SystemdTestUtils.buildSystemdSlices(opts); + + try { + return SystemdTestUtils.systemdRunJava(opts); + } finally { + cleanupFiles(files); + } + } + + private static void cleanupFiles(ResultFiles files) throws IOException { + try { + if (files.memory() != null) { + Files.delete(files.memory()); + } + if (files.cpu() != null) { + Files.delete(files.cpu()); + } + if (files.sliceDotDDir() != null) { + FileUtils.deleteFileTreeUnchecked(files.sliceDotDDir()); + } + } catch (NoSuchFileException e) { + // ignore + } + } + + private static OutputAnalyzer systemdRunJava(SystemdRunOptions opts) throws Exception { + return execute(buildJavaCommand(opts)); + } + + /** + * Create systemd slice files under /etc/systemd/system. + * + * The JDK will then run within that slice as provided by the SystemdRunOptions. + * + * @param runOpts The systemd slice options to use when running the test. + * @return The systemd slice files (for cleanup-purposes later). + * @throws Exception + */ + private static ResultFiles buildSystemdSlices(SystemdRunOptions runOpts) throws Exception { + String sliceName = sliceName(runOpts); + String sliceNameCpu = sliceNameCpu(runOpts); + + // Generate systemd slices for cpu/memory + String memorySliceContent = getMemorySlice(runOpts, sliceName); + String cpuSliceContent = getCpuSlice(runOpts, sliceName); + + // Ensure base directory exists + Files.createDirectories(SYSTEMD_CONFIG_HOME); + Path sliceDotDDir = null; + if (runOpts.hasSliceDLimit()) { + String dirName = String.format("%s.slice.d", SLICE_NAMESPACE_PREFIX); + sliceDotDDir = SYSTEMD_CONFIG_HOME.resolve(Path.of(dirName)); + // Using createDirectories since we only need to ensure the directory + // exists. Ignore it if already existent. + Files.createDirectories(sliceDotDDir); + + if (runOpts.sliceDMemoryLimit != null) { + Path memoryConfig = sliceDotDDir.resolve(Path.of(SLICE_D_MEM_CONFIG_FILE)); + Files.writeString(memoryConfig, + getMemoryDSliceContent(runOpts), + StandardOpenOption.TRUNCATE_EXISTING, + StandardOpenOption.CREATE); + } + if (runOpts.sliceDCpuLimit != null) { + Path cpuConfig = sliceDotDDir.resolve(Path.of(SLICE_D_CPU_CONFIG_FILE)); + Files.writeString(cpuConfig, + getCPUDSliceContent(runOpts), + StandardOpenOption.TRUNCATE_EXISTING, + StandardOpenOption.CREATE); + } + } + + Path memory, cpu; + try { + // memory slice + memory = SYSTEMD_CONFIG_HOME.resolve(Path.of(sliceFileName(sliceName))); + // cpu slice nested in memory + cpu = SYSTEMD_CONFIG_HOME.resolve(Path.of(sliceFileName(sliceNameCpu))); + Files.writeString(memory, memorySliceContent); + Files.writeString(cpu, cpuSliceContent); + } catch (IOException e) { + throw new AssertionError("Failed to write systemd slice files"); + } + + systemdDaemonReload(cpu, memory, sliceDotDDir); + + return new ResultFiles(memory, cpu, sliceDotDDir); + } + + private static String sliceName(SystemdRunOptions runOpts) { + // Slice name may include '-' which is a hierarchical slice indicator. + // Replace '-' with '_' to avoid side-effects. + return SLICE_NAMESPACE_PREFIX + "-" + runOpts.sliceName.replace("-", "_"); + } + + private static String sliceNameCpu(SystemdRunOptions runOpts) { + String slice = sliceName(runOpts); + return String.format("%s-cpu", slice); + } + + private static void systemdDaemonReload(Path cpu, Path memory, Path sliceDdir) throws Exception { + List daemonReload = systemCtl(); + daemonReload.add("daemon-reload"); + + if (execute(daemonReload).getExitValue() != 0) { + if (RUN_AS_USER) { + cleanupFiles(new ResultFiles(cpu, memory, sliceDdir)); + // When run as user the systemd user manager needs to be + // accessible and working. This is usually the case when + // connected via SSH or user login, but may not work for + // sessions set up via 'su ' or similar. + // In that case, 'systemctl --user status' usually doesn't + // work. There is no other option than skip the test. + String msg = "Service user@.service not properly configured. " + + "Skipping the test!"; + throw new SkippedException(msg); + } else { + throw new AssertionError("Failed to reload systemd daemon"); + } + } + } + + private static List systemCtl() { + return commandWithUser("systemctl"); + } + + /** + * 'baseCommand' or 'baseCommand --user' as list, depending on the cgroups + * version and running user. + * + * @return 'baseCommand' if we are the root user, 'systemctl --user' if + * the current user is non-root and we are on cgroups v2. Note: + * Cgroups v1 and non-root is not possible as tests are skipped then. + */ + private static List commandWithUser(String baseCommand) { + List command = new ArrayList<>(); + command.add(baseCommand); + if (RUN_AS_USER) { + command.add("--user"); + } + return command; + } + + private static String getCpuSlice(SystemdRunOptions runOpts, String sliceName) { + String basicSliceFormat = getBasicSliceFormat(); + return String.format(basicSliceFormat, sliceName, getCPUSliceContent(runOpts)); + } + + private static String getCPUSliceContent(SystemdRunOptions runOpts) { + String format = basicCPUContentFormat(); + return String.format(format, runOpts.cpuLimit); + } + + private static String getMemorySlice(SystemdRunOptions runOpts, String sliceName) { + String basicSliceFormat = getBasicSliceFormat(); + return String.format(basicSliceFormat, sliceName, getMemorySliceContent(runOpts)); + } + + private static String getMemoryDSliceContent(SystemdRunOptions runOpts) { + String format = "[Slice]\n" + basicMemoryContentFormat(); + return String.format(format, runOpts.sliceDMemoryLimit); + } + + private static String getCPUDSliceContent(SystemdRunOptions runOpts) { + String format = "[Slice]\n" + basicCPUContentFormat(); + return String.format(format, runOpts.sliceDCpuLimit); + } + + private static String basicCPUContentFormat() { + return """ + CPUAccounting=true + CPUQuota=%s + """; + } + + private static String basicMemoryContentFormat() { + return """ + MemoryAccounting=true + MemoryLimit=%s + """; + } + + private static String getMemorySliceContent(SystemdRunOptions runOpts) { + String format = basicMemoryContentFormat(); + + return String.format(format, runOpts.memoryLimit); + } + + private static String getBasicSliceFormat() { + return """ + [Unit] + Description=OpenJDK Tests Slice for %s + Before=slices.target + + [Slice] + %s + """; + } + + private static String sliceFileName(String sliceName) { + return String.format("%s.slice", sliceName); + } + + /** + * Build the java command to run inside a systemd slice + * + * @param SystemdRunOptions options for running the systemd slice test + * + * @return command + * @throws Exception + */ + private static List buildJavaCommand(SystemdRunOptions opts) throws Exception { + // systemd-run [--user] --slice .slice --scope + List javaCmd = systemdRun(); + javaCmd.add("--slice"); + javaCmd.add(sliceFileName(sliceNameCpu(opts))); + javaCmd.add("--scope"); + javaCmd.add(Path.of(Utils.TEST_JDK, "bin", "java").toString()); + javaCmd.addAll(opts.javaOpts); + javaCmd.add(opts.classToRun); + javaCmd.addAll(opts.classParams); + return javaCmd; + } + + private static List systemdRun() { + return commandWithUser("systemd-run"); + } + + /** + * Execute a specified command in a process, report diagnostic info. + * + * @param command to be executed + * @return The output from the process + * @throws Exception + */ + private static OutputAnalyzer execute(List command) throws Exception { + return execute(command.toArray(String[]::new)); + } + + /** + * Execute a specified command in a process, report diagnostic info. + * + * @param command to be executed + * @return The output from the process + * @throws Exception + */ + private static OutputAnalyzer execute(String... command) throws Exception { + ProcessBuilder pb = new ProcessBuilder(command); + System.out.println("[COMMAND]\n" + Utils.getCommandLine(pb)); + + Process p = pb.start(); + long pid = p.pid(); + OutputAnalyzer output = new OutputAnalyzer(p); + + int max = MAX_LINES_TO_COPY_FOR_CHILD_STDOUT; + String stdout = output.getStdout(); + String stdoutLimited = limitLines(stdout, max); + System.out.println("[STDERR]\n" + output.getStderr()); + System.out.println("[STDOUT]\n" + stdoutLimited); + if (stdout != stdoutLimited) { + System.out.printf("Child process STDOUT is limited to %d lines\n", + max); + } + + String stdoutLogFile = String.format("systemd-stdout-%d.log", pid); + writeOutputToFile(stdout, stdoutLogFile); + System.out.println("Full child process STDOUT was saved to " + stdoutLogFile); + + return output; + } + + private static void writeOutputToFile(String output, String fileName) throws Exception { + try (FileWriter fw = new FileWriter(fileName)) { + fw.write(output, 0, output.length()); + } + } + + private static String limitLines(String buffer, int nrOfLines) { + List l = Arrays.asList(buffer.split("\\R")); + if (l.size() < nrOfLines) { + return buffer; + } + + return String.join("\n", l.subList(0, nrOfLines)); + } +} diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/format/ArrayDiff.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/format/ArrayDiff.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/format/ArrayDiff.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/format/ArrayDiff.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -107,7 +107,7 @@ * @throws NullPointerException if at least one of the arrays is null * @return an ArrayDiff instance for the two arrays and formatting parameters provided */ - @SuppressWarnings("rawtypes") + @SuppressWarnings({"rawtypes", "unchecked"}) public static ArrayDiff of(Object first, Object second, int width, int contextBefore) { Objects.requireNonNull(first); Objects.requireNonNull(second); diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/hprof/model/JavaHeapObject.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/model/JavaHeapObject.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/hprof/model/JavaHeapObject.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/model/JavaHeapObject.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,12 +35,6 @@ import java.util.Map; import jdk.test.lib.hprof.util.Misc; - -/** - * - * @author Bill Foote - */ - /** * Represents an object that's allocated out of the Java heap. It occupies * memory in the VM, and is the sort of thing that in a JDK 1.1 VM had diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/hprof/model/JavaStatic.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/model/JavaStatic.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/hprof/model/JavaStatic.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/model/JavaStatic.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,11 +31,6 @@ package jdk.test.lib.hprof.model; /** - * - * @author Bill Foote - */ - -/** * Represents the value of a static field of a JavaClass */ diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/hprof/model/JavaThing.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/model/JavaThing.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/hprof/model/JavaThing.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/model/JavaThing.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,12 +31,6 @@ package jdk.test.lib.hprof.model; /** - * - * @author Bill Foote - */ - - -/** * Represents a java "Thing". A thing is anything that can be the value of * a field. This includes JavaHeapObject, JavaObjectRef, and JavaValue. */ diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/hprof/model/Root.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/model/Root.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/hprof/model/Root.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/model/Root.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,12 +33,6 @@ import jdk.test.lib.hprof.util.Misc; /** - * - * @author Bill Foote - */ - - -/** * Represents a member of the rootset, that is, one of the objects that * the GC starts from when marking reachable objects. */ diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/hprof/model/Snapshot.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/model/Snapshot.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/hprof/model/Snapshot.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/model/Snapshot.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ package jdk.test.lib.hprof.model; +import java.io.IOException; import java.lang.ref.SoftReference; import java.util.*; @@ -37,11 +38,6 @@ import jdk.test.lib.hprof.util.Misc; /** - * - * @author Bill Foote - */ - -/** * Represents a snapshot of the Java objects in the VM at one instant. * This is the top-level "model" object read out of a single .hprof or .bod * file. @@ -626,7 +622,7 @@ } @Override - public void close() throws Exception { + public void close() throws IOException { readBuf.close(); } diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/hprof/model/StackFrame.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/model/StackFrame.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/hprof/model/StackFrame.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/model/StackFrame.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,12 +31,6 @@ package jdk.test.lib.hprof.model; /** - * - * @author Bill Foote - */ - - -/** * Represents a stack frame. */ diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/hprof/model/StackTrace.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/model/StackTrace.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/hprof/model/StackTrace.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/model/StackTrace.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,12 +31,6 @@ package jdk.test.lib.hprof.model; /** - * - * @author Bill Foote - */ - - -/** * Represents a stack trace, that is, an ordered collection of stack frames. */ diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/hprof/parser/FileReadBuffer.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/parser/FileReadBuffer.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/hprof/parser/FileReadBuffer.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/parser/FileReadBuffer.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -86,7 +86,7 @@ } @Override - public void close() throws Exception { + public void close() throws IOException { file.close(); } } diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/hprof/parser/MappedReadBuffer.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/parser/MappedReadBuffer.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/hprof/parser/MappedReadBuffer.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/parser/MappedReadBuffer.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -127,7 +127,7 @@ } @Override - public void close() throws Exception { + public void close() throws IOException { file.close(); } diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/hprof/parser/ReadBuffer.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/parser/ReadBuffer.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/hprof/parser/ReadBuffer.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/parser/ReadBuffer.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,4 +43,5 @@ public short getShort(long pos) throws IOException; public int getInt(long pos) throws IOException; public long getLong(long pos) throws IOException; + public void close() throws IOException; } diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/hprof/parser/Reader.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/parser/Reader.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/hprof/parser/Reader.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/hprof/parser/Reader.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,6 +63,7 @@ * @param heapFile The name of a file containing a heap dump * @param callStack If true, read the call stack of allocaation sites */ + @SuppressWarnings("try") public static Snapshot readFile(String heapFile, boolean callStack, int debugLevel) throws IOException { @@ -136,6 +137,7 @@ * * @param heapFile The name of a file containing a heap dump */ + @SuppressWarnings("try") public static String getStack(String heapFile, int debugLevel) throws IOException { int dumpNumber = 1; diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/jfr/Events.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/jfr/Events.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/jfr/Events.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/jfr/Events.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -233,7 +233,7 @@ private static void assertThread(RecordedThread eventThread, Thread thread) { assertNotNull(eventThread, "Thread in event was null"); - assertEquals(eventThread.getJavaThreadId(), thread.getId(), "Wrong thread id"); + assertEquals(eventThread.getJavaThreadId(), thread.threadId(), "Wrong thread id"); assertEquals(eventThread.getJavaName(), thread.getName(), "Wrong thread name"); ThreadGroup threadGroup = thread.getThreadGroup(); diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/jvmti/DebugeeClass.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/jvmti/DebugeeClass.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/jvmti/DebugeeClass.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/jvmti/DebugeeClass.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,8 @@ package jdk.test.lib.jvmti; +import java.io.Serial; + /** * Base class for debuggee class in JVMTI tests. * @@ -49,6 +51,7 @@ /** * This method is used to load library with native methods implementation, if needed. */ + @SuppressWarnings("restricted") public static void loadLibrary(String name) { try { System.loadLibrary(name); @@ -70,6 +73,9 @@ } public class Failure extends RuntimeException { + @Serial + private static final long serialVersionUID = -4069390356498980839L; + public Failure() { } diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/jvmti/jvmti_common.hpp openjdk-21-21.0.9+10/test/lib/jdk/test/lib/jvmti/jvmti_common.hpp --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/jvmti/jvmti_common.hpp 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/jvmti/jvmti_common.hpp 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -429,7 +429,27 @@ return thread; } +/* Used in a couple of nsk/jvmti/scenarios tests to convert jbyteArray to a JVMTI allocated */ +static unsigned char* jni_array_to_jvmti_allocated(jvmtiEnv *jvmti, JNIEnv *jni, jbyteArray arr, jint* len_ptr) { + unsigned char* new_arr = nullptr; + + jint len = jni->GetArrayLength(arr); + if (len <= 0) { + fatal(jni, "JNI GetArrayLength returned a non-positive value"); + } + jbyte* jni_arr = jni->GetByteArrayElements(arr, nullptr); + if (jni_arr == nullptr) { + fatal(jni, "JNI GetByteArrayElements returned nullptr"); + } + jvmtiError err = jvmti->Allocate(len, &new_arr); + check_jvmti_status(jni, err, "JVMTI Allocate returned an error code"); + memcpy(new_arr, jni_arr, (size_t)len); + jni->ReleaseByteArrayElements(arr, jni_arr, JNI_ABORT); + + *len_ptr = len; + return new_arr; +} /* Commonly used helper functions */ const char* diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/management/ThreadMXBeanTool.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/management/ThreadMXBeanTool.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/management/ThreadMXBeanTool.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/management/ThreadMXBeanTool.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,7 @@ + Integer.toHexString(System.identityHashCode(object)); ThreadMXBean tmx = ManagementFactory.getThreadMXBean(); while (thread.isAlive()) { - ThreadInfo ti = tmx.getThreadInfo(thread.getId()); + ThreadInfo ti = tmx.getThreadInfo(thread.threadId()); if (ti.getThreadState() == state && (want == null || want.equals(ti.getLockName()))) { return; @@ -60,7 +60,7 @@ public static void waitUntilInNative(Thread thread) throws InterruptedException { ThreadMXBean tmx = ManagementFactory.getThreadMXBean(); while (thread.isAlive()) { - ThreadInfo ti = tmx.getThreadInfo(thread.getId()); + ThreadInfo ti = tmx.getThreadInfo(thread.threadId()); if (ti.isInNative()) { return; } diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/net/IPSupport.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/net/IPSupport.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/net/IPSupport.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/net/IPSupport.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,6 +66,7 @@ } } + @SuppressWarnings("try") private static boolean isSupported(Class addressType) { ProtocolFamily family = addressType == Inet4Address.class ? StandardProtocolFamily.INET : StandardProtocolFamily.INET6; diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/process/ProcessTools.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/process/ProcessTools.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/process/ProcessTools.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/process/ProcessTools.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -987,7 +987,7 @@ String[] classArgs = new String[args.length - 2]; System.arraycopy(args, 2, classArgs, 0, args.length - 2); Class c = Class.forName(className); - Method mainMethod = c.getMethod("main", new Class[] { String[].class }); + Method mainMethod = c.getMethod("main", new Class[] { String[].class }); mainMethod.setAccessible(true); if (testThreadFactoryName.equals("Virtual")) { diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/security/CertificateBuilder.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/security/CertificateBuilder.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/security/CertificateBuilder.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/security/CertificateBuilder.java 2025-10-13 07:49:24.000000000 +0000 @@ -52,6 +52,7 @@ import sun.security.x509.SubjectAlternativeNameExtension; import sun.security.x509.URIName; import sun.security.x509.KeyIdentifier; +import sun.security.x509.X500Name; /** * Helper class that builds and signs X.509 certificates. @@ -88,7 +89,7 @@ public class CertificateBuilder { private final CertificateFactory factory; - private X500Principal subjectName = null; + private X500Name subjectName = null; private BigInteger serialNumber = null; private PublicKey publicKey = null; private Date notBefore = null; @@ -114,7 +115,7 @@ * on this certificate. */ public CertificateBuilder setSubjectName(X500Principal name) { - subjectName = name; + subjectName = X500Name.asX500Name(name); return this; } @@ -124,7 +125,23 @@ * @param name The subject name in RFC 2253 format */ public CertificateBuilder setSubjectName(String name) { - subjectName = new X500Principal(name); + try { + subjectName = new X500Name(name); + } catch (IOException ioe) { + throw new IllegalArgumentException(ioe); + } + return this; + } + + /** + * Set the subject name for the certificate. This method is useful when + * you need more control over the contents of the subject name. + * + * @param name an {@code X500Name} to be used as the subject name + * on this certificate + */ + public CertificateBuilder setSubjectName(X500Name name) { + subjectName = name; return this; } diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/security/OpensslArtifactFetcher.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/security/OpensslArtifactFetcher.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/security/OpensslArtifactFetcher.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/security/OpensslArtifactFetcher.java 2025-10-13 07:49:24.000000000 +0000 @@ -23,14 +23,12 @@ package jdk.test.lib.security; -import java.io.File; - import java.nio.file.Path; import jdk.test.lib.Platform; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.artifacts.Artifact; import jdk.test.lib.artifacts.ArtifactResolver; -import jdk.test.lib.artifacts.ArtifactResolverException; +import jtreg.SkippedException; public class OpensslArtifactFetcher { @@ -50,6 +48,7 @@ and return that path, if download fails then return null. * * @return openssl binary path of the current version + * @throws SkippedException if a valid version of OpenSSL cannot be found */ public static String getOpensslPath() { String path = getOpensslFromSystemProp(OPENSSL_BUNDLE_VERSION); @@ -76,7 +75,16 @@ path = fetchOpenssl(MACOSX_AARCH64.class); } } - return verifyOpensslVersion(path, OPENSSL_BUNDLE_VERSION) ? path : null; + + if (!verifyOpensslVersion(path, OPENSSL_BUNDLE_VERSION)) { + String exMsg = "Can't find the version: " + + OpensslArtifactFetcher.getTestOpensslBundleVersion() + + " of openssl binary on this machine, please install" + + " and set openssl path with property 'test.openssl.path'"; + throw new SkippedException(exMsg); + } else { + return path; + } } private static String getOpensslFromSystemProp(String version) { @@ -112,23 +120,9 @@ } private static String fetchOpenssl(Class clazz) { - String path = null; - try { - path = ArtifactResolver.resolve(clazz).entrySet().stream() - .findAny().get().getValue() + File.separator + "openssl" - + File.separator + "bin" + File.separator + "openssl"; - System.out.println("path: " + path); - } catch (ArtifactResolverException e) { - Throwable cause = e.getCause(); - if (cause == null) { - System.out.println("Cannot resolve artifact, " - + "please check if JIB jar is present in classpath."); - } else { - throw new RuntimeException("Fetch artifact failed: " + clazz - + "\nPlease make sure the artifact is available.", e); - } - } - return path; + return ArtifactResolver.fetchOne(clazz) + .resolve("openssl").resolve("bin").resolve("openssl") + .toString(); } // retrieve the provider directory path from /bin/openssl diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/security/XMLUtils.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/security/XMLUtils.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/security/XMLUtils.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/security/XMLUtils.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -198,6 +198,7 @@ String dm = DigestMethod.SHA256; String cm = CanonicalizationMethod.EXCLUSIVE; String tr = Transform.ENVELOPED; + Map props = new HashMap<>(); public Signer(PrivateKey privateKey) { this.privateKey = Objects.requireNonNull(privateKey); @@ -247,6 +248,11 @@ return sm(method, null); } + public Signer prop(String name, Object o) { + props.put(name, o); + return this; + } + // Signs different sources // Signs an XML file in detached mode @@ -254,7 +260,7 @@ Document newDocument = DocumentBuilderFactory.newInstance() .newDocumentBuilder().newDocument(); FAC.newXMLSignature(buildSignedInfo(uri.toString()), buildKeyInfo()).sign( - new DOMSignContext(privateKey, newDocument)); + withProps(new DOMSignContext(privateKey, newDocument))); return newDocument; } @@ -264,7 +270,8 @@ .newDocumentBuilder().newDocument(); DOMSignContext ctxt = new DOMSignContext(privateKey, newDocument); ctxt.setBaseURI(base.toString()); - FAC.newXMLSignature(buildSignedInfo(ref.toString()), buildKeyInfo()).sign(ctxt); + FAC.newXMLSignature(buildSignedInfo(ref.toString()), buildKeyInfo()) + .sign(withProps(ctxt)); return newDocument; } @@ -275,7 +282,7 @@ .transform(new DOMSource(document), result); Document newDocument = (Document) result.getNode(); FAC.newXMLSignature(buildSignedInfo(""), buildKeyInfo()).sign( - new DOMSignContext(privateKey, newDocument.getDocumentElement())); + withProps(new DOMSignContext(privateKey, newDocument.getDocumentElement()))); return newDocument; } @@ -290,7 +297,7 @@ id, null, null)), null, null) - .sign(new DOMSignContext(privateKey, newDocument)); + .sign(withProps(new DOMSignContext(privateKey, newDocument))); return newDocument; } @@ -308,7 +315,7 @@ "object", null, null)), null, null) - .sign(new DOMSignContext(privateKey, newDocument)); + .sign(withProps(new DOMSignContext(privateKey, newDocument))); return newDocument; } @@ -325,10 +332,18 @@ "object", null, null)), null, null) - .sign(new DOMSignContext(privateKey, newDocument)); + .sign(withProps(new DOMSignContext(privateKey, newDocument))); return newDocument; } + // Add props to a context + private DOMSignContext withProps(DOMSignContext ctxt) { + for (var e : props.entrySet()) { + ctxt.setProperty(e.getKey(), e.getValue()); + } + return ctxt; + } + // Builds a SignedInfo for a string reference private SignedInfo buildSignedInfo(String ref) throws Exception { return buildSignedInfo(FAC.newReference( @@ -426,6 +441,7 @@ private Boolean secureValidation = null; private String baseURI = null; private final KeyStore ks; + Map props = new HashMap<>(); public Validator(KeyStore ks) { this.ks = ks; @@ -441,6 +457,11 @@ return this; } + public Validator prop(String name, Object o) { + props.put(name, o); + return this; + } + public boolean validate(Document document) throws Exception { return validate(document, null); } @@ -471,12 +492,21 @@ secureValidation); } return XMLSignatureFactory.getInstance("DOM") - .unmarshalXMLSignature(valContext).validate(valContext); + .unmarshalXMLSignature(valContext) + .validate(withProps(valContext)); } } return false; } + // Add props to a context + private DOMValidateContext withProps(DOMValidateContext ctxt) { + for (var e : props.entrySet()) { + ctxt.setProperty(e.getKey(), e.getValue()); + } + return ctxt; + } + // Find public key from KeyInfo, ks will be used if it's KeyName private static class MyKeySelector extends KeySelector { private final KeyStore ks; diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/thread/VThreadPinner.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/thread/VThreadPinner.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/thread/VThreadPinner.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/thread/VThreadPinner.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -94,7 +94,9 @@ throw e; if (ex instanceof Error e) throw e; - throw (X) ex; + @SuppressWarnings("unchecked") + var x = (X) ex; + throw x; } } diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/thread/VThreadRunner.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/thread/VThreadRunner.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/thread/VThreadRunner.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/thread/VThreadRunner.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -94,7 +94,9 @@ throw e; if (ex instanceof Error e) throw e; - throw (X) ex; + @SuppressWarnings("unchecked") + var x = (X) ex; + throw x; } } diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/lib/util/FileUtils.java openjdk-21-21.0.9+10/test/lib/jdk/test/lib/util/FileUtils.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/lib/util/FileUtils.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/lib/util/FileUtils.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,7 @@ import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; +import java.nio.file.StandardCopyOption; import java.nio.file.attribute.BasicFileAttributes; import java.time.Instant; import java.util.ArrayList; @@ -48,6 +49,8 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; +import java.util.stream.Stream; + import jdk.test.lib.Platform; import com.sun.management.UnixOperatingSystemMXBean; @@ -266,7 +269,7 @@ (new InputStreamReader(proc.getInputStream())); // Skip the first line as it is the "df" output header. if (reader.readLine() != null ) { - Set mountPoints = new HashSet(); + Set mountPoints = new HashSet<>(); String mountPoint = null; while ((mountPoint = reader.readLine()) != null) { if (!mountPoints.add(mountPoint)) { @@ -299,8 +302,8 @@ }; }); - final AtomicReference throwableReference = - new AtomicReference(); + final AtomicReference throwableReference = + new AtomicReference<>(); thr.setUncaughtExceptionHandler( new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread t, Throwable e) { @@ -315,7 +318,7 @@ throw new RuntimeException(ie); } - Throwable uncaughtException = (Throwable)throwableReference.get(); + Throwable uncaughtException = throwableReference.get(); if (uncaughtException != null) { throw new RuntimeException(uncaughtException); } @@ -364,7 +367,32 @@ }); } + /** + * Copies a directory and all entries in the directory to a destination path. + * Makes the access permission of the destination entries writable. + * + * @param src the path of the source directory + * @param dst the path of the destination directory + * @throws IOException if an I/O error occurs while walking the file tree + * @throws RuntimeException if an I/O error occurs during the copy operation + * or if the source or destination paths are invalid + */ + public static void copyDirectory(Path src, Path dst) throws IOException { + try (Stream stream = Files.walk(src)) { + stream.forEach(sourcePath -> { + try { + Path destPath = dst.resolve(src.relativize(sourcePath)); + Files.copy(sourcePath, destPath, StandardCopyOption.REPLACE_EXISTING); + destPath.toFile().setWritable(true); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + } + } + // Return the current process handle count + @SuppressWarnings("restricted") public static long getProcessHandleCount() { if (IS_WINDOWS) { if (!nativeLibLoaded) { diff -Nru openjdk-21-21.0.8+9/test/lib/jdk/test/whitebox/WhiteBox.java openjdk-21-21.0.9+10/test/lib/jdk/test/whitebox/WhiteBox.java --- openjdk-21-21.0.8+9/test/lib/jdk/test/whitebox/WhiteBox.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/lib/jdk/test/whitebox/WhiteBox.java 2025-10-13 07:49:24.000000000 +0000 @@ -295,6 +295,10 @@ public native void NMTFreeArena(long arena); public native void NMTArenaMalloc(long arena, long size); + // Sanitizers + public native boolean isAsanEnabled(); + public native boolean isUbsanEnabled(); + // Compiler public native boolean isC2OrJVMCIIncluded(); public native boolean isJVMCISupportedByGC(); @@ -729,6 +733,7 @@ public native void printOsInfo(); public native long hostPhysicalMemory(); public native long hostPhysicalSwap(); + public native int hostCPUs(); // Decoder public native void disableElfSectionCache(); diff -Nru openjdk-21-21.0.8+9/test/micro/org/openjdk/bench/java/net/UnixSocketChannelReadWrite.java openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/net/UnixSocketChannelReadWrite.java --- openjdk-21-21.0.8+9/test/micro/org/openjdk/bench/java/net/UnixSocketChannelReadWrite.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/net/UnixSocketChannelReadWrite.java 2025-10-13 07:49:24.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,6 @@ import java.nio.channels.SocketChannel; import java.nio.file.*; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; import org.openjdk.jmh.annotations.*; @@ -52,22 +51,10 @@ private ReadThread rt; private ByteBuffer bb = ByteBuffer.allocate(1); - private static volatile String tempDir; - private static final AtomicInteger count = new AtomicInteger(0); private volatile Path socket; - static { - try { - Path p = Files.createTempDirectory("readWriteTest"); - tempDir = p.toString(); - } catch (IOException e) { - tempDir = null; - } - } - private ServerSocketChannel getServerSocketChannel() throws IOException { - int next = count.incrementAndGet(); - socket = Paths.get(tempDir, Integer.toString(next)); + socket = Files.createTempDirectory(UnixSocketChannelReadWrite.class.getSimpleName()).resolve("sock"); UnixDomainSocketAddress addr = UnixDomainSocketAddress.of(socket); ServerSocketChannel c = ServerSocketChannel.open(StandardProtocolFamily.UNIX); c.bind(addr); @@ -93,7 +80,7 @@ s2.close(); ssc.close(); Files.delete(socket); - Files.delete(Path.of(tempDir)); + Files.delete(socket.getParent()); rt.join(); } diff -Nru openjdk-21-21.0.8+9/test/micro/org/openjdk/bench/java/util/stream/tasks/DataProviders.java openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/util/stream/tasks/DataProviders.java --- openjdk-21-21.0.8+9/test/micro/org/openjdk/bench/java/util/stream/tasks/DataProviders.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/util/stream/tasks/DataProviders.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.openjdk.bench.java.util.stream.tasks; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.stream.Stream; - -public class DataProviders { - public static Stream dictionary() throws IOException { - BufferedReader r = new BufferedReader(new InputStreamReader(DataProviders.class.getResourceAsStream("cmudict-0.7b.txt"))); - // Strip out the copyright notice and special chars - return r.lines().filter(w -> w.charAt(0) >= 'A' && w.charAt(0) <= 'Z').map(w -> w.substring(0, w.indexOf(" "))).onClose(() -> { - try { - r.close(); - } catch (IOException e) { - // swallow - } - }); - } -} diff -Nru openjdk-21-21.0.8+9/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Bulk.java openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Bulk.java --- openjdk-21-21.0.8+9/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Bulk.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Bulk.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.openjdk.bench.java.util.stream.tasks.DictionaryWordValue; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Level; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.Arrays; -import java.util.concurrent.RecursiveTask; -import java.util.concurrent.TimeUnit; -import java.util.function.BinaryOperator; -import java.util.function.Function; - - -/** - * Bulk scenario: searching max "wordValue" through the dictionary (array of strings). - */ -@BenchmarkMode(Mode.Throughput) -@Warmup(iterations = 4, time = 2, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 4, time = 2, timeUnit = TimeUnit.SECONDS) -@Fork(value = 3) -@OutputTimeUnit(TimeUnit.SECONDS) -@State(Scope.Benchmark) -public class Bulk { - - @Setup(Level.Trial) - public void loadData() { - // cause classload and problem initialization - DictionaryProblem.class.getName(); - } - - @Benchmark - public int hm_seq() { - int max = 0; - for (String s : DictionaryProblem.get()) { - int v = DictionaryProblem.wordValue(s); - if (v > max) { - max = v; - } - } - return max; - } - - @Benchmark - public int hm_par() { - return new Task(DictionaryProblem.get(), 0, DictionaryProblem.get().length).invoke(); - } - - @Benchmark - public int bulk_seq_inner() { - return Arrays.stream(DictionaryProblem.get()) - .map(new Function() { - @Override - public Integer apply(String s) { - return DictionaryProblem.wordValue(s); - } - }) - .reduce(0, new BinaryOperator() { - @Override - public Integer apply(Integer l, Integer r) { - return l > r ? l : r; - } - }); - } - - @Benchmark - public int bulk_par_inner() { - return Arrays.stream(DictionaryProblem.get()).parallel() - .map(new Function() { - @Override - public Integer apply(String s) { - return DictionaryProblem.wordValue(s); - } - }) - .reduce(0, new BinaryOperator() { - @Override - public Integer apply(Integer l, Integer r) { - return l > r ? l : r; - } - }); - } - - - public static class Task extends RecursiveTask { - private static final int FORK_LIMIT = 500; - - private final String[] words; - private final int start, end; - - Task(String[] w, int start, int end) { - this.words = w; - this.start = start; - this.end = end; - } - - @Override - protected Integer compute() { - int size = end - start; - if (size > FORK_LIMIT) { - int mid = start + size / 2; - Task t1 = new Task(words, start, mid); - Task t2 = new Task(words, mid, end); - t1.fork(); - Integer v2 = t2.invoke(); - Integer v1 = t1.join(); - return Math.max(v1, v2); - } else { - int max = 0; - for (int i = start; i < end; i++) { - int v = DictionaryProblem.wordValue(words[i]); - if (v > max) { - max = v; - } - } - return max; - } - } - } - - -} diff -Nru openjdk-21-21.0.8+9/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/DictionaryProblem.java openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/DictionaryProblem.java --- openjdk-21-21.0.8+9/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/DictionaryProblem.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/DictionaryProblem.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.openjdk.bench.java.util.stream.tasks.DictionaryWordValue; - -import org.openjdk.bench.java.util.stream.tasks.DataProviders; - -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class DictionaryProblem { - - private static final int DICTIONARY_REPEAT_RATE = 40; - - private static final String[] dict; - - static { - int size; - int idx = 0; - List d = Collections.emptyList(); - try (Stream s = DataProviders.dictionary()) { - d = s.collect(Collectors.toList()); - } catch (Exception e) { - // ignore - } - size = d.size() * DICTIONARY_REPEAT_RATE; - dict = new String[size]; - for (int i = 0; i < DICTIONARY_REPEAT_RATE; i++) { - d.sort(new IdxComparator(i)); - for (String s : d) { - // copy the whole string - dict[idx++] = new String(s.toCharArray()); - } - } - assert (idx == dict.length); - } - - public static String[] get() { - return dict; - } - - /** - * A word value is the sum of alphabet value of each characters in a word. - * - * @param word The word - * @return The word value - */ - public static int wordValue(String word) { - char[] ar = word.toLowerCase().toCharArray(); - int value = 0; - for (char c: ar) { - int v = c - 'a' + 1; - if (v < 1 || v > 26) { - // skip non-alphabet - continue; - } - value += (c - 'a' + 1); - } - return value; - } - - static class IdxComparator implements Comparator { - private final int index; - - public IdxComparator(int i) { - index = i; - } - - @Override - public int compare(String a, String b) { - if (a.length() > index && b.length() > index) { - return (a.charAt(index) - b.charAt(index)); - } else { - return (a.length() - b.length()); - } - } - } - -} diff -Nru openjdk-21-21.0.8+9/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Lambda.java openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Lambda.java --- openjdk-21-21.0.8+9/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Lambda.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Lambda.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.openjdk.bench.java.util.stream.tasks.DictionaryWordValue; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Level; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.Arrays; -import java.util.concurrent.TimeUnit; - -/** - * Bulk scenario: searching max "wordValue" through the dictionary (array of strings). - */ -@BenchmarkMode(Mode.Throughput) -@Warmup(iterations = 4, time = 2, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 4, time = 2, timeUnit = TimeUnit.SECONDS) -@Fork(value = 3) -@OutputTimeUnit(TimeUnit.SECONDS) -@State(Scope.Benchmark) -public class Lambda { - - @Setup(Level.Trial) - public void loadData() { - // cause classload and problem initialization - DictionaryProblem.class.getName(); - } - - public static Integer maxInt(Integer l, Integer r) { - return l > r ? l : r; - } - - @Benchmark - public int bulk_seq_lambda() { - return Arrays.stream(DictionaryProblem.get()) - .map(s -> DictionaryProblem.wordValue(s)) - .reduce(0, (l, r) -> l > r ? l : r); - } - - @Benchmark - public int bulk_seq_mref() { - return Arrays.stream(DictionaryProblem.get()) - .map(DictionaryProblem::wordValue) - .reduce(0, Lambda::maxInt); - } - - @Benchmark - public int bulk_par_lambda() { - return Arrays.stream(DictionaryProblem.get()).parallel() - .map(s -> DictionaryProblem.wordValue(s)) - .reduce(0, (l, r) -> l > r ? l : r); - } - - @Benchmark - public int bulk_par_mref() { - return Arrays.stream(DictionaryProblem.get()).parallel() - .map(DictionaryProblem::wordValue) - .reduce(0, Lambda::maxInt); - } - -} diff -Nru openjdk-21-21.0.8+9/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Xtras.java openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Xtras.java --- openjdk-21-21.0.8+9/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Xtras.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Xtras.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.openjdk.bench.java.util.stream.tasks.DictionaryWordValue; - -/** - * Bulk scenario: searching max "wordValue" through the dictionary (array of strings). - */ -public class Xtras { - - // no workloads yet - -} diff -Nru openjdk-21-21.0.8+9/test/micro/org/openjdk/bench/java/util/stream/tasks/PhoneCode/Bulk.java openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/util/stream/tasks/PhoneCode/Bulk.java --- openjdk-21-21.0.8+9/test/micro/org/openjdk/bench/java/util/stream/tasks/PhoneCode/Bulk.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/util/stream/tasks/PhoneCode/Bulk.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.openjdk.bench.java.util.stream.tasks.PhoneCode; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.concurrent.TimeUnit; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -import static org.openjdk.bench.java.util.stream.tasks.PhoneCode.PhoneCodeProblem.wordsForNumber; - -/** - * This benchmark compare various strategies solving the phone code problem. - * The result should offer some insights on strength/drawbacks of underlying - * implementation. - */ -@BenchmarkMode(Mode.Throughput) -@Warmup(iterations = 4, time = 2, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 4, time = 2, timeUnit = TimeUnit.SECONDS) -@Fork(value = 3) -@OutputTimeUnit(TimeUnit.MINUTES) -@State(Scope.Benchmark) -public class Bulk { - // several method choke up with 6-digit problem - private final static int SIZE = 5; - private Stream join(String head, - String tail, - Function> encoder) - { - Stream s = wordsForNumber(head).stream(); - - if (! tail.isEmpty()) { - s = s.flatMap(h -> encoder.apply(tail).map(t -> h + " " + t)); - } - - return s; - } - - private Stream encode_par1(String number) { - return IntStream.range(1, number.length() + 1) - .parallel() - .boxed() - .flatMap(i -> join(number.substring(0, i), - number.substring(i), - this::encode_par1)); - } - - private Stream encode_par2(String number) { - return IntStream.range(1, number.length() + 1) - .boxed() - .parallel() - .flatMap(i -> join(number.substring(0, i), - number.substring(i), - this::encode_par2)); - } - - private Stream encode_ser(String number) { - return IntStream.range(1, number.length() + 1) - .boxed() - .flatMap(i -> join(number.substring(0, i), - number.substring(i), - this::encode_ser)); - } - - private Stream encode_loop_concat(String number) { - if (number.isEmpty()) { - return Stream.empty(); - } - // full number - Stream s = wordsForNumber(number).stream(); - // split - for (int i = 1; i < number.length(); i++) { - s = Stream.concat(s, join(number.substring(0, i), - number.substring(i), - this::encode_loop_concat)); - } - - return s; - } - - private Collection encode_loop_collect(String number) { - if (number.isEmpty()) { - return Collections.emptySet(); - } - - Collection rv = new HashSet<>(); - - for (int i = 1; i <= number.length(); i++) { - join(number.substring(0, i), - number.substring(i), - s -> encode_loop_collect(s).stream()).forEach(rv::add); - } - - return rv; - } - - private Collection encode_inline(String number) { - if (number.isEmpty()) { - return Collections.emptySet(); - } - - Collection rv = new HashSet<>(); - - for (int i = 1; i < number.length(); i++) { - String front = number.substring(0, i); - String rest = number.substring(i); - wordsForNumber(front).stream() - .flatMap(h -> encode_inline(rest).stream().map(t -> h + " " + t)) - .forEach(rv::add); - } - - rv.addAll(wordsForNumber(number)); - - return rv; - } - - @Benchmark - public int bulk_par_range_concurrent() { - // force collect - return PhoneCodeProblem.get(SIZE) - .flatMap(this::encode_par1) - .collect(Collectors.toConcurrentMap( - Function.identity(), - Function.identity(), - (l, r) -> l)) - .keySet() - .size(); - } - - @Benchmark - public int bulk_par_boxed_range_concurrent() { - // force collect - return PhoneCodeProblem.get(SIZE) - .flatMap(this::encode_par2) - .collect(Collectors.toConcurrentMap( - Function.identity(), - Function.identity(), - (l, r) -> l)) - .keySet() - .size(); - } - - @Benchmark - public int bulk_par_range() { - // force collect - return PhoneCodeProblem.get(SIZE) - .flatMap(this::encode_par1) - .collect(Collectors.toSet()) - .size(); - } - - @Benchmark - public int bulk_par_boxed_range() { - // force collect - return PhoneCodeProblem.get(SIZE) - .flatMap(this::encode_par2) - .collect(Collectors.toSet()) - .size(); - } - - @Benchmark - public int bulk_ser_range() { - // force collect - return PhoneCodeProblem.get(SIZE) - .flatMap(this::encode_ser) - .collect(Collectors.toSet()) - .size(); - } - - @Benchmark - public int bulk_ser_loop_concat() { - // force collect - return PhoneCodeProblem.get(SIZE) - .flatMap(this::encode_loop_concat) - .collect(Collectors.toSet()) - .size(); - } - - @Benchmark - public int bulk_ser_loop_collect() { - return PhoneCodeProblem.get(SIZE) - .map(this::encode_loop_collect) - .map(Collection::size) - .reduce(0, Integer::sum); - } - - @Benchmark - public int bulk_ser_inline() { - return PhoneCodeProblem.get(SIZE) - .map(this::encode_inline) - .map(Collection::size) - .reduce(0, Integer::sum); - } -} diff -Nru openjdk-21-21.0.8+9/test/micro/org/openjdk/bench/java/util/stream/tasks/PhoneCode/PhoneCodeProblem.java openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/util/stream/tasks/PhoneCode/PhoneCodeProblem.java --- openjdk-21-21.0.8+9/test/micro/org/openjdk/bench/java/util/stream/tasks/PhoneCode/PhoneCodeProblem.java 2025-07-09 05:53:39.000000000 +0000 +++ openjdk-21-21.0.9+10/test/micro/org/openjdk/bench/java/util/stream/tasks/PhoneCode/PhoneCodeProblem.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.openjdk.bench.java.util.stream.tasks.PhoneCode; - -import org.openjdk.bench.java.util.stream.tasks.DataProviders; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * The phone coder problem is trying to find full list of possible - * mnemonic combination of numbers. - * - * The solution is based on Martin Odersky's devoxx 2010 scala talk, - * where numbers are not allowed in the result, which is not really - * correct, but we don't care. - */ -public class PhoneCodeProblem { - // Map Character 'A'-'Z' to digits "2"-"9", key is charCode - private static final Map CHAR_CODE; - // Map a string of digits to a collection of dictionary words - private static final Map> WORD_CODES; - - static { - HashMap mnemonics = new HashMap<>(8); - mnemonics.put("2", "ABC"); - mnemonics.put("3", "DEF"); - mnemonics.put("4", "GHI"); - mnemonics.put("5", "JKL"); - mnemonics.put("6", "MNO"); - mnemonics.put("7", "PQRS"); - mnemonics.put("8", "TUV"); - mnemonics.put("9", "WXYZ"); - - CHAR_CODE = new ConcurrentHashMap<>(); - mnemonics.entrySet().stream().forEach(e -> - e.getValue().chars().forEach(c -> - { CHAR_CODE.put(c, e.getKey()); } )); - - WORD_CODES = loadDictionary(); - // System.out.println("Dictionary loaded with " + WORD_CODES.size() + " number entries"); - } - - // Convert a word to its number form - private static String wordToNumber(String word) { - return word.chars().mapToObj(CHAR_CODE::get) - .reduce("", String::concat); - } - - // Prepare number -> word lookup table - private static Map> loadDictionary() { - try (Stream s = DataProviders.dictionary()) { - return s.filter(w -> w.length() > 1) - .filter(w -> w.matches("[a-zA-Z]*")) - .map(String::toUpperCase) - .collect(Collectors.groupingBy(PhoneCodeProblem::wordToNumber)); - } catch (Exception ex) { - ex.printStackTrace(System.err); - return Collections.emptyMap(); - } - } - - public static Collection wordsForNumber(String number) { - Collection rv = WORD_CODES.get(number); - return (null == rv) ? Collections.emptySet() : rv; - } - - public static Stream get(int length) { - String digits[] = { "2", "3", "4", "5", "6", "7", "8", "9" }; - - Stream s = Arrays.stream(digits); - for (int i = 1; i < length; i++) { - s = s.flatMap(d1 -> Arrays.stream(digits).map(d2 -> d1 + d2)); - } - return s; - } -}