diff --git a/.github/actions/build-jtreg/action.yml b/.github/actions/build-jtreg/action.yml index 3abfa260c17..0ba9937fb45 100644 --- a/.github/actions/build-jtreg/action.yml +++ b/.github/actions/build-jtreg/action.yml @@ -65,4 +65,4 @@ runs: with: name: bundles-jtreg-${{ steps.version.outputs.value }} path: jtreg/installed - retention-days: 1 + retention-days: 5 diff --git a/.github/actions/get-msys2/action.yml b/.github/actions/get-msys2/action.yml index 4ca5d2ab847..d93b6e3763b 100644 --- a/.github/actions/get-msys2/action.yml +++ b/.github/actions/get-msys2/action.yml @@ -30,15 +30,15 @@ runs: using: composite steps: - name: 'Install MSYS2' - uses: msys2/setup-msys2@v2.22.0 + id: msys2 + uses: msys2/setup-msys2@v2.28.0 with: install: 'autoconf tar unzip zip make' path-type: minimal - location: ${{ runner.tool_cache }}/msys2 + release: false # We can't run bash until this is completed, so stick with pwsh - name: 'Set MSYS2 path' run: | - # Prepend msys2/msys64/usr/bin to the PATH - echo "$env:RUNNER_TOOL_CACHE/msys2/msys64/usr/bin" >> $env:GITHUB_PATH + echo "${{ steps.msys2.outputs.msys2-location }}/usr/bin" >> $env:GITHUB_PATH shell: pwsh diff --git a/.github/actions/upload-bundles/action.yml b/.github/actions/upload-bundles/action.yml index dfa994baac0..ca5366f3d6c 100644 --- a/.github/actions/upload-bundles/action.yml +++ b/.github/actions/upload-bundles/action.yml @@ -91,5 +91,5 @@ runs: with: name: bundles-${{ inputs.platform }}${{ inputs.debug-suffix }}${{ inputs.static-suffix }}${{ inputs.bundle-suffix }} path: bundles - retention-days: 1 + retention-days: 5 if: steps.bundles.outputs.bundles-found == 'true' diff --git a/.github/workflows/build-alpine-linux.yml b/.github/workflows/build-alpine-linux.yml index ac5870ca675..a39b342a248 100644 --- a/.github/workflows/build-alpine-linux.yml +++ b/.github/workflows/build-alpine-linux.yml @@ -51,11 +51,15 @@ on: make-arguments: required: false type: string + dry-run: + required: false + type: boolean + default: false jobs: build-linux: name: build - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 container: image: alpine:3.20 @@ -104,9 +108,11 @@ jobs: make-target: '${{ inputs.make-target }} ${{ inputs.make-arguments }}' platform: ${{ inputs.platform }} debug-suffix: '${{ matrix.suffix }}' + if: ${{ inputs.dry-run == false }} - name: 'Upload bundles' uses: ./.github/actions/upload-bundles with: platform: ${{ inputs.platform }} debug-suffix: '${{ matrix.suffix }}' + if: ${{ inputs.dry-run == false }} diff --git a/.github/workflows/build-cross-compile.yml b/.github/workflows/build-cross-compile.yml index 3f4ba67f996..e70937f57b6 100644 --- a/.github/workflows/build-cross-compile.yml +++ b/.github/workflows/build-cross-compile.yml @@ -40,11 +40,15 @@ on: make-arguments: required: false type: string + dry-run: + required: false + type: boolean + default: false jobs: build-cross-compile: name: build - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false @@ -60,33 +64,33 @@ jobs: gnu-arch: aarch64 debian-arch: arm64 debian-repository: https://httpredir.debian.org/debian/ - debian-version: bullseye + debian-version: trixie tolerate-sysroot-errors: false - target-cpu: arm gnu-arch: arm debian-arch: armhf debian-repository: https://httpredir.debian.org/debian/ - debian-version: bullseye + debian-version: trixie tolerate-sysroot-errors: false gnu-abi: eabihf - target-cpu: s390x gnu-arch: s390x debian-arch: s390x debian-repository: https://httpredir.debian.org/debian/ - debian-version: bullseye + debian-version: trixie tolerate-sysroot-errors: false - target-cpu: ppc64le gnu-arch: powerpc64le debian-arch: ppc64el debian-repository: https://httpredir.debian.org/debian/ - debian-version: bullseye + debian-version: trixie tolerate-sysroot-errors: false - target-cpu: riscv64 gnu-arch: riscv64 debian-arch: riscv64 debian-repository: https://httpredir.debian.org/debian/ - debian-version: sid - tolerate-sysroot-errors: true + debian-version: trixie + tolerate-sysroot-errors: false steps: - name: 'Checkout the JDK source' @@ -189,4 +193,4 @@ jobs: with: make-target: 'hotspot ${{ inputs.make-arguments }}' platform: linux-${{ matrix.target-cpu }} - if: steps.create-sysroot.outcome == 'success' || steps.get-cached-sysroot.outputs.cache-hit == 'true' + if: ((steps.create-sysroot.outcome == 'success' || steps.get-cached-sysroot.outputs.cache-hit == 'true') && inputs.dry-run == false) diff --git a/.github/workflows/build-linux.yml b/.github/workflows/build-linux.yml index 9c991eed419..0680dea6bbe 100644 --- a/.github/workflows/build-linux.yml +++ b/.github/workflows/build-linux.yml @@ -61,6 +61,10 @@ on: make-arguments: required: false type: string + dry-run: + required: false + type: boolean + default: false bundle-suffix: required: false type: string @@ -71,7 +75,7 @@ on: jobs: build-linux: name: build - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false @@ -111,9 +115,21 @@ jobs: if [[ '${{ inputs.apt-architecture }}' != '' ]]; then sudo dpkg --add-architecture ${{ inputs.apt-architecture }} fi - sudo apt-get update - sudo apt-get install --only-upgrade apt - sudo apt-get install gcc-${{ inputs.gcc-major-version }}${{ inputs.gcc-package-suffix }} g++-${{ inputs.gcc-major-version }}${{ inputs.gcc-package-suffix }} libxrandr-dev${{ steps.arch.outputs.suffix }} libxtst-dev${{ steps.arch.outputs.suffix }} libcups2-dev${{ steps.arch.outputs.suffix }} libasound2-dev${{ steps.arch.outputs.suffix }} ${{ inputs.apt-extra-packages }} + sudo apt update + sudo apt install --only-upgrade apt + sudo apt install \ + gcc-${{ inputs.gcc-major-version }}${{ inputs.gcc-package-suffix }} \ + g++-${{ inputs.gcc-major-version }}${{ inputs.gcc-package-suffix }} \ + libasound2-dev${{ steps.arch.outputs.suffix }} \ + libcups2-dev${{ steps.arch.outputs.suffix }} \ + libfontconfig1-dev${{ steps.arch.outputs.suffix }} \ + libx11-dev${{ steps.arch.outputs.suffix }} \ + libxext-dev${{ steps.arch.outputs.suffix }} \ + libxrandr-dev${{ steps.arch.outputs.suffix }} \ + libxrender-dev${{ steps.arch.outputs.suffix }} \ + libxt-dev${{ steps.arch.outputs.suffix }} \ + libxtst-dev${{ steps.arch.outputs.suffix }} \ + ${{ inputs.apt-extra-packages }} sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${{ inputs.gcc-major-version }} 100 --slave /usr/bin/g++ g++ /usr/bin/g++-${{ inputs.gcc-major-version }} - name: 'Configure' @@ -139,6 +155,7 @@ jobs: make-target: '${{ inputs.make-target }} ${{ inputs.make-arguments }}' platform: ${{ inputs.platform }} debug-suffix: "${{ matrix.debug-level == 'debug' && '-debug' || '' }}" + if: ${{ inputs.dry-run == false }} - name: 'Upload bundles' uses: ./.github/actions/upload-bundles @@ -147,3 +164,4 @@ jobs: debug-suffix: "${{ matrix.debug-level == 'debug' && '-debug' || '' }}" bundle-suffix: ${{ inputs.bundle-suffix }} static-suffix: ${{ inputs.static-suffix }} + if: ${{ inputs.dry-run == false }} diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml index 90bb6af044f..0a12df668e5 100644 --- a/.github/workflows/build-macos.yml +++ b/.github/workflows/build-macos.yml @@ -54,6 +54,10 @@ on: make-arguments: required: false type: string + dry-run: + required: false + type: boolean + default: false jobs: build-macos: @@ -118,9 +122,11 @@ jobs: make-target: '${{ inputs.make-target }} ${{ inputs.make-arguments }}' platform: ${{ inputs.platform }} debug-suffix: '${{ matrix.suffix }}' + if: ${{ inputs.dry-run == false }} - name: 'Upload bundles' uses: ./.github/actions/upload-bundles with: platform: ${{ inputs.platform }} debug-suffix: '${{ matrix.suffix }}' + if: ${{ inputs.dry-run == false }} diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 9bb43a8b83c..a3091b94cef 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -54,6 +54,10 @@ on: make-arguments: required: false type: string + dry-run: + required: false + type: boolean + default: false env: # These are needed to make the MSYS2 bash work properly @@ -139,6 +143,7 @@ jobs: # Set PATH to "", so just GITHUB_PATH is included PATH: '' shell: env /usr/bin/bash --login -eo pipefail {0} + if: ${{ inputs.dry-run == false }} - name: 'Build' id: build @@ -147,9 +152,11 @@ jobs: make-target: '${{ inputs.make-target }} ${{ inputs.make-arguments }}' platform: ${{ inputs.platform }} debug-suffix: '${{ matrix.suffix }}' + if: ${{ inputs.dry-run == false }} - name: 'Upload bundles' uses: ./.github/actions/upload-bundles with: platform: ${{ inputs.platform }} debug-suffix: '${{ matrix.suffix }}' + if: ${{ inputs.dry-run == false }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8c058440ad7..09e6ed65a47 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -28,9 +28,7 @@ name: 'OpenJDK GHA Sanity Checks' on: push: branches-ignore: - - master - pr/* - - jdk* workflow_dispatch: inputs: platforms: @@ -43,6 +41,9 @@ on: make-arguments: description: 'Additional make arguments' required: false + dry-run: + description: 'Dry run: skip actual builds and tests' + required: false concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -56,7 +57,7 @@ jobs: prepare: name: 'Prepare the run' - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 env: # List of platforms to exclude by default EXCLUDED_PLATFORMS: 'alpine-linux-x64' @@ -70,6 +71,7 @@ jobs: windows-x64: ${{ steps.include.outputs.windows-x64 }} windows-aarch64: ${{ steps.include.outputs.windows-aarch64 }} docs: ${{ steps.include.outputs.docs }} + dry-run: ${{ steps.include.outputs.dry-run }} steps: - name: 'Checkout the scripts' @@ -143,6 +145,35 @@ jobs: echo 'false' } + function check_dry_run() { + if [[ $GITHUB_EVENT_NAME == workflow_dispatch ]]; then + # Take the user-specified one. + echo '${{ github.event.inputs.dry-run }}' + return + elif [[ $GITHUB_EVENT_NAME == push ]]; then + # Cut out the real branch name + BRANCH=${GITHUB_REF##*/} + + # Dry run rebuilds the caches in current branch, so they can be reused + # for any child PR branches. Because of this, we want to trigger this + # workflow in master branch, so that actual PR branches can use the cache. + # This workflow would trigger every time contributors sync their master + # branches in their personal forks. + if [[ $BRANCH == "master" ]]; then + echo 'true' + return + fi + + # ...same for stabilization branches + if [[ $BRANCH =~ "jdk(.*)" ]]; then + echo 'true' + return + fi + fi + + echo 'false' + } + echo "linux-x64=$(check_platform linux-x64 linux x64)" >> $GITHUB_OUTPUT echo "linux-x64-variants=$(check_platform linux-x64-variants variants)" >> $GITHUB_OUTPUT echo "linux-cross-compile=$(check_platform linux-cross-compile cross-compile)" >> $GITHUB_OUTPUT @@ -152,6 +183,7 @@ jobs: echo "windows-x64=$(check_platform windows-x64 windows x64)" >> $GITHUB_OUTPUT echo "windows-aarch64=$(check_platform windows-aarch64 windows aarch64)" >> $GITHUB_OUTPUT echo "docs=$(check_platform docs)" >> $GITHUB_OUTPUT + echo "dry-run=$(check_dry_run)" >> $GITHUB_OUTPUT ### ### Build jobs @@ -166,6 +198,7 @@ jobs: gcc-major-version: '10' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.linux-x64 == 'true' build-linux-x64-hs-nopch: @@ -180,6 +213,7 @@ jobs: extra-conf-options: '--disable-precompiled-headers' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.linux-x64-variants == 'true' build-linux-x64-hs-zero: @@ -194,6 +228,7 @@ jobs: extra-conf-options: '--with-jvm-variants=zero --disable-precompiled-headers' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.linux-x64-variants == 'true' build-linux-x64-hs-minimal: @@ -208,6 +243,7 @@ jobs: extra-conf-options: '--with-jvm-variants=minimal --disable-precompiled-headers' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.linux-x64-variants == 'true' build-linux-x64-hs-optimized: @@ -223,6 +259,7 @@ jobs: extra-conf-options: '--with-debug-level=optimized --disable-precompiled-headers' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.linux-x64-variants == 'true' build-linux-x64-static: @@ -238,6 +275,7 @@ jobs: gcc-major-version: '10' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} static-suffix: "-static" if: needs.prepare.outputs.linux-x64 == 'true' @@ -254,6 +292,7 @@ jobs: gcc-major-version: '10' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} # Upload static libs bundles separately to avoid interference with normal linux-x64 bundle. # This bundle is not used by testing jobs, but downstreams use it to check that # dependent projects, e.g. libgraal, builds fine. @@ -268,6 +307,7 @@ jobs: gcc-major-version: '10' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.linux-cross-compile == 'true' build-alpine-linux-x64: @@ -278,6 +318,7 @@ jobs: platform: alpine-linux-x64 configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.alpine-linux-x64 == 'true' build-macos-x64: @@ -286,10 +327,11 @@ jobs: uses: ./.github/workflows/build-macos.yml with: platform: macos-x64 - runs-on: 'macos-13' - xcode-toolset-version: '14.3.1' + runs-on: 'macos-15-intel' + xcode-toolset-version: '16.4' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.macos-x64 == 'true' build-macos-aarch64: @@ -298,10 +340,11 @@ jobs: uses: ./.github/workflows/build-macos.yml with: platform: macos-aarch64 - runs-on: 'macos-14' - xcode-toolset-version: '15.4' + runs-on: 'macos-15' + xcode-toolset-version: '16.4' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.macos-aarch64 == 'true' build-windows-x64: @@ -314,6 +357,7 @@ jobs: msvc-toolset-architecture: 'x86.x64' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.windows-x64 == 'true' build-windows-aarch64: @@ -328,6 +372,7 @@ jobs: extra-conf-options: '--openjdk-target=aarch64-unknown-cygwin' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.windows-aarch64 == 'true' build-docs: @@ -344,6 +389,7 @@ jobs: gcc-major-version: '10' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.docs == 'true' ### @@ -353,45 +399,53 @@ jobs: test-linux-x64: name: linux-x64 needs: + - prepare - build-linux-x64 uses: ./.github/workflows/test.yml with: platform: linux-x64 bootjdk-platform: linux-x64 - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} debug-suffix: -debug test-linux-x64-static: name: linux-x64-static needs: + - prepare - build-linux-x64 - build-linux-x64-static uses: ./.github/workflows/test.yml with: platform: linux-x64 bootjdk-platform: linux-x64 - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} static-suffix: "-static" test-macos-aarch64: name: macos-aarch64 needs: + - prepare - build-macos-aarch64 uses: ./.github/workflows/test.yml with: platform: macos-aarch64 bootjdk-platform: macos-aarch64 - runs-on: macos-14 - xcode-toolset-version: '15.4' + runs-on: macos-15 + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} + xcode-toolset-version: '16.4' debug-suffix: -debug test-windows-x64: name: windows-x64 needs: + - prepare - build-windows-x64 uses: ./.github/workflows/test.yml with: platform: windows-x64 bootjdk-platform: windows-x64 runs-on: windows-2025 + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} debug-suffix: -debug diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 665ae224372..f2c8916a369 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,6 +40,10 @@ on: xcode-toolset-version: required: false type: string + dry-run: + required: false + type: boolean + default: false debug-suffix: required: false type: string @@ -147,6 +151,7 @@ jobs: platform: ${{ inputs.platform }} debug-suffix: ${{ matrix.debug-suffix }} static-suffix: ${{ inputs.static-suffix }} + if: ${{ inputs.dry-run == false }} - name: 'Install dependencies' run: | @@ -199,6 +204,7 @@ jobs: && bash ./.github/scripts/gen-test-summary.sh "$GITHUB_STEP_SUMMARY" "$GITHUB_OUTPUT" env: PATH: ${{ steps.path.outputs.value }} + if: ${{ inputs.dry-run == false }} # This is a separate step, since if the markdown from a step gets bigger than # 1024 kB it is skipped, but then the short summary above is still generated diff --git a/.jcheck/conf b/.jcheck/conf index 6ab5c2d64c2..27adc61e534 100644 --- a/.jcheck/conf +++ b/.jcheck/conf @@ -1,7 +1,7 @@ [general] -project=jdk +project=jdk-updates jbs=JDK -version=25 +version=25.0.3 [checks] error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists,copyright diff --git a/README.md b/README.md index b3f30676b3c..e5800fecd57 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,11 @@ -# Welcome to the JDK! +# Welcome to OpenJDK 25 Updates! + +The JDK 25 Updates project uses two GitHub repositories. +Updates are continuously developed in the repository [jdk25u-dev](https://github.com/openjdk/jdk25u-dev). This is the repository usually targeted by contributors. +The [jdk25u](https://github.com/openjdk/jdk25u) repository is used for rampdown of the update releases of jdk25u and only accepts critical changes that must make the next release during rampdown. (You probably do not want to target jdk25u). + +For more OpenJDK 25 updates specific information such as timelines and contribution guidelines see the [project wiki page](https://wiki.openjdk.org/display/JDKUpdates/JDK+25u/). + For build instructions please see the [online documentation](https://openjdk.org/groups/build/doc/building.html), diff --git a/doc/building.html b/doc/building.html index da8465bc532..51ced17fe99 100644 --- a/doc/building.html +++ b/doc/building.html @@ -668,7 +668,7 @@

Microsoft Visual Studio

(Note that this version is often presented as "MSVC 14.28", and reported by cl.exe as 19.28.) Older versions will not be accepted by configure and will not work. The maximum accepted version -of Visual Studio is 2022.

+of Visual Studio is 2026.

If you have multiple versions of Visual Studio installed, configure will by default pick the latest. You can request a specific version to be used by setting diff --git a/doc/building.md b/doc/building.md index 1a9fe6b2e78..11af23d9447 100644 --- a/doc/building.md +++ b/doc/building.md @@ -468,7 +468,7 @@ available for this update. The minimum accepted version is Visual Studio 2019 version 16.8. (Note that this version is often presented as "MSVC 14.28", and reported by cl.exe as 19.28.) Older versions will not be accepted by `configure` and will not work. -The maximum accepted version of Visual Studio is 2022. +The maximum accepted version of Visual Studio is 2026. If you have multiple versions of Visual Studio installed, `configure` will by default pick the latest. You can request a specific version to be used by diff --git a/make/StaticLibs.gmk b/make/StaticLibs.gmk index 3cf2a4dd136..17fd19800e9 100644 --- a/make/StaticLibs.gmk +++ b/make/StaticLibs.gmk @@ -116,6 +116,9 @@ else ifeq ($(call isTargetOs, aix), true) $(eval STATIC_LIB_EXPORT_FILES += $(lib).exp) \ ) STATIC_LIBS := -Wl,-bexpfull $(STATIC_LIB_FILES) $(addprefix -Wl$(COMMA)-bE:, $(STATIC_LIB_EXPORT_FILES)) + ifeq ($(DEBUG_LEVEL), slowdebug) + STATIC_LIBS += -Wl,-bbigtoc + endif else $(error Unsupported platform) endif diff --git a/make/autoconf/basic_tools.m4 b/make/autoconf/basic_tools.m4 index 5815c55c962..0f5691759b6 100644 --- a/make/autoconf/basic_tools.m4 +++ b/make/autoconf/basic_tools.m4 @@ -378,7 +378,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_COMPLEX_TOOLS], # 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 --git a/make/autoconf/boot-jdk.m4 b/make/autoconf/boot-jdk.m4 index feb16c7d179..0015109825b 100644 --- a/make/autoconf/boot-jdk.m4 +++ b/make/autoconf/boot-jdk.m4 @@ -446,6 +446,9 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS], # Force en-US environment UTIL_ADD_JVM_ARG_IF_OK([-Duser.language=en -Duser.country=US],boot_jdk_jvmargs,[$JAVA]) + UTIL_ADD_JVM_ARG_IF_OK([-Xlog:all=off:stdout],boot_jdk_jvmargs,[$JAVA]) + UTIL_ADD_JVM_ARG_IF_OK([-Xlog:all=warning:stderr],boot_jdk_jvmargs,[$JAVA]) + if test "x$BOOTJDK_USE_LOCAL_CDS" = xtrue; then # Use our own CDS archive UTIL_ADD_JVM_ARG_IF_OK([$boot_jdk_cds_args -Xshare:auto],boot_jdk_jvmargs,[$JAVA]) diff --git a/make/autoconf/configure.ac b/make/autoconf/configure.ac index e05b5ae3b90..2e608f893d6 100644 --- a/make/autoconf/configure.ac +++ b/make/autoconf/configure.ac @@ -221,6 +221,9 @@ JDKOPT_SETUP_UNDEFINED_BEHAVIOR_SANITIZER # LeakSanitizer JDKOPT_SETUP_LEAK_SANITIZER +# Setup static analyzer +JDKOPT_SETUP_STATIC_ANALYZER + # Fallback linker # This needs to go before 'LIB_DETERMINE_DEPENDENCIES' JDKOPT_SETUP_FALLBACK_LINKER diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4 index e80d9a98957..3a61840e8c9 100644 --- a/make/autoconf/flags-cflags.m4 +++ b/make/autoconf/flags-cflags.m4 @@ -736,8 +736,15 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_CPU_DEP], $1_CFLAGS_CPU_JVM="${$1_CFLAGS_CPU_JVM} -mminimal-toc" elif test "x$FLAGS_CPU" = xppc64le; then # Little endian machine uses ELFv2 ABI. - # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. - $1_CFLAGS_CPU="-mcpu=power8 -mtune=power10" + # Use Power8 for target cpu, this is the first CPU to support PPC64 LE with ELFv2 ABI. + # Use Power10 for tuning target, this is supported by gcc >= 10 + POWER_TUNE_VERSION="-mtune=power10" + FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [${POWER_TUNE_VERSION}], + IF_FALSE: [ + POWER_TUNE_VERSION="-mtune=power8" + ] + ) + $1_CFLAGS_CPU="-mcpu=power8 ${POWER_TUNE_VERSION}" $1_CFLAGS_CPU_JVM="${$1_CFLAGS_CPU_JVM} -DABI_ELFv2" fi elif test "x$FLAGS_CPU" = xs390x; then @@ -933,7 +940,7 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_CPU_DEP], # ACLE and this flag are required to build the aarch64 SVE related functions in # libvectormath. Apple Silicon does not support SVE; use macOS as a proxy for # that check. - if test "x$OPENJDK_TARGET_CPU" = "xaarch64" && test "x$OPENJDK_TARGET_CPU" = "xlinux"; then + if test "x$OPENJDK_TARGET_CPU" = "xaarch64" && test "x$OPENJDK_TARGET_OS" = "xlinux"; then if test "x$TOOLCHAIN_TYPE" = xgcc || test "x$TOOLCHAIN_TYPE" = xclang; then AC_LANG_PUSH(C) OLD_CFLAGS="$CFLAGS" @@ -947,6 +954,17 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_CPU_DEP], [ AC_MSG_RESULT([yes]) $2SVE_CFLAGS="-march=armv8-a+sve" + # Switching the initialization mode with gcc from 'pattern' to 'zero' + # avoids the use of unsupported `__builtin_clear_padding` for variable + # length aggregates + if test "x$DEBUG_LEVEL" != xrelease && test "x$TOOLCHAIN_TYPE" = xgcc ; then + INIT_ZERO_FLAG="-ftrivial-auto-var-init=zero" + FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [$INIT_ZERO_FLAG], + IF_TRUE: [ + $2SVE_CFLAGS="${$2SVE_CFLAGS} $INIT_ZERO_FLAG" + ] + ) + fi ], [ AC_MSG_RESULT([no]) diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4 index 289ed935fdf..d4299078abf 100644 --- a/make/autoconf/jdk-options.m4 +++ b/make/autoconf/jdk-options.m4 @@ -479,6 +479,31 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_ADDRESS_SANITIZER], AC_SUBST(ASAN_ENABLED) ]) +################################################################################ +# +# Static analyzer +# +AC_DEFUN_ONCE([JDKOPT_SETUP_STATIC_ANALYZER], +[ + UTIL_ARG_ENABLE(NAME: static-analyzer, DEFAULT: false, RESULT: STATIC_ANALYZER_ENABLED, + DESC: [enable the GCC static analyzer], + CHECK_AVAILABLE: [ + AC_MSG_CHECKING([if static analyzer is available]) + if test "x$TOOLCHAIN_TYPE" = "xgcc"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + AVAILABLE=false + fi + ], + IF_ENABLED: [ + STATIC_ANALYZER_CFLAGS="-fanalyzer -Wno-analyzer-fd-leak" + CFLAGS_JDKLIB="$CFLAGS_JDKLIB $STATIC_ANALYZER_CFLAGS" + CFLAGS_JDKEXE="$CFLAGS_JDKEXE $STATIC_ANALYZER_CFLAGS" + ]) + AC_SUBST(STATIC_ANALYZER_ENABLED) +]) + ################################################################################ # # LeakSanitizer diff --git a/make/autoconf/lib-tests.m4 b/make/autoconf/lib-tests.m4 index d2a4fcbb191..23f3d443a6c 100644 --- a/make/autoconf/lib-tests.m4 +++ b/make/autoconf/lib-tests.m4 @@ -28,7 +28,7 @@ ################################################################################ # Minimum supported versions -JTREG_MINIMUM_VERSION=7.5.1 +JTREG_MINIMUM_VERSION=8 GTEST_MINIMUM_VERSION=1.14.0 ################################################################################ diff --git a/make/autoconf/libraries.m4 b/make/autoconf/libraries.m4 index bf697928f1b..8dc3d55ed0c 100644 --- a/make/autoconf/libraries.m4 +++ b/make/autoconf/libraries.m4 @@ -136,12 +136,8 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES], BASIC_JVM_LIBS="$BASIC_JVM_LIBS $LIBPTHREAD" fi - # librt for legacy clock_gettime + # librt - for timers (timer_* functions) if test "x$OPENJDK_TARGET_OS" = xlinux; then - # Hotspot needs to link librt to get the clock_* functions. - # But once our supported minimum build and runtime platform - # has glibc 2.17, this can be removed as the functions are - # in libc. BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lrt" fi diff --git a/make/autoconf/toolchain_microsoft.m4 b/make/autoconf/toolchain_microsoft.m4 index 17ad2666b3a..f577cf1a2a1 100644 --- a/make/autoconf/toolchain_microsoft.m4 +++ b/make/autoconf/toolchain_microsoft.m4 @@ -25,7 +25,7 @@ ################################################################################ # The order of these defines the priority by which we try to find them. -VALID_VS_VERSIONS="2022 2019" +VALID_VS_VERSIONS="2022 2019 2026" VS_DESCRIPTION_2019="Microsoft Visual Studio 2019" VS_VERSION_INTERNAL_2019=142 @@ -57,6 +57,21 @@ VS_SDK_PLATFORM_NAME_2022= VS_SUPPORTED_2022=true VS_TOOLSET_SUPPORTED_2022=true +VS_DESCRIPTION_2026="Microsoft Visual Studio 2026" +VS_VERSION_INTERNAL_2026=145 +VS_MSVCR_2026=vcruntime140.dll +VS_VCRUNTIME_1_2026=vcruntime140_1.dll +VS_MSVCP_2026=msvcp140.dll +VS_ENVVAR_2026="VS180COMNTOOLS" +VS_USE_UCRT_2026="true" +VS_VS_INSTALLDIR_2026="Microsoft Visual Studio/18" +VS_EDITIONS_2026="BuildTools Community Professional Enterprise" +VS_SDK_INSTALLDIR_2026= +VS_VS_PLATFORM_NAME_2026="v145" +VS_SDK_PLATFORM_NAME_2026= +VS_SUPPORTED_2026=true +VS_TOOLSET_SUPPORTED_2026=true + ################################################################################ AC_DEFUN([TOOLCHAIN_CHECK_POSSIBLE_VISUAL_STUDIO_ROOT], diff --git a/make/common/Utils.gmk b/make/common/Utils.gmk index 03009ec3ca4..4868a9f12c0 100644 --- a/make/common/Utils.gmk +++ b/make/common/Utils.gmk @@ -78,7 +78,7 @@ EscapeDollar = $(subst $$,\$$,$(subst \$$,$$,$(strip $1))) ################################################################################ # This macro works just like EscapeDollar above, but for #. -EscapeHash = $(subst \#,\\\#,$(subst \\\#,\#,$(strip $1))) +EscapeHash = $(subst $(HASH),\$(HASH),$(subst \$(HASH),$(HASH),$(strip $1))) ################################################################################ # This macro translates $ into $$ to protect the string from make itself. diff --git a/make/conf/github-actions.conf b/make/conf/github-actions.conf index 27845ffbd7a..438e4b3ce8d 100644 --- a/make/conf/github-actions.conf +++ b/make/conf/github-actions.conf @@ -26,7 +26,7 @@ # Versions and download locations for dependencies used by GitHub Actions (GHA) GTEST_VERSION=1.14.0 -JTREG_VERSION=7.5.1+1 +JTREG_VERSION=8+2 LINUX_X64_BOOT_JDK_EXT=tar.gz LINUX_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_linux-x64_bin.tar.gz diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 9bedc77cc28..4f2bd27d54c 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -1174,9 +1174,9 @@ var getJibProfilesDependencies = function (input, common) { jtreg: { server: "jpg", product: "jtreg", - version: "7.5.1", - build_number: "1", - file: "bundles/jtreg-7.5.1+1.zip", + version: "8", + build_number: "2", + file: "bundles/jtreg-8+2.zip", environment_name: "JT_HOME", environment_path: input.get("jtreg", "home_path") + "/bin", configure_args: "--with-jtreg=" + input.get("jtreg", "home_path"), diff --git a/make/conf/version-numbers.conf b/make/conf/version-numbers.conf index f5ee4e23c8b..f82c7822485 100644 --- a/make/conf/version-numbers.conf +++ b/make/conf/version-numbers.conf @@ -28,15 +28,15 @@ DEFAULT_VERSION_FEATURE=25 DEFAULT_VERSION_INTERIM=0 -DEFAULT_VERSION_UPDATE=0 +DEFAULT_VERSION_UPDATE=3 DEFAULT_VERSION_PATCH=0 DEFAULT_VERSION_EXTRA1=0 DEFAULT_VERSION_EXTRA2=0 DEFAULT_VERSION_EXTRA3=0 -DEFAULT_VERSION_DATE=2025-09-16 +DEFAULT_VERSION_DATE=2026-04-21 DEFAULT_VERSION_CLASSFILE_MAJOR=69 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" DEFAULT_VERSION_CLASSFILE_MINOR=0 DEFAULT_VERSION_DOCS_API_SINCE=11 DEFAULT_ACCEPTABLE_BOOT_VERSIONS="24 25" DEFAULT_JDK_SOURCE_TARGET_VERSION=25 -DEFAULT_PROMOTED_VERSION_PRE= +DEFAULT_PROMOTED_VERSION_PRE=ea diff --git a/make/data/ubsan/ubsan_default_options.c b/make/data/ubsan/ubsan_default_options.c index 05e4722e45a..5615436e39f 100644 --- a/make/data/ubsan/ubsan_default_options.c +++ b/make/data/ubsan/ubsan_default_options.c @@ -62,5 +62,8 @@ // thread so it is easier to track down. You can override these options by setting the environment // variable UBSAN_OPTIONS. ATTRIBUTE_DEFAULT_VISIBILITY ATTRIBUTE_USED const char* __ubsan_default_options() { - return "halt_on_error=1,print_stacktrace=1" _LLVM_SYMBOLIZER(LLVM_SYMBOLIZER); + return "halt_on_error=1," + "handle_segv=0," + "handle_sigbus=0," + "print_stacktrace=1" _LLVM_SYMBOLIZER(LLVM_SYMBOLIZER); } diff --git a/make/hotspot/lib/CompileJvm.gmk b/make/hotspot/lib/CompileJvm.gmk index 6b5edc85b23..f7a7732993a 100644 --- a/make/hotspot/lib/CompileJvm.gmk +++ b/make/hotspot/lib/CompileJvm.gmk @@ -156,6 +156,10 @@ ifeq ($(call isTargetOs, windows), true) WIN_EXPORT_FILE := $(JVM_OUTPUTDIR)/win-exports.def endif + ifeq ($(SHIP_DEBUG_SYMBOLS), public) + CFLAGS_STRIPPED_DEBUGINFO := -DHAS_STRIPPED_DEBUGINFO + endif + JVM_LDFLAGS += -def:$(WIN_EXPORT_FILE) endif @@ -181,6 +185,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJVM, \ CFLAGS := $(JVM_CFLAGS), \ abstract_vm_version.cpp_CXXFLAGS := $(CFLAGS_VM_VERSION), \ arguments.cpp_CXXFLAGS := $(CFLAGS_VM_VERSION), \ + whitebox.cpp_CXXFLAGS := $(CFLAGS_STRIPPED_DEBUGINFO), \ DISABLED_WARNINGS_gcc := $(DISABLED_WARNINGS_gcc), \ DISABLED_WARNINGS_gcc_ad_$(HOTSPOT_TARGET_CPU_ARCH).cpp := nonnull, \ DISABLED_WARNINGS_gcc_bytecodeInterpreter.cpp := unused-label, \ diff --git a/make/ide/vscode/hotspot/CreateVSCodeProject.gmk b/make/ide/vscode/hotspot/CreateVSCodeProject.gmk index 11f25c152f6..9e5671b8250 100644 --- a/make/ide/vscode/hotspot/CreateVSCodeProject.gmk +++ b/make/ide/vscode/hotspot/CreateVSCodeProject.gmk @@ -84,6 +84,8 @@ define CreateFromTemplate $(SED) -e 's!{{TOPDIR}}!$(call SedEscape,$(call FixPath,$(TOPDIR)))!g' \ -e 's!{{TOPDIR_RELATIVE}}!$(call SedEscape,$(call FixPath,$(strip \ $(call RelativePath,$(OUTPUTDIR),$(TOPDIR)))))!g' \ + -e 's!{{TOPDIR_BASE}}!$(notdir $(TOPDIR))!g' \ + -e 's!{{OUTPUT_BASE}}!$(notdir $(OUTPUTDIR))!g' \ -e 's!{{WORKSPACE_ROOT}}!$(call SedEscape,$(call FixPath,$(WORKSPACE_ROOT)))!g' \ -e 's!{{OUTPUTDIR}}!$(call SedEscape,$(call FixPath,$(OUTPUTDIR)))!g' \ -e 's!{{CONF_NAME}}!$(CONF_NAME)!g' \ diff --git a/make/ide/vscode/hotspot/template-workspace.jsonc b/make/ide/vscode/hotspot/template-workspace.jsonc index 30533c7ce84..af62d151b24 100644 --- a/make/ide/vscode/hotspot/template-workspace.jsonc +++ b/make/ide/vscode/hotspot/template-workspace.jsonc @@ -1,12 +1,12 @@ { "folders": [ { - "name": "Source root", + "name": "Source root ({{TOPDIR_BASE}})", "path": "{{TOPDIR}}" }, // {{EXTRA_WORKSPACE_ROOT}} { - "name": "Build artifacts", + "name": "Build artifacts ({{OUTPUT_BASE}})", "path": "{{OUTPUTDIR}}" } ], diff --git a/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java b/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java index d8752bca142..cbef22d91c0 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java @@ -542,10 +542,10 @@ private void handleDateTimeFormatPatterns(String[] patternKeys, Map= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')) { if (count != 0) { - converter.convert(calendarType, lastLetter, count, jrePattern); + converter.convert(calendarType, patternKey, lastLetter, count, jrePattern); lastLetter = 0; count = 0; } @@ -627,7 +627,7 @@ private String translateDateFormatLetters(CalendarType calendarType, String cldr count++; continue; } - converter.convert(calendarType, lastLetter, count, jrePattern); + converter.convert(calendarType, patternKey, lastLetter, count, jrePattern); lastLetter = c; count = 1; } @@ -637,7 +637,7 @@ private String translateDateFormatLetters(CalendarType calendarType, String cldr } if (count != 0) { - converter.convert(calendarType, lastLetter, count, jrePattern); + converter.convert(calendarType, patternKey, lastLetter, count, jrePattern); } if (cldrFormat.contentEquals(jrePattern)) { return cldrFormat; @@ -661,7 +661,7 @@ private String toMetaZoneKey(String tzKey) { * on the support given by the SimpleDateFormat and the j.t.f.DateTimeFormatter * for date-time formatting. */ - private void convertDateTimePatternLetter(CalendarType calendarType, char cldrLetter, int count, StringBuilder sb) { + private void convertDateTimePatternLetter(CalendarType calendarType, String patternKey, char cldrLetter, int count, StringBuilder sb) { switch (cldrLetter) { case 'u': case 'U': @@ -683,7 +683,7 @@ private void convertDateTimePatternLetter(CalendarType calendarType, char cldrLe * Perform a conversion of CLDR date-time format pattern letter which is * specific to the SimpleDateFormat. */ - private void convertSDFLetter(CalendarType calendarType, char cldrLetter, int count, StringBuilder sb) { + private void convertSDFLetter(CalendarType calendarType, String patternKey, char cldrLetter, int count, StringBuilder sb) { switch (cldrLetter) { case 'G': if (calendarType != CalendarType.GREGORIAN) { @@ -722,6 +722,17 @@ private void convertSDFLetter(CalendarType calendarType, char cldrLetter, int co appendN('z', count, sb); break; + case 'y': + // If the style is FULL/LONG for a Japanese Calendar, make the + // count == 4 for Gan-nen + if (calendarType == CalendarType.JAPANESE && + (patternKey.contains("full-") || + patternKey.contains("long-"))) { + count = 4; + } + appendN(cldrLetter, count, sb); + break; + case 'Z': if (count == 4 || count == 5) { sb.append("XXX"); @@ -767,6 +778,7 @@ private void handleSkeletonPatterns(Map myMap, CalendarType cale .collect(Collectors.toMap( e -> calendarPrefix + e.getKey(), e -> translateDateFormatLetters(calendarType, + e.getKey(), (String)e.getValue(), this::convertDateTimePatternLetter) )) @@ -775,7 +787,7 @@ private void handleSkeletonPatterns(Map myMap, CalendarType cale @FunctionalInterface private interface ConvertDateTimeLetters { - void convert(CalendarType calendarType, char cldrLetter, int count, StringBuilder sb); + void convert(CalendarType calendarType, String patternKey, char cldrLetter, int count, StringBuilder sb); } /** diff --git a/make/modules/java.desktop/lib/ClientLibraries.gmk b/make/modules/java.desktop/lib/ClientLibraries.gmk index dcb41defba3..5cb7501b6f4 100644 --- a/make/modules/java.desktop/lib/ClientLibraries.gmk +++ b/make/modules/java.desktop/lib/ClientLibraries.gmk @@ -177,7 +177,8 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false) endif LIBSPLASHSCREEN_CFLAGS += -DSPLASHSCREEN -DPNG_NO_MMX_CODE \ - -DPNG_ARM_NEON_OPT=0 -DPNG_ARM_NEON_IMPLEMENTATION=0 + -DPNG_ARM_NEON_OPT=0 -DPNG_ARM_NEON_IMPLEMENTATION=0 \ + -DPNG_LOONGARCH_LSX_OPT=0 ifeq ($(call isTargetOs, linux)+$(call isTargetCpuArch, ppc), true+true) LIBSPLASHSCREEN_CFLAGS += -DPNG_POWERPC_VSX_OPT=0 @@ -235,7 +236,7 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false) DISABLED_WARNINGS_gcc_dgif_lib.c := sign-compare, \ DISABLED_WARNINGS_gcc_jcmaster.c := implicit-fallthrough, \ DISABLED_WARNINGS_gcc_jdphuff.c := shift-negative-value, \ - DISABLED_WARNINGS_gcc_png.c := maybe-uninitialized unused-function, \ + DISABLED_WARNINGS_gcc_png.c := maybe-uninitialized, \ DISABLED_WARNINGS_gcc_pngerror.c := maybe-uninitialized, \ DISABLED_WARNINGS_gcc_splashscreen_gfx_impl.c := implicit-fallthrough \ maybe-uninitialized, \ @@ -246,7 +247,6 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false) DISABLED_WARNINGS_clang := deprecated-non-prototype, \ DISABLED_WARNINGS_clang_dgif_lib.c := sign-compare, \ DISABLED_WARNINGS_clang_gzwrite.c := format-nonliteral, \ - DISABLED_WARNINGS_clang_png.c := unused-function, \ DISABLED_WARNINGS_clang_splashscreen_impl.c := sign-compare \ unused-but-set-variable unused-function, \ DISABLED_WARNINGS_clang_splashscreen_png.c := \ diff --git a/make/modules/jdk.jpackage/Lib.gmk b/make/modules/jdk.jpackage/Lib.gmk index e9c55548b0d..5b9b6e3fcfe 100644 --- a/make/modules/jdk.jpackage/Lib.gmk +++ b/make/modules/jdk.jpackage/Lib.gmk @@ -68,7 +68,7 @@ $(eval $(call SetupJdkExecutable, BUILD_JPACKAGEAPPLAUNCHER, \ -rpath @executable_path/../PlugIns/, \ LIBS_macosx := -framework Cocoa, \ LIBS_windows := msi.lib ole32.lib shell32.lib shlwapi.lib user32.lib, \ - LIBS_linux := $(LIBDL), \ + LIBS_linux := $(LIBDL) $(LIBPTHREAD), \ MANIFEST := $(JAVA_MANIFEST), \ MANIFEST_VERSION := $(VERSION_NUMBER_FOUR_POSITIONS) \ )) @@ -97,7 +97,7 @@ ifeq ($(call isTargetOs, linux), true) DISABLED_WARNINGS_clang_JvmLauncherLib.c := format-nonliteral, \ DISABLED_WARNINGS_clang_tstrings.cpp := format-nonliteral, \ LD_SET_ORIGIN := false, \ - LIBS_linux := $(LIBDL), \ + LIBS_linux := $(LIBDL) $(LIBPTHREAD), \ )) TARGETS += $(BUILD_LIBJPACKAGEAPPLAUNCHERAUX) diff --git a/make/test/JtregNativeJdk.gmk b/make/test/JtregNativeJdk.gmk index 60a88ca1c9a..00ef4bece58 100644 --- a/make/test/JtregNativeJdk.gmk +++ b/make/test/JtregNativeJdk.gmk @@ -62,7 +62,8 @@ BUILD_JDK_JTREG_LIBRARIES_JDK_LIBS_libGetXSpace := java.base:libjava ifeq ($(call isTargetOs, windows), true) BUILD_JDK_JTREG_EXCLUDE += libDirectIO.c libInheritedChannel.c \ libExplicitAttach.c libImplicitAttach.c \ - exelauncher.c + exelauncher.c \ + libChangeSignalDisposition.c exePrintSignalDisposition.c BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeNullCallerTest := $(LIBCXX) BUILD_JDK_JTREG_EXECUTABLES_LIBS_exerevokeall := advapi32.lib @@ -137,6 +138,7 @@ ifneq ($(filter build-test-jdk-jtreg-native, $(MAKECMDGOALS)), ) OUTPUT_DIR := $(BUILD_JDK_JTREG_OUTPUT_DIR), \ EXCLUDE := $(BUILD_JDK_JTREG_EXCLUDE), \ EXTRA_FILES := $(BUILD_JDK_JTREG_EXTRA_FILES), \ + LIBS := $(LIBPTHREAD), \ )) endif diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index f367362b4d8..6899526a282 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -3454,10 +3454,6 @@ encode %{ __ mov(dst_reg, (uint64_t)1); %} - enc_class aarch64_enc_mov_byte_map_base(iRegP dst, immByteMapBase src) %{ - __ load_byte_map_base($dst$$Register); - %} - enc_class aarch64_enc_mov_n(iRegN dst, immN src) %{ Register dst_reg = as_Register($dst$$reg); address con = (address)$src$$constant; @@ -4554,20 +4550,6 @@ operand immP_1() interface(CONST_INTER); %} -// Card Table Byte Map Base -operand immByteMapBase() -%{ - // Get base of card map - predicate(BarrierSet::barrier_set()->is_a(BarrierSet::CardTableBarrierSet) && - SHENANDOAHGC_ONLY(!BarrierSet::barrier_set()->is_a(BarrierSet::ShenandoahBarrierSet) &&) - (CardTable::CardValue*)n->get_ptr() == ((CardTableBarrierSet*)(BarrierSet::barrier_set()))->card_table()->byte_map_base()); - match(ConP); - - op_cost(0); - format %{ %} - interface(CONST_INTER); -%} - // Float and Double operands // Double Immediate operand immD() @@ -6854,20 +6836,6 @@ instruct loadConP1(iRegPNoSp dst, immP_1 con) ins_pipe(ialu_imm); %} -// Load Byte Map Base Constant - -instruct loadByteMapBase(iRegPNoSp dst, immByteMapBase con) -%{ - match(Set dst con); - - ins_cost(INSN_COST); - format %{ "adr $dst, $con\t# Byte Map Base" %} - - ins_encode(aarch64_enc_mov_byte_map_base(dst, con)); - - ins_pipe(ialu_imm); -%} - // Load Narrow Pointer Constant instruct loadConN(iRegNNoSp dst, immN con) diff --git a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp index a6aab24349a..b1b215a2170 100644 --- a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp @@ -310,7 +310,18 @@ static void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registe __ add(sp, sp, 32 * wordSize); } +#ifdef R18_RESERVED + /* + Do not modify r18_tls when restoring registers if it is a reserved register. On Windows, + for example, r18_tls is used to store the pointer to the current thread's TEB (where TLS + variables are stored). Therefore, modifying r18_tls would corrupt the TEB pointer. + */ + __ pop(RegSet::range(r0, r17), sp); + __ ldp(zr, r19, Address(__ post(sp, 2 * wordSize))); + __ pop(RegSet::range(r20, r29), sp); +#else __ pop(RegSet::range(r0, r29), sp); +#endif } static void restore_live_registers_except_r0(StubAssembler* sasm, bool restore_fpu_registers = true) { @@ -323,8 +334,20 @@ static void restore_live_registers_except_r0(StubAssembler* sasm, bool restore_f __ add(sp, sp, 32 * wordSize); } +#ifdef R18_RESERVED + /* + Do not modify r18_tls when restoring registers if it is a reserved register. On Windows, + for example, r18_tls is used to store the pointer to the current thread's TEB (where TLS + variables are stored). Therefore, modifying r18_tls would corrupt the TEB pointer. + */ + __ ldp(zr, r1, Address(__ post(sp, 2 * wordSize))); + __ pop(RegSet::range(r2, r17), sp); + __ ldp(zr, r19, Address(__ post(sp, 2 * wordSize))); + __ pop(RegSet::range(r20, r29), sp); +#else __ ldp(zr, r1, Address(__ post(sp, 16))); __ pop(RegSet::range(r2, r29), sp); +#endif } diff --git a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp index 869e26d3359..302701e1cad 100644 --- a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp @@ -331,13 +331,7 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Label* slo __ ldr(rscratch2, thread_disarmed_and_epoch_addr); __ cmp(rscratch1, rscratch2); } else { - assert(patching_type == NMethodPatchingType::conc_data_patch, "must be"); - // Subsequent loads of oops must occur after load of guard value. - // BarrierSetNMethod::disarm sets guard with release semantics. - __ membar(__ LoadLoad); - Address thread_disarmed_addr(rthread, in_bytes(bs_nm->thread_disarmed_guard_value_offset())); - __ ldrw(rscratch2, thread_disarmed_addr); - __ cmpw(rscratch1, rscratch2); + ShouldNotReachHere(); } __ br(condition, barrier_target); diff --git a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.hpp index 0d6bfc98a72..fa093a6ef69 100644 --- a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.hpp @@ -39,8 +39,7 @@ class Node; enum class NMethodPatchingType { stw_instruction_and_data_patch, - conc_instruction_and_data_patch, - conc_data_patch + conc_instruction_and_data_patch }; class BarrierSetAssembler: public CHeapObj { diff --git a/src/hotspot/cpu/aarch64/gc/shared/barrierSetNMethod_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shared/barrierSetNMethod_aarch64.cpp index c45611c882b..88c90a548d1 100644 --- a/src/hotspot/cpu/aarch64/gc/shared/barrierSetNMethod_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetNMethod_aarch64.cpp @@ -58,8 +58,6 @@ static int entry_barrier_offset(nmethod* nm) { return -4 * (4 + slow_path_size(nm)); case NMethodPatchingType::conc_instruction_and_data_patch: return -4 * (10 + slow_path_size(nm)); - case NMethodPatchingType::conc_data_patch: - return -4 * (5 + slow_path_size(nm)); } ShouldNotReachHere(); return 0; diff --git a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp index a12d4e2beec..c89847b9d52 100644 --- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp @@ -67,7 +67,7 @@ class ShenandoahBarrierSetAssembler: public BarrierSetAssembler { Register scratch, RegSet saved_regs); public: - virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::conc_data_patch; } + virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::conc_instruction_and_data_patch; } #ifdef COMPILER1 void gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub); diff --git a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp index 276fdd013db..c7ad3e73620 100644 --- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp @@ -1824,3 +1824,14 @@ void InterpreterMacroAssembler::load_method_entry(Register cache, Register index add(cache, cache, Array::base_offset_in_bytes()); lea(cache, Address(cache, index)); } + +#ifdef ASSERT +void InterpreterMacroAssembler::verify_field_offset(Register reg) { + // Verify the field offset is not in the header, implicitly checks for 0 + Label L; + subs(zr, reg, oopDesc::base_offset_in_bytes()); + br(Assembler::GE, L); + stop("bad field offset"); + bind(L); +} +#endif diff --git a/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp b/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp index 447d4f8244e..bbc405e2ea8 100644 --- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp @@ -319,6 +319,8 @@ class InterpreterMacroAssembler: public MacroAssembler { void load_resolved_indy_entry(Register cache, Register index); void load_field_entry(Register cache, Register index, int bcp_offset = 1); void load_method_entry(Register cache, Register index, int bcp_offset = 1); + + void verify_field_offset(Register reg) NOT_DEBUG_RETURN; }; #endif // CPU_AARCH64_INTERP_MASM_AARCH64_HPP diff --git a/src/hotspot/cpu/aarch64/javaFrameAnchor_aarch64.hpp b/src/hotspot/cpu/aarch64/javaFrameAnchor_aarch64.hpp index 8d125d3c027..a6e7d74f528 100644 --- a/src/hotspot/cpu/aarch64/javaFrameAnchor_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/javaFrameAnchor_aarch64.hpp @@ -39,24 +39,22 @@ // 3 - restoring an old state (javaCalls) void clear(void) { + // No hardware barriers are necessary. All members are volatile and the profiler + // is run from a signal handler and only observers the thread its running on. + // clearing _last_Java_sp must be first _last_Java_sp = nullptr; - OrderAccess::release(); _last_Java_fp = nullptr; _last_Java_pc = nullptr; } void copy(JavaFrameAnchor* src) { - // In order to make sure the transition state is valid for "this" + // No hardware barriers are necessary. All members are volatile and the profiler + // is run from a signal handler and only observers the thread its running on. + // We must clear _last_Java_sp before copying the rest of the new data - // - // Hack Alert: Temporary bugfix for 4717480/4721647 - // To act like previous version (pd_cache_state) don't null _last_Java_sp - // unless the value is changing - // if (_last_Java_sp != src->_last_Java_sp) { _last_Java_sp = nullptr; - OrderAccess::release(); } _last_Java_fp = src->_last_Java_fp; _last_Java_pc = src->_last_Java_pc; diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index a277a689280..a424bd7f275 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -639,12 +639,13 @@ void MacroAssembler::set_last_Java_frame(Register last_java_sp, last_java_sp = esp; } - str(last_java_sp, Address(rthread, JavaThread::last_Java_sp_offset())); - // last_java_fp is optional if (last_java_fp->is_valid()) { str(last_java_fp, Address(rthread, JavaThread::last_Java_fp_offset())); } + + // We must set sp last. + str(last_java_sp, Address(rthread, JavaThread::last_Java_sp_offset())); } void MacroAssembler::set_last_Java_frame(Register last_java_sp, diff --git a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp index fcfe153a9a5..cb588adb6c6 100644 --- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp @@ -168,6 +168,7 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, Register temp_reg, bool load_bc_into_bc_reg/*=true*/, int byte_no) { + assert_different_registers(bc_reg, temp_reg); if (!RewriteBytecodes) return; Label L_patch_done; @@ -231,9 +232,12 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, __ stop("patching the wrong bytecode"); __ bind(L_okay); #endif - - // patch bytecode - __ strb(bc_reg, at_bcp(0)); + // Patch bytecode with release store to coordinate with ResolvedFieldEntry loads + // in fast bytecode codelets. load_field_entry has a memory barrier that gains + // the needed ordering, together with control dependency on entering the fast codelet + // itself. + __ lea(temp_reg, at_bcp(0)); + __ stlrb(bc_reg, temp_reg); __ bind(L_patch_done); } @@ -3082,6 +3086,7 @@ void TemplateTable::fast_storefield(TosState state) // R1: field offset, R2: field holder, R5: flags load_resolved_field_entry(r2, r2, noreg, r1, r5); + __ verify_field_offset(r1); { Label notVolatile; @@ -3171,6 +3176,8 @@ void TemplateTable::fast_accessfield(TosState state) __ load_field_entry(r2, r1); __ load_sized_value(r1, Address(r2, in_bytes(ResolvedFieldEntry::field_offset_offset())), sizeof(int), true /*is_signed*/); + __ verify_field_offset(r1); + __ load_unsigned_byte(r3, Address(r2, in_bytes(ResolvedFieldEntry::flags_offset()))); // r0: object @@ -3237,7 +3244,9 @@ void TemplateTable::fast_xaccess(TosState state) __ ldr(r0, aaddress(0)); // access constant pool cache __ load_field_entry(r2, r3, 2); + __ load_sized_value(r1, Address(r2, in_bytes(ResolvedFieldEntry::field_offset_offset())), sizeof(int), true /*is_signed*/); + __ verify_field_offset(r1); // 8179954: We need to make sure that the code generated for // volatile accesses forms a sequentially-consistent set of diff --git a/src/hotspot/cpu/ppc/abstractInterpreter_ppc.cpp b/src/hotspot/cpu/ppc/abstractInterpreter_ppc.cpp index beadce33637..9c74e6f53e7 100644 --- a/src/hotspot/cpu/ppc/abstractInterpreter_ppc.cpp +++ b/src/hotspot/cpu/ppc/abstractInterpreter_ppc.cpp @@ -100,7 +100,7 @@ int AbstractInterpreter::size_activation(int max_stack, // It is also guaranteed to be walkable even though it is in a skeletal state // // is_top_frame == true: -// We're processing the *oldest* interpreter frame! +// We're processing the *youngest* interpreter frame on top of stack! // // pop_frame_extra_args: // If this is != 0 we are returning to a deoptimized frame by popping @@ -131,8 +131,9 @@ void AbstractInterpreter::layout_activation(Method* method, #ifdef ASSERT if (caller->is_interpreted_frame()) { assert(locals_base <= caller->interpreter_frame_expression_stack(), "bad placement"); - const int caller_abi_bytesize = (is_bottom_frame ? frame::top_ijava_frame_abi_size : frame::parent_ijava_frame_abi_size); - intptr_t* l2 = caller->sp() + method->max_locals() - 1 + (caller_abi_bytesize / Interpreter::stackElementSize); + // If the bottom frame's caller was thawed then it has frame::java_abi (aka parent_ijava_frame_abi). + // With an ordinary i2c call it would keep the larger frame::top_ijava_frame_abi + intptr_t* l2 = caller->sp() + method->max_locals() - 1 + (frame::parent_ijava_frame_abi_size / Interpreter::stackElementSize); assert(locals_base >= l2, "bad placement"); } #endif diff --git a/src/hotspot/cpu/ppc/atomicAccess_ppc.hpp b/src/hotspot/cpu/ppc/atomicAccess_ppc.hpp new file mode 100644 index 00000000000..579bfd3cb00 --- /dev/null +++ b/src/hotspot/cpu/ppc/atomicAccess_ppc.hpp @@ -0,0 +1,649 @@ +/* + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025 SAP SE. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_PPC_ATOMICACCESS_PPC_HPP +#define CPU_PPC_ATOMICACCESS_PPC_HPP + +#ifndef PPC64 +#error "Atomic currently only implemented for PPC64" +#endif + +#include "orderAccess_ppc.hpp" +#include "utilities/debug.hpp" + +// Implementation of class AtomicAccess + +// +// machine barrier instructions: +// +// - sync two-way memory barrier, aka fence +// - lwsync orders Store|Store, +// Load|Store, +// Load|Load, +// but not Store|Load +// - eieio orders memory accesses for device memory (only) +// - isync invalidates speculatively executed instructions +// From the POWER ISA 2.06 documentation: +// "[...] an isync instruction prevents the execution of +// instructions following the isync until instructions +// preceding the isync have completed, [...]" +// From IBM's AIX assembler reference: +// "The isync [...] instructions causes the processor to +// refetch any instructions that might have been fetched +// prior to the isync instruction. The instruction isync +// causes the processor to wait for all previous instructions +// to complete. Then any instructions already fetched are +// discarded and instruction processing continues in the +// environment established by the previous instructions." +// +// semantic barrier instructions: +// (as defined in orderAccess.hpp) +// +// - release orders Store|Store, (maps to lwsync) +// Load|Store +// - acquire orders Load|Store, (maps to lwsync) +// Load|Load +// - fence orders Store|Store, (maps to sync) +// Load|Store, +// Load|Load, +// Store|Load +// + +inline void pre_membar(atomic_memory_order order) { + switch (order) { + case memory_order_relaxed: + case memory_order_acquire: break; + case memory_order_release: + case memory_order_acq_rel: __asm__ __volatile__ ("lwsync" : : : "memory"); break; + default /*conservative*/ : __asm__ __volatile__ ("sync" : : : "memory"); break; + } +} + +inline void post_membar(atomic_memory_order order) { + switch (order) { + case memory_order_relaxed: + case memory_order_release: break; + case memory_order_acquire: + case memory_order_acq_rel: __asm__ __volatile__ ("isync" : : : "memory"); break; + default /*conservative*/ : __asm__ __volatile__ ("sync" : : : "memory"); break; + } +} + + + +template +struct Atomic::PlatformAdd { + template + D add_then_fetch(D volatile* dest, I add_value, atomic_memory_order order) const; + + template + D fetch_then_add(D volatile* dest, I add_value, atomic_memory_order order) const { + return add_then_fetch(dest, add_value, order) - add_value; + } +}; + +template<> +template +inline D Atomic::PlatformAdd<4>::add_then_fetch(D volatile* dest, I add_value, + atomic_memory_order order) const { + STATIC_ASSERT(4 == sizeof(I)); + STATIC_ASSERT(4 == sizeof(D)); + + D result; + + pre_membar(order); + + __asm__ __volatile__ ( + "1: lwarx %[result], 0, %[dest] \n" + " add %[result], %[result], %[add_value] \n" + " stwcx. %[result], 0, %[dest] \n" + " bne- 1b \n" + : [result] "=&r" (result) + : [add_value] "r" (add_value), + [dest] "b" (dest) + : "cc", "memory" ); + + post_membar(order); + + return result; +} + + +template<> +template +inline D Atomic::PlatformAdd<8>::add_then_fetch(D volatile* dest, I add_value, + atomic_memory_order order) const { + STATIC_ASSERT(8 == sizeof(I)); + STATIC_ASSERT(8 == sizeof(D)); + + D result; + + pre_membar(order); + + __asm__ __volatile__ ( + "1: ldarx %[result], 0, %[dest] \n" + " add %[result], %[result], %[add_value] \n" + " stdcx. %[result], 0, %[dest] \n" + " bne- 1b \n" + : [result] "=&r" (result) + : [add_value] "r" (add_value), + [dest] "b" (dest) + : "cc", "memory" ); + + post_membar(order); + + return result; +} + +template<> +template +inline T Atomic::PlatformXchg<4>::operator()(T volatile* dest, + T exchange_value, + atomic_memory_order order) const { + STATIC_ASSERT(4 == sizeof(T)); + // Note that xchg doesn't necessarily do an acquire + // (see synchronizer.cpp). + + T old_value; + + pre_membar(order); + + __asm__ __volatile__ ( + /* atomic loop */ + "1: \n" + " lwarx %[old_value], 0, %[dest] \n" + " stwcx. %[exchange_value], 0, %[dest] \n" + " bne- 1b \n" + /* exit */ + "2: \n" + /* out */ + : [old_value] "=&r" (old_value) + /* in */ + : [dest] "b" (dest), + [exchange_value] "r" (exchange_value) + /* clobber */ + : "cc", + "memory" + ); + + post_membar(order); + + return old_value; +} + +template<> +template +inline T Atomic::PlatformXchg<8>::operator()(T volatile* dest, + T exchange_value, + atomic_memory_order order) const { + STATIC_ASSERT(8 == sizeof(T)); + // Note that xchg doesn't necessarily do an acquire + // (see synchronizer.cpp). + + T old_value; + + pre_membar(order); + + __asm__ __volatile__ ( + /* atomic loop */ + "1: \n" + " ldarx %[old_value], 0, %[dest] \n" + " stdcx. %[exchange_value], 0, %[dest] \n" + " bne- 1b \n" + /* exit */ + "2: \n" + /* out */ + : [old_value] "=&r" (old_value) + /* in */ + : [dest] "b" (dest), + [exchange_value] "r" (exchange_value) + /* clobber */ + : "cc", + "memory" + ); + + post_membar(order); + + return old_value; +} + +template<> +template +inline T Atomic::PlatformCmpxchg<1>::operator()(T volatile* dest, + T compare_value, + T exchange_value, + atomic_memory_order order) const { + STATIC_ASSERT(1 == sizeof(T)); + + // Note that cmpxchg guarantees a two-way memory barrier across + // the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not + // specified otherwise (see atomicAccess.hpp). + + const unsigned int masked_compare_val = (unsigned int)(unsigned char)compare_value; + + unsigned int old_value; + + pre_membar(order); + + __asm__ __volatile__ ( + /* simple guard */ + " lbz %[old_value], 0(%[dest]) \n" + " cmpw %[masked_compare_val], %[old_value] \n" + " bne- 2f \n" + /* atomic loop */ + "1: \n" + " lbarx %[old_value], 0, %[dest] \n" + " cmpw %[masked_compare_val], %[old_value] \n" + " bne- 2f \n" + " stbcx. %[exchange_value], 0, %[dest] \n" + " bne- 1b \n" + /* exit */ + "2: \n" + /* out */ + : [old_value] "=&r" (old_value) + /* in */ + : [dest] "b" (dest), + [masked_compare_val] "r" (masked_compare_val), + [exchange_value] "r" (exchange_value) + /* clobber */ + : "cc", + "memory" + ); + + post_membar(order); + + return PrimitiveConversions::cast((unsigned char)old_value); +} + +template<> +template +inline T Atomic::PlatformCmpxchg<4>::operator()(T volatile* dest, + T compare_value, + T exchange_value, + atomic_memory_order order) const { + STATIC_ASSERT(4 == sizeof(T)); + + // Note that cmpxchg guarantees a two-way memory barrier across + // the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not + // specified otherwise (see atomicAccess.hpp). + + T old_value; + + pre_membar(order); + + __asm__ __volatile__ ( + /* simple guard */ + " lwz %[old_value], 0(%[dest]) \n" + " cmpw %[compare_value], %[old_value] \n" + " bne- 2f \n" + /* atomic loop */ + "1: \n" + " lwarx %[old_value], 0, %[dest] \n" + " cmpw %[compare_value], %[old_value] \n" + " bne- 2f \n" + " stwcx. %[exchange_value], 0, %[dest] \n" + " bne- 1b \n" + /* exit */ + "2: \n" + /* out */ + : [old_value] "=&r" (old_value) + /* in */ + : [dest] "b" (dest), + [compare_value] "r" (compare_value), + [exchange_value] "r" (exchange_value) + /* clobber */ + : "cc", + "memory" + ); + + post_membar(order); + + return old_value; +} + +template<> +template +inline T Atomic::PlatformCmpxchg<8>::operator()(T volatile* dest, + T compare_value, + T exchange_value, + atomic_memory_order order) const { + STATIC_ASSERT(8 == sizeof(T)); + + // Note that cmpxchg guarantees a two-way memory barrier across + // the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not + // specified otherwise (see atomicAccess.hpp). + + T old_value; + + pre_membar(order); + + __asm__ __volatile__ ( + /* simple guard */ + " ld %[old_value], 0(%[dest]) \n" + " cmpd %[compare_value], %[old_value] \n" + " bne- 2f \n" + /* atomic loop */ + "1: \n" + " ldarx %[old_value], 0, %[dest] \n" + " cmpd %[compare_value], %[old_value] \n" + " bne- 2f \n" + " stdcx. %[exchange_value], 0, %[dest] \n" + " bne- 1b \n" + /* exit */ + "2: \n" + /* out */ + : [old_value] "=&r" (old_value) + /* in */ + : [dest] "b" (dest), + [compare_value] "r" (compare_value), + [exchange_value] "r" (exchange_value) + /* clobber */ + : "cc", + "memory" + ); + + post_membar(order); + + return old_value; +} + +template +struct Atomic::PlatformOrderedLoad +{ + template + T operator()(const volatile T* p) const { + T t = Atomic::load(p); + // Use twi-isync for load_acquire (faster than lwsync). + __asm__ __volatile__ ("twi 0,%0,0\n isync\n" : : "r" (t) : "memory"); + return t; + } +}; + +template<> +class Atomic::PlatformBitops<4, true> { +public: + template + T fetch_then_and(T volatile* dest, T bits, atomic_memory_order order) const { + STATIC_ASSERT(4 == sizeof(T)); + T old_value, result; + + pre_membar(order); + + __asm__ __volatile__ ( + "1: lwarx %[old_value], 0, %[dest] \n" + " and %[result], %[old_value], %[bits] \n" + " stwcx. %[result], 0, %[dest] \n" + " bne- 1b \n" + : [old_value] "=&r" (old_value), + [result] "=&r" (result) + : [dest] "b" (dest), + [bits] "r" (bits) + : "cc", "memory" ); + + post_membar(order); + return old_value; + } + + template + T fetch_then_or(T volatile* dest, T bits, atomic_memory_order order) const { + STATIC_ASSERT(4 == sizeof(T)); + T old_value, result; + + pre_membar(order); + + __asm__ __volatile__ ( + "1: lwarx %[old_value], 0, %[dest] \n" + " or %[result], %[old_value], %[bits] \n" + " stwcx. %[result], 0, %[dest] \n" + " bne- 1b \n" + : [old_value] "=&r" (old_value), + [result] "=&r" (result) + : [dest] "b" (dest), + [bits] "r" (bits) + : "cc", "memory" ); + + post_membar(order); + return old_value; + } + + template + T fetch_then_xor(T volatile* dest, T bits, atomic_memory_order order) const { + STATIC_ASSERT(4 == sizeof(T)); + T old_value, result; + + pre_membar(order); + + __asm__ __volatile__ ( + "1: lwarx %[old_value], 0, %[dest] \n" + " xor %[result], %[old_value], %[bits] \n" + " stwcx. %[result], 0, %[dest] \n" + " bne- 1b \n" + : [old_value] "=&r" (old_value), + [result] "=&r" (result) + : [dest] "b" (dest), + [bits] "r" (bits) + : "cc", "memory" ); + + post_membar(order); + return old_value; + } + + template + T and_then_fetch(T volatile* dest, T bits, atomic_memory_order order) const { + STATIC_ASSERT(4 == sizeof(T)); + T result; + + pre_membar(order); + + __asm__ __volatile__ ( + "1: lwarx %[result], 0, %[dest] \n" + " and %[result], %[result], %[bits] \n" + " stwcx. %[result], 0, %[dest] \n" + " bne- 1b \n" + : [result] "=&r" (result) + : [dest] "b" (dest), + [bits] "r" (bits) + : "cc", "memory" ); + + post_membar(order); + return result; + } + + template + T or_then_fetch(T volatile* dest, T bits, atomic_memory_order order) const { + STATIC_ASSERT(4 == sizeof(T)); + T result; + + pre_membar(order); + + __asm__ __volatile__ ( + "1: lwarx %[result], 0, %[dest] \n" + " or %[result], %[result], %[bits] \n" + " stwcx. %[result], 0, %[dest] \n" + " bne- 1b \n" + : [result] "=&r" (result) + : [dest] "b" (dest), + [bits] "r" (bits) + : "cc", "memory" ); + + post_membar(order); + return result; + } + + template + T xor_then_fetch(T volatile* dest, T bits, atomic_memory_order order) const { + STATIC_ASSERT(4 == sizeof(T)); + T result; + + pre_membar(order); + + __asm__ __volatile__ ( + "1: lwarx %[result], 0, %[dest] \n" + " xor %[result], %[result], %[bits] \n" + " stwcx. %[result], 0, %[dest] \n" + " bne- 1b \n" + : [result] "=&r" (result) + : [dest] "b" (dest), + [bits] "r" (bits) + : "cc", "memory" ); + + post_membar(order); + return result; + } +}; + +template<> +class Atomic::PlatformBitops<8, true> { +public: + template + T fetch_then_and(T volatile* dest, T bits, atomic_memory_order order) const { + STATIC_ASSERT(8 == sizeof(T)); + T old_value, result; + + pre_membar(order); + + __asm__ __volatile__ ( + "1: ldarx %[old_value], 0, %[dest] \n" + " and %[result], %[old_value], %[bits] \n" + " stdcx. %[result], 0, %[dest] \n" + " bne- 1b \n" + : [old_value] "=&r" (old_value), + [result] "=&r" (result) + : [dest] "b" (dest), + [bits] "r" (bits) + : "cc", "memory" ); + + post_membar(order); + return old_value; + } + + template + T fetch_then_or(T volatile* dest, T bits, atomic_memory_order order) const { + STATIC_ASSERT(8 == sizeof(T)); + T old_value, result; + + pre_membar(order); + + __asm__ __volatile__ ( + "1: ldarx %[old_value], 0, %[dest] \n" + " or %[result], %[old_value], %[bits] \n" + " stdcx. %[result], 0, %[dest] \n" + " bne- 1b \n" + : [old_value] "=&r" (old_value), + [result] "=&r" (result) + : [dest] "b" (dest), + [bits] "r" (bits) + : "cc", "memory" ); + + post_membar(order); + return old_value; + } + + template + T fetch_then_xor(T volatile* dest, T bits, atomic_memory_order order) const { + STATIC_ASSERT(8 == sizeof(T)); + T old_value, result; + + pre_membar(order); + + __asm__ __volatile__ ( + "1: ldarx %[old_value], 0, %[dest] \n" + " xor %[result], %[old_value], %[bits] \n" + " stdcx. %[result], 0, %[dest] \n" + " bne- 1b \n" + : [old_value] "=&r" (old_value), + [result] "=&r" (result) + : [dest] "b" (dest), + [bits] "r" (bits) + : "cc", "memory" ); + + post_membar(order); + return old_value; + } + + template + T and_then_fetch(T volatile* dest, T bits, atomic_memory_order order) const { + STATIC_ASSERT(8 == sizeof(T)); + T result; + + pre_membar(order); + + __asm__ __volatile__ ( + "1: ldarx %[result], 0, %[dest] \n" + " and %[result], %[result], %[bits] \n" + " stdcx. %[result], 0, %[dest] \n" + " bne- 1b \n" + : [result] "=&r" (result) + : [dest] "b" (dest), + [bits] "r" (bits) + : "cc", "memory" ); + + post_membar(order); + return result; + } + + template + T or_then_fetch(T volatile* dest, T bits, atomic_memory_order order) const { + STATIC_ASSERT(8 == sizeof(T)); + T result; + + pre_membar(order); + + __asm__ __volatile__ ( + "1: ldarx %[result], 0, %[dest] \n" + " or %[result], %[result], %[bits] \n" + " stdcx. %[result], 0, %[dest] \n" + " bne- 1b \n" + : [result] "=&r" (result) + : [dest] "b" (dest), + [bits] "r" (bits) + : "cc", "memory" ); + + post_membar(order); + return result; + } + + template + T xor_then_fetch(T volatile* dest, T bits, atomic_memory_order order) const { + STATIC_ASSERT(8 == sizeof(T)); + T result; + + pre_membar(order); + + __asm__ __volatile__ ( + "1: ldarx %[result], 0, %[dest] \n" + " xor %[result], %[result], %[bits] \n" + " stdcx. %[result], 0, %[dest] \n" + " bne- 1b \n" + : [result] "=&r" (result) + : [dest] "b" (dest), + [bits] "r" (bits) + : "cc", "memory" ); + + post_membar(order); + return result; + } +}; +#endif // CPU_PPC_ATOMICACCESS_PPC_HPP diff --git a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp index f48b1bc5f66..390623f48a1 100644 --- a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp @@ -40,8 +40,7 @@ class Node; enum class NMethodPatchingType { stw_instruction_and_data_patch, - conc_instruction_and_data_patch, - conc_data_patch + conc_instruction_and_data_patch }; class BarrierSetAssembler: public CHeapObj { diff --git a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.hpp b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.hpp index 6ee70b4b4ea..b058dcf1a2e 100644 --- a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.hpp @@ -69,7 +69,7 @@ class ShenandoahBarrierSetAssembler: public BarrierSetAssembler { Register preserve); public: - virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::conc_data_patch; } + virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::conc_instruction_and_data_patch; } /* ==== C1 stubs ==== */ #ifdef COMPILER1 diff --git a/src/hotspot/cpu/ppc/interp_masm_ppc.hpp b/src/hotspot/cpu/ppc/interp_masm_ppc.hpp index d3969427db3..9140dd7ca4e 100644 --- a/src/hotspot/cpu/ppc/interp_masm_ppc.hpp +++ b/src/hotspot/cpu/ppc/interp_masm_ppc.hpp @@ -133,8 +133,13 @@ class InterpreterMacroAssembler: public MacroAssembler { void get_cache_index_at_bcp(Register Rdst, int bcp_offset, size_t index_size); void load_resolved_indy_entry(Register cache, Register index); - void load_field_entry(Register cache, Register index, int bcp_offset = 1); - void load_method_entry(Register cache, Register index, int bcp_offset = 1); + void load_field_or_method_entry(bool is_method, Register cache, Register index, int bcp_offset, bool for_fast_bytecode); + void load_field_entry(Register cache, Register index, int bcp_offset = 1, bool for_fast_bytecode = false) { + load_field_or_method_entry(false, cache, index, bcp_offset, for_fast_bytecode); + } + void load_method_entry(Register cache, Register index, int bcp_offset = 1, bool for_fast_bytecode = false) { + load_field_or_method_entry(true, cache, index, bcp_offset, for_fast_bytecode); + } void get_u4(Register Rdst, Register Rsrc, int offset, signedOrNot is_signed); diff --git a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp index 29fb54250c2..4fa7b614aca 100644 --- a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp @@ -468,33 +468,33 @@ void InterpreterMacroAssembler::load_resolved_indy_entry(Register cache, Registe add(cache, cache, index); } -void InterpreterMacroAssembler::load_field_entry(Register cache, Register index, int bcp_offset) { +void InterpreterMacroAssembler::load_field_or_method_entry(bool is_method, Register cache, Register index, int bcp_offset, bool for_fast_bytecode) { + const int entry_size = is_method ? sizeof(ResolvedMethodEntry) : sizeof(ResolvedFieldEntry), + base_offset = is_method ? Array::base_offset_in_bytes() : Array::base_offset_in_bytes(), + entries_offset = is_method ? in_bytes(ConstantPoolCache::method_entries_offset()) : in_bytes(ConstantPoolCache::field_entries_offset()); + // Get index out of bytecode pointer get_cache_index_at_bcp(index, bcp_offset, sizeof(u2)); // Take shortcut if the size is a power of 2 - if (is_power_of_2(sizeof(ResolvedFieldEntry))) { + if (is_power_of_2(entry_size)) { // Scale index by power of 2 - sldi(index, index, log2i_exact(sizeof(ResolvedFieldEntry))); + sldi(index, index, log2i_exact(entry_size)); } else { // Scale the index to be the entry index * sizeof(ResolvedFieldEntry) - mulli(index, index, sizeof(ResolvedFieldEntry)); + mulli(index, index, entry_size); } // Get address of field entries array - ld_ptr(cache, in_bytes(ConstantPoolCache::field_entries_offset()), R27_constPoolCache); - addi(cache, cache, Array::base_offset_in_bytes()); + ld_ptr(cache, entries_offset, R27_constPoolCache); + addi(cache, cache, base_offset); add(cache, cache, index); -} -void InterpreterMacroAssembler::load_method_entry(Register cache, Register index, int bcp_offset) { - // Get index out of bytecode pointer - get_cache_index_at_bcp(index, bcp_offset, sizeof(u2)); - // Scale the index to be the entry index * sizeof(ResolvedMethodEntry) - mulli(index, index, sizeof(ResolvedMethodEntry)); - - // Get address of field entries array - ld_ptr(cache, ConstantPoolCache::method_entries_offset(), R27_constPoolCache); - addi(cache, cache, Array::base_offset_in_bytes()); - add(cache, cache, index); // method_entries + base_offset + scaled index + if (for_fast_bytecode) { + // Prevent speculative loading from ResolvedFieldEntry/ResolvedMethodEntry as it can miss the info written by another thread. + // TemplateTable::patch_bytecode uses release-store. + // We reached here via control dependency (Bytecode dispatch has used the rewritten Bytecode). + // So, we can use control-isync based ordering. + isync(); + } } // Load object from cpool->resolved_references(index). @@ -1266,11 +1266,11 @@ void InterpreterMacroAssembler::verify_method_data_pointer() { lhz(R11_scratch1, in_bytes(DataLayout::bci_offset()), R28_mdx); ld(R12_scratch2, in_bytes(Method::const_offset()), R19_method); addi(R11_scratch1, R11_scratch1, in_bytes(ConstMethod::codes_offset())); - add(R11_scratch1, R12_scratch2, R12_scratch2); + add(R11_scratch1, R11_scratch1, R12_scratch2); cmpd(CR0, R11_scratch1, R14_bcp); beq(CR0, verify_continue); - call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::verify_mdp ), R19_method, R14_bcp, R28_mdx); + call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::verify_mdp), R19_method, R14_bcp, R28_mdx); bind(verify_continue); #endif diff --git a/src/hotspot/cpu/ppc/orderAccess_ppc.hpp b/src/hotspot/cpu/ppc/orderAccess_ppc.hpp new file mode 100644 index 00000000000..f5fa8da755f --- /dev/null +++ b/src/hotspot/cpu/ppc/orderAccess_ppc.hpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025 SAP SE. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_PPC_ORDERACCESS_PPC_HPP +#define CPU_PPC_ORDERACCESS_PPC_HPP + +#ifndef PPC64 +#error "OrderAccess currently only implemented for PPC64" +#endif + +// Compiler version last used for testing: gcc 4.1.2 +// Please update this information when this file changes + +// Implementation of class OrderAccess. + +// +// Machine barrier instructions: +// +// - sync Two-way memory barrier, aka fence. +// - lwsync orders Store|Store, +// Load|Store, +// Load|Load, +// but not Store|Load +// - eieio orders Store|Store +// - isync Invalidates speculatively executed instructions, +// but isync may complete before storage accesses +// associated with instructions preceding isync have +// been performed. +// +// Semantic barrier instructions: +// (as defined in orderAccess.hpp) +// +// - release orders Store|Store, (maps to lwsync) +// Load|Store +// - acquire orders Load|Store, (maps to lwsync) +// Load|Load +// - fence orders Store|Store, (maps to sync) +// Load|Store, +// Load|Load, +// Store|Load +// + +#define inlasm_sync() __asm__ __volatile__ ("sync" : : : "memory"); +#define inlasm_lwsync() __asm__ __volatile__ ("lwsync" : : : "memory"); +#define inlasm_eieio() __asm__ __volatile__ ("eieio" : : : "memory"); +#define inlasm_isync() __asm__ __volatile__ ("isync" : : : "memory"); + +inline void OrderAccess::loadload() { inlasm_lwsync(); } +inline void OrderAccess::storestore() { inlasm_lwsync(); } +inline void OrderAccess::loadstore() { inlasm_lwsync(); } +inline void OrderAccess::storeload() { inlasm_sync(); } + +inline void OrderAccess::acquire() { inlasm_lwsync(); } +inline void OrderAccess::release() { inlasm_lwsync(); } +inline void OrderAccess::fence() { inlasm_sync(); } +inline void OrderAccess::cross_modify_fence_impl() + { inlasm_isync(); } + +#undef inlasm_sync +#undef inlasm_lwsync +#undef inlasm_eieio +#undef inlasm_isync + +#endif // CPU_PPC_ORDERACCESS_PPC_HPP diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 128e566d0f3..a04e397c52b 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -12583,27 +12583,27 @@ instruct countTrailingZerosL_cnttzd(iRegIdst dst, iRegLsrc src) %{ %} // Expand nodes for byte_reverse_int. -instruct insrwi_a(iRegIdst dst, iRegIsrc src, immI16 pos, immI16 shift) %{ - effect(DEF dst, USE src, USE pos, USE shift); +instruct insrwi_a(iRegIdst dst, iRegIsrc src, immI16 n, immI16 b) %{ + effect(DEF dst, USE src, USE n, USE b); predicate(false); - format %{ "INSRWI $dst, $src, $pos, $shift" %} + format %{ "INSRWI $dst, $src, $n, $b" %} size(4); ins_encode %{ - __ insrwi($dst$$Register, $src$$Register, $shift$$constant, $pos$$constant); + __ insrwi($dst$$Register, $src$$Register, $n$$constant, $b$$constant); %} ins_pipe(pipe_class_default); %} // As insrwi_a, but with USE_DEF. -instruct insrwi(iRegIdst dst, iRegIsrc src, immI16 pos, immI16 shift) %{ - effect(USE_DEF dst, USE src, USE pos, USE shift); +instruct insrwi(iRegIdst dst, iRegIsrc src, immI16 n, immI16 b) %{ + effect(USE_DEF dst, USE src, USE n, USE b); predicate(false); - format %{ "INSRWI $dst, $src, $pos, $shift" %} + format %{ "INSRWI $dst, $src, $n, $b" %} size(4); ins_encode %{ - __ insrwi($dst$$Register, $src$$Register, $shift$$constant, $pos$$constant); + __ insrwi($dst$$Register, $src$$Register, $n$$constant, $b$$constant); %} ins_pipe(pipe_class_default); %} @@ -12625,12 +12625,12 @@ instruct bytes_reverse_int_Ex(iRegIdst dst, iRegIsrc src) %{ iRegLdst tmpI3; urShiftI_reg_imm(tmpI1, src, imm24); - insrwi_a(dst, tmpI1, imm24, imm8); + insrwi_a(dst, tmpI1, imm8, imm24); urShiftI_reg_imm(tmpI2, src, imm16); - insrwi(dst, tmpI2, imm8, imm16); + insrwi(dst, tmpI2, imm16, imm8); urShiftI_reg_imm(tmpI3, src, imm8); insrwi(dst, tmpI3, imm8, imm8); - insrwi(dst, src, imm0, imm8); + insrwi(dst, src, imm8, imm0); %} %} @@ -12748,7 +12748,7 @@ instruct bytes_reverse_ushort_Ex(iRegIdst dst, iRegIsrc src) %{ immI16 imm8 %{ (int) 8 %} urShiftI_reg_imm(dst, src, imm8); - insrwi(dst, src, imm16, imm8); + insrwi(dst, src, imm8, imm16); %} %} @@ -12777,7 +12777,7 @@ instruct bytes_reverse_short_Ex(iRegIdst dst, iRegIsrc src) %{ iRegLdst tmpI1; urShiftI_reg_imm(tmpI1, src, imm8); - insrwi(tmpI1, src, imm16, imm8); + insrwi(tmpI1, src, imm8, imm16); extsh(dst, tmpI1); %} %} diff --git a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp index 7431f77aeff..e3a8028f471 100644 --- a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp @@ -148,7 +148,9 @@ void TemplateTable::patch_bytecode(Bytecodes::Code new_bc, Register Rnew_bc, Reg __ bind(L_fast_patch); } - // Patch bytecode. + // Patch bytecode with release store to coordinate with ResolvedFieldEntry + // and ResolvedMethodEntry loads in fast bytecode codelets. + __ release(); __ stb(Rnew_bc, 0, R14_bcp); __ bind(L_patch_done); @@ -312,6 +314,7 @@ void TemplateTable::fast_aldc(LdcType type) { // We are resolved if the resolved reference cache entry contains a // non-null object (CallSite, etc.) __ get_cache_index_at_bcp(R31, 1, index_size); // Load index. + // Only rewritten during link time. So, no need for memory barriers for accessing resolved info. __ load_resolved_reference_at_index(R17_tos, R31, R11_scratch1, R12_scratch2, &is_null); // Convert null sentinel to null @@ -3109,7 +3112,7 @@ void TemplateTable::fast_storefield(TosState state) { const ConditionRegister CR_is_vol = CR2; // Non-volatile condition register (survives runtime call in do_oop_store). // Constant pool already resolved => Load flags and offset of field. - __ load_field_entry(Rcache, Rscratch); + __ load_field_entry(Rcache, Rscratch, 1, /* for_fast_bytecode */ true); jvmti_post_field_mod(Rcache, Rscratch, false /* not static */); load_resolved_field_entry(noreg, Rcache, noreg, Roffset, Rflags, false); // Uses R11, R12 @@ -3190,7 +3193,7 @@ void TemplateTable::fast_accessfield(TosState state) { // R12_scratch2 used by load_field_cp_cache_entry // Constant pool already resolved. Get the field offset. - __ load_field_entry(Rcache, Rscratch); + __ load_field_entry(Rcache, Rscratch, 1, /* for_fast_bytecode */ true); load_resolved_field_entry(noreg, Rcache, noreg, Roffset, Rflags, false); // Uses R11, R12 // JVMTI support @@ -3329,7 +3332,7 @@ void TemplateTable::fast_xaccess(TosState state) { __ ld(Rclass_or_obj, 0, R18_locals); // Constant pool already resolved. Get the field offset. - __ load_field_entry(Rcache, Rscratch, 2); + __ load_field_entry(Rcache, Rscratch, 2, /* for_fast_bytecode */ true); load_resolved_field_entry(noreg, Rcache, noreg, Roffset, Rflags, false); // Uses R11, R12 // JVMTI support not needed, since we switch back to single bytecode as soon as debugger attaches. @@ -3490,7 +3493,7 @@ void TemplateTable::fast_invokevfinal(int byte_no) { assert(byte_no == f2_byte, "use this argument"); Register Rcache = R31; - __ load_method_entry(Rcache, R11_scratch1); + __ load_method_entry(Rcache, R11_scratch1, 1, /* for_fast_bytecode */ true); invokevfinal_helper(Rcache, R11_scratch1, R12_scratch2, R22_tmp2, R23_tmp3); } diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.cpp b/src/hotspot/cpu/ppc/vm_version_ppc.cpp index ec2766ac75b..721364ce412 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp @@ -97,6 +97,10 @@ void VM_Version::initialize() { FLAG_SET_ERGO(TrapBasedRangeChecks, false); } + if (FLAG_IS_DEFAULT(UsePopCountInstruction)) { + FLAG_SET_ERGO(UsePopCountInstruction, true); + } + if (PowerArchitecturePPC64 >= 9) { // Performance is good since Power9. if (FLAG_IS_DEFAULT(SuperwordUseVSX)) { @@ -105,6 +109,10 @@ void VM_Version::initialize() { } MaxVectorSize = SuperwordUseVSX ? 16 : 8; + if (!SuperwordUseVSX && FLAG_IS_DEFAULT(EnableVectorSupport)) { + // VectorSupport intrinsics currently have issues with MaxVectorSize < 16 (JDK-8370803). + FLAG_SET_ERGO(EnableVectorSupport, false); + } if (FLAG_IS_DEFAULT(AlignVector)) { FLAG_SET_ERGO(AlignVector, false); } diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp index 3317ccc3b53..0712b60fb2a 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp @@ -912,6 +912,43 @@ class Assembler : public AbstractAssembler { emit(insn); } + public: + + static uint32_t encode_csrrw(Register Rd, const uint32_t csr, Register Rs1) { + guarantee(is_uimm12(csr), "csr is invalid"); + uint32_t insn = 0; + patch((address)&insn, 6, 0, 0b1110011); + patch((address)&insn, 14, 12, 0b001); + patch_reg((address)&insn, 7, Rd); + patch_reg((address)&insn, 15, Rs1); + patch((address)&insn, 31, 20, csr); + return insn; + } + + static uint32_t encode_jal(Register Rd, const int32_t offset) { + guarantee(is_simm21(offset) && ((offset % 2) == 0), "offset is invalid."); + uint32_t insn = 0; + patch((address)&insn, 6, 0, 0b1101111); + patch_reg((address)&insn, 7, Rd); + patch((address)&insn, 19, 12, (uint32_t)((offset >> 12) & 0xff)); + patch((address)&insn, 20, (uint32_t)((offset >> 11) & 0x1)); + patch((address)&insn, 30, 21, (uint32_t)((offset >> 1) & 0x3ff)); + patch((address)&insn, 31, (uint32_t)((offset >> 20) & 0x1)); + return insn; + } + + static uint32_t encode_jalr(Register Rd, Register Rs, const int32_t offset) { + guarantee(is_simm12(offset), "offset is invalid."); + uint32_t insn = 0; + patch((address)&insn, 6, 0, 0b1100111); + patch_reg((address)&insn, 7, Rd); + patch((address)&insn, 14, 12, 0b000); + patch_reg((address)&insn, 15, Rs); + int32_t val = offset & 0xfff; + patch((address)&insn, 31, 20, val); + return insn; + } + protected: enum barrier { @@ -1988,6 +2025,7 @@ enum VectorMask { // Vector Narrowing Integer Right Shift Instructions INSN(vnsra_wi, 0b1010111, 0b011, 0b101101); + INSN(vnsrl_wi, 0b1010111, 0b011, 0b101100); #undef INSN @@ -3666,19 +3704,15 @@ enum Nf { // -------------------------- // Upper Immediate Instruction // -------------------------- -#define INSN(NAME) \ - void NAME(Register Rd, int32_t imm) { \ - /* lui -> c.lui */ \ - if (do_compress() && (Rd != x0 && Rd != x2 && imm != 0 && is_simm18(imm))) { \ - c_lui(Rd, imm); \ - return; \ - } \ - _lui(Rd, imm); \ + void lui(Register Rd, int32_t imm) { + /* lui -> c.lui */ + if (do_compress() && (Rd != x0 && Rd != x2 && imm != 0 && is_simm18(imm))) { + c_lui(Rd, imm); + return; + } + _lui(Rd, imm); } - INSN(lui); - -#undef INSN // Cache Management Operations // These instruction may be turned off for user space. diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp index 08d35c2831a..30148651818 100644 --- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp @@ -401,7 +401,7 @@ void LIR_Assembler::return_op(LIR_Opr result, C1SafepointPollStub* code_stub) { code_stub->set_safepoint_offset(__ offset()); __ relocate(relocInfo::poll_return_type); - __ safepoint_poll(*code_stub->entry(), true /* at_return */, false /* acquire */, true /* in_nmethod */); + __ safepoint_poll(*code_stub->entry(), true /* at_return */, true /* in_nmethod */); __ ret(); } @@ -1354,6 +1354,7 @@ void LIR_Assembler::align_call(LIR_Code code) { } void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) { + Assembler::IncompressibleScope scope(_masm); address call = __ reloc_call(Address(op->addr(), rtype)); if (call == nullptr) { bailout("reloc call address stub overflow"); @@ -1364,6 +1365,7 @@ void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) { } void LIR_Assembler::ic_call(LIR_OpJavaCall* op) { + Assembler::IncompressibleScope scope(_masm); address call = __ ic_call(op->addr()); if (call == nullptr) { bailout("reloc call address stub overflow"); @@ -1856,6 +1858,10 @@ void LIR_Assembler::leal(LIR_Opr addr, LIR_Opr dest, LIR_PatchCode patch_code, C void LIR_Assembler::rt_call(LIR_Opr result, address dest, const LIR_OprList* args, LIR_Opr tmp, CodeEmitInfo* info) { assert(!tmp->is_valid(), "don't need temporary"); + Assembler::IncompressibleScope scope(_masm); + // Post call nops must be natural aligned due to cmodx rules. + align_call(lir_rtcall); + __ rt_call(dest); if (info != nullptr) { diff --git a/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp index b9ebd49779e..31925f7f263 100644 --- a/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp @@ -772,7 +772,7 @@ void LIRGenerator::do_ArrayCopy(Intrinsic* x) { ciArrayKlass* expected_type = nullptr; arraycopy_helper(x, &flags, &expected_type); if (x->check_flag(Instruction::OmitChecksFlag)) { - flags = 0; + flags = (flags & LIR_OpArrayCopy::get_initial_copy_flags()); } __ arraycopy(src.result(), src_pos.result(), dst.result(), dst_pos.result(), length.result(), tmp, diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp index ce13ebde74f..d8a7fba146b 100644 --- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp @@ -1952,16 +1952,15 @@ void C2_MacroAssembler::arrays_hashcode(Register ary, Register cnt, Register res mv(pow31_3, 29791); // [31^^3] mv(pow31_2, 961); // [31^^2] - slli(chunks_end, chunks, chunks_end_shift); - add(chunks_end, ary, chunks_end); + shadd(chunks_end, chunks, ary, t0, chunks_end_shift); andi(cnt, cnt, stride - 1); // don't forget about tail! bind(WIDE_LOOP); - mulw(result, result, pow31_4); // 31^^4 * h arrays_hashcode_elload(t0, Address(ary, 0 * elsize), eltype); arrays_hashcode_elload(t1, Address(ary, 1 * elsize), eltype); arrays_hashcode_elload(tmp5, Address(ary, 2 * elsize), eltype); arrays_hashcode_elload(tmp6, Address(ary, 3 * elsize), eltype); + mulw(result, result, pow31_4); // 31^^4 * h mulw(t0, t0, pow31_3); // 31^^3 * ary[i+0] addw(result, result, t0); mulw(t1, t1, pow31_2); // 31^^2 * ary[i+1] @@ -1976,8 +1975,7 @@ void C2_MacroAssembler::arrays_hashcode(Register ary, Register cnt, Register res beqz(cnt, DONE); bind(TAIL); - slli(chunks_end, cnt, chunks_end_shift); - add(chunks_end, ary, chunks_end); + shadd(chunks_end, cnt, ary, t0, chunks_end_shift); bind(TAIL_LOOP); arrays_hashcode_elload(t0, Address(ary), eltype); @@ -2393,18 +2391,7 @@ static void float_to_float16_slow_path(C2_MacroAssembler& masm, C2GeneralStub(); __ bind(stub.entry()); - __ fmv_x_w(dst, src); - - // preserve the payloads of non-canonical NaNs. - __ srai(dst, dst, 13); - // preserve the sign bit. - __ srai(tmp, dst, 13); - __ slli(tmp, tmp, 10); - __ mv(t0, 0x3ff); - __ orr(tmp, tmp, t0); - - // get the result by merging sign bit and payloads of preserved non-canonical NaNs. - __ andr(dst, dst, tmp); + __ float_to_float16_NaN(dst, src, t0, tmp); __ j(stub.continuation()); #undef __ @@ -2412,7 +2399,7 @@ static void float_to_float16_slow_path(C2_MacroAssembler& masm, C2GeneralStub(dst, src, xtmp, 130, float_to_float16_slow_path); + auto stub = C2CodeStub::make(dst, src, xtmp, 64, float_to_float16_slow_path); // On riscv, NaN needs a special process as fcvt does not work in that case. @@ -2491,41 +2478,80 @@ static void float_to_float16_v_slow_path(C2_MacroAssembler& masm, #define __ masm. VectorRegister dst = stub.data<0>(); VectorRegister src = stub.data<1>(); - VectorRegister tmp = stub.data<2>(); + VectorRegister vtmp = stub.data<2>(); + assert_different_registers(dst, src, vtmp); + __ bind(stub.entry()); + // Active elements (NaNs) are marked in v0 mask register. // mul is already set to mf2 in float_to_float16_v. - // preserve the payloads of non-canonical NaNs. - __ vnsra_wi(dst, src, 13, Assembler::v0_t); - - // preserve the sign bit. - __ vnsra_wi(tmp, src, 26, Assembler::v0_t); - __ vsll_vi(tmp, tmp, 10, Assembler::v0_t); - __ mv(t0, 0x3ff); - __ vor_vx(tmp, tmp, t0, Assembler::v0_t); - - // get the result by merging sign bit and payloads of preserved non-canonical NaNs. - __ vand_vv(dst, dst, tmp, Assembler::v0_t); + // Float (32 bits) + // Bit: 31 30 to 23 22 to 0 + // +---+------------------+-----------------------------+ + // | S | Exponent | Mantissa (Fraction) | + // +---+------------------+-----------------------------+ + // 1 bit 8 bits 23 bits + // + // Float (16 bits) + // Bit: 15 14 to 10 9 to 0 + // +---+----------------+------------------+ + // | S | Exponent | Mantissa | + // +---+----------------+------------------+ + // 1 bit 5 bits 10 bits + const int fp_sign_bits = 1; + const int fp32_bits = 32; + const int fp32_mantissa_2nd_part_bits = 9; + const int fp32_mantissa_3rd_part_bits = 4; + const int fp16_exponent_bits = 5; + const int fp16_mantissa_bits = 10; + + // preserve the sign bit and exponent, clear mantissa. + __ vnsra_wi(dst, src, fp32_bits - fp_sign_bits - fp16_exponent_bits, Assembler::v0_t); + __ vsll_vi(dst, dst, fp16_mantissa_bits, Assembler::v0_t); + + // Preserve high order bit of float NaN in the + // binary16 result NaN (tenth bit); OR in remaining + // bits into lower 9 bits of binary 16 significand. + // | (doppel & 0x007f_e000) >> 13 // 10 bits + // | (doppel & 0x0000_1ff0) >> 4 // 9 bits + // | (doppel & 0x0000_000f)); // 4 bits + // + // Check j.l.Float.floatToFloat16 for more information. + // 10 bits + __ vnsrl_wi(vtmp, src, fp32_mantissa_2nd_part_bits + fp32_mantissa_3rd_part_bits, Assembler::v0_t); + __ mv(t0, 0x3ff); // retain first part of mantissa in a float 32 + __ vand_vx(vtmp, vtmp, t0, Assembler::v0_t); + __ vor_vv(dst, dst, vtmp, Assembler::v0_t); + // 9 bits + __ vnsrl_wi(vtmp, src, fp32_mantissa_3rd_part_bits, Assembler::v0_t); + __ mv(t0, 0x1ff); // retain second part of mantissa in a float 32 + __ vand_vx(vtmp, vtmp, t0, Assembler::v0_t); + __ vor_vv(dst, dst, vtmp, Assembler::v0_t); + // 4 bits + // Narrow shift is necessary to move data from 32 bits element to 16 bits element in vector register. + __ vnsrl_wi(vtmp, src, 0, Assembler::v0_t); + __ vand_vi(vtmp, vtmp, 0xf, Assembler::v0_t); + __ vor_vv(dst, dst, vtmp, Assembler::v0_t); __ j(stub.continuation()); #undef __ } // j.l.Float.float16ToFloat -void C2_MacroAssembler::float_to_float16_v(VectorRegister dst, VectorRegister src, VectorRegister vtmp, - Register tmp, uint vector_length) { +void C2_MacroAssembler::float_to_float16_v(VectorRegister dst, VectorRegister src, + VectorRegister vtmp, Register tmp, uint vector_length) { assert_different_registers(dst, src, vtmp); auto stub = C2CodeStub::make - (dst, src, vtmp, 28, float_to_float16_v_slow_path); + (dst, src, vtmp, 56, float_to_float16_v_slow_path); // On riscv, NaN needs a special process as vfncvt_f_f_w does not work in that case. vsetvli_helper(BasicType::T_FLOAT, vector_length, Assembler::m1); // check whether there is a NaN. - // replace v_fclass with vmseq_vv as performance optimization. + // replace v_fclass with vmfne_vv as performance optimization. vmfne_vv(v0, src, src); vcpop_m(t0, v0); diff --git a/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp b/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp index d1278c419a0..cc685645ec5 100644 --- a/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp +++ b/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp @@ -287,7 +287,7 @@ void DowncallLinker::StubGenerator::generate() { __ membar(MacroAssembler::AnyAny); } - __ safepoint_poll(L_safepoint_poll_slow_path, true /* at_return */, true /* acquire */, false /* in_nmethod */); + __ safepoint_poll(L_safepoint_poll_slow_path, true /* at_return */, false /* in_nmethod */); __ lwu(t0, Address(xthread, JavaThread::suspend_flags_offset())); __ bnez(t0, L_safepoint_poll_slow_path); diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp index 7e9bea381a5..387db778c1f 100644 --- a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp @@ -241,10 +241,6 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Label* slo __ lwu(t0, *guard); switch (patching_type) { - case NMethodPatchingType::conc_data_patch: - // Subsequent loads of oops must occur after load of guard value. - // BarrierSetNMethod::disarm sets guard with release semantics. - __ membar(MacroAssembler::LoadLoad); // fall through to stw_instruction_and_data_patch case NMethodPatchingType::stw_instruction_and_data_patch: { // With STW patching, no data or instructions are updated concurrently, diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.hpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.hpp index 7061dca738c..63a7032bb84 100644 --- a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.hpp @@ -40,8 +40,7 @@ class Node; enum class NMethodPatchingType { stw_instruction_and_data_patch, - conc_instruction_and_data_patch, - conc_data_patch + conc_instruction_and_data_patch }; class BarrierSetAssembler: public CHeapObj { diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp index f24e4f789bc..ac619f83f7d 100644 --- a/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp +++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp @@ -50,8 +50,6 @@ static int entry_barrier_offset(nmethod* nm) { switch (bs_asm->nmethod_patching_type()) { case NMethodPatchingType::stw_instruction_and_data_patch: return -4 * (4 + slow_path_size(nm)); - case NMethodPatchingType::conc_data_patch: - return -4 * (5 + slow_path_size(nm)); case NMethodPatchingType::conc_instruction_and_data_patch: return -4 * (15 + slow_path_size(nm)); } diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp index 7d12cc8cbb6..3fe7c8d1740 100644 --- a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp @@ -69,7 +69,7 @@ class ShenandoahBarrierSetAssembler: public BarrierSetAssembler { public: - virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::conc_data_patch; } + virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::conc_instruction_and_data_patch; } #ifdef COMPILER1 void gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub); diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp index fae34a9c770..eececc93393 100644 --- a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp +++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp @@ -645,7 +645,7 @@ void InterpreterMacroAssembler::remove_activation(TosState state, // the stack, will call InterpreterRuntime::at_unwind. Label slow_path; Label fast_path; - safepoint_poll(slow_path, true /* at_return */, false /* acquire */, false /* in_nmethod */); + safepoint_poll(slow_path, true /* at_return */, false /* in_nmethod */); j(fast_path); bind(slow_path); @@ -1937,6 +1937,15 @@ void InterpreterMacroAssembler::load_method_entry(Register cache, Register index } #ifdef ASSERT +void InterpreterMacroAssembler::verify_field_offset(Register reg) { + // Verify the field offset is not in the header, implicitly checks for 0 + Label L; + mv(t0, oopDesc::base_offset_in_bytes()); + bge(reg, t0, L); + stop("bad field offset"); + bind(L); +} + void InterpreterMacroAssembler::verify_access_flags(Register access_flags, uint32_t flag, const char* msg, bool stop_by_hit) { Label L; diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.hpp b/src/hotspot/cpu/riscv/interp_masm_riscv.hpp index 891db16b243..13e77b1a359 100644 --- a/src/hotspot/cpu/riscv/interp_masm_riscv.hpp +++ b/src/hotspot/cpu/riscv/interp_masm_riscv.hpp @@ -300,6 +300,8 @@ class InterpreterMacroAssembler: public MacroAssembler { void load_field_entry(Register cache, Register index, int bcp_offset = 1); void load_method_entry(Register cache, Register index, int bcp_offset = 1); + void verify_field_offset(Register reg) NOT_DEBUG_RETURN; + #ifdef ASSERT void verify_access_flags(Register access_flags, uint32_t flag, const char* msg, bool stop_by_hit = true); diff --git a/src/hotspot/cpu/riscv/javaFrameAnchor_riscv.hpp b/src/hotspot/cpu/riscv/javaFrameAnchor_riscv.hpp index 1293fae0c0b..6bf1230914a 100644 --- a/src/hotspot/cpu/riscv/javaFrameAnchor_riscv.hpp +++ b/src/hotspot/cpu/riscv/javaFrameAnchor_riscv.hpp @@ -39,25 +39,23 @@ // 3 - restoring an old state (javaCalls) void clear(void) { + // No hardware barriers are necessary. All members are volatile and the profiler + // is run from a signal handler and the only observer is the thread its running on. + // clearing _last_Java_sp must be first _last_Java_sp = nullptr; - OrderAccess::release(); _last_Java_fp = nullptr; _last_Java_pc = nullptr; } void copy(JavaFrameAnchor* src) { - // In order to make sure the transition state is valid for "this" + // No hardware barriers are necessary. All members are volatile and the profiler + // is run from a signal handler and the only observer is the thread its running on. + // We must clear _last_Java_sp before copying the rest of the new data - // - // Hack Alert: Temporary bugfix for 4717480/4721647 - // To act like previous version (pd_cache_state) don't null _last_Java_sp - // unless the value is changing - // assert(src != nullptr, "Src should not be null."); if (_last_Java_sp != src->_last_Java_sp) { _last_Java_sp = nullptr; - OrderAccess::release(); } _last_Java_fp = src->_last_Java_fp; _last_Java_pc = src->_last_Java_pc; diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index 55894916527..4e3d30c4081 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -97,52 +97,52 @@ bool MacroAssembler::is_pc_relative_at(address instr) { // auipc + load // auipc + fload_load return (is_auipc_at(instr)) && - (is_addi_at(instr + instruction_size) || - is_jalr_at(instr + instruction_size) || - is_load_at(instr + instruction_size) || - is_float_load_at(instr + instruction_size)) && + (is_addi_at(instr + MacroAssembler::instruction_size) || + is_jalr_at(instr + MacroAssembler::instruction_size) || + is_load_at(instr + MacroAssembler::instruction_size) || + is_float_load_at(instr + MacroAssembler::instruction_size)) && check_pc_relative_data_dependency(instr); } // ie:ld(Rd, Label) bool MacroAssembler::is_load_pc_relative_at(address instr) { return is_auipc_at(instr) && // auipc - is_ld_at(instr + instruction_size) && // ld + is_ld_at(instr + MacroAssembler::instruction_size) && // ld check_load_pc_relative_data_dependency(instr); } bool MacroAssembler::is_movptr1_at(address instr) { return is_lui_at(instr) && // Lui - is_addi_at(instr + instruction_size) && // Addi - is_slli_shift_at(instr + instruction_size * 2, 11) && // Slli Rd, Rs, 11 - is_addi_at(instr + instruction_size * 3) && // Addi - is_slli_shift_at(instr + instruction_size * 4, 6) && // Slli Rd, Rs, 6 - (is_addi_at(instr + instruction_size * 5) || - is_jalr_at(instr + instruction_size * 5) || - is_load_at(instr + instruction_size * 5)) && // Addi/Jalr/Load + is_addi_at(instr + MacroAssembler::instruction_size) && // Addi + is_slli_shift_at(instr + MacroAssembler::instruction_size * 2, 11) && // Slli Rd, Rs, 11 + is_addi_at(instr + MacroAssembler::instruction_size * 3) && // Addi + is_slli_shift_at(instr + MacroAssembler::instruction_size * 4, 6) && // Slli Rd, Rs, 6 + (is_addi_at(instr + MacroAssembler::instruction_size * 5) || + is_jalr_at(instr + MacroAssembler::instruction_size * 5) || + is_load_at(instr + MacroAssembler::instruction_size * 5)) && // Addi/Jalr/Load check_movptr1_data_dependency(instr); } bool MacroAssembler::is_movptr2_at(address instr) { return is_lui_at(instr) && // lui - is_lui_at(instr + instruction_size) && // lui - is_slli_shift_at(instr + instruction_size * 2, 18) && // slli Rd, Rs, 18 - is_add_at(instr + instruction_size * 3) && - (is_addi_at(instr + instruction_size * 4) || - is_jalr_at(instr + instruction_size * 4) || - is_load_at(instr + instruction_size * 4)) && // Addi/Jalr/Load + is_lui_at(instr + MacroAssembler::instruction_size) && // lui + is_slli_shift_at(instr + MacroAssembler::instruction_size * 2, 18) && // slli Rd, Rs, 18 + is_add_at(instr + MacroAssembler::instruction_size * 3) && + (is_addi_at(instr + MacroAssembler::instruction_size * 4) || + is_jalr_at(instr + MacroAssembler::instruction_size * 4) || + is_load_at(instr + MacroAssembler::instruction_size * 4)) && // Addi/Jalr/Load check_movptr2_data_dependency(instr); } bool MacroAssembler::is_li16u_at(address instr) { return is_lui_at(instr) && // lui - is_srli_at(instr + instruction_size) && // srli + is_srli_at(instr + MacroAssembler::instruction_size) && // srli check_li16u_data_dependency(instr); } bool MacroAssembler::is_li32_at(address instr) { return is_lui_at(instr) && // lui - is_addiw_at(instr + instruction_size) && // addiw + is_addiw_at(instr + MacroAssembler::instruction_size) && // addiw check_li32_data_dependency(instr); } @@ -355,14 +355,15 @@ void MacroAssembler::call_VM(Register oop_result, } void MacroAssembler::post_call_nop() { + assert(!in_compressible_scope(), "Must be"); + assert_alignment(pc()); if (!Continuations::enabled()) { return; } - relocate(post_call_nop_Relocation::spec(), [&] { - InlineSkippedInstructionsCounter skipCounter(this); - nop(); - li32(zr, 0); - }); + relocate(post_call_nop_Relocation::spec()); + InlineSkippedInstructionsCounter skipCounter(this); + nop(); + li32(zr, 0); } // these are no-ops overridden by InterpreterMacroAssembler @@ -389,12 +390,14 @@ void MacroAssembler::set_last_Java_frame(Register last_java_sp, last_java_sp = esp; } - sd(last_java_sp, Address(xthread, JavaThread::last_Java_sp_offset())); - // last_java_fp is optional if (last_java_fp->is_valid()) { sd(last_java_fp, Address(xthread, JavaThread::last_Java_fp_offset())); } + + // We must set sp last. + sd(last_java_sp, Address(xthread, JavaThread::last_Java_sp_offset())); + } void MacroAssembler::set_last_Java_frame(Register last_java_sp, @@ -3402,6 +3405,8 @@ void MacroAssembler::decode_klass_not_null(Register r, Register tmp) { void MacroAssembler::decode_klass_not_null(Register dst, Register src, Register tmp) { assert(UseCompressedClassPointers, "should only be used for compressed headers"); + assert_different_registers(dst, tmp); + assert_different_registers(src, tmp); if (CompressedKlassPointers::base() == nullptr) { if (CompressedKlassPointers::shift() != 0) { @@ -3412,18 +3417,13 @@ void MacroAssembler::decode_klass_not_null(Register dst, Register src, Register return; } - Register xbase = dst; - if (dst == src) { - xbase = tmp; - } + Register xbase = tmp; - assert_different_registers(src, xbase); mv(xbase, (uintptr_t)CompressedKlassPointers::base()); if (CompressedKlassPointers::shift() != 0) { - Register t = src == dst ? dst : t0; - assert_different_registers(t, xbase); - shadd(dst, src, xbase, t, CompressedKlassPointers::shift()); + // dst = (src << shift) + xbase + shadd(dst, src, xbase, dst /* temporary, dst != xbase */, CompressedKlassPointers::shift()); } else { add(dst, xbase, src); } @@ -3773,11 +3773,8 @@ void MacroAssembler::check_klass_subtype(Register sub_klass, bind(L_failure); } -void MacroAssembler::safepoint_poll(Label& slow_path, bool at_return, bool acquire, bool in_nmethod, Register tmp_reg) { +void MacroAssembler::safepoint_poll(Label& slow_path, bool at_return, bool in_nmethod, Register tmp_reg) { ld(tmp_reg, Address(xthread, JavaThread::polling_word_offset())); - if (acquire) { - membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); - } if (at_return) { bgtu(in_nmethod ? sp : fp, tmp_reg, slow_path, /* is_far */ true); } else { @@ -5019,7 +5016,7 @@ address MacroAssembler::reloc_call(Address entry, Register tmp) { address MacroAssembler::ic_call(address entry, jint method_index) { RelocationHolder rh = virtual_call_Relocation::spec(pc(), method_index); - IncompressibleScope scope(this); // relocations + assert(!in_compressible_scope(), "Must be"); movptr(t0, (address)Universe::non_oop_word(), t1); assert_cond(entry != nullptr); return reloc_call(Address(entry, rh)); @@ -5113,7 +5110,7 @@ address MacroAssembler::emit_reloc_call_address_stub(int insts_call_instruction_ int MacroAssembler::max_reloc_call_address_stub_size() { // Max stub size: alignment nop, target address. - return 1 * instruction_size + wordSize; + return 1 * MacroAssembler::instruction_size + wordSize; } int MacroAssembler::static_call_stub_size() { @@ -5344,42 +5341,6 @@ void MacroAssembler::add2_with_carry(Register final_dest_hi, Register dest_hi, R add(final_dest_hi, dest_hi, carry); } -/** - * Multiply 32 bit by 32 bit first loop. - */ -void MacroAssembler::multiply_32_x_32_loop(Register x, Register xstart, Register x_xstart, - Register y, Register y_idx, Register z, - Register carry, Register product, - Register idx, Register kdx) { - // jlong carry, x[], y[], z[]; - // for (int idx=ystart, kdx=ystart+1+xstart; idx >= 0; idx--, kdx--) { - // long product = y[idx] * x[xstart] + carry; - // z[kdx] = (int)product; - // carry = product >>> 32; - // } - // z[xstart] = (int)carry; - - Label L_first_loop, L_first_loop_exit; - blez(idx, L_first_loop_exit); - - shadd(t0, xstart, x, t0, LogBytesPerInt); - lwu(x_xstart, Address(t0, 0)); - - bind(L_first_loop); - subiw(idx, idx, 1); - shadd(t0, idx, y, t0, LogBytesPerInt); - lwu(y_idx, Address(t0, 0)); - mul(product, x_xstart, y_idx); - add(product, product, carry); - srli(carry, product, 32); - subiw(kdx, kdx, 1); - shadd(t0, kdx, z, t0, LogBytesPerInt); - sw(product, Address(t0, 0)); - bgtz(idx, L_first_loop); - - bind(L_first_loop_exit); -} - /** * Multiply 64 bit by 64 bit first loop. */ @@ -5596,77 +5557,16 @@ void MacroAssembler::multiply_to_len(Register x, Register xlen, Register y, Regi const Register carry = tmp5; const Register product = xlen; const Register x_xstart = tmp0; + const Register jdx = tmp1; mv(idx, ylen); // idx = ylen; addw(kdx, xlen, ylen); // kdx = xlen+ylen; mv(carry, zr); // carry = 0; - Label L_multiply_64_x_64_loop, L_done; - + Label L_done; subiw(xstart, xlen, 1); bltz(xstart, L_done); - const Register jdx = tmp1; - - if (AvoidUnalignedAccesses) { - int base_offset = arrayOopDesc::base_offset_in_bytes(T_INT); - assert((base_offset % (UseCompactObjectHeaders ? 4 : - (UseCompressedClassPointers ? 8 : 4))) == 0, "Must be"); - - if ((base_offset % 8) == 0) { - // multiply_64_x_64_loop emits 8-byte load/store to access two elements - // at a time from int arrays x and y. When base_offset is 8 bytes, these - // accesses are naturally aligned if both xlen and ylen are even numbers. - orr(t0, xlen, ylen); - test_bit(t0, t0, 0); - beqz(t0, L_multiply_64_x_64_loop); - } - - Label L_second_loop_unaligned, L_third_loop, L_third_loop_exit; - - multiply_32_x_32_loop(x, xstart, x_xstart, y, y_idx, z, carry, product, idx, kdx); - shadd(t0, xstart, z, t0, LogBytesPerInt); - sw(carry, Address(t0, 0)); - - bind(L_second_loop_unaligned); - mv(carry, zr); - mv(jdx, ylen); - subiw(xstart, xstart, 1); - bltz(xstart, L_done); - - subi(sp, sp, 2 * wordSize); - sd(z, Address(sp, 0)); - sd(zr, Address(sp, wordSize)); - shadd(t0, xstart, z, t0, LogBytesPerInt); - addi(z, t0, 4); - shadd(t0, xstart, x, t0, LogBytesPerInt); - lwu(product, Address(t0, 0)); - - blez(jdx, L_third_loop_exit); - - bind(L_third_loop); - subiw(jdx, jdx, 1); - shadd(t0, jdx, y, t0, LogBytesPerInt); - lwu(t0, Address(t0, 0)); - mul(t1, t0, product); - add(t0, t1, carry); - shadd(tmp6, jdx, z, t1, LogBytesPerInt); - lwu(t1, Address(tmp6, 0)); - add(t0, t0, t1); - sw(t0, Address(tmp6, 0)); - srli(carry, t0, 32); - bgtz(jdx, L_third_loop); - - bind(L_third_loop_exit); - ld(z, Address(sp, 0)); - addi(sp, sp, 2 * wordSize); - shadd(t0, xstart, z, t0, LogBytesPerInt); - sw(carry, Address(t0, 0)); - - j(L_second_loop_unaligned); - } - - bind(L_multiply_64_x_64_loop); multiply_64_x_64_loop(x, xstart, x_xstart, y, y_idx, z, carry, product, idx, kdx); Label L_second_loop_aligned; @@ -5974,13 +5874,14 @@ void MacroAssembler::fill_words(Register base, Register cnt, Register value) { // in cnt. // // NOTE: This is intended to be used in the zero_blocks() stub. If -// you want to use it elsewhere, note that cnt must be >= CacheLineSize. +// you want to use it elsewhere, note that cnt must be >= zicboz_block_size. void MacroAssembler::zero_dcache_blocks(Register base, Register cnt, Register tmp1, Register tmp2) { + int zicboz_block_size = VM_Version::zicboz_block_size.value(); Label initial_table_end, loop; // Align base with cache line size. neg(tmp1, base); - andi(tmp1, tmp1, CacheLineSize - 1); + andi(tmp1, tmp1, zicboz_block_size - 1); // tmp1: the number of bytes to be filled to align the base with cache line size. add(base, base, tmp1); @@ -5990,16 +5891,16 @@ void MacroAssembler::zero_dcache_blocks(Register base, Register cnt, Register tm la(tmp1, initial_table_end); sub(tmp2, tmp1, tmp2); jr(tmp2); - for (int i = -CacheLineSize + wordSize; i < 0; i += wordSize) { + for (int i = -zicboz_block_size + wordSize; i < 0; i += wordSize) { sd(zr, Address(base, i)); } bind(initial_table_end); - mv(tmp1, CacheLineSize / wordSize); + mv(tmp1, zicboz_block_size / wordSize); bind(loop); cbo_zero(base); sub(cnt, cnt, tmp1); - addi(base, base, CacheLineSize); + addi(base, base, zicboz_block_size); bge(cnt, tmp1, loop); } @@ -6054,6 +5955,62 @@ void MacroAssembler::java_round_double(Register dst, FloatRegister src, FloatReg bind(done); } +// Helper routine processing the slow path of NaN when converting float to float16 +void MacroAssembler::float_to_float16_NaN(Register dst, FloatRegister src, + Register tmp1, Register tmp2) { + fmv_x_w(dst, src); + + // Float (32 bits) + // Bit: 31 30 to 23 22 to 0 + // +---+------------------+-----------------------------+ + // | S | Exponent | Mantissa (Fraction) | + // +---+------------------+-----------------------------+ + // 1 bit 8 bits 23 bits + // + // Float (16 bits) + // Bit: 15 14 to 10 9 to 0 + // +---+----------------+------------------+ + // | S | Exponent | Mantissa | + // +---+----------------+------------------+ + // 1 bit 5 bits 10 bits + const int fp_sign_bits = 1; + const int fp32_bits = 32; + const int fp32_exponent_bits = 8; + const int fp32_mantissa_1st_part_bits = 10; + const int fp32_mantissa_2nd_part_bits = 9; + const int fp32_mantissa_3rd_part_bits = 4; + const int fp16_exponent_bits = 5; + const int fp16_mantissa_bits = 10; + + // preserve the sign bit and exponent, clear mantissa. + srai(tmp2, dst, fp32_bits - fp_sign_bits - fp16_exponent_bits); + slli(tmp2, tmp2, fp16_mantissa_bits); + + // Preserve high order bit of float NaN in the + // binary16 result NaN (tenth bit); OR in remaining + // bits into lower 9 bits of binary 16 significand. + // | (doppel & 0x007f_e000) >> 13 // 10 bits + // | (doppel & 0x0000_1ff0) >> 4 // 9 bits + // | (doppel & 0x0000_000f)); // 4 bits + // + // Check j.l.Float.floatToFloat16 for more information. + // 10 bits + int left_shift = fp_sign_bits + fp32_exponent_bits + 32; + int right_shift = left_shift + fp32_mantissa_2nd_part_bits + fp32_mantissa_3rd_part_bits; + slli(tmp1, dst, left_shift); + srli(tmp1, tmp1, right_shift); + orr(tmp2, tmp2, tmp1); + // 9 bits + left_shift += fp32_mantissa_1st_part_bits; + right_shift = left_shift + fp32_mantissa_3rd_part_bits; + slli(tmp1, dst, left_shift); + srli(tmp1, tmp1, right_shift); + orr(tmp2, tmp2, tmp1); + // 4 bits + andi(tmp1, dst, 0xf); + orr(dst, tmp2, tmp1); +} + #define FCVT_SAFE(FLOATCVT, FLOATSIG) \ void MacroAssembler::FLOATCVT##_safe(Register dst, FloatRegister src, Register tmp) { \ Label done; \ diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp index 6276663762a..13b70d5dbd7 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -44,7 +44,7 @@ class MacroAssembler: public Assembler { MacroAssembler(CodeBuffer* code) : Assembler(code) {} - void safepoint_poll(Label& slow_path, bool at_return, bool acquire, bool in_nmethod, Register tmp_reg = t0); + void safepoint_poll(Label& slow_path, bool at_return, bool in_nmethod, Register tmp_reg = t0); // Alignment int align(int modulus, int extra_offset = 0); @@ -1240,7 +1240,7 @@ class MacroAssembler: public Assembler { void far_jump(const Address &entry, Register tmp = t1); static int far_branch_size() { - return 2 * 4; // auipc + jalr, see far_call() & far_jump() + return 2 * MacroAssembler::instruction_size; // auipc + jalr, see far_call() & far_jump() } void load_byte_map_base(Register reg); @@ -1384,10 +1384,6 @@ class MacroAssembler: public Assembler { void adc(Register dst, Register src1, Register src2, Register carry); void add2_with_carry(Register final_dest_hi, Register dest_hi, Register dest_lo, Register src1, Register src2, Register carry); - void multiply_32_x_32_loop(Register x, Register xstart, Register x_xstart, - Register y, Register y_idx, Register z, - Register carry, Register product, - Register idx, Register kdx); void multiply_64_x_64_loop(Register x, Register xstart, Register x_xstart, Register y, Register y_idx, Register z, Register carry, Register product, @@ -1435,6 +1431,9 @@ class MacroAssembler: public Assembler { void java_round_float(Register dst, FloatRegister src, FloatRegister ftmp); void java_round_double(Register dst, FloatRegister src, FloatRegister ftmp); + // Helper routine processing the slow path of NaN when converting float to float16 + void float_to_float16_NaN(Register dst, FloatRegister src, Register tmp1, Register tmp2); + // vector load/store unit-stride instructions void vlex_v(VectorRegister vd, Register base, Assembler::SEW sew, VectorMask vm = unmasked) { switch (sew) { @@ -1648,9 +1647,9 @@ class MacroAssembler: public Assembler { public: enum { // movptr - movptr1_instruction_size = 6 * instruction_size, // lui, addi, slli, addi, slli, addi. See movptr1(). - movptr2_instruction_size = 5 * instruction_size, // lui, lui, slli, add, addi. See movptr2(). - load_pc_relative_instruction_size = 2 * instruction_size // auipc, ld + movptr1_instruction_size = 6 * MacroAssembler::instruction_size, // lui, addi, slli, addi, slli, addi. See movptr1(). + movptr2_instruction_size = 5 * MacroAssembler::instruction_size, // lui, lui, slli, add, addi. See movptr2(). + load_pc_relative_instruction_size = 2 * MacroAssembler::instruction_size // auipc, ld }; static bool is_load_pc_relative_at(address branch); @@ -1705,11 +1704,11 @@ class MacroAssembler: public Assembler { // addi/jalr/load static bool check_movptr1_data_dependency(address instr) { address lui = instr; - address addi1 = lui + instruction_size; - address slli1 = addi1 + instruction_size; - address addi2 = slli1 + instruction_size; - address slli2 = addi2 + instruction_size; - address last_instr = slli2 + instruction_size; + address addi1 = lui + MacroAssembler::instruction_size; + address slli1 = addi1 + MacroAssembler::instruction_size; + address addi2 = slli1 + MacroAssembler::instruction_size; + address slli2 = addi2 + MacroAssembler::instruction_size; + address last_instr = slli2 + MacroAssembler::instruction_size; return extract_rs1(addi1) == extract_rd(lui) && extract_rs1(addi1) == extract_rd(addi1) && extract_rs1(slli1) == extract_rd(addi1) && @@ -1729,10 +1728,10 @@ class MacroAssembler: public Assembler { // addi/jalr/load static bool check_movptr2_data_dependency(address instr) { address lui1 = instr; - address lui2 = lui1 + instruction_size; - address slli = lui2 + instruction_size; - address add = slli + instruction_size; - address last_instr = add + instruction_size; + address lui2 = lui1 + MacroAssembler::instruction_size; + address slli = lui2 + MacroAssembler::instruction_size; + address add = slli + MacroAssembler::instruction_size; + address last_instr = add + MacroAssembler::instruction_size; return extract_rd(add) == extract_rd(lui2) && extract_rs1(add) == extract_rd(lui2) && extract_rs2(add) == extract_rd(slli) && @@ -1746,7 +1745,7 @@ class MacroAssembler: public Assembler { // srli static bool check_li16u_data_dependency(address instr) { address lui = instr; - address srli = lui + instruction_size; + address srli = lui + MacroAssembler::instruction_size; return extract_rs1(srli) == extract_rd(lui) && extract_rs1(srli) == extract_rd(srli); @@ -1757,7 +1756,7 @@ class MacroAssembler: public Assembler { // addiw static bool check_li32_data_dependency(address instr) { address lui = instr; - address addiw = lui + instruction_size; + address addiw = lui + MacroAssembler::instruction_size; return extract_rs1(addiw) == extract_rd(lui) && extract_rs1(addiw) == extract_rd(addiw); @@ -1768,7 +1767,7 @@ class MacroAssembler: public Assembler { // jalr/addi/load/float_load static bool check_pc_relative_data_dependency(address instr) { address auipc = instr; - address last_instr = auipc + instruction_size; + address last_instr = auipc + MacroAssembler::instruction_size; return extract_rs1(last_instr) == extract_rd(auipc); } @@ -1778,7 +1777,7 @@ class MacroAssembler: public Assembler { // load static bool check_load_pc_relative_data_dependency(address instr) { address auipc = instr; - address load = auipc + instruction_size; + address load = auipc + MacroAssembler::instruction_size; return extract_rd(load) == extract_rd(auipc) && extract_rs1(load) == extract_rd(load); diff --git a/src/hotspot/cpu/riscv/methodHandles_riscv.cpp b/src/hotspot/cpu/riscv/methodHandles_riscv.cpp index 39b6737631d..d770999df96 100644 --- a/src/hotspot/cpu/riscv/methodHandles_riscv.cpp +++ b/src/hotspot/cpu/riscv/methodHandles_riscv.cpp @@ -93,14 +93,60 @@ void MethodHandles::verify_klass(MacroAssembler* _masm, void MethodHandles::verify_ref_kind(MacroAssembler* _masm, int ref_kind, Register member_reg, Register temp) {} +void MethodHandles::verify_method(MacroAssembler* _masm, Register method, vmIntrinsics::ID iid) { + BLOCK_COMMENT("verify_method {"); + __ verify_method_ptr(method); + if (VerifyMethodHandles) { + Label L_ok; + assert_different_registers(method, t0, t1); + const Register method_holder = t1; + __ load_method_holder(method_holder, method); + + switch (iid) { + case vmIntrinsicID::_invokeBasic: + // Require compiled LambdaForm class to be fully initialized. + __ lbu(t0, Address(method_holder, InstanceKlass::init_state_offset())); + __ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); + __ mv(t1, InstanceKlass::fully_initialized); + __ beq(t0, t1, L_ok); + break; + case vmIntrinsicID::_linkToStatic: + __ clinit_barrier(method_holder, t0, &L_ok); + break; + + case vmIntrinsicID::_linkToVirtual: + case vmIntrinsicID::_linkToSpecial: + case vmIntrinsicID::_linkToInterface: + // Class initialization check is too strong here. Just ensure that class initialization has been initiated. + __ lbu(t0, Address(method_holder, InstanceKlass::init_state_offset())); + __ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); + __ mv(t1, InstanceKlass::being_initialized); + __ bge(t0, t1, L_ok); + + // init_state check failed, but it may be an abstract interface method + __ lhu(t0, Address(method, Method::access_flags_offset())); + __ test_bit(t1, t0, exact_log2(JVM_ACC_ABSTRACT)); + __ bnez(t1, L_ok); + break; + + default: + fatal("unexpected intrinsic %d: %s", vmIntrinsics::as_int(iid), vmIntrinsics::name_at(iid)); + } + + // Method holder init state check failed for a concrete method. + __ stop("Method holder klass is not initialized"); + __ BIND(L_ok); + } + BLOCK_COMMENT("} verify_method"); +} #endif //ASSERT void MethodHandles::jump_from_method_handle(MacroAssembler* _masm, Register method, Register temp, - bool for_compiler_entry) { + bool for_compiler_entry, vmIntrinsics::ID iid) { assert(method == xmethod, "interpreter calling convention"); Label L_no_such_method; __ beqz(xmethod, L_no_such_method); - __ verify_method_ptr(method); + verify_method(_masm, method, iid); if (!for_compiler_entry && JvmtiExport::can_post_interpreter_events()) { Label run_compiled_code; @@ -158,7 +204,7 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm, __ BIND(L); } - jump_from_method_handle(_masm, method_temp, temp2, for_compiler_entry); + jump_from_method_handle(_masm, method_temp, temp2, for_compiler_entry, vmIntrinsics::_invokeBasic); BLOCK_COMMENT("} jump_to_lambda_form"); } @@ -437,8 +483,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, // After figuring out which concrete method to call, jump into it. // Note that this works in the interpreter with no data motion. // But the compiled version will require that r2_recv be shifted out. - __ verify_method_ptr(xmethod); - jump_from_method_handle(_masm, xmethod, temp1, for_compiler_entry); + jump_from_method_handle(_masm, xmethod, temp1, for_compiler_entry, iid); if (iid == vmIntrinsics::_linkToInterface) { __ bind(L_incompatible_class_change_error); __ far_jump(RuntimeAddress(SharedRuntime::throw_IncompatibleClassChangeError_entry())); diff --git a/src/hotspot/cpu/riscv/methodHandles_riscv.hpp b/src/hotspot/cpu/riscv/methodHandles_riscv.hpp index 6017b26c66d..ffc3b3ab676 100644 --- a/src/hotspot/cpu/riscv/methodHandles_riscv.hpp +++ b/src/hotspot/cpu/riscv/methodHandles_riscv.hpp @@ -39,6 +39,8 @@ enum /* platform_dependent_constants */ { Register obj, vmClassID klass_id, const char* error_message = "wrong klass") NOT_DEBUG_RETURN; + static void verify_method(MacroAssembler* _masm, Register method, vmIntrinsics::ID iid) NOT_DEBUG_RETURN; + static void verify_method_handle(MacroAssembler* _masm, Register mh_reg) { verify_klass(_masm, mh_reg, VM_CLASS_ID(java_lang_invoke_MethodHandle), "reference is a MH"); @@ -49,7 +51,7 @@ enum /* platform_dependent_constants */ { // Similar to InterpreterMacroAssembler::jump_from_interpreted. // Takes care of special dispatch from single stepping too. static void jump_from_method_handle(MacroAssembler* _masm, Register method, Register temp, - bool for_compiler_entry); + bool for_compiler_entry, vmIntrinsics::ID iid); static void jump_to_lambda_form(MacroAssembler* _masm, Register recv, Register method_temp, diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp index 31947b520d0..50076d7c8ce 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp @@ -33,6 +33,7 @@ #include "runtime/safepoint.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" +#include "utilities/align.hpp" #include "utilities/ostream.hpp" #ifdef COMPILER1 #include "c1/c1_Runtime1.hpp" @@ -46,128 +47,111 @@ bool NativeInstruction::is_call_at(address addr) { } //----------------------------------------------------------------------------- -// NativeFarCall -// -// Implements direct far calling loading an address from the stub section version of reloc call. - -class NativeFarCall: public NativeInstruction { - public: - enum RISCV_specific_constants { - return_address_offset = 3 * NativeInstruction::instruction_size, // auipc + ld + jalr - }; - - address instruction_address() const { return addr_at(0); } - address next_instruction_address() const { return addr_at(return_address_offset); } - address return_address() const { return addr_at(return_address_offset); } - address destination() const; - address reloc_destination(address orig_address); - - void set_destination(address dest); - void verify(); - void print(); - - bool set_destination_mt_safe(address dest, bool assert_lock = true); - bool reloc_set_destination(address dest); - - private: - address stub_address(); - - static void set_stub_address_destination_at(address dest, address value); - static address stub_address_destination_at(address src); - public: - - static NativeFarCall* at(address addr); - static bool is_at(address addr); - static bool is_call_before(address return_address); -}; +// NativeCall -address NativeFarCall::destination() const { +address NativeCall::destination() const { address addr = instruction_address(); - assert(NativeFarCall::is_at(addr), "unexpected code at call site"); + assert(NativeCall::is_at(addr), "unexpected code at call site"); - address destination = MacroAssembler::target_addr_for_insn(addr); + address stub_addr = MacroAssembler::target_addr_for_insn(addr); CodeBlob* cb = CodeCache::find_blob(addr); - assert(cb && cb->is_nmethod(), "sanity"); + assert(cb != nullptr && cb->is_nmethod(), "nmethod expected"); nmethod *nm = (nmethod *)cb; - assert(nm != nullptr, "Sanity"); - assert(nm->stub_contains(destination), "Sanity"); - assert(destination != nullptr, "Sanity"); - return stub_address_destination_at(destination); + assert(nm->stub_contains(stub_addr), "Sanity"); + assert(stub_addr != nullptr, "Sanity"); + + return stub_address_destination_at(stub_addr); } -address NativeFarCall::reloc_destination(address orig_address) { +address NativeCall::reloc_destination() { address call_addr = instruction_address(); + assert(NativeCall::is_at(call_addr), "unexpected code at call site"); CodeBlob *code = CodeCache::find_blob(call_addr); assert(code != nullptr, "Could not find the containing code blob"); address stub_addr = nullptr; - if (code != nullptr && code->is_nmethod()) { - stub_addr = trampoline_stub_Relocation::get_trampoline_for(call_addr, (nmethod*)code); + if (code->is_nmethod()) { + // TODO: Need to revisit this when porting the AOT features. + stub_addr = trampoline_stub_Relocation::get_trampoline_for(call_addr, code->as_nmethod()); + assert(stub_addr != nullptr, "Sanity"); } - if (stub_addr != nullptr) { - stub_addr = MacroAssembler::target_addr_for_insn(call_addr); - } return stub_addr; } -void NativeFarCall::set_destination(address dest) { - address addr = instruction_address(); - assert(NativeFarCall::is_at(addr), "unexpected code at call site"); - Unimplemented(); -} - -void NativeFarCall::verify() { - assert(NativeFarCall::is_at(instruction_address()), "unexpected code at call site"); +void NativeCall::verify() { + assert(NativeCall::is_at(instruction_address()), "unexpected code at call site"); } -void NativeFarCall::print() { - assert(NativeFarCall::is_at(instruction_address()), "unexpected code at call site"); - tty->print_cr(PTR_FORMAT ": auipc,ld,jalr x1, offset/reg, ", p2i(addr_at(0))); +void NativeCall::print() { + assert(NativeCall::is_at(instruction_address()), "unexpected code at call site"); + tty->print_cr(PTR_FORMAT ": auipc,ld,jalr x1, offset/reg, ", p2i(instruction_address())); +} + +void NativeCall::optimize_call(address dest, bool mt_safe) { + // Skip over auipc + ld + address jmp_ins_pc = instruction_address() + 2 * NativeInstruction::instruction_size; + // Rutime calls may be unaligned, but they are never changed after relocation. + assert(!mt_safe || is_aligned(jmp_ins_pc, NativeInstruction::instruction_size), "Must be naturally aligned: %p", jmp_ins_pc); + // If reachable use JAL + if (Assembler::reachable_from_branch_at(jmp_ins_pc, dest)) { + int64_t distance = dest - jmp_ins_pc; + uint32_t new_jal = Assembler::encode_jal(ra, distance); + Atomic::store((uint32_t *)jmp_ins_pc, new_jal); + } else if (!MacroAssembler::is_jalr_at(jmp_ins_pc)) { // The jalr is always identical: jalr ra, 0(t1) + uint32_t new_jalr = Assembler::encode_jalr(ra, t1, 0); + Atomic::store((uint32_t *)jmp_ins_pc, new_jalr); + } else { + // No change to instruction stream + return; + } + // We changed instruction stream + if (mt_safe) { + // IC invalidate provides a leading full fence, it thus happens after we changed the instruction stream. + ICache::invalidate_range(jmp_ins_pc, NativeInstruction::instruction_size); + } } -bool NativeFarCall::set_destination_mt_safe(address dest, bool assert_lock) { - assert(NativeFarCall::is_at(addr_at(0)), "unexpected code at call site"); - assert(!assert_lock || - (CodeCache_lock->is_locked() || SafepointSynchronize::is_at_safepoint()) || - CompiledICLocker::is_safe(addr_at(0)), +bool NativeCall::set_destination_mt_safe(address dest) { + assert(NativeCall::is_at(instruction_address()), "unexpected code at call site"); + assert((CodeCache_lock->is_locked() || SafepointSynchronize::is_at_safepoint()) || + CompiledICLocker::is_safe(instruction_address()), "concurrent code patching"); - address call_addr = addr_at(0); - assert(NativeFarCall::is_at(call_addr), "unexpected code at call site"); - address stub_addr = stub_address(); + assert(stub_addr != nullptr, "No stub?"); + set_stub_address_destination_at(stub_addr, dest); // release + // optimize_call happens after we stored new address in addr stub. + // patches jalr -> jal/jal -> jalr depending on dest + optimize_call(dest, true); - if (stub_addr != nullptr) { - set_stub_address_destination_at(stub_addr, dest); - return true; - } - - return false; + return true; } -bool NativeFarCall::reloc_set_destination(address dest) { - address call_addr = addr_at(0); - assert(NativeFarCall::is_at(call_addr), "unexpected code at call site"); +// The argument passed in is the address to the stub containing the destination +bool NativeCall::reloc_set_destination(address stub_addr) { + address call_addr = instruction_address(); + assert(NativeCall::is_at(call_addr), "unexpected code at call site"); CodeBlob *code = CodeCache::find_blob(call_addr); assert(code != nullptr, "Could not find the containing code blob"); - address stub_addr = nullptr; - if (code != nullptr && code->is_nmethod()) { - stub_addr = trampoline_stub_Relocation::get_trampoline_for(call_addr, (nmethod*)code); - } + if (code->is_nmethod()) { + // TODO: Need to revisit this when porting the AOT features. + assert(stub_addr != nullptr, "Sanity"); + assert(stub_addr == trampoline_stub_Relocation::get_trampoline_for(call_addr, code->as_nmethod()), "Sanity"); + MacroAssembler::pd_patch_instruction_size(call_addr, stub_addr); // patches auipc + ld to stub_addr - if (stub_addr != nullptr) { - MacroAssembler::pd_patch_instruction_size(call_addr, stub_addr); + address dest = stub_address_destination_at(stub_addr); + optimize_call(dest, false); // patches jalr -> jal/jal -> jalr depending on dest } return true; } -void NativeFarCall::set_stub_address_destination_at(address dest, address value) { +void NativeCall::set_stub_address_destination_at(address dest, address value) { assert_cond(dest != nullptr); assert_cond(value != nullptr); @@ -175,31 +159,24 @@ void NativeFarCall::set_stub_address_destination_at(address dest, address value) OrderAccess::release(); } -address NativeFarCall::stub_address_destination_at(address src) { +address NativeCall::stub_address_destination_at(address src) { assert_cond(src != nullptr); address dest = (address)get_data64_at(src); return dest; } -address NativeFarCall::stub_address() { - address call_addr = addr_at(0); +address NativeCall::stub_address() { + address call_addr = instruction_address(); CodeBlob *code = CodeCache::find_blob(call_addr); assert(code != nullptr, "Could not find the containing code blob"); - address dest = MacroAssembler::pd_call_destination(call_addr); - assert(code->contains(dest), "Sanity"); - return dest; -} - -NativeFarCall* NativeFarCall::at(address addr) { - assert_cond(addr != nullptr); - assert(NativeFarCall::is_at(addr), "unexpected code at call site: %p", addr); - NativeFarCall* call = (NativeFarCall*)(addr); - return call; + address stub_addr = MacroAssembler::target_addr_for_insn(call_addr); + assert(code->contains(stub_addr), "Sanity"); + return stub_addr; } -bool NativeFarCall::is_at(address addr) { +bool NativeCall::is_at(address addr) { assert_cond(addr != nullptr); const int instr_size = NativeInstruction::instruction_size; if (MacroAssembler::is_auipc_at(addr) && @@ -209,65 +186,23 @@ bool NativeFarCall::is_at(address addr) { (MacroAssembler::extract_rd(addr + instr_size) == x6) && (MacroAssembler::extract_rs1(addr + instr_size) == x6) && (MacroAssembler::extract_rs1(addr + 2 * instr_size) == x6) && - (MacroAssembler::extract_rd(addr + 2 * instr_size) == x1)) { + (MacroAssembler::extract_rd(addr + 2 * instr_size) == x1)) { + return true; + } + if (MacroAssembler::is_auipc_at(addr) && + MacroAssembler::is_ld_at(addr + instr_size) && + MacroAssembler::is_jal_at(addr + 2 * instr_size) && + (MacroAssembler::extract_rd(addr) == x6) && + (MacroAssembler::extract_rd(addr + instr_size) == x6) && + (MacroAssembler::extract_rs1(addr + instr_size) == x6) && + (MacroAssembler::extract_rd(addr + 2 * instr_size) == x1)) { return true; } return false; } -bool NativeFarCall::is_call_before(address return_address) { - return NativeFarCall::is_at(return_address - return_address_offset); -} - -//----------------------------------------------------------------------------- -// NativeCall - -address NativeCall::instruction_address() const { - return NativeFarCall::at(addr_at(0))->instruction_address(); -} - -address NativeCall::next_instruction_address() const { - return NativeFarCall::at(addr_at(0))->next_instruction_address(); -} - -address NativeCall::return_address() const { - return NativeFarCall::at(addr_at(0))->return_address(); -} - -address NativeCall::destination() const { - return NativeFarCall::at(addr_at(0))->destination(); -} - -address NativeCall::reloc_destination(address orig_address) { - return NativeFarCall::at(addr_at(0))->reloc_destination(orig_address); -} - -void NativeCall::set_destination(address dest) { - NativeFarCall::at(addr_at(0))->set_destination(dest); -} - -void NativeCall::verify() { - NativeFarCall::at(addr_at(0))->verify();; -} - -void NativeCall::print() { - NativeFarCall::at(addr_at(0))->print();; -} - -bool NativeCall::set_destination_mt_safe(address dest, bool assert_lock) { - return NativeFarCall::at(addr_at(0))->set_destination_mt_safe(dest, assert_lock); -} - -bool NativeCall::reloc_set_destination(address dest) { - return NativeFarCall::at(addr_at(0))->reloc_set_destination(dest); -} - -bool NativeCall::is_at(address addr) { - return NativeFarCall::is_at(addr); -} - bool NativeCall::is_call_before(address return_address) { - return NativeFarCall::is_call_before(return_address); + return NativeCall::is_at(return_address - NativeCall::instruction_size); } NativeCall* nativeCall_at(address addr) { @@ -280,7 +215,7 @@ NativeCall* nativeCall_at(address addr) { NativeCall* nativeCall_before(address return_address) { assert_cond(return_address != nullptr); NativeCall* call = nullptr; - call = (NativeCall*)(return_address - NativeFarCall::return_address_offset); + call = (NativeCall*)(return_address - NativeCall::instruction_size); DEBUG_ONLY(call->verify()); return call; } @@ -339,19 +274,6 @@ void NativeMovConstReg::print() { p2i(instruction_address()), data()); } -//------------------------------------------------------------------- - -int NativeMovRegMem::offset() const { - Unimplemented(); - return 0; -} - -void NativeMovRegMem::set_offset(int x) { Unimplemented(); } - -void NativeMovRegMem::verify() { - Unimplemented(); -} - //-------------------------------------------------------------------------------- void NativeJump::verify() { } @@ -432,7 +354,9 @@ void NativeIllegalInstruction::insert(address code_pos) { } bool NativeInstruction::is_stop() { - return uint_at(0) == 0xc0101073; // an illegal instruction, 'csrrw x0, time, x0' + // an illegal instruction, 'csrrw x0, time, x0' + uint32_t encoded = Assembler::encode_csrrw(x0, Assembler::time, x0); + return uint_at(0) == encoded; } //------------------------------------------------------------------- @@ -481,6 +405,8 @@ void NativeGeneralJump::insert_unconditional(address code_pos, address entry) { MacroAssembler a(&cb); Assembler::IncompressibleScope scope(&a); // Fixed length: see NativeGeneralJump::get_instruction_size() + MacroAssembler::assert_alignment(code_pos); + int32_t offset = 0; a.movptr(t1, entry, offset, t0); // lui, lui, slli, add a.jr(t1, offset); // jalr @@ -512,6 +438,7 @@ bool NativePostCallNop::decode(int32_t& oopmap_slot, int32_t& cb_offset) const { } bool NativePostCallNop::patch(int32_t oopmap_slot, int32_t cb_offset) { + MacroAssembler::assert_alignment(addr_at(4)); if (((oopmap_slot & 0xff) != oopmap_slot) || ((cb_offset & 0xffffff) != cb_offset)) { return false; // cannot encode } @@ -523,14 +450,17 @@ bool NativePostCallNop::patch(int32_t oopmap_slot, int32_t cb_offset) { return true; // successfully encoded } -void NativeDeoptInstruction::verify() { +bool NativeDeoptInstruction::is_deopt_at(address instr) { + assert(instr != nullptr, "Must be"); + uint32_t value = Assembler::ld_instr(instr); + uint32_t encoded = Assembler::encode_csrrw(x0, Assembler::instret, x0); + return value == encoded; } // Inserts an undefined instruction at a given pc void NativeDeoptInstruction::insert(address code_pos) { - // 0xc0201073 encodes CSRRW x0, instret, x0 - uint32_t insn = 0xc0201073; - uint32_t *pos = (uint32_t *) code_pos; - *pos = insn; + MacroAssembler::assert_alignment(code_pos); + uint32_t encoded = Assembler::encode_csrrw(x0, Assembler::instret, x0); + Assembler::sd_instr(code_pos, encoded); ICache::invalidate_range(code_pos, 4); } diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp index d8f5fa57816..a50f14d7923 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp @@ -37,7 +37,7 @@ // - NativeInstruction // - - NativeCall // - - NativeMovConstReg -// - - NativeMovRegMem +// - - NativeMovRegMem - Unimplemented // - - NativeJump // - - NativeGeneralJump // - - NativeIllegalInstruction @@ -94,7 +94,6 @@ class NativeInstruction { static uint64_t get_data64_at(address src) { return Bytes::get_native_u8(src); } public: - inline friend NativeInstruction* nativeInstruction_at(address addr); static bool maybe_cpool_ref(address instr) { @@ -112,6 +111,7 @@ NativeCall* nativeCall_before(address return_address); // The NativeCall is an abstraction for accessing/manipulating native // call instructions (used to manipulate inline caches, primitive & // DSO calls, etc.). +// NativeCall is reloc call on RISC-V. See MacroAssembler::reloc_call. class NativeCall: private NativeInstruction { // private: when common code is using byte_size() private: @@ -119,34 +119,48 @@ class NativeCall: private NativeInstruction { // Use byte_size() as it can be changed in runtime // Since instruction_size exists on NativeInstruction we need // to overload and hide it. - instruction_size = 3 * Assembler::instruction_size // auipc + ld + jalr + instruction_size = 3 * NativeInstruction::instruction_size // auipc + ld + jalr }; - public: + public: static int byte_size() { - return 3 * NativeInstruction::instruction_size; // auipc + ld + jalr + return NativeCall::instruction_size; // auipc + ld + jalr } // Creation friend NativeCall* nativeCall_at(address addr); friend NativeCall* nativeCall_before(address return_address); - address instruction_address() const; - address next_instruction_address() const; - address return_address() const; + address instruction_address() const { return addr_at(0); } + address next_instruction_address() const { return addr_at(NativeCall::instruction_size); } + address return_address() const { return addr_at(NativeCall::instruction_size); } address destination() const; - address reloc_destination(address orig_address); + address reloc_destination(); void verify_alignment() {} // do nothing on riscv void verify(); void print(); - void set_destination(address dest); - bool set_destination_mt_safe(address dest, bool assert_lock = true); + void set_destination(address dest) { Unimplemented(); } + // patch stub to target address of the reloc call + bool set_destination_mt_safe(address dest); + // patch reloc call to stub address bool reloc_set_destination(address dest); static bool is_at(address addr); static bool is_call_before(address return_address); + + private: + // return stub address, without checking stub address in locs + address stub_address(); + // set target address at stub + static void set_stub_address_destination_at(address dest, address value); + // return target address at stub + static address stub_address_destination_at(address src); + // We either have a jalr or jal depending on distance to old destination. + // This method emits a new jal if new destination is within jal reach. + // Otherwise restores the jalr which can reach any destination. + void optimize_call(address dest, bool mt_safe = true); }; // An interface for accessing/manipulating native mov reg, imm instructions. @@ -219,38 +233,18 @@ inline NativeMovConstReg* nativeMovConstReg_before(address addr) { // NativeMovRegMem to keep some compilers happy. class NativeMovRegMem: public NativeInstruction { public: - enum RISCV_specific_constants { - instruction_size = NativeInstruction::instruction_size, - instruction_offset = 0, - data_offset = 0, - next_instruction_offset = NativeInstruction::instruction_size - }; - - int instruction_start() const { return instruction_offset; } - - address instruction_address() const { return addr_at(instruction_offset); } + int num_bytes_to_end_of_patch() const { Unimplemented(); return 0; } - int num_bytes_to_end_of_patch() const { return instruction_offset + instruction_size; } + int offset() const { Unimplemented(); return 0; } - int offset() const; + void set_offset(int x) { Unimplemented(); } - void set_offset(int x); - - void add_offset_in_bytes(int add_offset) { - set_offset(offset() + add_offset); - } - - void verify(); - void print(); - - private: - inline friend NativeMovRegMem* nativeMovRegMem_at(address addr); + void add_offset_in_bytes(int add_offset) { Unimplemented(); } }; inline NativeMovRegMem* nativeMovRegMem_at(address addr) { - NativeMovRegMem* test = (NativeMovRegMem*)(addr - NativeMovRegMem::instruction_offset); - DEBUG_ONLY(test->verify()); - return test; + Unimplemented(); + return (NativeMovRegMem*)nullptr; } class NativeJump: public NativeInstruction { @@ -363,14 +357,7 @@ class NativeDeoptInstruction: public NativeInstruction { address instruction_address() const { return addr_at(instruction_offset); } address next_instruction_address() const { return addr_at(instruction_size); } - void verify(); - - static bool is_deopt_at(address instr) { - assert(instr != nullptr, ""); - uint32_t value = Assembler::ld_instr(instr); - // 0xc0201073 encodes CSRRW x0, instret, x0 - return value == 0xc0201073; - } + static bool is_deopt_at(address instr); // MT-safe patching static void insert(address code_pos); diff --git a/src/hotspot/cpu/riscv/relocInfo_riscv.cpp b/src/hotspot/cpu/riscv/relocInfo_riscv.cpp index 7bee372b0ef..ccd8b891996 100644 --- a/src/hotspot/cpu/riscv/relocInfo_riscv.cpp +++ b/src/hotspot/cpu/riscv/relocInfo_riscv.cpp @@ -72,13 +72,12 @@ void Relocation::pd_set_data_value(address x, bool verify_only) { } address Relocation::pd_call_destination(address orig_addr) { - assert(is_call(), "should be an address instruction here"); + assert(is_call(), "should be a call here"); if (NativeCall::is_at(addr())) { - return nativeCall_at(addr())->reloc_destination(orig_addr); + return nativeCall_at(addr())->reloc_destination(); } - // Non call reloc + if (orig_addr != nullptr) { - // the extracted address from the instructions in address orig_addr address new_addr = MacroAssembler::pd_call_destination(orig_addr); // If call is branch to self, don't try to relocate it, just leave it // as branch to self. This happens during code generation if the code @@ -87,20 +86,19 @@ address Relocation::pd_call_destination(address orig_addr) { new_addr = (new_addr == orig_addr) ? addr() : new_addr; return new_addr; } + return MacroAssembler::pd_call_destination(addr()); } void Relocation::pd_set_call_destination(address x) { - assert(is_call(), "should be an address instruction here"); + assert(is_call(), "should be a call here"); if (NativeCall::is_at(addr())) { - NativeCall* nc = nativeCall_at(addr()); - if (nc->reloc_set_destination(x)) { - return; - } + NativeCall* call = nativeCall_at(addr()); + call->reloc_set_destination(x); + } else { + MacroAssembler::pd_patch_instruction_size(addr(), x); + assert(pd_call_destination(addr()) == x, "fail in reloc"); } - MacroAssembler::pd_patch_instruction_size(addr(), x); - address pd_call = pd_call_destination(addr()); - assert(pd_call == x, "fail in reloc"); } address* Relocation::pd_address_in_code() { diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index e838ee184fb..9b7e7138710 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -1184,6 +1184,8 @@ bool is_CAS(int opcode, bool maybe_volatile) } } +constexpr uint64_t MAJIK_DWORD = 0xabbaabbaabbaabbaull; + // predicate controlling translation of CAS // // returns true if CAS needs to use an acquiring load otherwise false @@ -1269,6 +1271,26 @@ int CallDynamicJavaDirectNode::compute_padding(int current_offset) const return align_up(current_offset, alignment_required()) - current_offset; } +int CallRuntimeDirectNode::compute_padding(int current_offset) const +{ + return align_up(current_offset, alignment_required()) - current_offset; +} + +int CallLeafDirectNode::compute_padding(int current_offset) const +{ + return align_up(current_offset, alignment_required()) - current_offset; +} + +int CallLeafDirectVectorNode::compute_padding(int current_offset) const +{ + return align_up(current_offset, alignment_required()) - current_offset; +} + +int CallLeafNoFPDirectNode::compute_padding(int current_offset) const +{ + return align_up(current_offset, alignment_required()) - current_offset; +} + //============================================================================= #ifndef PRODUCT @@ -1343,10 +1365,15 @@ void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const { st->print("# stack bang size=%d\n\t", framesize); } - st->print("sd fp, [sp, #%d]\n\t", - 2 * wordSize); - st->print("sd ra, [sp, #%d]\n\t", - wordSize); - if (PreserveFramePointer) { st->print("sub fp, sp, #%d\n\t", 2 * wordSize); } st->print("sub sp, sp, #%d\n\t", framesize); + st->print("sd fp, [sp, #%d]\n\t", framesize - 2 * wordSize); + st->print("sd ra, [sp, #%d]\n\t", framesize - wordSize); + if (PreserveFramePointer) { st->print("add fp, sp, #%d\n\t", framesize); } + + if (VerifyStackAtCalls) { + st->print("mv t2, %ld\n\t", MAJIK_DWORD); + st->print("sd t2, [sp, #%d]\n\t", framesize - 3 * wordSize); + } if (C->stub_function() == nullptr) { st->print("ld t0, [guard]\n\t"); @@ -1396,6 +1423,11 @@ void MachPrologNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const { __ build_frame(framesize); + if (VerifyStackAtCalls) { + __ mv(t2, MAJIK_DWORD); + __ sd(t2, Address(sp, framesize - 3 * wordSize)); + } + if (C->stub_function() == nullptr) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); // Dummy labels for just measuring the code size @@ -1417,10 +1449,6 @@ void MachPrologNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const { bs->nmethod_entry_barrier(masm, slow_path, continuation, guard); } - if (VerifyStackAtCalls) { - Unimplemented(); - } - C->output()->set_frame_complete(__ offset()); if (C->has_mach_constant_base_node()) { @@ -1493,7 +1521,7 @@ void MachEpilogNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const { code_stub = &stub->entry(); } __ relocate(relocInfo::poll_return_type); - __ safepoint_poll(*code_stub, true /* at_return */, false /* acquire */, true /* in_nmethod */); + __ safepoint_poll(*code_stub, true /* at_return */, true /* in_nmethod */); } } @@ -2271,10 +2299,6 @@ encode %{ __ mv(dst_reg, 1); %} - enc_class riscv_enc_mov_byte_map_base(iRegP dst) %{ - __ load_byte_map_base($dst$$Register); - %} - enc_class riscv_enc_mov_n(iRegN dst, immN src) %{ Register dst_reg = as_Register($dst$$reg); address con = (address)$src$$constant; @@ -2414,7 +2438,13 @@ encode %{ enc_class riscv_enc_call_epilog() %{ if (VerifyStackAtCalls) { // Check that stack depth is unchanged: find majik cookie on stack - __ call_Unimplemented(); + int framesize = ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP, -3 * VMRegImpl::slots_per_word)); + Label stack_ok; + __ ld(t1, Address(sp, framesize)); + __ mv(t2, MAJIK_DWORD); + __ beq(t2, t1, stack_ok); + __ stop("MAJIK_DWORD not found"); + __ bind(stack_ok); } %} @@ -2825,21 +2855,6 @@ operand immP_1() interface(CONST_INTER); %} -// Card Table Byte Map Base -operand immByteMapBase() -%{ - // Get base of card map - predicate(BarrierSet::barrier_set()->is_a(BarrierSet::CardTableBarrierSet) && - SHENANDOAHGC_ONLY(!BarrierSet::barrier_set()->is_a(BarrierSet::ShenandoahBarrierSet) &&) - (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() %{ @@ -3843,13 +3858,18 @@ opclass immIorL(immI, immL); pipeline %{ attributes %{ - // RISC-V instructions are of fixed length - fixed_size_instructions; // Fixed size instructions TODO does - max_instructions_per_bundle = 2; // Generic RISC-V 1, Sifive Series 7 2 - // RISC-V instructions come in 32-bit word units - instruction_unit_size = 4; // An instruction is 4 bytes long - instruction_fetch_unit_size = 64; // The processor fetches one line - instruction_fetch_units = 1; // of 64 bytes + // RISC-V instructions are of length 2 or 4 bytes. + variable_size_instructions; + instruction_unit_size = 2; + + // Up to 4 instructions per bundle + max_instructions_per_bundle = 4; + + // The RISC-V processor fetches 64 bytes... + instruction_fetch_unit_size = 64; + + // ...in one line. + instruction_fetch_units = 1; // List of nop instructions nops( MachNop ); @@ -4799,18 +4819,6 @@ instruct loadConP1(iRegPNoSp dst, immP_1 con) 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) %{ @@ -8195,7 +8203,7 @@ instruct unnecessary_membar_volatile_rvtso() %{ ins_cost(0); size(0); - + format %{ "#@unnecessary_membar_volatile_rvtso (unnecessary so empty encoding)" %} ins_encode %{ __ block_comment("unnecessary_membar_volatile_rvtso"); @@ -8431,6 +8439,17 @@ instruct castVV(vReg dst) ins_pipe(pipe_class_empty); %} +instruct castVVMask(vRegMask dst) +%{ + match(Set dst (CastVV dst)); + + size(0); + format %{ "# castVV of $dst" %} + ins_encode(/* empty encoding */); + ins_cost(0); + ins_pipe(pipe_class_empty); +%} + // ============================================================================ // Convert Instructions @@ -8536,7 +8555,7 @@ instruct convD2F_reg(fRegF dst, fRegD src) %{ // single <-> half precision -instruct convHF2F_reg_reg(fRegF dst, iRegINoSp src, iRegINoSp tmp) %{ +instruct convHF2F_reg_reg(fRegF dst, iRegIorL2I src, iRegINoSp tmp) %{ match(Set dst (ConvHF2F src)); effect(TEMP tmp); format %{ "fmv.h.x $dst, $src\t# move source from $src to $dst\n\t" @@ -8565,7 +8584,7 @@ instruct convF2HF_reg_reg(iRegINoSp dst, fRegF src, fRegF ftmp, iRegINoSp xtmp) instruct reinterpretS2HF(fRegF dst, iRegI src) %{ match(Set dst (ReinterpretS2HF src)); - format %{ "fmv.h.x $dst, $src" %} + format %{ "fmv.h.x $dst, $src\t# reinterpretS2HF" %} ins_encode %{ __ fmv_h_x($dst$$FloatRegister, $src$$Register); %} @@ -8585,7 +8604,7 @@ instruct convF2HFAndS2HF(fRegF dst, fRegF src) instruct reinterpretHF2S(iRegINoSp dst, fRegF src) %{ match(Set dst (ReinterpretHF2S src)); - format %{ "fmv.x.h $dst, $src" %} + format %{ "fmv.x.h $dst, $src\t# reinterpretHF2S" %} ins_encode %{ __ fmv_x_h($dst$$Register, $src$$FloatRegister); %} @@ -8947,7 +8966,7 @@ instruct encodeKlass_not_null(iRegNNoSp dst, iRegP src) %{ instruct decodeKlass_not_null(iRegPNoSp dst, iRegN src, iRegPNoSp tmp) %{ match(Set dst (DecodeNKlass src)); - effect(TEMP tmp); + effect(TEMP_DEF dst, TEMP tmp); ins_cost(ALU_COST); format %{ "decode_klass_not_null $dst, $src\t#@decodeKlass_not_null" %} @@ -10518,6 +10537,7 @@ instruct CallRuntimeDirect(method meth) ins_encode(riscv_enc_java_to_runtime(meth)); ins_pipe(pipe_class_call); + ins_alignment(4); %} // Call Runtime Instruction @@ -10535,6 +10555,7 @@ instruct CallLeafDirect(method meth) ins_encode(riscv_enc_java_to_runtime(meth)); ins_pipe(pipe_class_call); + ins_alignment(4); %} // Call Runtime Instruction without safepoint and with vector arguments @@ -10552,6 +10573,7 @@ instruct CallLeafDirectVector(method meth) ins_encode(riscv_enc_java_to_runtime(meth)); ins_pipe(pipe_class_call); + ins_alignment(4); %} // Call Runtime Instruction @@ -10569,6 +10591,7 @@ instruct CallLeafNoFPDirect(method meth) ins_encode(riscv_enc_java_to_runtime(meth)); ins_pipe(pipe_class_call); + ins_alignment(4); %} // ============================================================================ diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad index 8b5759ce11c..a824f33367c 100644 --- a/src/hotspot/cpu/riscv/riscv_v.ad +++ b/src/hotspot/cpu/riscv/riscv_v.ad @@ -110,15 +110,16 @@ source %{ if (vlen < 4) { return false; } + break; case Op_VectorCastHF2F: case Op_VectorCastF2HF: case Op_AddVHF: + case Op_SubVHF: + case Op_MulVHF: case Op_DivVHF: case Op_MaxVHF: case Op_MinVHF: - case Op_MulVHF: case Op_SqrtVHF: - case Op_SubVHF: return UseZvfh; case Op_FmaVHF: return UseZvfh && UseFMA; @@ -146,13 +147,28 @@ source %{ if (!UseRVV) { return false; } + switch (opcode) { case Op_SelectFromTwoVector: // There is no masked version of selectFrom two vector, i.e. selectFrom(av, bv, mask) in vector API. return false; + // Currently, the masked versions of the following 8 Float16 operations are disabled. + // When the support for Float16 vector classes is added in VectorAPI and the masked + // Float16 IR can be generated, these masked operations will be enabled and relevant + // backend support added. + case Op_AddVHF: + case Op_SubVHF: + case Op_MulVHF: + case Op_DivVHF: + case Op_MaxVHF: + case Op_MinVHF: + case Op_SqrtVHF: + case Op_FmaVHF: + return false; default: break; } + return match_rule_supported_vector(opcode, vlen, bt); } diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp index 391be81c1ae..3b2d7977b7c 100644 --- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp +++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp @@ -213,7 +213,7 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm) { // Is vector's size (in bytes) bigger than a size saved by default? // riscv does not ovlerlay the floating-point registers on vector registers like aarch64. bool SharedRuntime::is_wide_vector(int size) { - return UseRVV; + return UseRVV && size > 0; } // --------------------------------------------------------------------------- @@ -1004,20 +1004,23 @@ static void gen_continuation_enter(MacroAssembler* masm, __ bnez(c_rarg2, call_thaw); - // Make sure the call is patchable - __ align(NativeInstruction::instruction_size); - - const address tr_call = __ reloc_call(resolve); - if (tr_call == nullptr) { - fatal("CodeCache is full at gen_continuation_enter"); - } + address call_pc; + { + Assembler::IncompressibleScope scope(masm); + // Make sure the call is patchable + __ align(NativeInstruction::instruction_size); - oop_maps->add_gc_map(__ pc() - start, map); - __ post_call_nop(); + call_pc = __ reloc_call(resolve); + if (call_pc == nullptr) { + fatal("CodeCache is full at gen_continuation_enter"); + } + oop_maps->add_gc_map(__ pc() - start, map); + __ post_call_nop(); + } __ j(exit); - address stub = CompiledDirectCall::emit_to_interp_stub(masm, tr_call); + address stub = CompiledDirectCall::emit_to_interp_stub(masm, call_pc); if (stub == nullptr) { fatal("CodeCache is full at gen_continuation_enter"); } @@ -1036,26 +1039,36 @@ static void gen_continuation_enter(MacroAssembler* masm, __ bnez(c_rarg2, call_thaw); - // Make sure the call is patchable - __ align(NativeInstruction::instruction_size); + address call_pc; + { + Assembler::IncompressibleScope scope(masm); + // Make sure the call is patchable + __ align(NativeInstruction::instruction_size); - const address tr_call = __ reloc_call(resolve); - if (tr_call == nullptr) { - fatal("CodeCache is full at gen_continuation_enter"); - } + call_pc = __ reloc_call(resolve); + if (call_pc == nullptr) { + fatal("CodeCache is full at gen_continuation_enter"); + } - oop_maps->add_gc_map(__ pc() - start, map); - __ post_call_nop(); + oop_maps->add_gc_map(__ pc() - start, map); + __ post_call_nop(); + } __ j(exit); __ bind(call_thaw); - ContinuationEntry::_thaw_call_pc_offset = __ pc() - start; - __ rt_call(CAST_FROM_FN_PTR(address, StubRoutines::cont_thaw())); - oop_maps->add_gc_map(__ pc() - start, map->deep_copy()); - ContinuationEntry::_return_pc_offset = __ pc() - start; - __ post_call_nop(); + // Post call nops must be natural aligned due to cmodx rules. + { + Assembler::IncompressibleScope scope(masm); + __ align(NativeInstruction::instruction_size); + + ContinuationEntry::_thaw_call_pc_offset = __ pc() - start; + __ rt_call(CAST_FROM_FN_PTR(address, StubRoutines::cont_thaw())); + oop_maps->add_gc_map(__ pc() - start, map->deep_copy()); + ContinuationEntry::_return_pc_offset = __ pc() - start; + __ post_call_nop(); + } __ bind(exit); ContinuationEntry::_cleanup_offset = __ pc() - start; @@ -1084,7 +1097,7 @@ static void gen_continuation_enter(MacroAssembler* masm, __ jr(x11); // the exception handler } - address stub = CompiledDirectCall::emit_to_interp_stub(masm, tr_call); + address stub = CompiledDirectCall::emit_to_interp_stub(masm, call_pc); if (stub == nullptr) { fatal("CodeCache is full at gen_continuation_enter"); } @@ -1117,10 +1130,16 @@ static void gen_continuation_yield(MacroAssembler* masm, __ mv(c_rarg1, sp); + // Post call nops must be natural aligned due to cmodx rules. + __ align(NativeInstruction::instruction_size); + frame_complete = __ pc() - start; address the_pc = __ pc(); - __ post_call_nop(); // this must be exactly after the pc value that is pushed into the frame info, we use this nop for fast CodeBlob lookup + { + Assembler::IncompressibleScope scope(masm); + __ post_call_nop(); // this must be exactly after the pc value that is pushed into the frame info, we use this nop for fast CodeBlob lookup + } __ mv(c_rarg0, xthread); __ set_last_Java_frame(sp, fp, the_pc, t0); @@ -1777,15 +1796,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // check for safepoint operation in progress and/or pending suspend requests { - // We need an acquire here to ensure that any subsequent load of the - // global SafepointSynchronize::_state flag is ordered after this load - // of the thread-local polling word. We don't want this poll to - // return false (i.e. not safepointing) and a later poll of the global - // SafepointSynchronize::_state spuriously to return true. - // This is to avoid a race when we're in a native->Java transition - // racing the code which wakes up from a safepoint. - - __ safepoint_poll(safepoint_in_progress, true /* at_return */, true /* acquire */, false /* in_nmethod */); + __ safepoint_poll(safepoint_in_progress, true /* at_return */, false /* in_nmethod */); __ lwu(t0, Address(xthread, JavaThread::suspend_flags_offset())); __ bnez(t0, safepoint_in_progress); __ bind(safepoint_in_progress_done); @@ -2475,7 +2486,7 @@ void SharedRuntime::generate_deopt_blob() { // EPILOG must remove this many slots. // RISCV needs two words for RA (return address) and FP (frame pointer). uint SharedRuntime::in_preserve_stack_slots() { - return 2 * VMRegImpl::slots_per_word; + return 2 * VMRegImpl::slots_per_word + (VerifyStackAtCalls ? 0 : 2) ; } uint SharedRuntime::out_preserve_stack_slots() { diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp index c58f6bc338d..58796e8892c 100644 --- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp @@ -683,10 +683,11 @@ class StubGenerator: public StubCodeGenerator { address start = __ pc(); if (UseBlockZeroing) { - // Ensure count >= 2*CacheLineSize so that it still deserves a cbo.zero - // after alignment. + int zicboz_block_size = VM_Version::zicboz_block_size.value(); + // Ensure count >= 2 * zicboz_block_size so that it still deserves + // a cbo.zero after alignment. Label small; - int low_limit = MAX2(2 * CacheLineSize, BlockZeroingLowLimit) / wordSize; + int low_limit = MAX2(2 * zicboz_block_size, (int)BlockZeroingLowLimit) / wordSize; __ mv(tmp1, low_limit); __ blt(cnt, tmp1, small); __ zero_dcache_blocks(base, cnt, tmp1, tmp2); @@ -6354,18 +6355,8 @@ class StubGenerator: public StubCodeGenerator { __ ret(); __ bind(NaN_SLOW); - __ fmv_x_w(dst, src); - - // preserve the payloads of non-canonical NaNs. - __ srai(dst, dst, 13); - // preserve the sign bit. - __ srai(t1, dst, 13); - __ slli(t1, t1, 10); - __ mv(t0, 0x3ff); - __ orr(t1, t1, t0); - - // get the result by merging sign bit and payloads of preserved non-canonical NaNs. - __ andr(dst, dst, t1); + + __ float_to_float16_NaN(dst, src, t0, t1); __ ret(); return entry; diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp index b8de3547c83..a478cd7b183 100644 --- a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp @@ -1148,9 +1148,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { Label L; __ ld(x28, Address(xmethod, Method::native_function_offset())); ExternalAddress unsatisfied(SharedRuntime::native_method_throw_unsatisfied_link_error_entry()); - __ la(t, unsatisfied); - __ load_long_misaligned(t1, Address(t, 0), t0, 2); // 2 bytes aligned, but not 4 or 8 - + __ la(t1, unsatisfied); __ bne(x28, t1, L); __ call_VM(noreg, CAST_FROM_FN_PTR(address, @@ -1229,15 +1227,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { { Label L, Continue; - // We need an acquire here to ensure that any subsequent load of the - // global SafepointSynchronize::_state flag is ordered after this load - // of the thread-local polling word. We don't want this poll to - // return false (i.e. not safepointing) and a later poll of the global - // SafepointSynchronize::_state spuriously to return true. - // - // This is to avoid a race when we're in a native->Java transition - // racing the code which wakes up from a safepoint. - __ safepoint_poll(L, true /* at_return */, true /* acquire */, false /* in_nmethod */); + __ safepoint_poll(L, true /* at_return */, false /* in_nmethod */); __ lwu(t1, Address(xthread, JavaThread::suspend_flags_offset())); __ beqz(t1, Continue); __ bind(L); @@ -1388,7 +1378,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { Label slow_path; Label fast_path; - __ safepoint_poll(slow_path, true /* at_return */, false /* acquire */, false /* in_nmethod */); + __ safepoint_poll(slow_path, true /* at_return */, false /* in_nmethod */); __ j(fast_path); __ bind(slow_path); diff --git a/src/hotspot/cpu/riscv/templateTable_riscv.cpp b/src/hotspot/cpu/riscv/templateTable_riscv.cpp index f6bf1e79f92..2c4ea70b9f8 100644 --- a/src/hotspot/cpu/riscv/templateTable_riscv.cpp +++ b/src/hotspot/cpu/riscv/templateTable_riscv.cpp @@ -133,6 +133,7 @@ Address TemplateTable::at_bcp(int offset) { void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, Register temp_reg, bool load_bc_into_bc_reg /*=true*/, int byte_no) { + assert_different_registers(bc_reg, temp_reg); if (!RewriteBytecodes) { return; } Label L_patch_done; @@ -196,7 +197,11 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, __ bind(L_okay); #endif - // patch bytecode + // Patch bytecode with release store to coordinate with ResolvedFieldEntry loads + // in fast bytecode codelets. load_field_entry has a memory barrier that gains + // the needed ordering, together with control dependency on entering the fast codelet + // itself. + __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); __ sb(bc_reg, at_bcp(0)); __ bind(L_patch_done); } @@ -703,7 +708,6 @@ void TemplateTable::index_check(Register array, Register index) { __ mv(x11, index); } Label ok; - __ sext(index, index, 32); __ bltu(index, length, ok); __ mv(x13, array); __ mv(t1, Interpreter::_throw_ArrayIndexOutOfBoundsException_entry); @@ -1047,7 +1051,7 @@ void TemplateTable::aastore() { transition(vtos, vtos); // stack: ..., array, index, value __ ld(x10, at_tos()); // value - __ ld(x12, at_tos_p1()); // index + __ lw(x12, at_tos_p1()); // index __ ld(x13, at_tos_p2()); // array index_check(x13, x12); // kills x11 @@ -1457,9 +1461,9 @@ void TemplateTable::iinc() { transition(vtos, vtos); __ load_signed_byte(x11, at_bcp(2)); // get constant locals_index(x12); - __ ld(x10, iaddress(x12, x10, _masm)); + __ lw(x10, iaddress(x12, x10, _masm)); __ addw(x10, x10, x11); - __ sd(x10, iaddress(x12, t0, _masm)); + __ sw(x10, iaddress(x12, t0, _masm)); } void TemplateTable::wide_iinc() { @@ -1472,9 +1476,9 @@ void TemplateTable::wide_iinc() { __ orr(x11, x11, t1); locals_index_wide(x12); - __ ld(x10, iaddress(x12, t0, _masm)); + __ lw(x10, iaddress(x12, t0, _masm)); __ addw(x10, x10, x11); - __ sd(x10, iaddress(x12, t0, _masm)); + __ sw(x10, iaddress(x12, t0, _masm)); } void TemplateTable::convert() { @@ -3017,6 +3021,7 @@ void TemplateTable::fast_storefield(TosState state) { // X11: field offset, X12: field holder, X13: flags load_resolved_field_entry(x12, x12, noreg, x11, x13); + __ verify_field_offset(x11); { Label notVolatile; @@ -3104,6 +3109,8 @@ void TemplateTable::fast_accessfield(TosState state) { __ load_field_entry(x12, x11); __ load_sized_value(x11, Address(x12, in_bytes(ResolvedFieldEntry::field_offset_offset())), sizeof(int), true /*is_signed*/); + __ verify_field_offset(x11); + __ load_unsigned_byte(x13, Address(x12, in_bytes(ResolvedFieldEntry::flags_offset()))); // x10: object @@ -3159,7 +3166,9 @@ void TemplateTable::fast_xaccess(TosState state) { __ ld(x10, aaddress(0)); // access constant pool cache __ load_field_entry(x12, x13, 2); + __ load_sized_value(x11, Address(x12, in_bytes(ResolvedFieldEntry::field_offset_offset())), sizeof(int), true /*is_signed*/); + __ verify_field_offset(x11); // make sure exception is reported in correct bcp range (getfield is // next instruction) diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp index eca1bb83ab6..fb04c272385 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp @@ -147,7 +147,7 @@ void VM_Version::common_initialize() { if (FLAG_IS_DEFAULT(AvoidUnalignedAccesses)) { FLAG_SET_DEFAULT(AvoidUnalignedAccesses, - unaligned_access.value() != MISALIGNED_FAST); + unaligned_scalar.value() != MISALIGNED_SCALAR_FAST); } if (!AvoidUnalignedAccesses) { @@ -162,7 +162,7 @@ void VM_Version::common_initialize() { // This machine has fast unaligned memory accesses if (FLAG_IS_DEFAULT(UseUnalignedAccesses)) { FLAG_SET_DEFAULT(UseUnalignedAccesses, - unaligned_access.value() == MISALIGNED_FAST); + (unaligned_scalar.value() == MISALIGNED_SCALAR_FAST)); } #ifdef __riscv_ztso @@ -181,12 +181,13 @@ void VM_Version::common_initialize() { FLAG_SET_DEFAULT(UsePopCountInstruction, false); } - if (UseZicboz) { + if (UseZicboz && zicboz_block_size.enabled() && zicboz_block_size.value() > 0) { + assert(is_power_of_2(zicboz_block_size.value()), "Sanity"); if (FLAG_IS_DEFAULT(UseBlockZeroing)) { FLAG_SET_DEFAULT(UseBlockZeroing, true); } if (FLAG_IS_DEFAULT(BlockZeroingLowLimit)) { - FLAG_SET_DEFAULT(BlockZeroingLowLimit, 2 * CacheLineSize); + FLAG_SET_DEFAULT(BlockZeroingLowLimit, 4 * zicboz_block_size.value()); } } else if (UseBlockZeroing) { warning("Block zeroing is not available"); @@ -194,24 +195,19 @@ void VM_Version::common_initialize() { } if (UseRVV) { - if (!ext_V.enabled() && FLAG_IS_DEFAULT(UseRVV)) { - warning("RVV is not supported on this CPU"); - FLAG_SET_DEFAULT(UseRVV, false); - } else { - // read vector length from vector CSR vlenb - _initial_vector_length = cpu_vector_length(); - } + // read vector length from vector CSR vlenb + _initial_vector_length = cpu_vector_length(); } - // Misc Intrinsics could depend on RVV + // Misc Intrinsics that could depend on RVV. - if (UseZba || UseRVV) { + if (!AvoidUnalignedAccesses && (UseZba || UseRVV)) { if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) { FLAG_SET_DEFAULT(UseCRC32Intrinsics, true); } } else { if (!FLAG_IS_DEFAULT(UseCRC32Intrinsics)) { - warning("CRC32 intrinsic requires Zba or RVV instructions (not available on this CPU)"); + warning("CRC32 intrinsic are not available on this CPU."); } FLAG_SET_DEFAULT(UseCRC32Intrinsics, false); } @@ -269,6 +265,11 @@ void VM_Version::c2_initialize() { } } + if (FLAG_IS_DEFAULT(AlignVector)) { + FLAG_SET_DEFAULT(AlignVector, + unaligned_vector.value() != MISALIGNED_VECTOR_FAST); + } + // NOTE: Make sure codes dependent on UseRVV are put after MaxVectorSize initialize, // as there are extra checks inside it which could disable UseRVV // in some situations. @@ -325,20 +326,40 @@ void VM_Version::c2_initialize() { FLAG_SET_DEFAULT(UseMulAddIntrinsic, true); } - if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { - FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, true); + if (!AvoidUnalignedAccesses) { + if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { + FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, true); + } + } else if (UseMultiplyToLenIntrinsic) { + warning("Intrinsics for BigInteger.multiplyToLen() not available on this CPU."); + FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, false); } - if (FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) { - FLAG_SET_DEFAULT(UseSquareToLenIntrinsic, true); + if (!AvoidUnalignedAccesses) { + if (FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) { + FLAG_SET_DEFAULT(UseSquareToLenIntrinsic, true); + } + } else if (UseSquareToLenIntrinsic) { + warning("Intrinsics for BigInteger.squareToLen() not available on this CPU."); + FLAG_SET_DEFAULT(UseSquareToLenIntrinsic, false); } - if (FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) { - FLAG_SET_DEFAULT(UseMontgomeryMultiplyIntrinsic, true); + if (!AvoidUnalignedAccesses) { + if (FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) { + FLAG_SET_DEFAULT(UseMontgomeryMultiplyIntrinsic, true); + } + } else if (UseMontgomeryMultiplyIntrinsic) { + warning("Intrinsics for BigInteger.montgomeryMultiply() not available on this CPU."); + FLAG_SET_DEFAULT(UseMontgomeryMultiplyIntrinsic, false); } - if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) { - FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, true); + if (!AvoidUnalignedAccesses) { + if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) { + FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, true); + } + } else if (UseMontgomerySquareIntrinsic) { + warning("Intrinsics for BigInteger.montgomerySquare() not available on this CPU."); + FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, false); } // Adler32 @@ -456,10 +477,6 @@ void VM_Version::c2_initialize() { warning("AES/CTR intrinsics are not available on this CPU"); FLAG_SET_DEFAULT(UseAESCTRIntrinsics, false); } - - if (FLAG_IS_DEFAULT(AlignVector)) { - FLAG_SET_DEFAULT(AlignVector, AvoidUnalignedAccesses); - } } #endif // COMPILER2 diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp index a0a42fb5463..85454593dfe 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.hpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp @@ -86,25 +86,27 @@ class VM_Version : public Abstract_VM_Version { } \ } \ - #define UPDATE_DEFAULT_DEP(flag, dep) \ - void update_flag() { \ - assert(enabled(), "Must be."); \ - /* dep must be declared before */ \ - assert((uintptr_t)(this) > \ - (uintptr_t)(&dep), "Invalid");\ - if (FLAG_IS_DEFAULT(flag)) { \ - if (dep.enabled()) { \ - FLAG_SET_DEFAULT(flag, true); \ - } else { \ - FLAG_SET_DEFAULT(flag, false); \ - } \ - } else { \ - /* Sync CPU features with flags */ \ - if (!flag) { \ - disable_feature(); \ - } \ - } \ - } \ + #define UPDATE_DEFAULT_DEP(flag, dep) \ + void update_flag() { \ + assert(enabled(), "Must be."); \ + /* dep must be declared before */ \ + assert((uintptr_t)(this) > \ + (uintptr_t)(&dep), "Invalid"); \ + if (FLAG_IS_DEFAULT(flag)) { \ + if (dep.enabled()) { \ + FLAG_SET_DEFAULT(flag, true); \ + } else { \ + FLAG_SET_DEFAULT(flag, false); \ + /* Sync CPU features with flags */ \ + disable_feature(); \ + } \ + } else { \ + /* Sync CPU features with flags */ \ + if (!flag) { \ + disable_feature(); \ + } \ + } \ + } \ #define NO_UPDATE_DEFAULT \ void update_flag() {} \ @@ -151,7 +153,8 @@ class VM_Version : public Abstract_VM_Version { // mvendorid Manufactory JEDEC id encoded, ISA vol 2 3.1.2.. // marchid Id for microarch. Mvendorid plus marchid uniquely identify the microarch. // mimpid A unique encoding of the version of the processor implementation. - // unaligned_access Unaligned memory accesses (unknown, unspported, emulated, slow, firmware, fast) + // unaligned_scalar Performance of misaligned scalar accesses (unknown, emulated, slow, fast, unsupported) + // unaligned_vector Performance of misaligned vector accesses (unknown, unspported, slow, fast) // satp mode SATP bits (number of virtual addr bits) mbare, sv39, sv48, sv57, sv64 public: @@ -160,45 +163,47 @@ class VM_Version : public Abstract_VM_Version { // Note: the order matters, depender should be after their dependee. E.g. ext_V before ext_Zvbb. // declaration name , extension name, bit pos ,in str, mapped flag) - #define RV_FEATURE_FLAGS(decl) \ - decl(ext_I , "i" , ('I' - 'A'), true , NO_UPDATE_DEFAULT) \ - decl(ext_M , "m" , ('M' - 'A'), true , NO_UPDATE_DEFAULT) \ - decl(ext_A , "a" , ('A' - 'A'), true , NO_UPDATE_DEFAULT) \ - decl(ext_F , "f" , ('F' - 'A'), true , NO_UPDATE_DEFAULT) \ - decl(ext_D , "d" , ('D' - 'A'), true , NO_UPDATE_DEFAULT) \ - decl(ext_C , "c" , ('C' - 'A'), true , UPDATE_DEFAULT(UseRVC)) \ - decl(ext_Q , "q" , ('Q' - 'A'), true , NO_UPDATE_DEFAULT) \ - decl(ext_H , "h" , ('H' - 'A'), true , NO_UPDATE_DEFAULT) \ - decl(ext_V , "v" , ('V' - 'A'), true , UPDATE_DEFAULT(UseRVV)) \ - decl(ext_Zicbom , "Zicbom" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbom)) \ - decl(ext_Zicboz , "Zicboz" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicboz)) \ - decl(ext_Zicbop , "Zicbop" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbop)) \ - decl(ext_Zba , "Zba" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZba)) \ - decl(ext_Zbb , "Zbb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbb)) \ - decl(ext_Zbc , "Zbc" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \ - decl(ext_Zbs , "Zbs" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbs)) \ - decl(ext_Zbkb , "Zbkb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbkb)) \ - decl(ext_Zcb , "Zcb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZcb)) \ - decl(ext_Zfa , "Zfa" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfa)) \ - decl(ext_Zfh , "Zfh" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfh)) \ - decl(ext_Zfhmin , "Zfhmin" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfhmin)) \ - decl(ext_Zicsr , "Zicsr" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \ - decl(ext_Zicntr , "Zicntr" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \ - decl(ext_Zifencei , "Zifencei" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \ - decl(ext_Zic64b , "Zic64b" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZic64b)) \ - decl(ext_Ztso , "Ztso" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZtso)) \ - decl(ext_Zihintpause , "Zihintpause" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZihintpause)) \ - decl(ext_Zacas , "Zacas" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZacas)) \ - decl(ext_Zvbb , "Zvbb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbb, ext_V)) \ - decl(ext_Zvbc , "Zvbc" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbc, ext_V)) \ - decl(ext_Zvfh , "Zvfh" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvfh, ext_V)) \ - decl(ext_Zvkn , "Zvkn" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvkn, ext_V)) \ - decl(ext_Zicond , "Zicond" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicond)) \ - decl(mvendorid , "VendorId" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ - decl(marchid , "ArchId" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ - decl(mimpid , "ImpId" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ - decl(unaligned_access, "Unaligned" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ - decl(satp_mode , "SATP" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ + #define RV_FEATURE_FLAGS(decl) \ + decl(ext_I , "i" , ('I' - 'A'), true , NO_UPDATE_DEFAULT) \ + decl(ext_M , "m" , ('M' - 'A'), true , NO_UPDATE_DEFAULT) \ + decl(ext_A , "a" , ('A' - 'A'), true , NO_UPDATE_DEFAULT) \ + decl(ext_F , "f" , ('F' - 'A'), true , NO_UPDATE_DEFAULT) \ + decl(ext_D , "d" , ('D' - 'A'), true , NO_UPDATE_DEFAULT) \ + decl(ext_C , "c" , ('C' - 'A'), true , UPDATE_DEFAULT(UseRVC)) \ + decl(ext_Q , "q" , ('Q' - 'A'), true , NO_UPDATE_DEFAULT) \ + decl(ext_H , "h" , ('H' - 'A'), true , NO_UPDATE_DEFAULT) \ + decl(ext_V , "v" , ('V' - 'A'), true , UPDATE_DEFAULT(UseRVV)) \ + decl(ext_Zicbom , "Zicbom" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbom)) \ + decl(ext_Zicboz , "Zicboz" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicboz)) \ + decl(ext_Zicbop , "Zicbop" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbop)) \ + decl(ext_Zba , "Zba" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZba)) \ + decl(ext_Zbb , "Zbb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbb)) \ + decl(ext_Zbc , "Zbc" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \ + decl(ext_Zbs , "Zbs" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbs)) \ + decl(ext_Zbkb , "Zbkb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbkb)) \ + decl(ext_Zcb , "Zcb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZcb)) \ + decl(ext_Zfa , "Zfa" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfa)) \ + decl(ext_Zfh , "Zfh" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfh)) \ + decl(ext_Zfhmin , "Zfhmin" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfhmin)) \ + decl(ext_Zicsr , "Zicsr" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \ + decl(ext_Zicntr , "Zicntr" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \ + decl(ext_Zifencei , "Zifencei" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \ + decl(ext_Zic64b , "Zic64b" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZic64b)) \ + decl(ext_Ztso , "Ztso" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZtso)) \ + decl(ext_Zihintpause , "Zihintpause" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZihintpause)) \ + decl(ext_Zacas , "Zacas" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZacas)) \ + decl(ext_Zvbb , "Zvbb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbb, ext_V)) \ + decl(ext_Zvbc , "Zvbc" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbc, ext_V)) \ + decl(ext_Zvfh , "Zvfh" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvfh, ext_V)) \ + decl(ext_Zvkn , "Zvkn" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvkn, ext_V)) \ + decl(ext_Zicond , "Zicond" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicond)) \ + decl(mvendorid , "VendorId" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ + decl(marchid , "ArchId" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ + decl(mimpid , "ImpId" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ + decl(satp_mode , "SATP" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ + decl(unaligned_scalar , "UnalignedScalar", RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ + decl(unaligned_vector , "UnalignedVector", RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ + decl(zicboz_block_size, "ZicbozBlockSize", RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ #define DECLARE_RV_FEATURE(NAME, PRETTY, BIT, FSTRING, FLAGF) \ struct NAME##RVFeatureValue : public RVFeatureValue { \ @@ -273,12 +278,19 @@ class VM_Version : public Abstract_VM_Version { static VM_MODE parse_satp_mode(const char* vm_mode); // Values from riscv_hwprobe() - enum UNALIGNED_ACCESS : int { - MISALIGNED_UNKNOWN = 0, - MISALIGNED_EMULATED = 1, - MISALIGNED_SLOW = 2, - MISALIGNED_FAST = 3, - MISALIGNED_UNSUPPORTED = 4 + enum UNALIGNED_SCALAR_ACCESS : int { + MISALIGNED_SCALAR_UNKNOWN = 0, + MISALIGNED_SCALAR_EMULATED = 1, + MISALIGNED_SCALAR_SLOW = 2, + MISALIGNED_SCALAR_FAST = 3, + MISALIGNED_SCALAR_UNSUPPORTED = 4 + }; + + enum UNALIGNED_VECTOR_ACCESS : int { + MISALIGNED_VECTOR_UNKNOWN = 0, + MISALIGNED_VECTOR_SLOW = 2, + MISALIGNED_VECTOR_FAST = 3, + MISALIGNED_VECTOR_UNSUPPORTED = 4 }; // Null terminated list diff --git a/src/hotspot/cpu/s390/gc/g1/g1_s390.ad b/src/hotspot/cpu/s390/gc/g1/g1_s390.ad index 31f60c4aeff..ce8c7463ad4 100644 --- a/src/hotspot/cpu/s390/gc/g1/g1_s390.ad +++ b/src/hotspot/cpu/s390/gc/g1/g1_s390.ad @@ -356,7 +356,7 @@ instruct g1CompareAndExchangeP(iRegP mem_ptr, rarg5RegP oldval, iRegP_N2P newval __ z_lgr($res$$Register, $oldval$$Register); // previous content - __ z_csg($oldval$$Register, $newval$$Register, 0, $mem_ptr$$reg); + __ z_csg($res$$Register, $newval$$Register, 0, $mem_ptr$$reg); write_barrier_post(masm, this, $mem_ptr$$Register /* store_addr */, diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index ee0376db078..cd4daf14639 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -1398,11 +1398,7 @@ void Assembler::addl(Address dst, Register src) { void Assembler::eaddl(Register dst, Address src1, Register src2, bool no_flags) { InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_32bit); - eevex_prefix_ndd(src1, dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, &attributes, no_flags); - emit_int8(0x01); - emit_operand(src2, src1, 0); + emit_eevex_or_demote(dst, src1, src2, VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_32bit, 0x01, no_flags, false /* is_map1 */, true /* is_commutative */); } void Assembler::addl(Register dst, int32_t imm32) { @@ -1432,11 +1428,7 @@ void Assembler::addl(Register dst, Register src) { } void Assembler::eaddl(Register dst, Register src1, Register src2, bool no_flags) { - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - // NDD shares its encoding bits with NDS bits for regular EVEX instruction. - // Therefore, DST is passed as the second argument to minimize changes in the leaf level routine. - (void)emit_eevex_prefix_or_demote_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, &attributes, no_flags); - emit_arith(0x03, 0xC0, src1, src2); + emit_eevex_prefix_or_demote_arith_ndd(dst, src1, src2, VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_32bit, 0x03, 0xC0, no_flags, true /* is_commutative */); } void Assembler::addr_nop_4() { @@ -1657,17 +1649,18 @@ void Assembler::eandl(Register dst, Register src1, Address src2, bool no_flags) emit_eevex_or_demote(dst, src1, src2, VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_32bit, 0x23, no_flags); } +void Assembler::eandl(Register dst, Address src1, Register src2, bool no_flags) { + InstructionMark im(this); + emit_eevex_or_demote(dst, src1, src2, VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_32bit, 0x21, no_flags, false /* is_map1 */, true /* is_commutative */); +} + void Assembler::andl(Register dst, Register src) { (void) prefix_and_encode(dst->encoding(), src->encoding()); emit_arith(0x23, 0xC0, dst, src); } void Assembler::eandl(Register dst, Register src1, Register src2, bool no_flags) { - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - // NDD shares its encoding bits with NDS bits for regular EVEX instruction. - // Therefore, DST is passed as the second argument to minimize changes in the leaf level routine. - (void) emit_eevex_prefix_or_demote_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, &attributes, no_flags); - emit_arith(0x23, 0xC0, src1, src2); + emit_eevex_prefix_or_demote_arith_ndd(dst, src1, src2, VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_32bit, 0x23, 0xC0, no_flags, true /* is_commutative */); } void Assembler::andnl(Register dst, Register src1, Register src2) { @@ -2519,7 +2512,7 @@ void Assembler::imull(Register dst, Register src) { } void Assembler::eimull(Register dst, Register src1, Register src2, bool no_flags) { - emit_eevex_or_demote(dst->encoding(), src1->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_32bit, 0xAF, no_flags, true /* is_map1 */, true /* swap */); + emit_eevex_or_demote(dst->encoding(), src1->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_32bit, 0xAF, no_flags, true /* is_map1 */, true /* swap */, true /* is_commutative */); } void Assembler::imull(Register dst, Address src, int32_t value) { @@ -4419,11 +4412,7 @@ void Assembler::enotl(Register dst, Register src) { } void Assembler::eorw(Register dst, Register src1, Register src2, bool no_flags) { - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - // NDD shares its encoding bits with NDS bits for regular EVEX instruction. - // Therefore, DST is passed as the second argument to minimize changes in the leaf level routine. - (void) emit_eevex_prefix_or_demote_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3C /* MAP4 */, &attributes, no_flags); - emit_arith(0x0B, 0xC0, src1, src2); + emit_eevex_prefix_or_demote_arith_ndd(dst, src1, src2, VEX_SIMD_66, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_16bit, 0x0B, 0xC0, no_flags, true /* is_commutative */); } void Assembler::orl(Address dst, int32_t imm32) { @@ -4467,11 +4456,7 @@ void Assembler::orl(Register dst, Register src) { } void Assembler::eorl(Register dst, Register src1, Register src2, bool no_flags) { - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - // NDD shares its encoding bits with NDS bits for regular EVEX instruction. - // Therefore, DST is passed as the second argument to minimize changes in the leaf level routine. - (void) emit_eevex_prefix_or_demote_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, &attributes, no_flags); - emit_arith(0x0B, 0xC0, src1, src2); + emit_eevex_prefix_or_demote_arith_ndd(dst, src1, src2, VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_32bit, 0x0B, 0xC0, no_flags, true /* is_commutative */); } void Assembler::orl(Address dst, Register src) { @@ -4483,11 +4468,7 @@ void Assembler::orl(Address dst, Register src) { void Assembler::eorl(Register dst, Address src1, Register src2, bool no_flags) { InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_32bit); - eevex_prefix_ndd(src1, dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, &attributes, no_flags); - emit_int8(0x09); - emit_operand(src2, src1, 0); + emit_eevex_or_demote(dst, src1, src2, VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_32bit, 0x09, no_flags, false /* is_map1 */, true /* is_commutative */); } void Assembler::orb(Address dst, int imm8) { @@ -4517,11 +4498,7 @@ void Assembler::orb(Address dst, Register src) { void Assembler::eorb(Register dst, Address src1, Register src2, bool no_flags) { InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_8bit); - eevex_prefix_ndd(src1, dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, &attributes, no_flags); - emit_int8(0x08); - emit_operand(src2, src1, 0); + emit_eevex_or_demote(dst, src1, src2, VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_8bit, 0x08, no_flags, false /* is_map1 */, true /* is_commutative */); } void Assembler::packsswb(XMMRegister dst, XMMRegister src) { @@ -7323,11 +7300,7 @@ void Assembler::xorl(Register dst, Register src) { } void Assembler::exorl(Register dst, Register src1, Register src2, bool no_flags) { - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - // NDD shares its encoding bits with NDS bits for regular EVEX instruction. - // Therefore, DST is passed as the second argument to minimize changes in the leaf level routine. - (void) emit_eevex_prefix_or_demote_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, &attributes, no_flags); - emit_arith(0x33, 0xC0, src1, src2); + emit_eevex_prefix_or_demote_arith_ndd(dst, src1, src2, VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_32bit, 0x33, 0xC0, no_flags, true /* is_commutative */); } void Assembler::xorl(Address dst, Register src) { @@ -7339,11 +7312,7 @@ void Assembler::xorl(Address dst, Register src) { void Assembler::exorl(Register dst, Address src1, Register src2, bool no_flags) { InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_32bit); - eevex_prefix_ndd(src1, dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, &attributes, no_flags); - emit_int8(0x31); - emit_operand(src2, src1, 0); + emit_eevex_or_demote(dst, src1, src2, VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_32bit, 0x31, no_flags, false /* is_map1 */, true /* is_commutative */); } void Assembler::xorb(Register dst, Address src) { @@ -7367,11 +7336,7 @@ void Assembler::xorb(Address dst, Register src) { void Assembler::exorb(Register dst, Address src1, Register src2, bool no_flags) { InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_8bit); - eevex_prefix_ndd(src1, dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, &attributes, no_flags); - emit_int8(0x30); - emit_operand(src2, src1, 0); + emit_eevex_or_demote(dst, src1, src2, VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_8bit, 0x30, no_flags, false /* is_map1 */, true /* is_commutative */); } void Assembler::xorw(Register dst, Address src) { @@ -12891,6 +12856,31 @@ void Assembler::eevex_prefix_ndd(Address adr, int ndd_enc, int xreg_enc, VexSimd vex_prefix(adr, ndd_enc, xreg_enc, pre, opc, attributes, /* nds_is_ndd */ true, no_flags); } +void Assembler::emit_eevex_or_demote(Register dst, Address src1, Register src2, VexSimdPrefix pre, VexOpcode opc, + int size, int opcode_byte, bool no_flags, bool is_map1, bool is_commutative) { + if (is_commutative && is_demotable(no_flags, dst->encoding(), src2->encoding())) { + // Opcode byte adjustment due to mismatch between NDD and equivalent demotable variant + opcode_byte += 2; + if (size == EVEX_64bit) { + emit_prefix_and_int8(get_prefixq(src1, dst, is_map1), opcode_byte); + } else { + // For 32-bit, 16-bit and 8-bit + if (size == EVEX_16bit) { + emit_int8(0x66); + } + prefix(src1, dst, false, is_map1); + emit_int8(opcode_byte); + } + } else { + bool vex_w = (size == EVEX_64bit) ? true : false; + InstructionAttr attributes(AVX_128bit, vex_w, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, size); + eevex_prefix_ndd(src1, dst->encoding(), src2->encoding(), pre, opc, &attributes, no_flags); + emit_int8(opcode_byte); + } + emit_operand(src2, src1, 0); +} + void Assembler::emit_eevex_or_demote(Register dst, Register src1, Address src2, VexSimdPrefix pre, VexOpcode opc, int size, int opcode_byte, bool no_flags, bool is_map1) { if (is_demotable(no_flags, dst->encoding(), src1->encoding())) { @@ -12991,18 +12981,20 @@ void Assembler::emit_eevex_or_demote(int dst_enc, int nds_enc, int src_enc, int8 } void Assembler::emit_eevex_or_demote(int dst_enc, int nds_enc, int src_enc, VexSimdPrefix pre, VexOpcode opc, - int size, int opcode_byte, bool no_flags, bool is_map1, bool swap) { + int size, int opcode_byte, bool no_flags, bool is_map1, bool swap, bool is_commutative) { int encode; bool is_prefixq = (size == EVEX_64bit) ? true : false; - if (is_demotable(no_flags, dst_enc, nds_enc)) { + bool first_operand_demotable = is_demotable(no_flags, dst_enc, nds_enc); + bool second_operand_demotable = is_commutative && is_demotable(no_flags, dst_enc, src_enc); + if (first_operand_demotable || second_operand_demotable) { if (size == EVEX_16bit) { emit_int8(0x66); } - + int src = first_operand_demotable ? src_enc : nds_enc; if (swap) { - encode = is_prefixq ? prefixq_and_encode(dst_enc, src_enc, is_map1) : prefix_and_encode(dst_enc, src_enc, is_map1); + encode = is_prefixq ? prefixq_and_encode(dst_enc, src, is_map1) : prefix_and_encode(dst_enc, src, is_map1); } else { - encode = is_prefixq ? prefixq_and_encode(src_enc, dst_enc, is_map1) : prefix_and_encode(src_enc, dst_enc, is_map1); + encode = is_prefixq ? prefixq_and_encode(src, dst_enc, is_map1) : prefix_and_encode(src, dst_enc, is_map1); } emit_opcode_prefix_and_encoding((unsigned char)opcode_byte, 0xC0, encode); } else { @@ -13050,6 +13042,26 @@ int Assembler::eevex_prefix_and_encode_nf(int dst_enc, int nds_enc, int src_enc, return vex_prefix_and_encode(dst_enc, nds_enc, src_enc, pre, opc, attributes, /* src_is_gpr */ true, /* nds_is_ndd */ false, no_flags); } +void Assembler::emit_eevex_prefix_or_demote_arith_ndd(Register dst, Register src1, Register src2, VexSimdPrefix pre, VexOpcode opc, + int size, int op1, int op2, bool no_flags, bool is_commutative) { + bool demotable = is_demotable(no_flags, dst->encoding(), src1->encoding()); + if (!demotable && is_commutative) { + if (is_demotable(no_flags, dst->encoding(), src2->encoding())) { + // swap src1 and src2 + Register tmp = src1; + src1 = src2; + src2 = tmp; + } + } + bool vex_w = (size == EVEX_64bit) ? true : false; + bool use_prefixq = vex_w; + InstructionAttr attributes(AVX_128bit, vex_w, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + // NDD shares its encoding bits with NDS bits for regular EVEX instruction. + // Therefore, DST is passed as the second argument to minimize changes in the leaf level routine. + (void)emit_eevex_prefix_or_demote_ndd(src1->encoding(), dst->encoding(), src2->encoding(), pre, opc, &attributes, no_flags, use_prefixq); + emit_arith(op1, op2, src1, src2); +} + void Assembler::emit_eevex_prefix_or_demote_arith_ndd(Register dst, Register nds, int32_t imm32, VexSimdPrefix pre, VexOpcode opc, int size, int op1, int op2, bool no_flags) { int dst_enc = dst->encoding(); @@ -13060,7 +13072,6 @@ void Assembler::emit_eevex_prefix_or_demote_arith_ndd(Register dst, Register nds } else { bool vex_w = (size == EVEX_64bit) ? true : false; InstructionAttr attributes(AVX_128bit, vex_w, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - //attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, size); attributes.set_is_evex_instruction(); vex_prefix_and_encode(0, dst_enc, nds_enc, pre, opc, &attributes, /* src_is_gpr */ true, /* nds_is_ndd */ true, no_flags); @@ -13689,7 +13700,7 @@ void Assembler::pdepq(Register dst, Register src1, Address src2) { void Assembler::sarxl(Register dst, Register src1, Register src2) { assert(VM_Version::supports_bmi2(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(dst->encoding(), src2->encoding(), src1->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F_38, &attributes, true); emit_int16((unsigned char)0xF7, (0xC0 | encode)); } @@ -13697,7 +13708,7 @@ void Assembler::sarxl(Register dst, Register src1, Register src2) { void Assembler::sarxl(Register dst, Address src1, Register src2) { assert(VM_Version::supports_bmi2(), ""); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_32bit); vex_prefix(src1, src2->encoding(), dst->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF7); @@ -13706,7 +13717,7 @@ void Assembler::sarxl(Register dst, Address src1, Register src2) { void Assembler::sarxq(Register dst, Register src1, Register src2) { assert(VM_Version::supports_bmi2(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(dst->encoding(), src2->encoding(), src1->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F_38, &attributes, true); emit_int16((unsigned char)0xF7, (0xC0 | encode)); } @@ -13714,7 +13725,7 @@ void Assembler::sarxq(Register dst, Register src1, Register src2) { void Assembler::sarxq(Register dst, Address src1, Register src2) { assert(VM_Version::supports_bmi2(), ""); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_64bit); vex_prefix(src1, src2->encoding(), dst->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF7); @@ -13723,7 +13734,7 @@ void Assembler::sarxq(Register dst, Address src1, Register src2) { void Assembler::shlxl(Register dst, Register src1, Register src2) { assert(VM_Version::supports_bmi2(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(dst->encoding(), src2->encoding(), src1->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes, true); emit_int16((unsigned char)0xF7, (0xC0 | encode)); } @@ -13731,7 +13742,7 @@ void Assembler::shlxl(Register dst, Register src1, Register src2) { void Assembler::shlxl(Register dst, Address src1, Register src2) { assert(VM_Version::supports_bmi2(), ""); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_32bit); vex_prefix(src1, src2->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF7); @@ -13740,7 +13751,7 @@ void Assembler::shlxl(Register dst, Address src1, Register src2) { void Assembler::shlxq(Register dst, Register src1, Register src2) { assert(VM_Version::supports_bmi2(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(dst->encoding(), src2->encoding(), src1->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes, true); emit_int16((unsigned char)0xF7, (0xC0 | encode)); } @@ -13748,7 +13759,7 @@ void Assembler::shlxq(Register dst, Register src1, Register src2) { void Assembler::shlxq(Register dst, Address src1, Register src2) { assert(VM_Version::supports_bmi2(), ""); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_64bit); vex_prefix(src1, src2->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF7); @@ -13757,7 +13768,7 @@ void Assembler::shlxq(Register dst, Address src1, Register src2) { void Assembler::shrxl(Register dst, Register src1, Register src2) { assert(VM_Version::supports_bmi2(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(dst->encoding(), src2->encoding(), src1->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F_38, &attributes, true); emit_int16((unsigned char)0xF7, (0xC0 | encode)); } @@ -13765,7 +13776,7 @@ void Assembler::shrxl(Register dst, Register src1, Register src2) { void Assembler::shrxl(Register dst, Address src1, Register src2) { assert(VM_Version::supports_bmi2(), ""); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_32bit); vex_prefix(src1, src2->encoding(), dst->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF7); @@ -13774,7 +13785,7 @@ void Assembler::shrxl(Register dst, Address src1, Register src2) { void Assembler::shrxq(Register dst, Register src1, Register src2) { assert(VM_Version::supports_bmi2(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(dst->encoding(), src2->encoding(), src1->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F_38, &attributes, true); emit_int16((unsigned char)0xF7, (0xC0 | encode)); } @@ -13782,7 +13793,7 @@ void Assembler::shrxq(Register dst, Register src1, Register src2) { void Assembler::shrxq(Register dst, Address src1, Register src2) { assert(VM_Version::supports_bmi2(), ""); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_64bit); vex_prefix(src1, src2->encoding(), dst->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF7); @@ -14543,11 +14554,7 @@ void Assembler::addq(Address dst, Register src) { void Assembler::eaddq(Register dst, Address src1, Register src2, bool no_flags) { InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_64bit); - eevex_prefix_ndd(src1, dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, &attributes, no_flags); - emit_int8(0x01); - emit_operand(src2, src1, 0); + emit_eevex_or_demote(dst, src1, src2, VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_64bit, 0x01, no_flags, false /* is_map1 */, true /* is_commutative */); } void Assembler::addq(Register dst, int32_t imm32) { @@ -14576,11 +14583,7 @@ void Assembler::addq(Register dst, Register src) { } void Assembler::eaddq(Register dst, Register src1, Register src2, bool no_flags) { - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - // NDD shares its encoding bits with NDS bits for regular EVEX instruction. - // Therefore, DST is passed as the second argument to minimize changes in the leaf level routine. - (void) emit_eevex_prefix_or_demote_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, &attributes, no_flags, true /* use_prefixq */); - emit_arith(0x03, 0xC0, src1, src2); + emit_eevex_prefix_or_demote_arith_ndd(dst, src1, src2, VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_64bit, 0x03, 0xC0, no_flags, true /* is_commutative */); } void Assembler::adcxq(Register dst, Register src) { @@ -14673,11 +14676,7 @@ void Assembler::andq(Register dst, Register src) { } void Assembler::eandq(Register dst, Register src1, Register src2, bool no_flags) { - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - // NDD shares its encoding bits with NDS bits for regular EVEX instruction. - // Therefore, DST is passed as the second argument to minimize changes in the leaf level routine. - (void) emit_eevex_prefix_or_demote_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, &attributes, no_flags, true /* use_prefixq */); - emit_arith(0x23, 0xC0, src1, src2); + emit_eevex_prefix_or_demote_arith_ndd(dst, src1, src2, VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_64bit, 0x23, 0xC0, no_flags, true /* is_commutative */); } void Assembler::andq(Address dst, Register src) { @@ -14688,11 +14687,7 @@ void Assembler::andq(Address dst, Register src) { void Assembler::eandq(Register dst, Address src1, Register src2, bool no_flags) { InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_64bit); - eevex_prefix_ndd(src1, dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, &attributes, no_flags); - emit_int8(0x21); - emit_operand(src2, src1, 0); + emit_eevex_or_demote(dst, src1, src2, VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_64bit, 0x21, no_flags, false /* is_map1 */, true /* is_commutative */); } void Assembler::andnq(Register dst, Register src1, Register src2) { @@ -15038,7 +15033,7 @@ void Assembler::eimulq(Register dst, Register src, bool no_flags) { } void Assembler::eimulq(Register dst, Register src1, Register src2, bool no_flags) { - emit_eevex_or_demote(dst->encoding(), src1->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_64bit, 0xAF, no_flags, true /* is_map1 */, true /* swap */); + emit_eevex_or_demote(dst->encoding(), src1->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_64bit, 0xAF, no_flags, true /* is_map1 */, true /* swap */, true /* is_commutative */); } void Assembler::imulq(Register src) { @@ -15500,11 +15495,7 @@ void Assembler::orq(Address dst, Register src) { void Assembler::eorq(Register dst, Address src1, Register src2, bool no_flags) { InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_64bit); - eevex_prefix_ndd(src1, dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, &attributes, no_flags); - emit_int8(0x09); - emit_operand(src2, src1, 0); + emit_eevex_or_demote(dst, src1, src2, VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_64bit, 0x09, no_flags, false /* is_map1 */, true /* is_commutative */); } void Assembler::orq(Register dst, int32_t imm32) { @@ -15544,13 +15535,8 @@ void Assembler::orq(Register dst, Register src) { } void Assembler::eorq(Register dst, Register src1, Register src2, bool no_flags) { - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - // NDD shares its encoding bits with NDS bits for regular EVEX instruction. - // Therefore, DST is passed as the second argument to minimize changes in the leaf level routine. - (void) emit_eevex_prefix_or_demote_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, &attributes, no_flags, true /* use_prefixq */); - emit_arith(0x0B, 0xC0, src1, src2); + emit_eevex_prefix_or_demote_arith_ndd(dst, src1, src2, VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_64bit, 0x0B, 0xC0, no_flags, true /* is_commutative */); } - void Assembler::popcntq(Register dst, Address src) { assert(VM_Version::supports_popcnt(), "must support"); InstructionMark im(this); @@ -16292,11 +16278,7 @@ void Assembler::xorq(Register dst, Register src) { } void Assembler::exorq(Register dst, Register src1, Register src2, bool no_flags) { - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - // NDD shares its encoding bits with NDS bits for regular EVEX instruction. - // Therefore, DST is passed as the second argument to minimize changes in the leaf level routine. - (void) emit_eevex_prefix_or_demote_ndd(src1->encoding(), dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, &attributes, no_flags, true /* use_prefixq */); - emit_arith(0x33, 0xC0, src1, src2); + emit_eevex_prefix_or_demote_arith_ndd(dst, src1, src2, VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_64bit, 0x33, 0xC0, no_flags, true /* is_commutative */); } void Assembler::xorq(Register dst, Address src) { @@ -16350,11 +16332,7 @@ void Assembler::esetzucc(Condition cc, Register dst) { void Assembler::exorq(Register dst, Address src1, Register src2, bool no_flags) { InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_64bit); - eevex_prefix_ndd(src1, dst->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, &attributes, no_flags); - emit_int8(0x31); - emit_operand(src2, src1, 0); + emit_eevex_or_demote(dst, src1, src2, VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, EVEX_64bit, 0x31, no_flags, false /* is_map1 */, true /* is_commutative */); } void InstructionAttr::set_address_attributes(int tuple_type, int input_size_in_bits) { diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp index b1959e23722..28e0cde2157 100644 --- a/src/hotspot/cpu/x86/assembler_x86.hpp +++ b/src/hotspot/cpu/x86/assembler_x86.hpp @@ -796,14 +796,20 @@ class Assembler : public AbstractAssembler { int emit_eevex_prefix_or_demote_ndd(int dst_enc, int nds_enc, VexSimdPrefix pre, VexOpcode opc, InstructionAttr *attributes, bool no_flags = false, bool use_prefixq = false); + void emit_eevex_prefix_or_demote_arith_ndd(Register dst, Register src1, Register src2, VexSimdPrefix pre, VexOpcode opc, + int size, int op1, int op2, bool no_flags = false, bool is_commutative = false); + void emit_eevex_prefix_or_demote_arith_ndd(Register dst, Register nds, int32_t imm32, VexSimdPrefix pre, VexOpcode opc, int size, int op1, int op2, bool no_flags); void emit_eevex_or_demote(Register dst, Register src1, Address src2, VexSimdPrefix pre, VexOpcode opc, int size, int opcode_byte, bool no_flags = false, bool is_map1 = false); + void emit_eevex_or_demote(Register dst, Address src1, Register src2, VexSimdPrefix pre, VexOpcode opc, + int size, int opcode_byte, bool no_flags = false, bool is_map1 = false, bool is_commutative = false); + void emit_eevex_or_demote(int dst_enc, int nds_enc, int src_enc, VexSimdPrefix pre, VexOpcode opc, - int size, int opcode_byte, bool no_flags, bool is_map1 = false, bool swap = false); + int size, int opcode_byte, bool no_flags, bool is_map1 = false, bool swap = false, bool is_commutative = false); void emit_eevex_or_demote(int dst_enc, int nds_enc, int src_enc, int8_t imm8, VexSimdPrefix pre, VexOpcode opc, int size, int opcode_byte, bool no_flags, bool is_map1 = false); @@ -1138,6 +1144,7 @@ class Assembler : public AbstractAssembler { void eandl(Register dst, Register src, int32_t imm32, bool no_flags); void andl(Register dst, Address src); void eandl(Register dst, Register src1, Address src2, bool no_flags); + void eandl(Register dst, Address src1, Register src2, bool no_flags); void andl(Register dst, Register src); void eandl(Register dst, Register src1, Register src2, bool no_flags); void andl(Address dst, Register src); diff --git a/src/hotspot/cpu/x86/c2_stubGenerator_x86_64_string.cpp b/src/hotspot/cpu/x86/c2_stubGenerator_x86_64_string.cpp index ee2d6d8a0be..962f7866259 100644 --- a/src/hotspot/cpu/x86/c2_stubGenerator_x86_64_string.cpp +++ b/src/hotspot/cpu/x86/c2_stubGenerator_x86_64_string.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Intel Corporation. All rights reserved. + * Copyright (c) 2024, 2026, Intel Corporation. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1330,10 +1330,12 @@ static void big_case_loop_helper(bool sizeKnown, int size, Label &noMatch, Label // Clarification: The BYTE_K compare above compares haystack[(n-32):(n-1)]. We need to // compare haystack[(k-1):(k-1+31)]. Subtracting either index gives shift value of // (k + 31 - n): x = (k-1+31)-(n-1) = k-1+31-n+1 = k+31-n. + // When isU is set, similarly, shift is from haystack[(n-32):(n-1)] to [(k-2):(k-2+31)] + if (sizeKnown) { - __ movl(temp2, 31 + size); + __ movl(temp2, (isU ? 30 : 31) + size); } else { - __ movl(temp2, 31); + __ movl(temp2, isU ? 30 : 31); __ addl(temp2, needleLen); } __ subl(temp2, hsLength); diff --git a/src/hotspot/cpu/x86/methodHandles_x86.cpp b/src/hotspot/cpu/x86/methodHandles_x86.cpp index f3683e7d09c..030091b3fe2 100644 --- a/src/hotspot/cpu/x86/methodHandles_x86.cpp +++ b/src/hotspot/cpu/x86/methodHandles_x86.cpp @@ -137,7 +137,7 @@ void MethodHandles::verify_method(MacroAssembler* _masm, Register method, Regist case vmIntrinsicID::_invokeBasic: // Require compiled LambdaForm class to be fully initialized. __ cmpb(Address(method_holder, InstanceKlass::init_state_offset()), InstanceKlass::fully_initialized); - __ jccb(Assembler::equal, L_ok); + __ jcc(Assembler::equal, L_ok); break; case vmIntrinsicID::_linkToStatic: @@ -154,7 +154,7 @@ void MethodHandles::verify_method(MacroAssembler* _masm, Register method, Regist // init_state check failed, but it may be an abstract interface method __ load_unsigned_short(temp, Address(method, Method::access_flags_offset())); __ testl(temp, JVM_ACC_ABSTRACT); - __ jccb(Assembler::notZero, L_ok); + __ jcc(Assembler::notZero, L_ok); break; default: diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp index 2f1e46f3132..2ba5fc69e88 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp @@ -393,6 +393,8 @@ class StubGenerator: public StubCodeGenerator { XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, XMMRegister xmm8); void ghash_last_8_avx2(Register subkeyHtbl); + void check_key_offset(Register key, int offset, int load_size); + // Load key and shuffle operation void ev_load_key(XMMRegister xmmdst, Register key, int offset, XMMRegister xmm_shuf_mask); void ev_load_key(XMMRegister xmmdst, Register key, int offset, Register rscratch); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_aes.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_aes.cpp index 26bf3f7d725..aa523cba524 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_aes.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_aes.cpp @@ -1759,25 +1759,43 @@ void StubGenerator::roundDeclast(XMMRegister xmm_reg) { __ vaesdeclast(xmm8, xmm8, xmm_reg, Assembler::AVX_512bit); } +// Check incoming byte offset against the int[] len. key is the pointer to the int[0]. +// This check happens often, so it is important for it to be very compact. +void StubGenerator::check_key_offset(Register key, int offset, int load_size) { +#ifdef ASSERT + Address key_length(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)); + assert((offset + load_size) % 4 == 0, "Alignment is good: %d + %d", offset, load_size); + int end_offset = (offset + load_size) / 4; + Label L_good; + __ cmpl(key_length, end_offset); + __ jccb(Assembler::greaterEqual, L_good); + __ hlt(); + __ bind(L_good); +#endif +} // Utility routine for loading a 128-bit key word in little endian format void StubGenerator::load_key(XMMRegister xmmdst, Register key, int offset, XMMRegister xmm_shuf_mask) { + check_key_offset(key, offset, 16); __ movdqu(xmmdst, Address(key, offset)); __ pshufb(xmmdst, xmm_shuf_mask); } void StubGenerator::load_key(XMMRegister xmmdst, Register key, int offset, Register rscratch) { + check_key_offset(key, offset, 16); __ movdqu(xmmdst, Address(key, offset)); __ pshufb(xmmdst, ExternalAddress(key_shuffle_mask_addr()), rscratch); } void StubGenerator::ev_load_key(XMMRegister xmmdst, Register key, int offset, XMMRegister xmm_shuf_mask) { + check_key_offset(key, offset, 16); __ movdqu(xmmdst, Address(key, offset)); __ pshufb(xmmdst, xmm_shuf_mask); __ evshufi64x2(xmmdst, xmmdst, xmmdst, 0x0, Assembler::AVX_512bit); } void StubGenerator::ev_load_key(XMMRegister xmmdst, Register key, int offset, Register rscratch) { + check_key_offset(key, offset, 16); __ movdqu(xmmdst, Address(key, offset)); __ pshufb(xmmdst, ExternalAddress(key_shuffle_mask_addr()), rscratch); __ evshufi64x2(xmmdst, xmmdst, xmmdst, 0x0, Assembler::AVX_512bit); @@ -3205,12 +3223,12 @@ void StubGenerator::ghash16_encrypt_parallel16_avx512(Register in, Register out, //AES round 9 roundEncode(AESKEY2, B00_03, B04_07, B08_11, B12_15); - ev_load_key(AESKEY2, key, 11 * 16, rbx); //AES rounds up to 11 (AES192) or 13 (AES256) //AES128 is done __ cmpl(NROUNDS, 52); __ jcc(Assembler::less, last_aes_rnd); __ bind(aes_192); + ev_load_key(AESKEY2, key, 11 * 16, rbx); roundEncode(AESKEY1, B00_03, B04_07, B08_11, B12_15); ev_load_key(AESKEY1, key, 12 * 16, rbx); roundEncode(AESKEY2, B00_03, B04_07, B08_11, B12_15); @@ -3506,10 +3524,10 @@ void StubGenerator::aesgcm_avx512(Register in, Register len, Register ct, Regist false, true, false, false, false, ghashin_offset, aesout_offset, HashKey_32); ghash16_avx512(false, true, false, false, true, in, pos, avx512_subkeyHtbl, AAD_HASHx, SHUF_MASK, stack_offset, 16 * 16, 0, HashKey_16); + __ addl(pos, 16 * 16); __ bind(MESG_BELOW_32_BLKS); __ subl(len, 16 * 16); - __ addl(pos, 16 * 16); gcm_enc_dec_last_avx512(len, in, pos, AAD_HASHx, SHUF_MASK, avx512_subkeyHtbl, ghashin_offset, HashKey_16, true, true); __ bind(GHASH_DONE); @@ -3998,13 +4016,15 @@ void StubGenerator::aesgcm_avx2(Register in, Register len, Register ct, Register const Register rounds = r10; const XMMRegister ctr_blockx = xmm9; const XMMRegister aad_hashx = xmm8; - Label encrypt_done, encrypt_by_8_new, encrypt_by_8; + Label encrypt_done, encrypt_by_8_new, encrypt_by_8, exit; //This routine should be called only for message sizes of 128 bytes or more. //Macro flow: //process 8 16 byte blocks in initial_num_blocks. //process 8 16 byte blocks at a time until all are done 'encrypt_by_8_new followed by ghash_last_8' __ xorl(pos, pos); + __ cmpl(len, 128); + __ jcc(Assembler::less, exit); //Generate 8 constants for htbl generateHtbl_8_block_avx2(subkeyHtbl); @@ -4072,6 +4092,7 @@ void StubGenerator::aesgcm_avx2(Register in, Register len, Register ct, Register __ vpxor(xmm0, xmm0, xmm0, Assembler::AVX_128bit); __ vpxor(xmm13, xmm13, xmm13, Assembler::AVX_128bit); + __ bind(exit); } #undef __ diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_exp.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_exp.cpp index b48ed80788b..f59647230ee 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_exp.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_exp.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2016, 2024, Intel Corporation. All rights reserved. -* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. +* Copyright (C) 2021, Tencent. All rights reserved. * Intel Math Library (LIBM) Source Code * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_log.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_log.cpp index 6aacfaaea03..e6e014fbf1b 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_log.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_log.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2016, 2024, Intel Corporation. All rights reserved. -* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. +* Copyright (C) 2021, Tencent. All rights reserved. * Intel Math Library (LIBM) Source Code * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_pow.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_pow.cpp index 4029e53d1b1..fb83f4f7d42 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_pow.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_pow.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2016, 2024, Intel Corporation. All rights reserved. -* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. +* Copyright (C) 2021, Tencent. All rights reserved. * Intel Math Library (LIBM) Source Code * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. diff --git a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp index 9ea4aeeccfa..46af93e9760 100644 --- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp @@ -465,13 +465,19 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dtan)); } } else if (kind == Interpreter::java_lang_math_tanh) { - assert(StubRoutines::dtanh() != nullptr, "not initialized"); + if (StubRoutines::dtanh() != nullptr) { __ movdbl(xmm0, Address(rsp, wordSize)); __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dtanh()))); + } else { + return nullptr; // Fallback to default implementation + } } else if (kind == Interpreter::java_lang_math_cbrt) { - assert(StubRoutines::dcbrt() != nullptr, "not initialized"); - __ movdbl(xmm0, Address(rsp, wordSize)); - __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dcbrt()))); + if (StubRoutines::dcbrt() != nullptr) { + __ movdbl(xmm0, Address(rsp, wordSize)); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dcbrt()))); + } else { + return nullptr; // Fallback to default implementation + } } else if (kind == Interpreter::java_lang_math_abs) { assert(StubRoutines::x86::double_sign_mask() != nullptr, "not initialized"); __ movdbl(xmm0, Address(rsp, wordSize)); diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 5011eb45991..8fc9c2f9eaa 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -138,7 +138,7 @@ class VM_Version_StubGenerator: public StubCodeGenerator { const uint32_t CPU_FAMILY_486 = (4 << CPU_FAMILY_SHIFT); bool use_evex = FLAG_IS_DEFAULT(UseAVX) || (UseAVX > 2); - Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4, std_cpuid24; + Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4, std_cpuid24, std_cpuid29; Label sef_cpuid, sefsl1_cpuid, ext_cpuid, ext_cpuid1, ext_cpuid5, ext_cpuid7; Label ext_cpuid8, done, wrapup, vector_save_restore, apx_save_restore_warning; Label legacy_setup, save_restore_except, legacy_save_restore, start_simd_check; @@ -337,6 +337,16 @@ class VM_Version_StubGenerator: public StubCodeGenerator { __ movl(Address(rsi, 0), rax); __ movl(Address(rsi, 4), rdx); + // + // cpuid(0x29) APX NCI NDD NF (EAX = 29H, ECX = 0). + // + __ bind(std_cpuid29); + __ movl(rax, 0x29); + __ movl(rcx, 0); + __ cpuid(); + __ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid29_offset()))); + __ movl(Address(rsi, 0), rbx); + // // cpuid(0x24) Converged Vector ISA Main Leaf (EAX = 24H, ECX = 0). // @@ -1015,16 +1025,6 @@ void VM_Version::get_processor_features() { _features.clear_feature(CPU_AVX10_2); } - // Currently APX support is only enabled for targets supporting AVX512VL feature. - bool apx_supported = os_supports_apx_egprs() && supports_apx_f() && supports_avx512vl(); - if (UseAPX && !apx_supported) { - warning("UseAPX is not supported on this CPU, setting it to false"); - FLAG_SET_DEFAULT(UseAPX, false); - } - - if (!UseAPX) { - _features.clear_feature(CPU_APX_F); - } if (UseAVX < 2) { _features.clear_feature(CPU_AVX2); @@ -1048,6 +1048,7 @@ void VM_Version::get_processor_features() { _features.clear_feature(CPU_VZEROUPPER); _features.clear_feature(CPU_AVX512BW); _features.clear_feature(CPU_AVX512VL); + _features.clear_feature(CPU_APX_F); _features.clear_feature(CPU_AVX512DQ); _features.clear_feature(CPU_AVX512_VNNI); _features.clear_feature(CPU_AVX512_VAES); @@ -1067,8 +1068,20 @@ void VM_Version::get_processor_features() { } } + // Currently APX support is only enabled for targets supporting AVX512VL feature. + bool apx_supported = os_supports_apx_egprs() && supports_apx_f() && supports_avx512vl(); + if (UseAPX && !apx_supported) { + warning("UseAPX is not supported on this CPU, setting it to false"); + FLAG_SET_DEFAULT(UseAPX, false); + } + + if (!UseAPX) { + _features.clear_feature(CPU_APX_F); + } + if (FLAG_IS_DEFAULT(IntelJccErratumMitigation)) { _has_intel_jcc_erratum = compute_has_intel_jcc_erratum(); + FLAG_SET_ERGO(IntelJccErratumMitigation, _has_intel_jcc_erratum); } else { _has_intel_jcc_erratum = IntelJccErratumMitigation; } @@ -2932,7 +2945,8 @@ VM_Version::VM_Features VM_Version::CpuidInfo::feature_flags() const { if (std_cpuid1_ecx.bits.popcnt != 0) vm_features.set_feature(CPU_POPCNT); if (sefsl1_cpuid7_edx.bits.apx_f != 0 && - xem_xcr0_eax.bits.apx_f != 0) { + xem_xcr0_eax.bits.apx_f != 0 && + std_cpuid29_ebx.bits.apx_nci_ndd_nf != 0) { vm_features.set_feature(CPU_APX_F); } if (std_cpuid1_ecx.bits.avx != 0 && diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index 3c8971e474b..78ae45ef4f8 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -303,6 +303,14 @@ class VM_Version : public Abstract_VM_Version { } bits; }; + union StdCpuidEax29Ecx0 { + uint32_t value; + struct { + uint32_t apx_nci_ndd_nf : 1, + : 31; + } bits; + }; + union StdCpuid24MainLeafEax { uint32_t value; struct { @@ -587,6 +595,10 @@ class VM_Version : public Abstract_VM_Version { StdCpuid24MainLeafEax std_cpuid24_eax; StdCpuid24MainLeafEbx std_cpuid24_ebx; + // cpuid function 0x29 APX Advanced Performance Extensions Leaf + // eax = 0x29, ecx = 0 + StdCpuidEax29Ecx0 std_cpuid29_ebx; + // cpuid function 0xB (processor topology) // ecx = 0 uint32_t tpl_cpuidB0_eax; @@ -707,6 +719,7 @@ class VM_Version : public Abstract_VM_Version { static ByteSize std_cpuid0_offset() { return byte_offset_of(CpuidInfo, std_max_function); } static ByteSize std_cpuid1_offset() { return byte_offset_of(CpuidInfo, std_cpuid1_eax); } static ByteSize std_cpuid24_offset() { return byte_offset_of(CpuidInfo, std_cpuid24_eax); } + static ByteSize std_cpuid29_offset() { return byte_offset_of(CpuidInfo, std_cpuid29_ebx); } static ByteSize dcp_cpuid4_offset() { return byte_offset_of(CpuidInfo, dcp_cpuid4_eax); } static ByteSize sef_cpuid7_offset() { return byte_offset_of(CpuidInfo, sef_cpuid7_eax); } static ByteSize sefsl1_cpuid7_offset() { return byte_offset_of(CpuidInfo, sefsl1_cpuid7_eax); } @@ -756,7 +769,9 @@ class VM_Version : public Abstract_VM_Version { _features.set_feature(CPU_SSE2); _features.set_feature(CPU_VZEROUPPER); } - static void set_apx_cpuFeatures() { _features.set_feature(CPU_APX_F); } + static void set_apx_cpuFeatures() { + _features.set_feature(CPU_APX_F); + } static void set_bmi_cpuFeatures() { _features.set_feature(CPU_BMI1); _features.set_feature(CPU_BMI2); diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index e7b401701ac..50a219f0824 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -2504,7 +2504,7 @@ static bool thread_cpu_time_unchecked(Thread* thread, jlong* p_sys_time, jlong* 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; } @@ -2515,7 +2515,7 @@ static bool thread_cpu_time_unchecked(Thread* thread, jlong* p_sys_time, jlong* 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 --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index 3535d027dbc..868725fdb67 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -154,7 +154,8 @@ julong os::Bsd::available_memory() { assert(kerr == KERN_SUCCESS, "host_statistics64 failed - check mach_host_self() and count"); if (kerr == KERN_SUCCESS) { - available = vmstat.free_count * os::vm_page_size(); + // free_count is just a lowerbound, other page categories can be freed too and make memory available + available = (vmstat.free_count + vmstat.inactive_count + vmstat.purgeable_count) * os::vm_page_size(); } #endif return available; diff --git a/src/hotspot/os/linux/cgroupSubsystem_linux.cpp b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp index 068914d7049..a9cabc87335 100644 --- a/src/hotspot/os/linux/cgroupSubsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp @@ -62,7 +62,7 @@ CgroupSubsystem* CgroupSubsystemFactory::create() { CgroupV1MemoryController* memory = nullptr; CgroupV1Controller* cpuset = nullptr; CgroupV1CpuController* cpu = nullptr; - CgroupV1Controller* cpuacct = nullptr; + CgroupV1CpuacctController* cpuacct = nullptr; CgroupV1Controller* pids = nullptr; CgroupInfo cg_infos[CG_INFO_LENGTH]; u1 cg_type_flags = INVALID_CGROUPS_GENERIC; @@ -105,9 +105,10 @@ CgroupSubsystem* CgroupSubsystemFactory::create() { CgroupV2CpuController* cpu = new CgroupV2CpuController(CgroupV2Controller(cg_infos[CPU_IDX]._mount_path, cg_infos[CPU_IDX]._cgroup_path, cg_infos[CPU_IDX]._read_only)); + CgroupV2CpuacctController* cpuacct = new CgroupV2CpuacctController(cpu); log_debug(os, container)("Detected cgroups v2 unified hierarchy"); cleanup(cg_infos); - return new CgroupV2Subsystem(memory, cpu, mem_other); + return new CgroupV2Subsystem(memory, cpu, cpuacct, mem_other); } /* @@ -150,7 +151,7 @@ CgroupSubsystem* CgroupSubsystemFactory::create() { cpu = new CgroupV1CpuController(CgroupV1Controller(info._root_mount_path, info._mount_path, info._read_only)); cpu->set_subsystem_path(info._cgroup_path); } else if (strcmp(info._name, "cpuacct") == 0) { - cpuacct = new CgroupV1Controller(info._root_mount_path, info._mount_path, info._read_only); + cpuacct = new CgroupV1CpuacctController(CgroupV1Controller(info._root_mount_path, info._mount_path, info._read_only)); cpuacct->set_subsystem_path(info._cgroup_path); } else if (strcmp(info._name, "pids") == 0) { pids = new CgroupV1Controller(info._root_mount_path, info._mount_path, info._read_only); @@ -856,6 +857,10 @@ jlong CgroupSubsystem::memory_soft_limit_in_bytes() { return memory_controller()->controller()->memory_soft_limit_in_bytes(phys_mem); } +jlong CgroupSubsystem::memory_throttle_limit_in_bytes() { + return memory_controller()->controller()->memory_throttle_limit_in_bytes(); +} + jlong CgroupSubsystem::memory_usage_in_bytes() { return memory_controller()->controller()->memory_usage_in_bytes(); } @@ -884,6 +889,10 @@ int CgroupSubsystem::cpu_shares() { return cpu_controller()->controller()->cpu_shares(); } +jlong CgroupSubsystem::cpu_usage_in_micros() { + return cpuacct_controller()->cpu_usage_in_micros(); +} + void CgroupSubsystem::print_version_specific_info(outputStream* st) { julong phys_mem = os::Linux::physical_memory(); memory_controller()->controller()->print_version_specific_info(st, phys_mem); diff --git a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp index 53b178397f8..82fc87ef4f4 100644 --- a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -102,6 +102,17 @@ log_trace(os, container)(log_string " is: %s", retval); \ } +#define CONTAINER_READ_NUMERICAL_KEY_VALUE_CHECKED(controller, filename, key, log_string, retval) \ +{ \ + bool is_ok; \ + is_ok = controller->read_numerical_key_value(filename, key, &retval); \ + if (!is_ok) { \ + log_trace(os, container)(log_string " failed: %d", OSCONTAINER_ERROR); \ + return OSCONTAINER_ERROR; \ + } \ + log_trace(os, container)(log_string " is: " JULONG_FORMAT, retval); \ +} + class CgroupController: public CHeapObj { protected: char* _cgroup_path; @@ -216,6 +227,18 @@ class CgroupCpuController: public CHeapObj { virtual const char* cgroup_path() = 0; }; +// Pure virtual class representing version agnostic CPU accounting controllers +class CgroupCpuacctController: public CHeapObj { + public: + virtual jlong cpu_usage_in_micros() = 0; + virtual bool needs_hierarchy_adjustment() = 0; + virtual bool is_read_only() = 0; + virtual const char* subsystem_path() = 0; + virtual void set_subsystem_path(const char* cgroup_path) = 0; + virtual const char* mount_point() = 0; + virtual const char* cgroup_path() = 0; +}; + // Pure virtual class representing version agnostic memory controllers class CgroupMemoryController: public CHeapObj { public: @@ -224,6 +247,7 @@ class CgroupMemoryController: public CHeapObj { virtual jlong memory_and_swap_limit_in_bytes(julong host_mem, julong host_swap) = 0; virtual jlong memory_and_swap_usage_in_bytes(julong host_mem, julong host_swap) = 0; virtual jlong memory_soft_limit_in_bytes(julong upper_bound) = 0; + virtual jlong memory_throttle_limit_in_bytes() = 0; virtual jlong memory_max_usage_in_bytes() = 0; virtual jlong rss_usage_in_bytes() = 0; virtual jlong cache_usage_in_bytes() = 0; @@ -250,15 +274,19 @@ class CgroupSubsystem: public CHeapObj { virtual const char * container_type() = 0; virtual CachingCgroupController* memory_controller() = 0; virtual CachingCgroupController* cpu_controller() = 0; + virtual CgroupCpuacctController* cpuacct_controller() = 0; int cpu_quota(); int cpu_period(); int cpu_shares(); + jlong cpu_usage_in_micros(); + jlong memory_usage_in_bytes(); jlong memory_and_swap_limit_in_bytes(); jlong memory_and_swap_usage_in_bytes(); jlong memory_soft_limit_in_bytes(); + jlong memory_throttle_limit_in_bytes(); jlong memory_max_usage_in_bytes(); jlong rss_usage_in_bytes(); jlong cache_usage_in_bytes(); diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp index 8d9c3edb72a..ce5ef3614d1 100644 --- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp @@ -123,6 +123,12 @@ void CgroupV1Controller::set_subsystem_path(const char* cgroup_path) { } } +jlong CgroupV1MemoryController::uses_mem_hierarchy() { + julong use_hierarchy; + CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.use_hierarchy", "Use Hierarchy", use_hierarchy); + return (jlong)use_hierarchy; +} + /* * The common case, containers, we have _root == _cgroup_path, and thus set the * controller path to the _mount_point. This is where the limits are exposed in @@ -159,13 +165,13 @@ void verbose_log(julong read_mem_limit, julong host_mem) { jlong CgroupV1MemoryController::read_memory_limit_in_bytes(julong phys_mem) { julong memlimit; CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.limit_in_bytes", "Memory Limit", memlimit); - if (memlimit >= phys_mem) { - verbose_log(memlimit, phys_mem); - return (jlong)-1; - } else { - verbose_log(memlimit, phys_mem); - return (jlong)memlimit; + if (memlimit >= phys_mem && uses_mem_hierarchy()) { + CONTAINER_READ_NUMERICAL_KEY_VALUE_CHECKED(reader(), "/memory.stat", + "hierarchical_memory_limit", "Hierarchical Memory Limit", + memlimit); } + verbose_log(memlimit, phys_mem); + return (jlong)((memlimit < phys_mem) ? memlimit : -1); } /* read_mem_swap @@ -183,12 +189,13 @@ jlong CgroupV1MemoryController::read_memory_limit_in_bytes(julong phys_mem) { jlong CgroupV1MemoryController::read_mem_swap(julong host_total_memsw) { julong memswlimit; CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.memsw.limit_in_bytes", "Memory and Swap Limit", memswlimit); - if (memswlimit >= host_total_memsw) { - log_trace(os, container)("Memory and Swap Limit is: Unlimited"); - return (jlong)-1; - } else { - return (jlong)memswlimit; + if (memswlimit >= host_total_memsw && uses_mem_hierarchy()) { + CONTAINER_READ_NUMERICAL_KEY_VALUE_CHECKED(reader(), "/memory.stat", + "hierarchical_memsw_limit", "Hierarchical Memory and Swap Limit", + memswlimit); } + verbose_log(memswlimit, host_total_memsw); + return (jlong)((memswlimit < host_total_memsw) ? memswlimit : -1); } jlong CgroupV1MemoryController::memory_and_swap_limit_in_bytes(julong host_mem, julong host_swap) { @@ -248,10 +255,16 @@ jlong CgroupV1MemoryController::memory_soft_limit_in_bytes(julong phys_mem) { } } +jlong CgroupV1MemoryController::memory_throttle_limit_in_bytes() { + // Log this string at trace level so as to make tests happy. + log_trace(os, container)("Memory Throttle Limit is not supported."); + return OSCONTAINER_ERROR; // not supported +} + // Constructor CgroupV1Subsystem::CgroupV1Subsystem(CgroupV1Controller* cpuset, CgroupV1CpuController* cpu, - CgroupV1Controller* cpuacct, + CgroupV1CpuacctController* cpuacct, CgroupV1Controller* pids, CgroupV1MemoryController* memory) : _cpuset(cpuset), @@ -416,6 +429,13 @@ int CgroupV1CpuController::cpu_shares() { return shares_int; } +jlong CgroupV1CpuacctController::cpu_usage_in_micros() { + julong cpu_usage; + CONTAINER_READ_NUMBER_CHECKED(reader(), "/cpuacct.usage", "CPU Usage", cpu_usage); + // Output is in nanoseconds, convert to microseconds. + return (jlong)cpu_usage / 1000; +} + /* pids_max * * Return the maximum number of tasks available to the process diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp index 0c191ab91c7..a986178f5bb 100644 --- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -82,6 +82,7 @@ class CgroupV1MemoryController final : public CgroupMemoryController { jlong memory_and_swap_limit_in_bytes(julong host_mem, julong host_swap) override; jlong memory_and_swap_usage_in_bytes(julong host_mem, julong host_swap) override; jlong memory_soft_limit_in_bytes(julong upper_bound) override; + jlong memory_throttle_limit_in_bytes() override; jlong memory_max_usage_in_bytes() override; jlong rss_usage_in_bytes() override; jlong cache_usage_in_bytes() override; @@ -99,6 +100,7 @@ class CgroupV1MemoryController final : public CgroupMemoryController { const char* mount_point() override { return reader()->mount_point(); } const char* cgroup_path() override { return reader()->cgroup_path(); } private: + jlong uses_mem_hierarchy(); jlong read_mem_swappiness(); jlong read_mem_swap(julong host_total_memsw); @@ -140,12 +142,41 @@ class CgroupV1CpuController final : public CgroupCpuController { } }; +class CgroupV1CpuacctController final : public CgroupCpuacctController { + + private: + CgroupV1Controller _reader; + CgroupV1Controller* reader() { return &_reader; } + public: + jlong cpu_usage_in_micros() override; + void set_subsystem_path(const char *cgroup_path) override { + reader()->set_subsystem_path(cgroup_path); + } + bool is_read_only() override { + return reader()->is_read_only(); + } + const char* subsystem_path() override { + return reader()->subsystem_path(); + } + const char* mount_point() override { + return reader()->mount_point(); + } + bool needs_hierarchy_adjustment() override { + return reader()->needs_hierarchy_adjustment(); + } + const char* cgroup_path() override { return reader()->cgroup_path(); } + + public: + CgroupV1CpuacctController(const CgroupV1Controller& reader) : _reader(reader) { + } +}; + class CgroupV1Subsystem: public CgroupSubsystem { public: CgroupV1Subsystem(CgroupV1Controller* cpuset, CgroupV1CpuController* cpu, - CgroupV1Controller* cpuacct, + CgroupV1CpuacctController* cpuacct, CgroupV1Controller* pids, CgroupV1MemoryController* memory); @@ -165,13 +196,14 @@ class CgroupV1Subsystem: public CgroupSubsystem { } CachingCgroupController* memory_controller() { return _memory; } CachingCgroupController* cpu_controller() { return _cpu; } + CgroupCpuacctController* cpuacct_controller() { return _cpuacct; } private: /* controllers */ CachingCgroupController* _memory = nullptr; CgroupV1Controller* _cpuset = nullptr; CachingCgroupController* _cpu = nullptr; - CgroupV1Controller* _cpuacct = nullptr; + CgroupV1CpuacctController* _cpuacct = nullptr; CgroupV1Controller* _pids = nullptr; }; diff --git a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp index cbadbb9db02..6472fdfccc5 100644 --- a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2020, 2025, Red Hat Inc. + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -114,12 +115,14 @@ int CgroupV2CpuController::cpu_quota() { // Constructor CgroupV2Subsystem::CgroupV2Subsystem(CgroupV2MemoryController * memory, CgroupV2CpuController* cpu, + CgroupV2CpuacctController* cpuacct, CgroupV2Controller unified) : _unified(unified) { CgroupUtil::adjust_controller(memory); CgroupUtil::adjust_controller(cpu); _memory = new CachingCgroupController(memory); _cpu = new CachingCgroupController(cpu); + _cpuacct = cpuacct; } bool CgroupV2Subsystem::is_containerized() { @@ -152,6 +155,17 @@ int CgroupV2CpuController::cpu_period() { return period; } +jlong CgroupV2CpuController::cpu_usage_in_micros() { + julong cpu_usage; + bool is_ok = reader()->read_numerical_key_value("/cpu.stat", "usage_usec", &cpu_usage); + if (!is_ok) { + log_trace(os, container)("CPU Usage failed: %d", OSCONTAINER_ERROR); + return OSCONTAINER_ERROR; + } + log_trace(os, container)("CPU Usage is: " JULONG_FORMAT, cpu_usage); + return (jlong)cpu_usage; +} + /* memory_usage_in_bytes * * Return the amount of used memory used by this cgroup and descendents @@ -173,10 +187,16 @@ jlong CgroupV2MemoryController::memory_soft_limit_in_bytes(julong phys_mem) { return mem_soft_limit; } +jlong CgroupV2MemoryController::memory_throttle_limit_in_bytes() { + jlong mem_throttle_limit; + CONTAINER_READ_NUMBER_CHECKED_MAX(reader(), "/memory.high", "Memory Throttle Limit", mem_throttle_limit); + return mem_throttle_limit; +} + jlong CgroupV2MemoryController::memory_max_usage_in_bytes() { - // Log this string at trace level so as to make tests happy. - log_trace(os, container)("Maximum Memory Usage is not supported."); - return OSCONTAINER_ERROR; // not supported + julong mem_max_usage; + CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.peak", "Maximum Memory Usage", mem_max_usage); + return mem_max_usage; } jlong CgroupV2MemoryController::rss_usage_in_bytes() { diff --git a/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp b/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp index 56dcadd670f..e26f37925ca 100644 --- a/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2020, 2024, Red Hat Inc. + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,6 +62,34 @@ class CgroupV2CpuController: public CgroupCpuController { int cpu_quota() override; int cpu_period() override; int cpu_shares() override; + jlong cpu_usage_in_micros(); + bool is_read_only() override { + return reader()->is_read_only(); + } + const char* subsystem_path() override { + return reader()->subsystem_path(); + } + bool needs_hierarchy_adjustment() override { + return reader()->needs_hierarchy_adjustment(); + } + void set_subsystem_path(const char* cgroup_path) override { + reader()->set_subsystem_path(cgroup_path); + } + const char* mount_point() override { return reader()->mount_point(); } + const char* cgroup_path() override { return reader()->cgroup_path(); } +}; + +class CgroupV2CpuacctController: public CgroupCpuacctController { + private: + CgroupV2CpuController* _reader; + CgroupV2CpuController* reader() { return _reader; } + public: + CgroupV2CpuacctController(CgroupV2CpuController* reader) : _reader(reader) { + } + // In cgroup v2, cpu usage is a part of the cpu controller. + jlong cpu_usage_in_micros() override { + return reader()->cpu_usage_in_micros(); + } bool is_read_only() override { return reader()->is_read_only(); } @@ -89,6 +118,7 @@ class CgroupV2MemoryController final: public CgroupMemoryController { jlong memory_and_swap_limit_in_bytes(julong host_mem, julong host_swp) override; jlong memory_and_swap_usage_in_bytes(julong host_mem, julong host_swp) override; jlong memory_soft_limit_in_bytes(julong upper_bound) override; + jlong memory_throttle_limit_in_bytes() override; jlong memory_usage_in_bytes() override; jlong memory_max_usage_in_bytes() override; jlong rss_usage_in_bytes() override; @@ -118,11 +148,14 @@ class CgroupV2Subsystem: public CgroupSubsystem { CachingCgroupController* _memory = nullptr; CachingCgroupController* _cpu = nullptr; + CgroupCpuacctController* _cpuacct = nullptr; + CgroupV2Controller* unified() { return &_unified; } public: CgroupV2Subsystem(CgroupV2MemoryController * memory, CgroupV2CpuController* cpu, + CgroupV2CpuacctController* cpuacct, CgroupV2Controller unified); char * cpu_cpuset_cpus() override; @@ -137,6 +170,7 @@ class CgroupV2Subsystem: public CgroupSubsystem { } CachingCgroupController* memory_controller() override { return _memory; } CachingCgroupController* cpu_controller() override { return _cpu; } + CgroupCpuacctController* cpuacct_controller() override { return _cpuacct; }; }; #endif // CGROUP_V2_SUBSYSTEM_LINUX_HPP diff --git a/src/hotspot/os/linux/osContainer_linux.cpp b/src/hotspot/os/linux/osContainer_linux.cpp index ecac7307c30..2ba4c252659 100644 --- a/src/hotspot/os/linux/osContainer_linux.cpp +++ b/src/hotspot/os/linux/osContainer_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -122,6 +122,11 @@ jlong OSContainer::memory_soft_limit_in_bytes() { return cgroup_subsystem->memory_soft_limit_in_bytes(); } +jlong OSContainer::memory_throttle_limit_in_bytes() { + assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); + return cgroup_subsystem->memory_throttle_limit_in_bytes(); +} + jlong OSContainer::memory_usage_in_bytes() { assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); return cgroup_subsystem->memory_usage_in_bytes(); @@ -177,6 +182,11 @@ int OSContainer::cpu_shares() { return cgroup_subsystem->cpu_shares(); } +jlong OSContainer::cpu_usage_in_micros() { + assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); + return cgroup_subsystem->cpu_usage_in_micros(); +} + jlong OSContainer::pids_max() { assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); return cgroup_subsystem->pids_max(); diff --git a/src/hotspot/os/linux/osContainer_linux.hpp b/src/hotspot/os/linux/osContainer_linux.hpp index dd29c7a4769..3c270e8ea50 100644 --- a/src/hotspot/os/linux/osContainer_linux.hpp +++ b/src/hotspot/os/linux/osContainer_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,6 +54,7 @@ class OSContainer: AllStatic { static jlong memory_and_swap_limit_in_bytes(); static jlong memory_and_swap_usage_in_bytes(); static jlong memory_soft_limit_in_bytes(); + static jlong memory_throttle_limit_in_bytes(); static jlong memory_usage_in_bytes(); static jlong memory_max_usage_in_bytes(); static jlong rss_usage_in_bytes(); @@ -69,6 +70,8 @@ class OSContainer: AllStatic { static int cpu_shares(); + static jlong cpu_usage_in_micros(); + static jlong pids_max(); static jlong pids_current(); }; diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 807014e7b0c..fc0578f4d9b 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -349,11 +349,20 @@ julong os::physical_memory() { return phys_mem; } +// Returns the resident set size (RSS) of the process. +// Falls back to using VmRSS from /proc/self/status if /proc/self/smaps_rollup is unavailable. +// Note: On kernels with memory cgroups or shared memory, VmRSS may underreport RSS. +// Users requiring accurate RSS values should be aware of this limitation. size_t os::rss() { size_t size = 0; - os::Linux::meminfo_t info; - if (os::Linux::query_process_memory_info(&info)) { - size = info.vmrss * K; + os::Linux::accurate_meminfo_t accurate_info; + if (os::Linux::query_accurate_process_memory_info(&accurate_info) && accurate_info.rss != -1) { + size = accurate_info.rss * K; + } else { + os::Linux::meminfo_t info; + if (os::Linux::query_process_memory_info(&info)) { + size = info.vmrss * K; + } } return size; } @@ -469,13 +478,11 @@ bool os::Linux::get_tick_information(CPUPerfTicks* pticks, int which_logical_cpu } #ifndef SYS_gettid -// i386: 224, amd64: 186, sparc: 143 +// i386: 224, amd64: 186 #if defined(__i386__) #define SYS_gettid 224 #elif defined(__amd64__) #define SYS_gettid 186 - #elif defined(__sparc__) - #define SYS_gettid 143 #else #error "Define SYS_gettid for this architecture" #endif @@ -2346,6 +2353,37 @@ bool os::Linux::query_process_memory_info(os::Linux::meminfo_t* info) { return false; } +// Accurate memory information need Linux 4.14 or newer +bool os::Linux::query_accurate_process_memory_info(os::Linux::accurate_meminfo_t* info) { + FILE* f = os::fopen("/proc/self/smaps_rollup", "r"); + if (f == nullptr) { + return false; + } + + const size_t num_values = sizeof(os::Linux::accurate_meminfo_t) / sizeof(size_t); + size_t num_found = 0; + char buf[256]; + info->rss = info->pss = info->pssdirty = info->pssanon = + info->pssfile = info->pssshmem = info->swap = info->swappss = -1; + + while (::fgets(buf, sizeof(buf), f) != nullptr && num_found < num_values) { + if ( (info->rss == -1 && sscanf(buf, "Rss: %zd kB", &info->rss) == 1) || + (info->pss == -1 && sscanf(buf, "Pss: %zd kB", &info->pss) == 1) || + (info->pssdirty == -1 && sscanf(buf, "Pss_Dirty: %zd kB", &info->pssdirty) == 1) || + (info->pssanon == -1 && sscanf(buf, "Pss_Anon: %zd kB", &info->pssanon) == 1) || + (info->pssfile == -1 && sscanf(buf, "Pss_File: %zd kB", &info->pssfile) == 1) || + (info->pssshmem == -1 && sscanf(buf, "Pss_Shmem: %zd kB", &info->pssshmem) == 1) || + (info->swap == -1 && sscanf(buf, "Swap: %zd kB", &info->swap) == 1) || + (info->swappss == -1 && sscanf(buf, "SwapPss: %zd kB", &info->swappss) == 1) + ) + { + num_found ++; + } + } + fclose(f); + return true; +} + #ifdef __GLIBC__ // For Glibc, print a one-liner with the malloc tunables. // Most important and popular is MALLOC_ARENA_MAX, but we are @@ -2430,6 +2468,7 @@ void os::Linux::print_uptime_info(outputStream* st) { if (ret == 0) { os::print_dhm(st, "OS uptime:", (long) sinfo.uptime); } + assert(ret == 0, "sysinfo failed: %s", os::strerror(errno)); } bool os::Linux::print_container_info(outputStream* st) { @@ -2487,9 +2526,18 @@ bool os::Linux::print_container_info(outputStream* st) { st->print_cr("%s", i == OSCONTAINER_ERROR ? "not supported" : "no shares"); } + jlong j = OSContainer::cpu_usage_in_micros(); + st->print("cpu_usage_in_micros: "); + if (j >= 0) { + st->print_cr(JLONG_FORMAT, j); + } else { + st->print_cr("%s", j == OSCONTAINER_ERROR ? "not supported" : "no usage"); + } + OSContainer::print_container_helper(st, OSContainer::memory_limit_in_bytes(), "memory_limit_in_bytes"); OSContainer::print_container_helper(st, OSContainer::memory_and_swap_limit_in_bytes(), "memory_and_swap_limit_in_bytes"); OSContainer::print_container_helper(st, OSContainer::memory_soft_limit_in_bytes(), "memory_soft_limit_in_bytes"); + OSContainer::print_container_helper(st, OSContainer::memory_throttle_limit_in_bytes(), "memory_throttle_limit_in_bytes"); OSContainer::print_container_helper(st, OSContainer::memory_usage_in_bytes(), "memory_usage_in_bytes"); OSContainer::print_container_helper(st, OSContainer::memory_max_usage_in_bytes(), "memory_max_usage_in_bytes"); OSContainer::print_container_helper(st, OSContainer::rss_usage_in_bytes(), "rss_usage_in_bytes"); @@ -2497,7 +2545,7 @@ bool os::Linux::print_container_info(outputStream* st) { OSContainer::print_version_specific_info(st); - jlong j = OSContainer::pids_max(); + j = OSContainer::pids_max(); st->print("maximum number of tasks: "); if (j > 0) { st->print_cr(JLONG_FORMAT, j); @@ -2543,16 +2591,18 @@ void os::print_memory_info(outputStream* st) { // values in struct sysinfo are "unsigned long" struct sysinfo si; - sysinfo(&si); - + int ret = sysinfo(&si); + assert(ret == 0, "sysinfo failed: %s", os::strerror(errno)); st->print(", physical " UINT64_FORMAT "k", os::physical_memory() >> 10); st->print("(" UINT64_FORMAT "k free)", os::available_memory() >> 10); - st->print(", swap " UINT64_FORMAT "k", - ((jlong)si.totalswap * si.mem_unit) >> 10); - st->print("(" UINT64_FORMAT "k free)", - ((jlong)si.freeswap * si.mem_unit) >> 10); + if (ret == 0) { + st->print(", swap " UINT64_FORMAT "k", + ((jlong)si.totalswap * si.mem_unit) >> 10); + st->print("(" UINT64_FORMAT "k free)", + ((jlong)si.freeswap * si.mem_unit) >> 10); + } st->cr(); st->print("Page Sizes: "); _page_sizes.print_on(st); @@ -2684,8 +2734,6 @@ const char* search_string = "CPU"; const char* search_string = "cpu"; #elif defined(S390) const char* search_string = "machine ="; -#elif defined(SPARC) -const char* search_string = "cpu"; #else const char* search_string = "Processor"; #endif @@ -2737,8 +2785,6 @@ void os::get_summary_cpu_info(char* cpuinfo, size_t length) { strncpy(cpuinfo, LP64_ONLY("RISCV64") NOT_LP64("RISCV32"), length); #elif defined(S390) strncpy(cpuinfo, "S390", length); -#elif defined(SPARC) - strncpy(cpuinfo, "sparcv9", length); #elif defined(ZERO_LIBARCH) strncpy(cpuinfo, ZERO_LIBARCH, length); #else @@ -5221,7 +5267,7 @@ int os::get_core_path(char* buffer, size_t bufferSize) { if (core_pattern[0] == '|') { written = jio_snprintf(buffer, bufferSize, - "\"%s\" (or dumping to %s/core.%d)", + "\"%s\" (alternatively, falling back to %s/core.%d)", &core_pattern[1], p, current_process_id()); } else if (pid_pos != nullptr) { *pid_pos = '\0'; diff --git a/src/hotspot/os/linux/os_linux.hpp b/src/hotspot/os/linux/os_linux.hpp index bd2e1ea3230..4e208a11300 100644 --- a/src/hotspot/os/linux/os_linux.hpp +++ b/src/hotspot/os/linux/os_linux.hpp @@ -181,6 +181,23 @@ class os::Linux { // fields will contain -1. static bool query_process_memory_info(meminfo_t* info); + // Output structure for query_accurate_process_memory_info() (all values in KB) + struct accurate_meminfo_t { + ssize_t rss; // current resident set size + ssize_t pss; // current proportional set size + ssize_t pssdirty; // proportional set size (dirty) + ssize_t pssanon; // proportional set size (anonymous mappings) + ssize_t pssfile; // proportional set size (file mappings) + ssize_t pssshmem; // proportional set size (shared mappings) + ssize_t swap; // swapped out + ssize_t swappss; // proportional set size (swapped out) + }; + + // Attempts to query accurate memory information from /proc/self/smaps_rollup and return it in the output structure. + // May fail (returns false) or succeed (returns true) but not all output fields are available; unavailable + // fields will contain -1. + static bool query_accurate_process_memory_info(accurate_meminfo_t* info); + // Tells if the user asked for transparent huge pages. static bool _thp_requested; diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp index 448ebce620a..d0c82135797 100644 --- a/src/hotspot/os/posix/os_posix.cpp +++ b/src/hotspot/os/posix/os_posix.cpp @@ -107,41 +107,60 @@ size_t os::_os_min_stack_allowed = PTHREAD_STACK_MIN; // Check core dump limit and report possible place where core can be found void os::check_core_dump_prerequisites(char* buffer, size_t bufferSize, bool check_only) { + stringStream buf(buffer, bufferSize); if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && !CreateCoredumpOnCrash) { - jio_snprintf(buffer, bufferSize, "CreateCoredumpOnCrash is disabled from command line"); - VMError::record_coredump_status(buffer, false); + buf.print("CreateCoredumpOnCrash is disabled from command line"); + VMError::record_coredump_status(buf.freeze(), false); } else { struct rlimit rlim; bool success = true; bool warn = true; char core_path[PATH_MAX]; if (get_core_path(core_path, PATH_MAX) <= 0) { - jio_snprintf(buffer, bufferSize, "core.%d (may not exist)", current_process_id()); + // In the warning message, let the user know. + if (check_only) { + buf.print("the core path couldn't be determined. It commonly defaults to "); + } + buf.print("core.%d%s", current_process_id(), check_only ? "" : " (may not exist)"); #ifdef LINUX } else if (core_path[0] == '"') { // redirect to user process - jio_snprintf(buffer, bufferSize, "Core dumps may be processed with %s", core_path); + if (check_only) { + buf.print("core dumps may be further processed by the following: "); + } else { + buf.print("Determined by the following: "); + } + buf.print("%s", core_path); #endif } else if (getrlimit(RLIMIT_CORE, &rlim) != 0) { - jio_snprintf(buffer, bufferSize, "%s (may not exist)", core_path); + if (check_only) { + buf.print("the rlimit couldn't be determined. If resource limits permit, the core dump will be located at "); + } + buf.print("%s%s", core_path, check_only ? "" : " (may not exist)"); } else { switch(rlim.rlim_cur) { case RLIM_INFINITY: - jio_snprintf(buffer, bufferSize, "%s", core_path); + buf.print("%s", core_path); warn = false; break; case 0: - jio_snprintf(buffer, bufferSize, "Core dumps have been disabled. To enable core dumping, try \"ulimit -c unlimited\" before starting Java again"); + buf.print("%s dumps have been disabled. To enable core dumping, try \"ulimit -c unlimited\" before starting Java again", check_only ? "core" : "Core"); success = false; break; default: - jio_snprintf(buffer, bufferSize, "%s (max size " UINT64_FORMAT " k). To ensure a full core dump, try \"ulimit -c unlimited\" before starting Java again", core_path, uint64_t(rlim.rlim_cur) / K); + if (check_only) { + buf.print("core dumps are constrained "); + } else { + buf.print( "%s ", core_path); + } + buf.print( "(max size " UINT64_FORMAT " k). To ensure a full core dump, try \"ulimit -c unlimited\" before starting Java again", uint64_t(rlim.rlim_cur) / K); break; } } + const char* result = buf.freeze(); if (!check_only) { - VMError::record_coredump_status(buffer, success); + VMError::record_coredump_status(result, success); } else if (warn) { - warning("CreateCoredumpOnCrash specified, but %s", buffer); + warning("CreateCoredumpOnCrash specified, but %s", result); } } } diff --git a/src/hotspot/os/posix/perfMemory_posix.cpp b/src/hotspot/os/posix/perfMemory_posix.cpp index cbbecea3a6a..e3483781794 100644 --- a/src/hotspot/os/posix/perfMemory_posix.cpp +++ b/src/hotspot/os/posix/perfMemory_posix.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2021 SAP SE. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -950,7 +950,7 @@ static int create_sharedmem_file(const char* dirname, const char* filename, size if (result == -1 ) break; if (!os::write(fd, &zero_int, 1)) { if (errno == ENOSPC) { - warning("Insufficient space for shared memory file:\n %s\nTry using the -Djava.io.tmpdir= option to select an alternate temp location.\n", filename); + warning("Insufficient space for shared memory file: %s/%s\n", dirname, filename); } result = OS_ERR; break; diff --git a/src/hotspot/os_cpu/aix_ppc/atomic_aix_ppc.hpp b/src/hotspot/os_cpu/aix_ppc/atomic_aix_ppc.hpp index 722dffc150d..9a314667fcb 100644 --- a/src/hotspot/os_cpu/aix_ppc/atomic_aix_ppc.hpp +++ b/src/hotspot/os_cpu/aix_ppc/atomic_aix_ppc.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2019 SAP SE. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,395 +23,5 @@ * */ -#ifndef OS_CPU_AIX_PPC_ATOMIC_AIX_PPC_HPP -#define OS_CPU_AIX_PPC_ATOMIC_AIX_PPC_HPP - -#ifndef PPC64 -#error "Atomic currently only implemented for PPC64" -#endif - -#include "orderAccess_aix_ppc.hpp" -#include "utilities/debug.hpp" - -// Implementation of class atomic - -// -// machine barrier instructions: -// -// - sync two-way memory barrier, aka fence -// - lwsync orders Store|Store, -// Load|Store, -// Load|Load, -// but not Store|Load -// - eieio orders memory accesses for device memory (only) -// - isync invalidates speculatively executed instructions -// From the POWER ISA 2.06 documentation: -// "[...] an isync instruction prevents the execution of -// instructions following the isync until instructions -// preceding the isync have completed, [...]" -// From IBM's AIX assembler reference: -// "The isync [...] instructions causes the processor to -// refetch any instructions that might have been fetched -// prior to the isync instruction. The instruction isync -// causes the processor to wait for all previous instructions -// to complete. Then any instructions already fetched are -// discarded and instruction processing continues in the -// environment established by the previous instructions." -// -// semantic barrier instructions: -// (as defined in orderAccess.hpp) -// -// - release orders Store|Store, (maps to lwsync) -// Load|Store -// - acquire orders Load|Store, (maps to lwsync) -// Load|Load -// - fence orders Store|Store, (maps to sync) -// Load|Store, -// Load|Load, -// Store|Load -// - -inline void pre_membar(atomic_memory_order order) { - switch (order) { - case memory_order_relaxed: - case memory_order_acquire: break; - case memory_order_release: - case memory_order_acq_rel: __asm__ __volatile__ ("lwsync" : : : "memory"); break; - default /*conservative*/ : __asm__ __volatile__ ("sync" : : : "memory"); break; - } -} - -inline void post_membar(atomic_memory_order order) { - switch (order) { - case memory_order_relaxed: - case memory_order_release: break; - case memory_order_acquire: - case memory_order_acq_rel: __asm__ __volatile__ ("isync" : : : "memory"); break; - default /*conservative*/ : __asm__ __volatile__ ("sync" : : : "memory"); break; - } -} - - -template -struct Atomic::PlatformAdd { - template - D add_then_fetch(D volatile* dest, I add_value, atomic_memory_order order) const; - - template - D fetch_then_add(D volatile* dest, I add_value, atomic_memory_order order) const { - return add_then_fetch(dest, add_value, order) - add_value; - } -}; - -template<> -template -inline D Atomic::PlatformAdd<4>::add_then_fetch(D volatile* dest, I add_value, - atomic_memory_order order) const { - STATIC_ASSERT(4 == sizeof(I)); - STATIC_ASSERT(4 == sizeof(D)); - - D result; - - pre_membar(order); - - __asm__ __volatile__ ( - "1: lwarx %0, 0, %2 \n" - " add %0, %0, %1 \n" - " stwcx. %0, 0, %2 \n" - " bne- 1b \n" - : /*%0*/"=&r" (result) - : /*%1*/"r" (add_value), /*%2*/"r" (dest) - : "cc", "memory" ); - - post_membar(order); - - return result; -} - - -template<> -template -inline D Atomic::PlatformAdd<8>::add_then_fetch(D volatile* dest, I add_value, - atomic_memory_order order) const { - STATIC_ASSERT(8 == sizeof(I)); - STATIC_ASSERT(8 == sizeof(D)); - - D result; - - pre_membar(order); - - __asm__ __volatile__ ( - "1: ldarx %0, 0, %2 \n" - " add %0, %0, %1 \n" - " stdcx. %0, 0, %2 \n" - " bne- 1b \n" - : /*%0*/"=&r" (result) - : /*%1*/"r" (add_value), /*%2*/"r" (dest) - : "cc", "memory" ); - - post_membar(order); - - return result; -} - -template<> -template -inline T Atomic::PlatformXchg<4>::operator()(T volatile* dest, - T exchange_value, - atomic_memory_order order) const { - // Note that xchg doesn't necessarily do an acquire - // (see synchronizer.cpp). - - T old_value; - const uint64_t zero = 0; - - pre_membar(order); - - __asm__ __volatile__ ( - /* atomic loop */ - "1: \n" - " lwarx %[old_value], %[dest], %[zero] \n" - " stwcx. %[exchange_value], %[dest], %[zero] \n" - " bne- 1b \n" - /* exit */ - "2: \n" - /* out */ - : [old_value] "=&r" (old_value), - "=m" (*dest) - /* in */ - : [dest] "b" (dest), - [zero] "r" (zero), - [exchange_value] "r" (exchange_value), - "m" (*dest) - /* clobber */ - : "cc", - "memory" - ); - - post_membar(order); - - return old_value; -} - -template<> -template -inline T Atomic::PlatformXchg<8>::operator()(T volatile* dest, - T exchange_value, - atomic_memory_order order) const { - STATIC_ASSERT(8 == sizeof(T)); - // Note that xchg doesn't necessarily do an acquire - // (see synchronizer.cpp). - - T old_value; - const uint64_t zero = 0; - - pre_membar(order); - - __asm__ __volatile__ ( - /* atomic loop */ - "1: \n" - " ldarx %[old_value], %[dest], %[zero] \n" - " stdcx. %[exchange_value], %[dest], %[zero] \n" - " bne- 1b \n" - /* exit */ - "2: \n" - /* out */ - : [old_value] "=&r" (old_value), - "=m" (*dest) - /* in */ - : [dest] "b" (dest), - [zero] "r" (zero), - [exchange_value] "r" (exchange_value), - "m" (*dest) - /* clobber */ - : "cc", - "memory" - ); - - post_membar(order); - - return old_value; -} - -template<> -template -inline T Atomic::PlatformCmpxchg<1>::operator()(T volatile* dest, - T compare_value, - T exchange_value, - atomic_memory_order order) const { - STATIC_ASSERT(1 == sizeof(T)); - - // Note that cmpxchg guarantees a two-way memory barrier across - // the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not - // specified otherwise (see atomic.hpp). - - // Using 32 bit internally. - volatile int *dest_base = (volatile int*)((uintptr_t)dest & ~3); - -#ifdef VM_LITTLE_ENDIAN - const unsigned int shift_amount = ((uintptr_t)dest & 3) * 8; -#else - const unsigned int shift_amount = ((~(uintptr_t)dest) & 3) * 8; -#endif - const unsigned int masked_compare_val = ((unsigned int)(unsigned char)compare_value), - masked_exchange_val = ((unsigned int)(unsigned char)exchange_value), - xor_value = (masked_compare_val ^ masked_exchange_val) << shift_amount; - - unsigned int old_value, value32; - - pre_membar(order); - - __asm__ __volatile__ ( - /* simple guard */ - " lbz %[old_value], 0(%[dest]) \n" - " cmpw %[masked_compare_val], %[old_value] \n" - " bne- 2f \n" - /* atomic loop */ - "1: \n" - " lwarx %[value32], 0, %[dest_base] \n" - /* extract byte and compare */ - " srd %[old_value], %[value32], %[shift_amount] \n" - " clrldi %[old_value], %[old_value], 56 \n" - " cmpw %[masked_compare_val], %[old_value] \n" - " bne- 2f \n" - /* replace byte and try to store */ - " xor %[value32], %[xor_value], %[value32] \n" - " stwcx. %[value32], 0, %[dest_base] \n" - " bne- 1b \n" - /* exit */ - "2: \n" - /* out */ - : [old_value] "=&r" (old_value), - [value32] "=&r" (value32), - "=m" (*dest), - "=m" (*dest_base) - /* in */ - : [dest] "b" (dest), - [dest_base] "b" (dest_base), - [shift_amount] "r" (shift_amount), - [masked_compare_val] "r" (masked_compare_val), - [xor_value] "r" (xor_value), - "m" (*dest), - "m" (*dest_base) - /* clobber */ - : "cc", - "memory" - ); - - post_membar(order); - - return PrimitiveConversions::cast((unsigned char)old_value); -} - -template<> -template -inline T Atomic::PlatformCmpxchg<4>::operator()(T volatile* dest, - T compare_value, - T exchange_value, - atomic_memory_order order) const { - STATIC_ASSERT(4 == sizeof(T)); - - // Note that cmpxchg guarantees a two-way memory barrier across - // the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not - // specified otherwise (see atomic.hpp). - - T old_value; - const uint64_t zero = 0; - - pre_membar(order); - - __asm__ __volatile__ ( - /* simple guard */ - " lwz %[old_value], 0(%[dest]) \n" - " cmpw %[compare_value], %[old_value] \n" - " bne- 2f \n" - /* atomic loop */ - "1: \n" - " lwarx %[old_value], %[dest], %[zero] \n" - " cmpw %[compare_value], %[old_value] \n" - " bne- 2f \n" - " stwcx. %[exchange_value], %[dest], %[zero] \n" - " bne- 1b \n" - /* exit */ - "2: \n" - /* out */ - : [old_value] "=&r" (old_value), - "=m" (*dest) - /* in */ - : [dest] "b" (dest), - [zero] "r" (zero), - [compare_value] "r" (compare_value), - [exchange_value] "r" (exchange_value), - "m" (*dest) - /* clobber */ - : "cc", - "memory" - ); - - post_membar(order); - - return old_value; -} - -template<> -template -inline T Atomic::PlatformCmpxchg<8>::operator()(T volatile* dest, - T compare_value, - T exchange_value, - atomic_memory_order order) const { - STATIC_ASSERT(8 == sizeof(T)); - - // Note that cmpxchg guarantees a two-way memory barrier across - // the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not - // specified otherwise (see atomic.hpp). - - T old_value; - const uint64_t zero = 0; - - pre_membar(order); - - __asm__ __volatile__ ( - /* simple guard */ - " ld %[old_value], 0(%[dest]) \n" - " cmpd %[compare_value], %[old_value] \n" - " bne- 2f \n" - /* atomic loop */ - "1: \n" - " ldarx %[old_value], %[dest], %[zero] \n" - " cmpd %[compare_value], %[old_value] \n" - " bne- 2f \n" - " stdcx. %[exchange_value], %[dest], %[zero] \n" - " bne- 1b \n" - /* exit */ - "2: \n" - /* out */ - : [old_value] "=&r" (old_value), - "=m" (*dest) - /* in */ - : [dest] "b" (dest), - [zero] "r" (zero), - [compare_value] "r" (compare_value), - [exchange_value] "r" (exchange_value), - "m" (*dest) - /* clobber */ - : "cc", - "memory" - ); - - post_membar(order); - - return old_value; -} - -template -struct Atomic::PlatformOrderedLoad { - template - T operator()(const volatile T* p) const { - T t = Atomic::load(p); - // Use twi-isync for load_acquire (faster than lwsync). - __asm__ __volatile__ ("twi 0,%0,0\n isync\n" : : "r" (t) : "memory"); - return t; - } -}; - -#endif // OS_CPU_AIX_PPC_ATOMIC_AIX_PPC_HPP +// Including inline assembler functions that are shared between multiple PPC64 platforms. +#include "atomicAccess_ppc.hpp" diff --git a/src/hotspot/os_cpu/aix_ppc/orderAccess_aix_ppc.hpp b/src/hotspot/os_cpu/aix_ppc/orderAccess_aix_ppc.hpp index 9ca6c18d5bb..d395add6d69 100644 --- a/src/hotspot/os_cpu/aix_ppc/orderAccess_aix_ppc.hpp +++ b/src/hotspot/os_cpu/aix_ppc/orderAccess_aix_ppc.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2019 SAP SE. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,62 +23,5 @@ * */ -#ifndef OS_CPU_AIX_PPC_ORDERACCESS_AIX_PPC_HPP -#define OS_CPU_AIX_PPC_ORDERACCESS_AIX_PPC_HPP - -// Included in orderAccess.hpp header file. - -// Compiler version last used for testing: xlc 12 -// Please update this information when this file changes - -// Implementation of class OrderAccess. - -// -// Machine barrier instructions: -// -// - sync Two-way memory barrier, aka fence. -// - lwsync orders Store|Store, -// Load|Store, -// Load|Load, -// but not Store|Load -// - eieio orders Store|Store -// - isync Invalidates speculatively executed instructions, -// but isync may complete before storage accesses -// associated with instructions preceding isync have -// been performed. -// -// Semantic barrier instructions: -// (as defined in orderAccess.hpp) -// -// - release orders Store|Store, (maps to lwsync) -// Load|Store -// - acquire orders Load|Store, (maps to lwsync) -// Load|Load -// - fence orders Store|Store, (maps to sync) -// Load|Store, -// Load|Load, -// Store|Load -// - -#define inlasm_sync() __asm__ __volatile__ ("sync" : : : "memory"); -#define inlasm_lwsync() __asm__ __volatile__ ("lwsync" : : : "memory"); -#define inlasm_eieio() __asm__ __volatile__ ("eieio" : : : "memory"); -#define inlasm_isync() __asm__ __volatile__ ("isync" : : : "memory"); - -inline void OrderAccess::loadload() { inlasm_lwsync(); } -inline void OrderAccess::storestore() { inlasm_lwsync(); } -inline void OrderAccess::loadstore() { inlasm_lwsync(); } -inline void OrderAccess::storeload() { inlasm_sync(); } - -inline void OrderAccess::acquire() { inlasm_lwsync(); } -inline void OrderAccess::release() { inlasm_lwsync(); } -inline void OrderAccess::fence() { inlasm_sync(); } -inline void OrderAccess::cross_modify_fence_impl() - { inlasm_isync(); } - -#undef inlasm_sync -#undef inlasm_lwsync -#undef inlasm_eieio -#undef inlasm_isync - -#endif // OS_CPU_AIX_PPC_ORDERACCESS_AIX_PPC_HPP +// Including inline assembler functions that are shared between multiple PPC64 platforms. +#include "orderAccess_ppc.hpp" diff --git a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp index 6c245f8f1a6..677e90883dc 100644 --- a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp +++ b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp @@ -209,8 +209,16 @@ frame os::fetch_compiled_frame_from_context(const void* ucVoid) { } intptr_t* os::fetch_bcp_from_context(const void* ucVoid) { - Unimplemented(); - return nullptr; + assert(ucVoid != nullptr, "invariant"); + const ucontext_t* uc = (const ucontext_t*)ucVoid; + assert(os::Posix::ucontext_is_interpreter(uc), "invariant"); +#if (FP_REG_NUM == 11) + assert(Rbcp == R7, "expected FP=R11, Rbcp=R7"); + return (intptr_t*)uc->uc_mcontext.arm_r7; +#else + assert(Rbcp == R11, "expected FP=R7, Rbcp=R11"); + return (intptr_t*)uc->uc_mcontext.arm_fp; // r11 +#endif } frame os::get_sender_for_C_frame(frame* fr) { diff --git a/src/hotspot/os_cpu/linux_ppc/atomic_linux_ppc.hpp b/src/hotspot/os_cpu/linux_ppc/atomic_linux_ppc.hpp index 1e4eb37cdac..9a314667fcb 100644 --- a/src/hotspot/os_cpu/linux_ppc/atomic_linux_ppc.hpp +++ b/src/hotspot/os_cpu/linux_ppc/atomic_linux_ppc.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2019 SAP SE. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,373 +23,5 @@ * */ -#ifndef OS_CPU_LINUX_PPC_ATOMIC_LINUX_PPC_HPP -#define OS_CPU_LINUX_PPC_ATOMIC_LINUX_PPC_HPP - -#ifndef PPC64 -#error "Atomic currently only implemented for PPC64" -#endif - -#include "orderAccess_linux_ppc.hpp" -#include "utilities/debug.hpp" - -// Implementation of class atomic - -// -// machine barrier instructions: -// -// - sync two-way memory barrier, aka fence -// - lwsync orders Store|Store, -// Load|Store, -// Load|Load, -// but not Store|Load -// - eieio orders memory accesses for device memory (only) -// - isync invalidates speculatively executed instructions -// From the POWER ISA 2.06 documentation: -// "[...] an isync instruction prevents the execution of -// instructions following the isync until instructions -// preceding the isync have completed, [...]" -// From IBM's AIX assembler reference: -// "The isync [...] instructions causes the processor to -// refetch any instructions that might have been fetched -// prior to the isync instruction. The instruction isync -// causes the processor to wait for all previous instructions -// to complete. Then any instructions already fetched are -// discarded and instruction processing continues in the -// environment established by the previous instructions." -// -// semantic barrier instructions: -// (as defined in orderAccess.hpp) -// -// - release orders Store|Store, (maps to lwsync) -// Load|Store -// - acquire orders Load|Store, (maps to lwsync) -// Load|Load -// - fence orders Store|Store, (maps to sync) -// Load|Store, -// Load|Load, -// Store|Load -// - -inline void pre_membar(atomic_memory_order order) { - switch (order) { - case memory_order_relaxed: - case memory_order_acquire: break; - case memory_order_release: - case memory_order_acq_rel: __asm__ __volatile__ ("lwsync" : : : "memory"); break; - default /*conservative*/ : __asm__ __volatile__ ("sync" : : : "memory"); break; - } -} - -inline void post_membar(atomic_memory_order order) { - switch (order) { - case memory_order_relaxed: - case memory_order_release: break; - case memory_order_acquire: - case memory_order_acq_rel: __asm__ __volatile__ ("isync" : : : "memory"); break; - default /*conservative*/ : __asm__ __volatile__ ("sync" : : : "memory"); break; - } -} - - -template -struct Atomic::PlatformAdd { - template - D add_then_fetch(D volatile* dest, I add_value, atomic_memory_order order) const; - - template - D fetch_then_add(D volatile* dest, I add_value, atomic_memory_order order) const { - return add_then_fetch(dest, add_value, order) - add_value; - } -}; - -template<> -template -inline D Atomic::PlatformAdd<4>::add_then_fetch(D volatile* dest, I add_value, - atomic_memory_order order) const { - STATIC_ASSERT(4 == sizeof(I)); - STATIC_ASSERT(4 == sizeof(D)); - - D result; - - pre_membar(order); - - __asm__ __volatile__ ( - "1: lwarx %0, 0, %2 \n" - " add %0, %0, %1 \n" - " stwcx. %0, 0, %2 \n" - " bne- 1b \n" - : /*%0*/"=&r" (result) - : /*%1*/"r" (add_value), /*%2*/"r" (dest) - : "cc", "memory" ); - - post_membar(order); - - return result; -} - - -template<> -template -inline D Atomic::PlatformAdd<8>::add_then_fetch(D volatile* dest, I add_value, - atomic_memory_order order) const { - STATIC_ASSERT(8 == sizeof(I)); - STATIC_ASSERT(8 == sizeof(D)); - - D result; - - pre_membar(order); - - __asm__ __volatile__ ( - "1: ldarx %0, 0, %2 \n" - " add %0, %0, %1 \n" - " stdcx. %0, 0, %2 \n" - " bne- 1b \n" - : /*%0*/"=&r" (result) - : /*%1*/"r" (add_value), /*%2*/"r" (dest) - : "cc", "memory" ); - - post_membar(order); - - return result; -} - -template<> -template -inline T Atomic::PlatformXchg<4>::operator()(T volatile* dest, - T exchange_value, - atomic_memory_order order) const { - // Note that xchg doesn't necessarily do an acquire - // (see synchronizer.cpp). - - T old_value; - const uint64_t zero = 0; - - pre_membar(order); - - __asm__ __volatile__ ( - /* atomic loop */ - "1: \n" - " lwarx %[old_value], %[dest], %[zero] \n" - " stwcx. %[exchange_value], %[dest], %[zero] \n" - " bne- 1b \n" - /* exit */ - "2: \n" - /* out */ - : [old_value] "=&r" (old_value), - "=m" (*dest) - /* in */ - : [dest] "b" (dest), - [zero] "r" (zero), - [exchange_value] "r" (exchange_value), - "m" (*dest) - /* clobber */ - : "cc", - "memory" - ); - - post_membar(order); - - return old_value; -} - -template<> -template -inline T Atomic::PlatformXchg<8>::operator()(T volatile* dest, - T exchange_value, - atomic_memory_order order) const { - STATIC_ASSERT(8 == sizeof(T)); - // Note that xchg doesn't necessarily do an acquire - // (see synchronizer.cpp). - - T old_value; - const uint64_t zero = 0; - - pre_membar(order); - - __asm__ __volatile__ ( - /* atomic loop */ - "1: \n" - " ldarx %[old_value], %[dest], %[zero] \n" - " stdcx. %[exchange_value], %[dest], %[zero] \n" - " bne- 1b \n" - /* exit */ - "2: \n" - /* out */ - : [old_value] "=&r" (old_value), - "=m" (*dest) - /* in */ - : [dest] "b" (dest), - [zero] "r" (zero), - [exchange_value] "r" (exchange_value), - "m" (*dest) - /* clobber */ - : "cc", - "memory" - ); - - post_membar(order); - - return old_value; -} - -template<> -template -inline T Atomic::PlatformCmpxchg<1>::operator()(T volatile* dest, - T compare_value, - T exchange_value, - atomic_memory_order order) const { - STATIC_ASSERT(1 == sizeof(T)); - - // Note that cmpxchg guarantees a two-way memory barrier across - // the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not - // specified otherwise (see atomic.hpp). - - // Using 32 bit internally. - unsigned int old_value, loaded_value; - pre_membar(order); - - __asm__ __volatile__ ( - /* atomic loop */ - "1: \n" - " lbarx %[old_value], 0, %[dest] \n" - /* extract byte and compare */ - " cmpw %[compare_value], %[old_value] \n" - " bne- 2f \n" - /* replace byte and try to store */ - " stbcx. %[exchange_value], 0, %[dest] \n" - " bne- 1b \n" - /* exit */ - "2: \n" - /* out */ - : [old_value] "=&r" (old_value), - [loaded_value] "=&r" (loaded_value), - "=m" (*dest) - /* in */ - : [dest] "b" (dest), - [compare_value] "r" (compare_value), - [exchange_value] "r" (exchange_value), - "m" (*dest) - /* clobber */ - : "cc", - "memory" - ); - - post_membar(order); - - return PrimitiveConversions::cast((unsigned char)old_value); -} - -template<> -template -inline T Atomic::PlatformCmpxchg<4>::operator()(T volatile* dest, - T compare_value, - T exchange_value, - atomic_memory_order order) const { - STATIC_ASSERT(4 == sizeof(T)); - - // Note that cmpxchg guarantees a two-way memory barrier across - // the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not - // specified otherwise (see atomic.hpp). - - T old_value; - const uint64_t zero = 0; - - pre_membar(order); - - __asm__ __volatile__ ( - /* simple guard */ - " lwz %[old_value], 0(%[dest]) \n" - " cmpw %[compare_value], %[old_value] \n" - " bne- 2f \n" - /* atomic loop */ - "1: \n" - " lwarx %[old_value], %[dest], %[zero] \n" - " cmpw %[compare_value], %[old_value] \n" - " bne- 2f \n" - " stwcx. %[exchange_value], %[dest], %[zero] \n" - " bne- 1b \n" - /* exit */ - "2: \n" - /* out */ - : [old_value] "=&r" (old_value), - "=m" (*dest) - /* in */ - : [dest] "b" (dest), - [zero] "r" (zero), - [compare_value] "r" (compare_value), - [exchange_value] "r" (exchange_value), - "m" (*dest) - /* clobber */ - : "cc", - "memory" - ); - - post_membar(order); - - return old_value; -} - -template<> -template -inline T Atomic::PlatformCmpxchg<8>::operator()(T volatile* dest, - T compare_value, - T exchange_value, - atomic_memory_order order) const { - STATIC_ASSERT(8 == sizeof(T)); - - // Note that cmpxchg guarantees a two-way memory barrier across - // the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not - // specified otherwise (see atomic.hpp). - - T old_value; - const uint64_t zero = 0; - - pre_membar(order); - - __asm__ __volatile__ ( - /* simple guard */ - " ld %[old_value], 0(%[dest]) \n" - " cmpd %[compare_value], %[old_value] \n" - " bne- 2f \n" - /* atomic loop */ - "1: \n" - " ldarx %[old_value], %[dest], %[zero] \n" - " cmpd %[compare_value], %[old_value] \n" - " bne- 2f \n" - " stdcx. %[exchange_value], %[dest], %[zero] \n" - " bne- 1b \n" - /* exit */ - "2: \n" - /* out */ - : [old_value] "=&r" (old_value), - "=m" (*dest) - /* in */ - : [dest] "b" (dest), - [zero] "r" (zero), - [compare_value] "r" (compare_value), - [exchange_value] "r" (exchange_value), - "m" (*dest) - /* clobber */ - : "cc", - "memory" - ); - - post_membar(order); - - return old_value; -} - -template -struct Atomic::PlatformOrderedLoad -{ - template - T operator()(const volatile T* p) const { - T t = Atomic::load(p); - // Use twi-isync for load_acquire (faster than lwsync). - __asm__ __volatile__ ("twi 0,%0,0\n isync\n" : : "r" (t) : "memory"); - return t; - } -}; - -#endif // OS_CPU_LINUX_PPC_ATOMIC_LINUX_PPC_HPP +// Including inline assembler functions that are shared between multiple PPC64 platforms. +#include "atomicAccess_ppc.hpp" diff --git a/src/hotspot/os_cpu/linux_ppc/orderAccess_linux_ppc.hpp b/src/hotspot/os_cpu/linux_ppc/orderAccess_linux_ppc.hpp index 2e6eb1f3878..d395add6d69 100644 --- a/src/hotspot/os_cpu/linux_ppc/orderAccess_linux_ppc.hpp +++ b/src/hotspot/os_cpu/linux_ppc/orderAccess_linux_ppc.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2014 SAP SE. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,66 +23,5 @@ * */ -#ifndef OS_CPU_LINUX_PPC_ORDERACCESS_LINUX_PPC_HPP -#define OS_CPU_LINUX_PPC_ORDERACCESS_LINUX_PPC_HPP - -// Included in orderAccess.hpp header file. - -#ifndef PPC64 -#error "OrderAccess currently only implemented for PPC64" -#endif - -// Compiler version last used for testing: gcc 4.1.2 -// Please update this information when this file changes - -// Implementation of class OrderAccess. - -// -// Machine barrier instructions: -// -// - sync Two-way memory barrier, aka fence. -// - lwsync orders Store|Store, -// Load|Store, -// Load|Load, -// but not Store|Load -// - eieio orders Store|Store -// - isync Invalidates speculatively executed instructions, -// but isync may complete before storage accesses -// associated with instructions preceding isync have -// been performed. -// -// Semantic barrier instructions: -// (as defined in orderAccess.hpp) -// -// - release orders Store|Store, (maps to lwsync) -// Load|Store -// - acquire orders Load|Store, (maps to lwsync) -// Load|Load -// - fence orders Store|Store, (maps to sync) -// Load|Store, -// Load|Load, -// Store|Load -// - -#define inlasm_sync() __asm__ __volatile__ ("sync" : : : "memory"); -#define inlasm_lwsync() __asm__ __volatile__ ("lwsync" : : : "memory"); -#define inlasm_eieio() __asm__ __volatile__ ("eieio" : : : "memory"); -#define inlasm_isync() __asm__ __volatile__ ("isync" : : : "memory"); - -inline void OrderAccess::loadload() { inlasm_lwsync(); } -inline void OrderAccess::storestore() { inlasm_lwsync(); } -inline void OrderAccess::loadstore() { inlasm_lwsync(); } -inline void OrderAccess::storeload() { inlasm_sync(); } - -inline void OrderAccess::acquire() { inlasm_lwsync(); } -inline void OrderAccess::release() { inlasm_lwsync(); } -inline void OrderAccess::fence() { inlasm_sync(); } -inline void OrderAccess::cross_modify_fence_impl() - { inlasm_isync(); } - -#undef inlasm_sync -#undef inlasm_lwsync -#undef inlasm_eieio -#undef inlasm_isync - -#endif // OS_CPU_LINUX_PPC_ORDERACCESS_LINUX_PPC_HPP +// Including inline assembler functions that are shared between multiple PPC64 platforms. +#include "orderAccess_ppc.hpp" diff --git a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp index d19128cafc2..a95bfb4ff96 100644 --- a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp +++ b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp @@ -89,6 +89,25 @@ #define RISCV_HWPROBE_MISALIGNED_UNSUPPORTED (4 << 0) #define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0) +#define RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE 6 + +#define RISCV_HWPROBE_KEY_HIGHEST_VIRT_ADDRESS 7 + +#define RISCV_HWPROBE_KEY_TIME_CSR_FREQ 8 + +#define RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF 9 +#define RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN 0 +#define RISCV_HWPROBE_MISALIGNED_SCALAR_EMULATED 1 +#define RISCV_HWPROBE_MISALIGNED_SCALAR_SLOW 2 +#define RISCV_HWPROBE_MISALIGNED_SCALAR_FAST 3 +#define RISCV_HWPROBE_MISALIGNED_SCALAR_UNSUPPORTED 4 + +#define RISCV_HWPROBE_KEY_MISALIGNED_VECTOR_PERF 10 +#define RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN 0 +#define RISCV_HWPROBE_MISALIGNED_VECTOR_SLOW 2 +#define RISCV_HWPROBE_MISALIGNED_VECTOR_FAST 3 +#define RISCV_HWPROBE_MISALIGNED_VECTOR_UNSUPPORTED 4 + #ifndef NR_riscv_hwprobe #ifndef NR_arch_specific_syscall #define NR_arch_specific_syscall 244 @@ -114,7 +133,12 @@ static struct riscv_hwprobe query[] = {{RISCV_HWPROBE_KEY_MVENDORID, 0}, {RISCV_HWPROBE_KEY_MIMPID, 0}, {RISCV_HWPROBE_KEY_BASE_BEHAVIOR, 0}, {RISCV_HWPROBE_KEY_IMA_EXT_0, 0}, - {RISCV_HWPROBE_KEY_CPUPERF_0, 0}}; + {RISCV_HWPROBE_KEY_CPUPERF_0, 0}, + {RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE, 0}, + {RISCV_HWPROBE_KEY_HIGHEST_VIRT_ADDRESS, 0}, + {RISCV_HWPROBE_KEY_TIME_CSR_FREQ, 0}, + {RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF, 0}, + {RISCV_HWPROBE_KEY_MISALIGNED_VECTOR_PERF, 0}}; bool RiscvHwprobe::probe_features() { assert(!rw_hwprobe_completed, "Called twice."); @@ -188,6 +212,9 @@ void RiscvHwprobe::add_features_from_query_result() { VM_Version::ext_Zbs.enable_feature(); } #ifndef PRODUCT + if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZICBOZ)) { + VM_Version::ext_Zicboz.enable_feature(); + } if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZBKB)) { VM_Version::ext_Zbkb.enable_feature(); } @@ -240,8 +267,22 @@ void RiscvHwprobe::add_features_from_query_result() { VM_Version::ext_Zicond.enable_feature(); } #endif + // RISCV_HWPROBE_KEY_CPUPERF_0 is deprecated and returns similar values + // to RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF. Keep it there for backward + // compatibility with old kernels. if (is_valid(RISCV_HWPROBE_KEY_CPUPERF_0)) { - VM_Version::unaligned_access.enable_feature( + VM_Version::unaligned_scalar.enable_feature( query[RISCV_HWPROBE_KEY_CPUPERF_0].value & RISCV_HWPROBE_MISALIGNED_MASK); + } else if (is_valid(RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF)) { + VM_Version::unaligned_scalar.enable_feature( + query[RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF].value); + } + + if (is_valid(RISCV_HWPROBE_KEY_MISALIGNED_VECTOR_PERF)) { + VM_Version::unaligned_vector.enable_feature( + query[RISCV_HWPROBE_KEY_MISALIGNED_VECTOR_PERF].value); + } + if (is_valid(RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE)) { + VM_Version::zicboz_block_size.enable_feature(query[RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE].value); } } diff --git a/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp index 506c78cacca..3c49e11c145 100644 --- a/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp +++ b/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp @@ -100,7 +100,6 @@ #endif uint32_t VM_Version::cpu_vector_length() { - assert(ext_V.enabled(), "should not call this"); return (uint32_t)read_csr(CSR_VLENB); } @@ -303,7 +302,7 @@ void VM_Version::rivos_features() { ext_Zvfh.enable_feature(); - unaligned_access.enable_feature(MISALIGNED_FAST); + unaligned_scalar.enable_feature(MISALIGNED_SCALAR_FAST); satp_mode.enable_feature(VM_SV48); // Features dependent on march/mimpid. diff --git a/src/hotspot/share/c1/c1_Compiler.cpp b/src/hotspot/share/c1/c1_Compiler.cpp index b5fa7dcf247..cce2b29d277 100644 --- a/src/hotspot/share/c1/c1_Compiler.cpp +++ b/src/hotspot/share/c1/c1_Compiler.cpp @@ -238,7 +238,7 @@ bool Compiler::is_intrinsic_supported(vmIntrinsics::ID id) { case vmIntrinsics::_counterTime: #endif case vmIntrinsics::_getObjectSize: -#if defined(X86) || defined(AARCH64) || defined(S390) || defined(RISCV) || defined(PPC64) +#if defined(X86) || defined(AARCH64) || defined(S390) || defined(RISCV64) || defined(PPC64) case vmIntrinsics::_clone: #endif break; diff --git a/src/hotspot/share/c1/c1_LIR.cpp b/src/hotspot/share/c1/c1_LIR.cpp index c1c94244fcc..4c8ebd5a09d 100644 --- a/src/hotspot/share/c1/c1_LIR.cpp +++ b/src/hotspot/share/c1/c1_LIR.cpp @@ -350,8 +350,9 @@ LIR_OpArrayCopy::LIR_OpArrayCopy(LIR_Opr src, LIR_Opr src_pos, LIR_Opr dst, LIR_ , _tmp(tmp) , _expected_type(expected_type) , _flags(flags) { -#if defined(X86) || defined(AARCH64) || defined(S390) || defined(RISCV) || defined(PPC64) - if (expected_type != nullptr && flags == 0) { +#if defined(X86) || defined(AARCH64) || defined(S390) || defined(RISCV64) || defined(PPC64) + if (expected_type != nullptr && + ((flags & ~LIR_OpArrayCopy::get_initial_copy_flags()) == 0)) { _stub = nullptr; } else { _stub = new ArrayCopyStub(this); diff --git a/src/hotspot/share/c1/c1_LIR.hpp b/src/hotspot/share/c1/c1_LIR.hpp index 0de69e658a3..c7726bf5c3f 100644 --- a/src/hotspot/share/c1/c1_LIR.hpp +++ b/src/hotspot/share/c1/c1_LIR.hpp @@ -1282,6 +1282,8 @@ class LIR_OpArrayCopy: public LIR_Op { int flags() const { return _flags; } ciArrayKlass* expected_type() const { return _expected_type; } ArrayCopyStub* stub() const { return _stub; } + static int get_initial_copy_flags() { return LIR_OpArrayCopy::unaligned | + LIR_OpArrayCopy::overlapping; } virtual void emit_code(LIR_Assembler* masm); virtual LIR_OpArrayCopy* as_OpArrayCopy() { return this; } diff --git a/src/hotspot/share/c1/c1_Runtime1.cpp b/src/hotspot/share/c1/c1_Runtime1.cpp index 7c41c09d378..57d22a38324 100644 --- a/src/hotspot/share/c1/c1_Runtime1.cpp +++ b/src/hotspot/share/c1/c1_Runtime1.cpp @@ -818,7 +818,7 @@ JRT_ENTRY(void, Runtime1::deoptimize(JavaThread* current, jint trap_request)) Deoptimization::DeoptReason reason = Deoptimization::trap_request_reason(trap_request); if (action == Deoptimization::Action_make_not_entrant) { - if (nm->make_not_entrant("C1 deoptimize")) { + if (nm->make_not_entrant(nmethod::InvalidationReason::C1_DEOPTIMIZE)) { if (reason == Deoptimization::Reason_tenured) { MethodData* trap_mdo = Deoptimization::get_method_data(current, method, true /*create_if_missing*/); if (trap_mdo != nullptr) { @@ -1110,7 +1110,7 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* current, C1StubId stub_id )) // safepoint, but if it's still alive then make it not_entrant. nmethod* nm = CodeCache::find_nmethod(caller_frame.pc()); if (nm != nullptr) { - nm->make_not_entrant("C1 code patch"); + nm->make_not_entrant(nmethod::InvalidationReason::C1_CODEPATCH); } Deoptimization::deoptimize_frame(current, caller_frame.id()); @@ -1358,7 +1358,7 @@ void Runtime1::patch_code(JavaThread* current, C1StubId stub_id) { // Make sure the nmethod is invalidated, i.e. made not entrant. nmethod* nm = CodeCache::find_nmethod(caller_frame.pc()); if (nm != nullptr) { - nm->make_not_entrant("C1 deoptimize for patching"); + nm->make_not_entrant(nmethod::InvalidationReason::C1_DEOPTIMIZE_FOR_PATCHING); } } @@ -1486,7 +1486,7 @@ JRT_ENTRY(void, Runtime1::predicate_failed_trap(JavaThread* current)) nmethod* nm = CodeCache::find_nmethod(caller_frame.pc()); assert (nm != nullptr, "no more nmethod?"); - nm->make_not_entrant("C1 predicate failed trap"); + nm->make_not_entrant(nmethod::InvalidationReason::C1_PREDICATE_FAILED_TRAP); methodHandle m(current, nm->method()); MethodData* mdo = m->method_data(); diff --git a/src/hotspot/share/cds/cds_globals.hpp b/src/hotspot/share/cds/cds_globals.hpp index 730902207f0..f4094aec1ac 100644 --- a/src/hotspot/share/cds/cds_globals.hpp +++ b/src/hotspot/share/cds/cds_globals.hpp @@ -121,6 +121,7 @@ \ product(ccstr, AOTCacheOutput, nullptr, \ "Specifies the file name for writing the AOT cache") \ + constraint(AOTCacheOutputConstraintFunc, AtParse) \ \ product(bool, AOTInvokeDynamicLinking, false, DIAGNOSTIC, \ "AOT-link JVM_CONSTANT_InvokeDynamic entries in cached " \ diff --git a/src/hotspot/share/cds/dynamicArchive.cpp b/src/hotspot/share/cds/dynamicArchive.cpp index b1072dbce9b..498ce6255e4 100644 --- a/src/hotspot/share/cds/dynamicArchive.cpp +++ b/src/hotspot/share/cds/dynamicArchive.cpp @@ -348,6 +348,7 @@ void DynamicArchiveBuilder::write_archive(char* serialized_data, AOTClassLocatio assert(dynamic_info != nullptr, "Sanity"); dynamic_info->open_as_output(); + dynamic_info->prepare_for_writing(); ArchiveHeapInfo no_heap_for_dynamic_dump; ArchiveBuilder::write_archive(dynamic_info, &no_heap_for_dynamic_dump); diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index a413aa2d8e8..80dfa5f19f3 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -766,7 +766,9 @@ void FileMapInfo::open_as_output() { } _fd = fd; _file_open = true; +} +void FileMapInfo::prepare_for_writing() { // Seek past the header. We will write the header after all regions are written // and their CRCs computed. size_t header_bytes = header()->header_size(); diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp index e0b33fc8245..a567d59a7cd 100644 --- a/src/hotspot/share/cds/filemap.hpp +++ b/src/hotspot/share/cds/filemap.hpp @@ -359,6 +359,7 @@ class FileMapInfo : public CHeapObj { // File manipulation. bool open_as_input() NOT_CDS_RETURN_(false); void open_as_output(); + void prepare_for_writing(); void write_header(); void write_region(int region, char* base, size_t size, bool read_only, bool allow_exec); diff --git a/src/hotspot/share/cds/lambdaFormInvokers.cpp b/src/hotspot/share/cds/lambdaFormInvokers.cpp index d6a51c87513..acaa05794a3 100644 --- a/src/hotspot/share/cds/lambdaFormInvokers.cpp +++ b/src/hotspot/share/cds/lambdaFormInvokers.cpp @@ -191,7 +191,7 @@ void LambdaFormInvokers::regenerate_holder_classes(TRAPS) { // make a copy of class bytes so GC will not affect us. char *buf = NEW_RESOURCE_ARRAY(char, len); memcpy(buf, (char*)h_bytes->byte_at_addr(0), len); - ClassFileStream st((u1*)buf, len, nullptr); + ClassFileStream st((u1*)buf, len, "jrt:/java.base"); regenerate_class(class_name, st, CHECK); } } diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index 6e58b8543de..2db7a3116a6 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -113,6 +113,7 @@ intx MetaspaceShared::_relocation_delta; char* MetaspaceShared::_requested_base_address; Array* MetaspaceShared::_archived_method_handle_intrinsics = nullptr; bool MetaspaceShared::_use_optimized_module_handling = true; +FileMapInfo* MetaspaceShared::_output_mapinfo = nullptr; // The CDS archive is divided into the following regions: // rw - read-write metadata @@ -321,6 +322,24 @@ void MetaspaceShared::initialize_for_static_dump() { MetaspaceShared::unrecoverable_writing_error(); } _symbol_region.init(&_symbol_rs, &_symbol_vs); + if (CDSConfig::is_dumping_preimage_static_archive()) { + // We are in the AOT training run. User code is executed. + // + // On Windows, if the user code closes System.out and we open the AOT config file for output + // only at VM exit, we might get back the same file HANDLE as stdout, and the AOT config + // file may get corrupted by UL logs. By opening early, we ensure that the output + // HANDLE is different than stdout so we can avoid such corruption. + open_output_mapinfo(); + } else { + // No need for the above as we won't execute any user code. + } +} + +void MetaspaceShared::open_output_mapinfo() { + const char* static_archive = CDSConfig::output_archive_path(); + assert(static_archive != nullptr, "sanity"); + _output_mapinfo = new FileMapInfo(static_archive, true); + _output_mapinfo->open_as_output(); } // Called by universe_post_init() @@ -551,14 +570,13 @@ class VM_PopulateDumpSharedSpace : public VM_Operation { public: - VM_PopulateDumpSharedSpace(StaticArchiveBuilder& b) : - VM_Operation(), _heap_info(), _map_info(nullptr), _builder(b) {} + VM_PopulateDumpSharedSpace(StaticArchiveBuilder& b, FileMapInfo* map_info) : + VM_Operation(), _heap_info(), _map_info(map_info), _builder(b) {} bool skip_operation() const { return false; } VMOp_Type type() const { return VMOp_PopulateDumpSharedSpace; } ArchiveHeapInfo* heap_info() { return &_heap_info; } - FileMapInfo* map_info() const { return _map_info; } void doit(); // outline because gdb sucks bool allow_nested_vm_operations() const { return true; } }; // class VM_PopulateDumpSharedSpace @@ -688,12 +706,6 @@ void VM_PopulateDumpSharedSpace::doit() { CppVtables::zero_archived_vtables(); // Write the archive file - if (CDSConfig::is_dumping_final_static_archive()) { - FileMapInfo::free_current_info(); // FIXME: should not free current info - } - const char* static_archive = CDSConfig::output_archive_path(); - assert(static_archive != nullptr, "sanity"); - _map_info = new FileMapInfo(static_archive, true); _map_info->populate_header(MetaspaceShared::core_region_alignment()); _map_info->set_early_serialized_data(early_serialized_data); _map_info->set_serialized_data(serialized_data); @@ -1012,7 +1024,14 @@ void MetaspaceShared::preload_and_dump_impl(StaticArchiveBuilder& builder, TRAPS } #endif - VM_PopulateDumpSharedSpace op(builder); + if (!CDSConfig::is_dumping_preimage_static_archive()) { + if (CDSConfig::is_dumping_final_static_archive()) { + FileMapInfo::free_current_info(); // FIXME: should not free current info + } + open_output_mapinfo(); + } + + VM_PopulateDumpSharedSpace op(builder, _output_mapinfo); VMThread::execute(&op); if (AOTCodeCache::is_on_for_dump() && CDSConfig::is_dumping_final_static_archive()) { @@ -1026,7 +1045,9 @@ void MetaspaceShared::preload_and_dump_impl(StaticArchiveBuilder& builder, TRAPS CDSConfig::disable_dumping_aot_code(); } - bool status = write_static_archive(&builder, op.map_info(), op.heap_info()); + bool status = write_static_archive(&builder, _output_mapinfo, op.heap_info()); + assert(!_output_mapinfo->is_open(), "Must be closed already"); + _output_mapinfo = nullptr; if (status && CDSConfig::is_dumping_preimage_static_archive()) { tty->print_cr("%s AOTConfiguration recorded: %s", CDSConfig::has_temp_aot_config_file() ? "Temporary" : "", AOTConfiguration); @@ -1044,11 +1065,10 @@ bool MetaspaceShared::write_static_archive(ArchiveBuilder* builder, FileMapInfo* // relocate the data so that it can be mapped to MetaspaceShared::requested_base_address() // without runtime relocation. builder->relocate_to_requested(); - - map_info->open_as_output(); if (!map_info->is_open()) { return false; } + map_info->prepare_for_writing(); builder->write_archive(map_info, heap_info); if (AllowArchivingWithJavaAgent) { @@ -1270,7 +1290,7 @@ void MetaspaceShared::unrecoverable_loading_error(const char* message) { } else if (CDSConfig::new_aot_flags_used()) { vm_exit_during_initialization("Unable to use AOT cache.", nullptr); } else { - vm_exit_during_initialization("Unable to use shared archive.", nullptr); + vm_exit_during_initialization("Unable to use shared archive. Unrecoverable archive loading error (run with -Xlog:aot,cds for details)", message); } } @@ -1287,6 +1307,10 @@ void MetaspaceShared::report_loading_error(const char* format, ...) { LogStream ls_cds(level, LogTagSetMapping::tagset()); LogStream& ls = CDSConfig::new_aot_flags_used() ? ls_aot : ls_cds; + if (!ls.is_enabled()) { + return; + } + va_list ap; va_start(ap, format); @@ -1394,6 +1418,7 @@ FileMapInfo* MetaspaceShared::open_static_archive() { FileMapInfo* mapinfo = new FileMapInfo(static_archive, true); if (!mapinfo->open_as_input()) { delete(mapinfo); + log_info(cds)("Opening of static archive %s failed", static_archive); return nullptr; } return mapinfo; diff --git a/src/hotspot/share/cds/metaspaceShared.hpp b/src/hotspot/share/cds/metaspaceShared.hpp index 130e7fe4484..f7746129d16 100644 --- a/src/hotspot/share/cds/metaspaceShared.hpp +++ b/src/hotspot/share/cds/metaspaceShared.hpp @@ -59,6 +59,7 @@ class MetaspaceShared : AllStatic { static char* _requested_base_address; static bool _use_optimized_module_handling; static Array* _archived_method_handle_intrinsics; + static FileMapInfo* _output_mapinfo; public: enum { @@ -180,6 +181,7 @@ class MetaspaceShared : AllStatic { private: static void read_extra_data(JavaThread* current, const char* filename) NOT_CDS_RETURN; static void fork_and_dump_final_static_archive(TRAPS); + static void open_output_mapinfo(); static bool write_static_archive(ArchiveBuilder* builder, FileMapInfo* map_info, ArchiveHeapInfo* heap_info); static FileMapInfo* open_static_archive(); static FileMapInfo* open_dynamic_archive(); diff --git a/src/hotspot/share/ci/ciClassList.hpp b/src/hotspot/share/ci/ciClassList.hpp index 618a052765e..bce1e52e80b 100644 --- a/src/hotspot/share/ci/ciClassList.hpp +++ b/src/hotspot/share/ci/ciClassList.hpp @@ -80,6 +80,7 @@ friend class ciObjectFactory; \ // Any more access must be given explicitly. #define CI_PACKAGE_ACCESS_TO \ friend class ciObjectFactory; \ +friend class VMStructs; \ friend class ciCallSite; \ friend class ciConstantPoolCache; \ friend class ciField; \ diff --git a/src/hotspot/share/ci/ciKlass.hpp b/src/hotspot/share/ci/ciKlass.hpp index 37091471a2a..8d03b910de5 100644 --- a/src/hotspot/share/ci/ciKlass.hpp +++ b/src/hotspot/share/ci/ciKlass.hpp @@ -107,7 +107,7 @@ class ciKlass : public ciType { bool is_in_encoding_range() { Klass* k = get_Klass(); bool is_in_encoding_range = CompressedKlassPointers::is_encodable(k); - assert(is_in_encoding_range || k->is_interface() || k->is_abstract(), "sanity"); + assert(is_in_encoding_range, "sanity"); return is_in_encoding_range; } diff --git a/src/hotspot/share/ci/ciReplay.cpp b/src/hotspot/share/ci/ciReplay.cpp index 5ea4336f35e..72ec2866c6e 100644 --- a/src/hotspot/share/ci/ciReplay.cpp +++ b/src/hotspot/share/ci/ciReplay.cpp @@ -802,7 +802,7 @@ class CompileReplay : public StackObj { // Make sure the existence of a prior compile doesn't stop this one nmethod* nm = (entry_bci != InvocationEntryBci) ? method->lookup_osr_nmethod_for(entry_bci, comp_level, true) : method->code(); if (nm != nullptr) { - nm->make_not_entrant("CI replay"); + nm->make_not_entrant(nmethod::InvalidationReason::CI_REPLAY); } replay_state = this; CompileBroker::compile_method(methodHandle(THREAD, method), entry_bci, comp_level, diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index 9c41ab44f82..5e28f3ec641 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -5841,15 +5841,6 @@ bool ClassFileParser::is_java_lang_ref_Reference_subclass() const { return _super_klass->reference_type() != REF_NONE; } -// Returns true if the future Klass will need to be addressable with a narrow Klass ID. -bool ClassFileParser::klass_needs_narrow_id() const { - // Classes that are never instantiated need no narrow Klass Id, since the - // only point of having a narrow id is to put it into an object header. Keeping - // never instantiated classes out of class space lessens the class space pressure. - // For more details, see JDK-8338526. - return !is_interface() && !is_abstract(); -} - // ---------------------------------------------------------------------------- // debugging diff --git a/src/hotspot/share/classfile/classFileParser.hpp b/src/hotspot/share/classfile/classFileParser.hpp index 707fbf6985f..9667c5c2a01 100644 --- a/src/hotspot/share/classfile/classFileParser.hpp +++ b/src/hotspot/share/classfile/classFileParser.hpp @@ -513,11 +513,6 @@ class ClassFileParser { bool is_hidden() const { return _is_hidden; } bool is_interface() const { return _access_flags.is_interface(); } - bool is_abstract() const { return _access_flags.is_abstract(); } - - // Returns true if the Klass to be generated will need to be addressable - // with a narrow Klass ID. - bool klass_needs_narrow_id() const; ClassLoaderData* loader_data() const { return _loader_data; } const Symbol* class_name() const { return _class_name; } diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp index e6c10859371..b8734dcea25 100644 --- a/src/hotspot/share/classfile/classLoader.cpp +++ b/src/hotspot/share/classfile/classLoader.cpp @@ -1192,10 +1192,7 @@ void ClassLoader::record_result(JavaThread* current, InstanceKlass* ik, oop loader = ik->class_loader(); char* src = (char*)stream->source(); if (src == nullptr) { - if (loader == nullptr) { - // JFR classes - ik->set_shared_classpath_index(0); - } + ik->set_shared_classpath_index(-1); // unsupported location return; } diff --git a/src/hotspot/share/classfile/resolutionErrors.cpp b/src/hotspot/share/classfile/resolutionErrors.cpp index 03af71bc26f..506f8891043 100644 --- a/src/hotspot/share/classfile/resolutionErrors.cpp +++ b/src/hotspot/share/classfile/resolutionErrors.cpp @@ -73,7 +73,7 @@ void ResolutionErrorTable::add_entry(const constantPoolHandle& pool, int cp_inde ResolutionErrorKey key(pool(), cp_index); ResolutionErrorEntry *entry = new ResolutionErrorEntry(error, message, cause, cause_msg); - _resolution_error_table->put(key, entry); + _resolution_error_table->put_when_absent(key, entry); } // create new nest host error entry @@ -85,7 +85,7 @@ void ResolutionErrorTable::add_entry(const constantPoolHandle& pool, int cp_inde ResolutionErrorKey key(pool(), cp_index); ResolutionErrorEntry *entry = new ResolutionErrorEntry(message); - _resolution_error_table->put(key, entry); + _resolution_error_table->put_when_absent(key, entry); } // find entry in the table @@ -126,6 +126,13 @@ ResolutionErrorEntry::~ResolutionErrorEntry() { } } +void ResolutionErrorEntry::set_nest_host_error(const char* message) { + assert(_nest_host_error == nullptr, "caller should have checked"); + assert_lock_strong(SystemDictionary_lock); + _nest_host_error = message; +} + + class ResolutionErrorDeleteIterate : StackObj { ConstantPool* p; diff --git a/src/hotspot/share/classfile/resolutionErrors.hpp b/src/hotspot/share/classfile/resolutionErrors.hpp index 60f8aea68ef..39859ad2b70 100644 --- a/src/hotspot/share/classfile/resolutionErrors.hpp +++ b/src/hotspot/share/classfile/resolutionErrors.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,10 +91,7 @@ class ResolutionErrorEntry : public CHeapObj { ~ResolutionErrorEntry(); // The incoming nest host error message is already in the C-Heap. - void set_nest_host_error(const char* message) { - _nest_host_error = message; - } - + void set_nest_host_error(const char* message); Symbol* error() const { return _error; } const char* message() const { return _message; } diff --git a/src/hotspot/share/classfile/stackMapTable.cpp b/src/hotspot/share/classfile/stackMapTable.cpp index 1ed72e998fb..0664491950b 100644 --- a/src/hotspot/share/classfile/stackMapTable.cpp +++ b/src/hotspot/share/classfile/stackMapTable.cpp @@ -132,8 +132,16 @@ bool StackMapTable::match_stackmap( } 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 --git a/src/hotspot/share/classfile/stackMapTable.hpp b/src/hotspot/share/classfile/stackMapTable.hpp index cc4202f3280..0ec7af9d0c9 100644 --- a/src/hotspot/share/classfile/stackMapTable.hpp +++ b/src/hotspot/share/classfile/stackMapTable.hpp @@ -67,7 +67,7 @@ class StackMapTable : public StackObj { // 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 --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index b1abb2ab0fe..ee526e9bb07 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -55,6 +55,7 @@ #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/access.inline.hpp" +#include "oops/constantPool.inline.hpp" #include "oops/instanceKlass.hpp" #include "oops/klass.inline.hpp" #include "oops/method.inline.hpp" @@ -1806,18 +1807,28 @@ Symbol* SystemDictionary::find_resolution_error(const constantPoolHandle& pool, void SystemDictionary::add_nest_host_error(const constantPoolHandle& pool, int which, - const char* message) { + const stringStream& message) { { MutexLocker ml(Thread::current(), SystemDictionary_lock); ResolutionErrorEntry* entry = ResolutionErrorTable::find_entry(pool, which); - if (entry != nullptr && entry->nest_host_error() == nullptr) { + if (entry == nullptr) { + // Only add a new entry to the resolution error table if one hasn't been found for this + // constant pool index. In this case resolution succeeded but there's an error in this nest host + // that we use the table to record. + assert(pool->resolved_klass_at(which) != nullptr, "klass should be resolved if there is no entry"); + ResolutionErrorTable::add_entry(pool, which, message.as_string(true /* on C-heap */)); + } else { // An existing entry means we had a true resolution failure (LinkageError) with our nest host, but we // still want to add the error message for the higher-level access checks to report. We should // only reach here under the same error condition, so we can ignore the potential race with setting - // the message. If we see it is already set then we can ignore it. - entry->set_nest_host_error(message); - } else { - ResolutionErrorTable::add_entry(pool, which, message); + // the message. + const char* nhe = entry->nest_host_error(); + if (nhe == nullptr) { + entry->set_nest_host_error(message.as_string(true /* on C-heap */)); + } else { + DEBUG_ONLY(const char* msg = message.base();) + assert(strcmp(nhe, msg) == 0, "New message %s, differs from original %s", msg, nhe); + } } } } diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp index 8cf2cd83b82..b8efef8edcb 100644 --- a/src/hotspot/share/classfile/systemDictionary.hpp +++ b/src/hotspot/share/classfile/systemDictionary.hpp @@ -280,7 +280,7 @@ class SystemDictionary : AllStatic { // Record a nest host resolution/validation error static void add_nest_host_error(const constantPoolHandle& pool, int which, - const char* message); + const stringStream& message); static const char* find_nest_host_error(const constantPoolHandle& pool, int which); static void add_to_initiating_loader(JavaThread* current, InstanceKlass* k, diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index 8bd09a0d947..bdf558b4a48 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -90,7 +90,7 @@ DEBUG_ONLY(bool SystemDictionaryShared::_class_loading_may_happen = true;) #ifdef ASSERT static void check_klass_after_loading(const Klass* k) { #ifdef _LP64 - if (k != nullptr && UseCompressedClassPointers && k->needs_narrow_id()) { + if (k != nullptr && UseCompressedClassPointers) { CompressedKlassPointers::check_encodable(k); } #endif diff --git a/src/hotspot/share/classfile/verifier.cpp b/src/hotspot/share/classfile/verifier.cpp index 0f1468f0309..f2eda58e660 100644 --- a/src/hotspot/share/classfile/verifier.cpp +++ b/src/hotspot/share/classfile/verifier.cpp @@ -781,7 +781,6 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) { // Merge with the next instruction { - int target; VerificationType type, type2; VerificationType atype; @@ -1606,9 +1605,8 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) { 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 : @@ -1619,19 +1617,16 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) { 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 : @@ -2280,15 +2275,14 @@ void ClassVerifier::verify_switch( } } } - 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 } @@ -2442,209 +2436,6 @@ void ClassVerifier::verify_field_instructions(RawBytecodeStream* bcs, } } -// Look at the method's handlers. If the bci is in the handler's try block -// then check if the handler_pc is already on the stack. If not, push it -// unless the handler has already been scanned. -void ClassVerifier::push_handlers(ExceptionTable* exhandlers, - GrowableArray* handler_list, - GrowableArray* handler_stack, - u4 bci) { - int exlength = exhandlers->length(); - for(int x = 0; x < exlength; x++) { - if (bci >= exhandlers->start_pc(x) && bci < exhandlers->end_pc(x)) { - u4 exhandler_pc = exhandlers->handler_pc(x); - if (!handler_list->contains(exhandler_pc)) { - handler_stack->append_if_missing(exhandler_pc); - handler_list->append(exhandler_pc); - } - } - } -} - -// Return TRUE if all code paths starting with start_bc_offset end in -// bytecode athrow or loop. -bool ClassVerifier::ends_in_athrow(u4 start_bc_offset) { - ResourceMark rm; - // Create bytecode stream. - RawBytecodeStream bcs(method()); - int code_length = method()->code_size(); - bcs.set_start(start_bc_offset); - - // Create stack for storing bytecode start offsets for if* and *switch. - GrowableArray* bci_stack = new GrowableArray(30); - // Create stack for handlers for try blocks containing this handler. - GrowableArray* handler_stack = new GrowableArray(30); - // Create list of handlers that have been pushed onto the handler_stack - // so that handlers embedded inside of their own TRY blocks only get - // scanned once. - GrowableArray* handler_list = new GrowableArray(30); - // Create list of visited branch opcodes (goto* and if*). - GrowableArray* visited_branches = new GrowableArray(30); - ExceptionTable exhandlers(_method()); - - while (true) { - if (bcs.is_last_bytecode()) { - // if no more starting offsets to parse or if at the end of the - // method then return false. - if ((bci_stack->is_empty()) || (bcs.end_bci() == code_length)) - return false; - // Pop a bytecode starting offset and scan from there. - bcs.set_start(bci_stack->pop()); - } - Bytecodes::Code opcode = bcs.raw_next(); - int bci = bcs.bci(); - - // If the bytecode is in a TRY block, push its handlers so they - // will get parsed. - push_handlers(&exhandlers, handler_list, handler_stack, bci); - - switch (opcode) { - case Bytecodes::_if_icmpeq: - case Bytecodes::_if_icmpne: - case Bytecodes::_if_icmplt: - case Bytecodes::_if_icmpge: - case Bytecodes::_if_icmpgt: - case Bytecodes::_if_icmple: - case Bytecodes::_ifeq: - case Bytecodes::_ifne: - case Bytecodes::_iflt: - case Bytecodes::_ifge: - case Bytecodes::_ifgt: - case Bytecodes::_ifle: - case Bytecodes::_if_acmpeq: - case Bytecodes::_if_acmpne: - case Bytecodes::_ifnull: - case Bytecodes::_ifnonnull: { - int target = bcs.dest(); - if (visited_branches->contains(bci)) { - if (bci_stack->is_empty()) { - if (handler_stack->is_empty()) { - return true; - } else { - // Parse the catch handlers for try blocks containing athrow. - bcs.set_start(handler_stack->pop()); - } - } else { - // Pop a bytecode starting offset and scan from there. - bcs.set_start(bci_stack->pop()); - } - } else { - if (target > bci) { // forward branch - if (target >= code_length) return false; - // Push the branch target onto the stack. - bci_stack->push(target); - // then, scan bytecodes starting with next. - bcs.set_start(bcs.next_bci()); - } else { // backward branch - // Push bytecode offset following backward branch onto the stack. - bci_stack->push(bcs.next_bci()); - // Check bytecodes starting with branch target. - bcs.set_start(target); - } - // Record target so we don't branch here again. - visited_branches->append(bci); - } - break; - } - - case Bytecodes::_goto: - case Bytecodes::_goto_w: { - int target = (opcode == Bytecodes::_goto ? bcs.dest() : bcs.dest_w()); - if (visited_branches->contains(bci)) { - if (bci_stack->is_empty()) { - if (handler_stack->is_empty()) { - return true; - } else { - // Parse the catch handlers for try blocks containing athrow. - bcs.set_start(handler_stack->pop()); - } - } else { - // Been here before, pop new starting offset from stack. - bcs.set_start(bci_stack->pop()); - } - } else { - if (target >= code_length) return false; - // Continue scanning from the target onward. - bcs.set_start(target); - // Record target so we don't branch here again. - 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 - // each switch alternative until either hit a 'return', 'athrow', or reach - // the end of the method's bytecodes. This is gross but should be okay - // because: - // 1. tableswitch and lookupswitch byte codes in handlers for ctor explicit - // constructor invocations should be rare. - // 2. if each switch alternative ends in an athrow then the parsing should be - // short. If there is no athrow then it is bogus code, anyway. - case Bytecodes::_lookupswitch: - case Bytecodes::_tableswitch: - { - address aligned_bcp = align_up(bcs.bcp() + 1, jintSize); - int default_offset = Bytes::get_Java_u4(aligned_bcp) + bci; - int keys, delta; - if (opcode == Bytecodes::_tableswitch) { - jint low = (jint)Bytes::get_Java_u4(aligned_bcp + jintSize); - jint high = (jint)Bytes::get_Java_u4(aligned_bcp + 2*jintSize); - // This is invalid, but let the regular bytecode verifier - // report this because the user will get a better error message. - if (low > high) return true; - keys = high - low + 1; - delta = 1; - } else { - keys = (int)Bytes::get_Java_u4(aligned_bcp + jintSize); - delta = 2; - } - // Invalid, let the regular bytecode verifier deal with it. - if (keys < 0) return true; - - // Push the offset of the next bytecode onto the stack. - bci_stack->push(bcs.next_bci()); - - // Push the switch alternatives onto the stack. - for (int i = 0; i < keys; i++) { - int target = bci + (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize); - if (target > code_length) return false; - bci_stack->push(target); - } - - // Start bytecode parsing for the switch at the default alternative. - if (default_offset > code_length) return false; - bcs.set_start(default_offset); - break; - } - - case Bytecodes::_return: - return false; - - case Bytecodes::_athrow: - { - if (bci_stack->is_empty()) { - if (handler_stack->is_empty()) { - return true; - } else { - // Parse the catch handlers for try blocks containing athrow. - bcs.set_start(handler_stack->pop()); - } - } else { - // Pop a bytecode offset and starting scanning from there. - bcs.set_start(bci_stack->pop()); - } - } - break; - - default: - ; - } // end switch - } // end while loop - - return false; -} - void ClassVerifier::verify_invoke_init( RawBytecodeStream* bcs, u2 ref_class_index, VerificationType ref_class_type, StackMapFrame* current_frame, u4 code_length, bool in_try_block, @@ -2669,25 +2460,6 @@ void ClassVerifier::verify_invoke_init( // sure that all catch clause paths end in a throw. Otherwise, this can // result in returning an incomplete object. if (in_try_block) { - ExceptionTable exhandlers(_method()); - int exlength = exhandlers.length(); - for(int i = 0; i < exlength; i++) { - u2 start_pc = exhandlers.start_pc(i); - u2 end_pc = exhandlers.end_pc(i); - - if (bci >= start_pc && bci < end_pc) { - if (!ends_in_athrow(exhandlers.handler_pc(i))) { - verify_error(ErrorContext::bad_code(bci), - "Bad method call from after the start of a try block"); - return; - } else if (log_is_enabled(Debug, verification)) { - ResourceMark rm(THREAD); - log_debug(verification)("Survived call to ends_in_athrow(): %s", - current_class()->name()->as_C_string()); - } - } - } - // Check the exception handler target stackmaps with the locals from the // incoming stackmap (before initialize_object() changes them to outgoing // state). diff --git a/src/hotspot/share/classfile/verifier.hpp b/src/hotspot/share/classfile/verifier.hpp index 7857d472705..290800be715 100644 --- a/src/hotspot/share/classfile/verifier.hpp +++ b/src/hotspot/share/classfile/verifier.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2024, 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 @@ -334,17 +334,6 @@ class ClassVerifier : public StackObj { bool* this_uninit, const constantPoolHandle& cp, StackMapTable* stackmap_table, TRAPS); - // Used by ends_in_athrow() to push all handlers that contain bci onto the - // handler_stack, if the handler has not already been pushed on the stack. - void push_handlers(ExceptionTable* exhandlers, - GrowableArray* handler_list, - GrowableArray* handler_stack, - u4 bci); - - // Returns true if all paths starting with start_bc_offset end in athrow - // bytecode or loop. - bool ends_in_athrow(u4 start_bc_offset); - void verify_invoke_instructions( RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame, bool in_try_block, bool* this_uninit, VerificationType return_type, diff --git a/src/hotspot/share/classfile/vmClasses.cpp b/src/hotspot/share/classfile/vmClasses.cpp index 813926e51a2..b5a19ce6391 100644 --- a/src/hotspot/share/classfile/vmClasses.cpp +++ b/src/hotspot/share/classfile/vmClasses.cpp @@ -210,9 +210,11 @@ void vmClasses::resolve_all(TRAPS) { #endif InstanceStackChunkKlass::init_offset_of_stack(); +#if INCLUDE_CDS if (CDSConfig::is_using_aot_linked_classes()) { AOTLinkedClassBulkLoader::load_javabase_classes(THREAD); } +#endif } #if INCLUDE_CDS diff --git a/src/hotspot/share/classfile/vmIntrinsics.cpp b/src/hotspot/share/classfile/vmIntrinsics.cpp index 6fd5c07e137..baa945cdddf 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.cpp +++ b/src/hotspot/share/classfile/vmIntrinsics.cpp @@ -289,8 +289,6 @@ bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) { case vmIntrinsics::_dsin: case vmIntrinsics::_dcos: case vmIntrinsics::_dtan: - case vmIntrinsics::_dtanh: - case vmIntrinsics::_dcbrt: case vmIntrinsics::_dlog: case vmIntrinsics::_dexp: case vmIntrinsics::_dpow: @@ -316,6 +314,13 @@ bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) { case vmIntrinsics::_fmaF: if (!InlineMathNatives || !UseFMA) return true; break; + case vmIntrinsics::_dtanh: + case vmIntrinsics::_dcbrt: + if (!InlineMathNatives || !InlineIntrinsics) return true; +#if defined(AMD64) && (defined(COMPILER1) || defined(COMPILER2)) + if (!UseLibmIntrinsic) return true; +#endif + break; case vmIntrinsics::_floatToFloat16: case vmIntrinsics::_float16ToFloat: if (!InlineIntrinsics) return true; diff --git a/src/hotspot/share/code/aotCodeCache.hpp b/src/hotspot/share/code/aotCodeCache.hpp index eaced55cc50..2446b37469b 100644 --- a/src/hotspot/share/code/aotCodeCache.hpp +++ b/src/hotspot/share/code/aotCodeCache.hpp @@ -362,8 +362,8 @@ class AOTCodeCache : public CHeapObj { static void init2() NOT_CDS_RETURN; static void close() NOT_CDS_RETURN; static bool is_on() CDS_ONLY({ return _cache != nullptr && !_cache->closing(); }) NOT_CDS_RETURN_(false); - static bool is_on_for_use() { return is_on() && _cache->for_use(); } - static bool is_on_for_dump() { return is_on() && _cache->for_dump(); } + static bool is_on_for_use() CDS_ONLY({ return is_on() && _cache->for_use(); }) NOT_CDS_RETURN_(false); + static bool is_on_for_dump() CDS_ONLY({ return is_on() && _cache->for_dump(); }) NOT_CDS_RETURN_(false); static bool is_dumping_adapter() NOT_CDS_RETURN_(false); static bool is_using_adapter() NOT_CDS_RETURN_(false); diff --git a/src/hotspot/share/code/codeBlob.cpp b/src/hotspot/share/code/codeBlob.cpp index cf21f1f89a4..96b9d8c0e0d 100644 --- a/src/hotspot/share/code/codeBlob.cpp +++ b/src/hotspot/share/code/codeBlob.cpp @@ -897,6 +897,7 @@ void CodeBlob::dump_for_addr(address addr, outputStream* st, bool verbose) const nm->print_nmethod(true); } else { nm->print_on(st); + nm->print_code_snippet(st, addr); } return; } diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index 902d4345622..169e938fd9d 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -227,11 +227,6 @@ void CodeCache::initialize_heaps() { if (!non_nmethod.set) { non_nmethod.size += compiler_buffer_size; - // Further down, just before FLAG_SET_ERGO(), all segment sizes are - // aligned down to the next lower multiple of min_size. For large page - // sizes, this may result in (non_nmethod.size == 0) which is not acceptable. - // Therefore, force non_nmethod.size to at least min_size. - non_nmethod.size = MAX2(non_nmethod.size, min_size); } if (!profiled.set && !non_profiled.set) { @@ -307,11 +302,10 @@ void CodeCache::initialize_heaps() { // Note: if large page support is enabled, min_size is at least the large // page size. This ensures that the code cache is covered by large pages. - non_profiled.size += non_nmethod.size & alignment_mask(min_size); - non_profiled.size += profiled.size & alignment_mask(min_size); - non_nmethod.size = align_down(non_nmethod.size, min_size); - profiled.size = align_down(profiled.size, min_size); - non_profiled.size = align_down(non_profiled.size, min_size); + non_nmethod.size = align_up(non_nmethod.size, min_size); + profiled.size = align_up(profiled.size, min_size); + non_profiled.size = align_up(non_profiled.size, min_size); + cache_size = non_nmethod.size + profiled.size + non_profiled.size; FLAG_SET_ERGO(NonNMethodCodeHeapSize, non_nmethod.size); FLAG_SET_ERGO(ProfiledCodeHeapSize, profiled.size); @@ -882,6 +876,7 @@ void CodeCache::do_unloading(bool unloading_occurred) { void CodeCache::verify_clean_inline_caches() { #ifdef ASSERT + if (!VerifyInlineCaches) return; NMethodIterator iter(NMethodIterator::not_unloading); while(iter.next()) { nmethod* nm = iter.method(); @@ -1361,7 +1356,7 @@ void CodeCache::make_marked_nmethods_deoptimized() { while(iter.next()) { nmethod* nm = iter.method(); if (nm->is_marked_for_deoptimization() && !nm->has_been_deoptimized() && nm->can_be_deoptimized()) { - nm->make_not_entrant("marked for deoptimization"); + nm->make_not_entrant(nmethod::InvalidationReason::MARKED_FOR_DEOPTIMIZATION); nm->make_deoptimized(); } } diff --git a/src/hotspot/share/code/compiledIC.hpp b/src/hotspot/share/code/compiledIC.hpp index 37ca090fa9c..624c1b428de 100644 --- a/src/hotspot/share/code/compiledIC.hpp +++ b/src/hotspot/share/code/compiledIC.hpp @@ -192,13 +192,13 @@ class CompiledDirectCall : public ResourceObj { static inline CompiledDirectCall* before(address return_addr) { CompiledDirectCall* st = new CompiledDirectCall(nativeCall_before(return_addr)); - st->verify(); + if (VerifyInlineCaches) st->verify(); return st; } static inline CompiledDirectCall* at(address native_call) { CompiledDirectCall* st = new CompiledDirectCall(nativeCall_at(native_call)); - st->verify(); + if (VerifyInlineCaches) st->verify(); return st; } diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index 412cf222997..4d39b715f25 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -1970,14 +1970,12 @@ void nmethod::invalidate_osr_method() { } } -void nmethod::log_state_change(const char* reason) const { - assert(reason != nullptr, "Must provide a reason"); - +void nmethod::log_state_change(InvalidationReason invalidation_reason) const { if (LogCompilation) { if (xtty != nullptr) { ttyLocker ttyl; // keep the following output all in one block xtty->begin_elem("make_not_entrant thread='%zu' reason='%s'", - os::current_thread_id(), reason); + os::current_thread_id(), invalidation_reason_to_string(invalidation_reason)); log_identity(xtty); xtty->stamp(); xtty->end_elem(); @@ -1986,7 +1984,7 @@ void nmethod::log_state_change(const char* reason) const { ResourceMark rm; stringStream ss(NEW_RESOURCE_ARRAY(char, 256), 256); - ss.print("made not entrant: %s", reason); + ss.print("made not entrant: %s", invalidation_reason_to_string(invalidation_reason)); CompileTask::print_ul(this, ss.freeze()); if (PrintCompilation) { @@ -2001,9 +1999,7 @@ void nmethod::unlink_from_method() { } // Invalidate code -bool nmethod::make_not_entrant(const char* reason) { - assert(reason != nullptr, "Must provide a reason"); - +bool nmethod::make_not_entrant(InvalidationReason invalidation_reason) { // This can be called while the system is already at a safepoint which is ok NoSafepointVerifier nsv; @@ -2061,7 +2057,7 @@ bool nmethod::make_not_entrant(const char* reason) { assert(success, "Transition can't fail"); // Log the transition once - log_state_change(reason); + log_state_change(invalidation_reason); // Remove nmethod from method. unlink_from_method(); @@ -2072,7 +2068,7 @@ bool nmethod::make_not_entrant(const char* reason) { // Invalidate can't occur while holding the NMethodState_lock JVMCINMethodData* nmethod_data = jvmci_nmethod_data(); if (nmethod_data != nullptr) { - nmethod_data->invalidate_nmethod_mirror(this); + nmethod_data->invalidate_nmethod_mirror(this, invalidation_reason); } #endif @@ -2110,7 +2106,9 @@ void nmethod::unlink() { // Clear the link between this nmethod and a HotSpotNmethod mirror JVMCINMethodData* nmethod_data = jvmci_nmethod_data(); if (nmethod_data != nullptr) { - nmethod_data->invalidate_nmethod_mirror(this); + nmethod_data->invalidate_nmethod_mirror(this, is_cold() ? + nmethod::InvalidationReason::UNLOADING_COLD : + nmethod::InvalidationReason::UNLOADING); } #endif @@ -4003,6 +4001,46 @@ void nmethod::print_value_on_impl(outputStream* st) const { #endif } +void nmethod::print_code_snippet(outputStream* st, address addr) const { + if (entry_point() <= addr && addr < code_end()) { + // Pointing into the nmethod's code. Try to disassemble some instructions around addr. + // Determine conservative start and end points. + address start; + if (frame_complete_offset() != CodeOffsets::frame_never_safe && + addr >= code_begin() + frame_complete_offset()) { + start = code_begin() + frame_complete_offset(); + } else { + start = (addr < verified_entry_point()) ? entry_point() : verified_entry_point(); + } + address start_for_hex_dump = start; // We can choose a different starting point for hex dump, below. + address end = code_end(); + + // Try using relocations to find closer instruction start and end points. + // (Some platforms have variable length instructions and can only + // disassemble correctly at instruction start addresses.) + RelocIterator iter((nmethod*)this, start); + while (iter.next() && iter.addr() < addr) { // find relocation before addr + // Note: There's a relocation which doesn't point to an instruction start: + // ZBarrierRelocationFormatStoreGoodAfterMov with ZGC on x86_64 + // We could detect and skip it, but hex dump is still usable when + // disassembler produces garbage in such a very rare case. + start = iter.addr(); + // We want at least 64 Bytes ahead in hex dump. + if (iter.addr() <= (addr - 64)) start_for_hex_dump = iter.addr(); + } + if (iter.has_current()) { + if (iter.addr() == addr) iter.next(); // find relocation after addr + if (iter.has_current()) end = iter.addr(); + } + + // Always print hex. Disassembler may still have problems when hitting an incorrect instruction start. + os::print_hex_dump(st, start_for_hex_dump, end, 1, /* print_ascii=*/false); + if (!Disassembler::is_abstract()) { + Disassembler::decode(start, end, st); + } + } +} + #ifndef PRODUCT void nmethod::print_calls(outputStream* st) { diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index 2ce6e5cd361..35adb84733a 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -471,6 +471,82 @@ class nmethod : public CodeBlob { void oops_do_set_strong_done(nmethod* old_head); public: + // If you change anything in this enum please patch + // vmStructs_jvmci.cpp accordingly. + enum class InvalidationReason : s1 { + NOT_INVALIDATED = -1, + C1_CODEPATCH, + C1_DEOPTIMIZE, + C1_DEOPTIMIZE_FOR_PATCHING, + C1_PREDICATE_FAILED_TRAP, + CI_REPLAY, + UNLOADING, + UNLOADING_COLD, + JVMCI_INVALIDATE, + JVMCI_MATERIALIZE_VIRTUAL_OBJECT, + JVMCI_REPLACED_WITH_NEW_CODE, + JVMCI_REPROFILE, + MARKED_FOR_DEOPTIMIZATION, + MISSING_EXCEPTION_HANDLER, + NOT_USED, + OSR_INVALIDATION_BACK_BRANCH, + OSR_INVALIDATION_FOR_COMPILING_WITH_C1, + OSR_INVALIDATION_OF_LOWER_LEVEL, + SET_NATIVE_FUNCTION, + UNCOMMON_TRAP, + WHITEBOX_DEOPTIMIZATION, + ZOMBIE, + INVALIDATION_REASONS_COUNT + }; + + + static const char* invalidation_reason_to_string(InvalidationReason invalidation_reason) { + switch (invalidation_reason) { + case InvalidationReason::C1_CODEPATCH: + return "C1 code patch"; + case InvalidationReason::C1_DEOPTIMIZE: + return "C1 deoptimized"; + case InvalidationReason::C1_DEOPTIMIZE_FOR_PATCHING: + return "C1 deoptimize for patching"; + case InvalidationReason::C1_PREDICATE_FAILED_TRAP: + return "C1 predicate failed trap"; + case InvalidationReason::CI_REPLAY: + return "CI replay"; + case InvalidationReason::JVMCI_INVALIDATE: + return "JVMCI invalidate"; + case InvalidationReason::JVMCI_MATERIALIZE_VIRTUAL_OBJECT: + return "JVMCI materialize virtual object"; + case InvalidationReason::JVMCI_REPLACED_WITH_NEW_CODE: + return "JVMCI replaced with new code"; + case InvalidationReason::JVMCI_REPROFILE: + return "JVMCI reprofile"; + case InvalidationReason::MARKED_FOR_DEOPTIMIZATION: + return "marked for deoptimization"; + case InvalidationReason::MISSING_EXCEPTION_HANDLER: + return "missing exception handler"; + case InvalidationReason::NOT_USED: + return "not used"; + case InvalidationReason::OSR_INVALIDATION_BACK_BRANCH: + return "OSR invalidation back branch"; + case InvalidationReason::OSR_INVALIDATION_FOR_COMPILING_WITH_C1: + return "OSR invalidation for compiling with C1"; + case InvalidationReason::OSR_INVALIDATION_OF_LOWER_LEVEL: + return "OSR invalidation of lower level"; + case InvalidationReason::SET_NATIVE_FUNCTION: + return "set native function"; + case InvalidationReason::UNCOMMON_TRAP: + return "uncommon trap"; + case InvalidationReason::WHITEBOX_DEOPTIMIZATION: + return "whitebox deoptimization"; + case InvalidationReason::ZOMBIE: + return "zombie"; + default: { + assert(false, "Unhandled reason"); + return "Unknown"; + } + } + } + // create nmethod with entry_bci static nmethod* new_nmethod(const methodHandle& method, int compile_id, @@ -633,8 +709,8 @@ class nmethod : public CodeBlob { // alive. It is used when an uncommon trap happens. Returns true // if this thread changed the state of the nmethod or false if // another thread performed the transition. - bool make_not_entrant(const char* reason); - bool make_not_used() { return make_not_entrant("not used"); } + bool make_not_entrant(InvalidationReason invalidation_reason); + bool make_not_used() { return make_not_entrant(InvalidationReason::NOT_USED); } bool is_marked_for_deoptimization() const { return deoptimization_status() != not_marked; } bool has_been_deoptimized() const { return deoptimization_status() == deoptimize_done; } @@ -917,6 +993,7 @@ class nmethod : public CodeBlob { void print_on_impl(outputStream* st) const; void print_code(); void print_value_on_impl(outputStream* st) const; + void print_code_snippet(outputStream* st, address addr) const; #if defined(SUPPORT_DATA_STRUCTS) // print output in opt build for disassembler library @@ -947,7 +1024,7 @@ class nmethod : public CodeBlob { // Logging void log_identity(xmlStream* log) const; void log_new_nmethod() const; - void log_state_change(const char* reason) const; + void log_state_change(InvalidationReason invalidation_reason) const; // Prints block-level comments, including nmethod specific block labels: void print_nmethod_labels(outputStream* stream, address block_begin, bool print_section_labels=true) const; diff --git a/src/hotspot/share/compiler/compilationPolicy.cpp b/src/hotspot/share/compiler/compilationPolicy.cpp index 39c90281c79..6f84dbeb40c 100644 --- a/src/hotspot/share/compiler/compilationPolicy.cpp +++ b/src/hotspot/share/compiler/compilationPolicy.cpp @@ -404,7 +404,7 @@ double CompilationPolicy::threshold_scale(CompLevel level, int feedback_k) { return 1; } -void CompilationPolicy::print_counters(const char* prefix, Method* m) { +void CompilationPolicy::print_counters_on(outputStream* st, const char* prefix, Method* m) { int invocation_count = m->invocation_count(); int backedge_count = m->backedge_count(); MethodData* mdh = m->method_data(); @@ -416,133 +416,140 @@ void CompilationPolicy::print_counters(const char* prefix, Method* m) { mdo_invocations_start = mdh->invocation_count_start(); mdo_backedges_start = mdh->backedge_count_start(); } - tty->print(" %stotal=%d,%d %smdo=%d(%d),%d(%d)", prefix, - invocation_count, backedge_count, prefix, - mdo_invocations, mdo_invocations_start, - mdo_backedges, mdo_backedges_start); - tty->print(" %smax levels=%d,%d", prefix, - m->highest_comp_level(), m->highest_osr_comp_level()); + st->print(" %stotal=%d,%d %smdo=%d(%d),%d(%d)", prefix, + invocation_count, backedge_count, prefix, + mdo_invocations, mdo_invocations_start, + mdo_backedges, mdo_backedges_start); + st->print(" %smax levels=%d,%d", prefix, m->highest_comp_level(), m->highest_osr_comp_level()); } -void CompilationPolicy::print_training_data(const char* prefix, Method* method) { +void CompilationPolicy::print_training_data_on(outputStream* st, const char* prefix, Method* method) { methodHandle m(Thread::current(), method); - tty->print(" %smtd: ", prefix); + st->print(" %smtd: ", prefix); MethodTrainingData* mtd = MethodTrainingData::find(m); if (mtd == nullptr) { - tty->print("null"); + st->print("null"); } else { MethodData* md = mtd->final_profile(); - tty->print("mdo="); + st->print("mdo="); if (md == nullptr) { - tty->print("null"); + st->print("null"); } else { int mdo_invocations = md->invocation_count(); int mdo_backedges = md->backedge_count(); int mdo_invocations_start = md->invocation_count_start(); int mdo_backedges_start = md->backedge_count_start(); - tty->print("%d(%d), %d(%d)", mdo_invocations, mdo_invocations_start, mdo_backedges, mdo_backedges_start); + st->print("%d(%d), %d(%d)", mdo_invocations, mdo_invocations_start, mdo_backedges, mdo_backedges_start); } CompileTrainingData* ctd = mtd->last_toplevel_compile(CompLevel_full_optimization); - tty->print(", deps="); + st->print(", deps="); if (ctd == nullptr) { - tty->print("null"); + st->print("null"); } else { - tty->print("%d", ctd->init_deps_left()); + st->print("%d", ctd->init_deps_left()); } } } // Print an event. -void CompilationPolicy::print_event(EventType type, Method* m, Method* im, int bci, CompLevel level) { +void CompilationPolicy::print_event_on(outputStream *st, EventType type, Method* m, Method* im, int bci, CompLevel level) { bool inlinee_event = m != im; - ttyLocker tty_lock; - tty->print("%lf: [", os::elapsedTime()); + st->print("%lf: [", os::elapsedTime()); switch(type) { case CALL: - tty->print("call"); + st->print("call"); break; case LOOP: - tty->print("loop"); + st->print("loop"); break; case COMPILE: - tty->print("compile"); + st->print("compile"); break; case FORCE_COMPILE: - tty->print("force-compile"); + st->print("force-compile"); break; case REMOVE_FROM_QUEUE: - tty->print("remove-from-queue"); + st->print("remove-from-queue"); break; case UPDATE_IN_QUEUE: - tty->print("update-in-queue"); + st->print("update-in-queue"); break; case REPROFILE: - tty->print("reprofile"); + st->print("reprofile"); break; case MAKE_NOT_ENTRANT: - tty->print("make-not-entrant"); + st->print("make-not-entrant"); break; default: - tty->print("unknown"); + st->print("unknown"); } - tty->print(" level=%d ", level); + st->print(" level=%d ", level); ResourceMark rm; char *method_name = m->name_and_sig_as_C_string(); - tty->print("[%s", method_name); + st->print("[%s", method_name); if (inlinee_event) { char *inlinee_name = im->name_and_sig_as_C_string(); - tty->print(" [%s]] ", inlinee_name); + st->print(" [%s]] ", inlinee_name); } - else tty->print("] "); - tty->print("@%d queues=%d,%d", bci, CompileBroker::queue_size(CompLevel_full_profile), - CompileBroker::queue_size(CompLevel_full_optimization)); + else st->print("] "); + st->print("@%d queues=%d,%d", bci, CompileBroker::queue_size(CompLevel_full_profile), + CompileBroker::queue_size(CompLevel_full_optimization)); - tty->print(" rate="); - if (m->prev_time() == 0) tty->print("n/a"); - else tty->print("%f", m->rate()); + st->print(" rate="); + if (m->prev_time() == 0) st->print("n/a"); + else st->print("%f", m->rate()); - tty->print(" k=%.2lf,%.2lf", threshold_scale(CompLevel_full_profile, Tier3LoadFeedback), - threshold_scale(CompLevel_full_optimization, Tier4LoadFeedback)); + st->print(" k=%.2lf,%.2lf", threshold_scale(CompLevel_full_profile, Tier3LoadFeedback), + threshold_scale(CompLevel_full_optimization, Tier4LoadFeedback)); if (type != COMPILE) { - print_counters("", m); + print_counters_on(st, "", m); if (inlinee_event) { - print_counters("inlinee ", im); + print_counters_on(st, "inlinee ", im); } - tty->print(" compilable="); + st->print(" compilable="); bool need_comma = false; if (!m->is_not_compilable(CompLevel_full_profile)) { - tty->print("c1"); + st->print("c1"); need_comma = true; } if (!m->is_not_osr_compilable(CompLevel_full_profile)) { - if (need_comma) tty->print(","); - tty->print("c1-osr"); + if (need_comma) st->print(","); + st->print("c1-osr"); need_comma = true; } if (!m->is_not_compilable(CompLevel_full_optimization)) { - if (need_comma) tty->print(","); - tty->print("c2"); + if (need_comma) st->print(","); + st->print("c2"); need_comma = true; } if (!m->is_not_osr_compilable(CompLevel_full_optimization)) { - if (need_comma) tty->print(","); - tty->print("c2-osr"); + if (need_comma) st->print(","); + st->print("c2-osr"); } - tty->print(" status="); + st->print(" status="); if (m->queued_for_compilation()) { - tty->print("in-queue"); - } else tty->print("idle"); - print_training_data("", m); + st->print("in-queue"); + } else st->print("idle"); + + print_training_data_on(st, "", m); if (inlinee_event) { - print_training_data("inlinee ", im); + print_training_data_on(st, "inlinee ", im); } } - tty->print_cr("]"); + st->print_cr("]"); + +} + +void CompilationPolicy::print_event(EventType type, Method* m, Method* im, int bci, CompLevel level) { + stringStream s; + print_event_on(&s, type, m, im, bci, level); + ResourceMark rm; + tty->print("%s", s.as_string()); } void CompilationPolicy::initialize() { @@ -924,7 +931,7 @@ void CompilationPolicy::compile(const methodHandle& mh, int bci, CompLevel level nmethod* osr_nm = mh->lookup_osr_nmethod_for(bci, CompLevel_simple, false); if (osr_nm != nullptr && osr_nm->comp_level() > CompLevel_simple) { // Invalidate the existing OSR nmethod so that a compile at CompLevel_simple is permitted. - osr_nm->make_not_entrant("OSR invalidation for compiling with C1"); + osr_nm->make_not_entrant(nmethod::InvalidationReason::OSR_INVALIDATION_FOR_COMPILING_WITH_C1); } compile(mh, bci, CompLevel_simple, THREAD); } @@ -1335,17 +1342,24 @@ CompLevel CompilationPolicy::standard_transition(const methodHandle& method, Com return next_level; } +template static inline bool apply_predicate(const methodHandle& method, CompLevel cur_level, int i, int b, bool delay_profiling, double delay_profiling_scale) { + if (delay_profiling) { + return Predicate::apply_scaled(method, cur_level, i, b, delay_profiling_scale); + } else { + return Predicate::apply(method, cur_level, i, b); + } +} + template CompLevel CompilationPolicy::transition_from_none(const methodHandle& method, CompLevel cur_level, bool delay_profiling, bool disable_feedback) { precond(cur_level == CompLevel_none); CompLevel next_level = cur_level; int i = method->invocation_count(); int b = method->backedge_count(); - double scale = delay_profiling ? Tier0ProfileDelayFactor : 1.0; // If we were at full profile level, would we switch to full opt? if (transition_from_full_profile(method, CompLevel_full_profile) == CompLevel_full_optimization) { next_level = CompLevel_full_optimization; - } else if (!CompilationModeFlag::disable_intermediate() && Predicate::apply_scaled(method, cur_level, i, b, scale)) { + } else if (!CompilationModeFlag::disable_intermediate() && apply_predicate(method, cur_level, i, b, delay_profiling, Tier0ProfileDelayFactor)) { // C1-generated fully profiled code is about 30% slower than the limited profile // code that has only invocation and backedge counters. The observation is that // if C2 queue is large enough we can spend too much time in the fully profiled code @@ -1387,13 +1401,12 @@ CompLevel CompilationPolicy::transition_from_limited_profile(const methodHandle& CompLevel next_level = cur_level; int i = method->invocation_count(); int b = method->backedge_count(); - double scale = delay_profiling ? Tier2ProfileDelayFactor : 1.0; MethodData* mdo = method->method_data(); if (mdo != nullptr) { if (mdo->would_profile()) { if (disable_feedback || (CompileBroker::queue_size(CompLevel_full_optimization) <= Tier3DelayOff * compiler_count(CompLevel_full_optimization) && - Predicate::apply_scaled(method, cur_level, i, b, scale))) { + apply_predicate(method, cur_level, i, b, delay_profiling, Tier2ProfileDelayFactor))) { next_level = CompLevel_full_profile; } } else { @@ -1403,7 +1416,7 @@ CompLevel CompilationPolicy::transition_from_limited_profile(const methodHandle& // If there is no MDO we need to profile if (disable_feedback || (CompileBroker::queue_size(CompLevel_full_optimization) <= Tier3DelayOff * compiler_count(CompLevel_full_optimization) && - Predicate::apply_scaled(method, cur_level, i, b, scale))) { + apply_predicate(method, cur_level, i, b, delay_profiling, Tier2ProfileDelayFactor))) { next_level = CompLevel_full_profile; } } @@ -1516,7 +1529,7 @@ void CompilationPolicy::method_back_branch_event(const methodHandle& mh, const m int osr_bci = nm->is_osr_method() ? nm->osr_entry_bci() : InvocationEntryBci; print_event(MAKE_NOT_ENTRANT, mh(), mh(), osr_bci, level); } - nm->make_not_entrant("OSR invalidation, back branch"); + nm->make_not_entrant(nmethod::InvalidationReason::OSR_INVALIDATION_BACK_BRANCH); } } // Fix up next_level if necessary to avoid deopts diff --git a/src/hotspot/share/compiler/compilationPolicy.hpp b/src/hotspot/share/compiler/compilationPolicy.hpp index 75374a2f830..f4a7c4c249b 100644 --- a/src/hotspot/share/compiler/compilationPolicy.hpp +++ b/src/hotspot/share/compiler/compilationPolicy.hpp @@ -287,8 +287,8 @@ class CompilationPolicy : AllStatic { // loop_event checks if a method should be OSR compiled at a different // level. static CompLevel loop_event(const methodHandle& method, CompLevel cur_level, JavaThread* THREAD); - static void print_counters(const char* prefix, Method* m); - static void print_training_data(const char* prefix, Method* method); + static void print_counters_on(outputStream* st, const char* prefix, Method* m); + static void print_training_data_on(outputStream* st, const char* prefix, Method* method); // Has a method been long around? // We don't remove old methods from the compile queue even if they have // very low activity (see select_task()). @@ -318,6 +318,7 @@ class CompilationPolicy : AllStatic { static void set_c2_count(int x) { _c2_count = x; } enum EventType { CALL, LOOP, COMPILE, FORCE_COMPILE, FORCE_RECOMPILE, REMOVE_FROM_QUEUE, UPDATE_IN_QUEUE, REPROFILE, MAKE_NOT_ENTRANT }; + static void print_event_on(outputStream *st, EventType type, Method* m, Method* im, int bci, CompLevel level); static void print_event(EventType type, Method* m, Method* im, int bci, CompLevel level); // Check if the method can be compiled, change level if necessary static void compile(const methodHandle& mh, int bci, CompLevel level, TRAPS); diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 705dcd7895b..e96fbeba964 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -28,6 +28,7 @@ #include "code/codeCache.hpp" #include "compiler/oopMap.hpp" #include "gc/g1/g1Allocator.inline.hpp" +#include "gc/g1/g1Analytics.hpp" #include "gc/g1/g1Arguments.hpp" #include "gc/g1/g1BarrierSet.hpp" #include "gc/g1/g1BatchedTask.hpp" @@ -387,22 +388,26 @@ HeapWord* G1CollectedHeap::allocate_new_tlab(size_t min_size, assert_heap_not_locked_and_not_at_safepoint(); assert(!is_humongous(requested_size), "we do not allow humongous TLABs"); - return attempt_allocation(min_size, requested_size, actual_size); + // Do not allow a GC because we are allocating a new TLAB to avoid an issue + // with UseGCOverheadLimit: although this GC would return null if the overhead + // limit would be exceeded, but it would likely free at least some space. + // So the subsequent outside-TLAB allocation could be successful anyway and + // the indication that the overhead limit had been exceeded swallowed. + return attempt_allocation(min_size, requested_size, actual_size, false /* allow_gc */); } -HeapWord* -G1CollectedHeap::mem_allocate(size_t word_size, - bool* gc_overhead_limit_was_exceeded) { +HeapWord* G1CollectedHeap::mem_allocate(size_t word_size, + bool* gc_overhead_limit_was_exceeded) { assert_heap_not_locked_and_not_at_safepoint(); if (is_humongous(word_size)) { return attempt_allocation_humongous(word_size); } size_t dummy = 0; - return attempt_allocation(word_size, word_size, &dummy); + return attempt_allocation(word_size, word_size, &dummy, true /* allow_gc */); } -HeapWord* G1CollectedHeap::attempt_allocation_slow(uint node_index, size_t word_size) { +HeapWord* G1CollectedHeap::attempt_allocation_slow(uint node_index, size_t word_size, bool allow_gc) { ResourceMark rm; // For retrieving the thread names in log messages. // Make sure you read the note in attempt_allocation_humongous(). @@ -429,6 +434,8 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(uint node_index, size_t word_ result = _allocator->attempt_allocation_locked(node_index, word_size); if (result != nullptr) { return result; + } else if (!allow_gc) { + return nullptr; } // Read the GC count while still holding the Heap_lock. @@ -446,8 +453,15 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(uint node_index, size_t word_ log_trace(gc, alloc)("%s: Unsuccessfully scheduled collection allocating %zu words", Thread::current()->name(), word_size); + // Has the gc overhead limit been reached in the meantime? If so, this mutator + // should receive null even when unsuccessfully scheduling a collection as well + // for global consistency. + if (gc_overhead_limit_exceeded()) { + return nullptr; + } + // We can reach here if we were unsuccessful in scheduling a collection (because - // another thread beat us to it). In this case immeditealy retry the allocation + // another thread beat us to it). In this case immediately retry the allocation // attempt because another thread successfully performed a collection and possibly // reclaimed enough space. The first attempt (without holding the Heap_lock) is // here and the follow-on attempt will be at the start of the next loop @@ -592,7 +606,8 @@ void G1CollectedHeap::dealloc_archive_regions(MemRegion range) { inline HeapWord* G1CollectedHeap::attempt_allocation(size_t min_word_size, size_t desired_word_size, - size_t* actual_word_size) { + size_t* actual_word_size, + bool allow_gc) { assert_heap_not_locked_and_not_at_safepoint(); assert(!is_humongous(desired_word_size), "attempt_allocation() should not " "be called for humongous allocation requests"); @@ -604,7 +619,7 @@ inline HeapWord* G1CollectedHeap::attempt_allocation(size_t min_word_size, if (result == nullptr) { *actual_word_size = desired_word_size; - result = attempt_allocation_slow(node_index, desired_word_size); + result = attempt_allocation_slow(node_index, desired_word_size, allow_gc); } assert_heap_not_locked(); @@ -688,6 +703,13 @@ HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size) { log_trace(gc, alloc)("%s: Unsuccessfully scheduled collection allocating %zu", Thread::current()->name(), word_size); + // Has the gc overhead limit been reached in the meantime? If so, this mutator + // should receive null even when unsuccessfully scheduling a collection as well + // for global consistency. + if (gc_overhead_limit_exceeded()) { + return nullptr; + } + // We can reach here if we were unsuccessful in scheduling a collection (because // another thread beat us to it). // Humongous object allocation always needs a lock, so we wait for the retry @@ -890,25 +912,62 @@ void G1CollectedHeap::resize_heap_if_necessary(size_t allocation_word_size) { } } +void G1CollectedHeap::update_gc_overhead_counter() { + assert(SafepointSynchronize::is_at_safepoint(), "precondition"); + + if (!UseGCOverheadLimit) { + return; + } + + bool gc_time_over_limit = (_policy->analytics()->long_term_pause_time_ratio() * 100) >= GCTimeLimit; + double free_space_percent = percent_of(num_available_regions() * G1HeapRegion::GrainBytes, max_capacity()); + bool free_space_below_limit = free_space_percent < GCHeapFreeLimit; + + log_debug(gc)("GC Overhead Limit: GC Time %f Free Space %f Counter %zu", + (_policy->analytics()->long_term_pause_time_ratio() * 100), + free_space_percent, + _gc_overhead_counter); + + if (gc_time_over_limit && free_space_below_limit) { + _gc_overhead_counter++; + } else { + _gc_overhead_counter = 0; + } +} + +bool G1CollectedHeap::gc_overhead_limit_exceeded() { + return _gc_overhead_counter >= GCOverheadLimitThreshold; +} + HeapWord* G1CollectedHeap::satisfy_failed_allocation_helper(size_t word_size, bool do_gc, bool maximal_compaction, bool expect_null_mutator_alloc_region) { - // Let's attempt the allocation first. - HeapWord* result = - attempt_allocation_at_safepoint(word_size, - expect_null_mutator_alloc_region); - if (result != nullptr) { - return result; - } + // Skip allocation if GC overhead limit has been exceeded to let the mutator run + // into an OOME. It can either exit "gracefully" or try to free up memory asap. + // For the latter situation, keep running GCs. If the mutator frees up enough + // memory quickly enough, the overhead(s) will go below the threshold(s) again + // and the VM may continue running. + // If we did not continue garbage collections, the (gc overhead) limit may decrease + // enough by itself to not count as exceeding the limit any more, in the worst + // case bouncing back-and-forth all the time. + if (!gc_overhead_limit_exceeded()) { + // Let's attempt the allocation first. + HeapWord* result = + attempt_allocation_at_safepoint(word_size, + expect_null_mutator_alloc_region); + if (result != nullptr) { + return result; + } - // In a G1 heap, we're supposed to keep allocation from failing by - // incremental pauses. Therefore, at least for now, we'll favor - // expansion over collection. (This might change in the future if we can - // do something smarter than full collection to satisfy a failed alloc.) - result = expand_and_allocate(word_size); - if (result != nullptr) { - return result; + // In a G1 heap, we're supposed to keep allocation from failing by + // incremental pauses. Therefore, at least for now, we'll favor + // expansion over collection. (This might change in the future if we can + // do something smarter than full collection to satisfy a failed alloc.) + result = expand_and_allocate(word_size); + if (result != nullptr) { + return result; + } } if (do_gc) { @@ -932,6 +991,10 @@ HeapWord* G1CollectedHeap::satisfy_failed_allocation_helper(size_t word_size, HeapWord* G1CollectedHeap::satisfy_failed_allocation(size_t word_size) { assert_at_safepoint_on_vm_thread(); + // Update GC overhead limits after the initial garbage collection leading to this + // allocation attempt. + update_gc_overhead_counter(); + // Attempts to allocate followed by Full GC. HeapWord* result = satisfy_failed_allocation_helper(word_size, @@ -966,6 +1029,10 @@ HeapWord* G1CollectedHeap::satisfy_failed_allocation(size_t word_size) { assert(!soft_ref_policy()->should_clear_all_soft_refs(), "Flag should have been handled and cleared prior to this point"); + if (gc_overhead_limit_exceeded()) { + log_info(gc)("GC Overhead Limit exceeded too often (%zu).", GCOverheadLimitThreshold); + } + // What else? We might try synchronous finalization later. If the total // space available is large enough for the allocation, then a more // complete compaction phase than we've tried so far might be @@ -1131,6 +1198,7 @@ class HumongousRegionSetChecker : public G1HeapRegionSetChecker { G1CollectedHeap::G1CollectedHeap() : CollectedHeap(), + _gc_overhead_counter(0), _service_thread(nullptr), _periodic_gc_task(nullptr), _free_arena_memory_task(nullptr), @@ -1690,6 +1758,66 @@ static bool gc_counter_less_than(uint x, uint y) { #define LOG_COLLECT_CONCURRENTLY_COMPLETE(cause, result) \ LOG_COLLECT_CONCURRENTLY(cause, "complete %s", BOOL_TO_STR(result)) +bool G1CollectedHeap::wait_full_mark_finished(GCCause::Cause cause, + uint old_marking_started_before, + uint old_marking_started_after, + uint old_marking_completed_after) { + // Request is finished if a full collection (concurrent or stw) + // was started after this request and has completed, e.g. + // started_before < completed_after. + if (gc_counter_less_than(old_marking_started_before, + old_marking_completed_after)) { + LOG_COLLECT_CONCURRENTLY_COMPLETE(cause, true); + return true; + } + + if (old_marking_started_after != old_marking_completed_after) { + // If there is an in-progress cycle (possibly started by us), then + // wait for that cycle to complete, e.g. + // while completed_now < started_after. + LOG_COLLECT_CONCURRENTLY(cause, "wait"); + MonitorLocker ml(G1OldGCCount_lock); + while (gc_counter_less_than(_old_marking_cycles_completed, + old_marking_started_after)) { + ml.wait(); + } + // Request is finished if the collection we just waited for was + // started after this request. + if (old_marking_started_before != old_marking_started_after) { + LOG_COLLECT_CONCURRENTLY(cause, "complete after wait"); + return true; + } + } + return false; +} + +// After calling wait_full_mark_finished(), this method determines whether we +// previously failed for ordinary reasons (concurrent cycle in progress, whitebox +// has control). Returns if this has been such an ordinary reason. +static bool should_retry_vm_op(GCCause::Cause cause, + VM_G1TryInitiateConcMark* op) { + if (op->cycle_already_in_progress()) { + // If VMOp failed because a cycle was already in progress, it + // is now complete. But it didn't finish this user-requested + // GC, so try again. + LOG_COLLECT_CONCURRENTLY(cause, "retry after in-progress"); + return true; + } else if (op->whitebox_attached()) { + // If WhiteBox wants control, wait for notification of a state + // change in the controller, then try again. Don't wait for + // release of control, since collections may complete while in + // control. Note: This won't recognize a STW full collection + // while waiting; we can't wait on multiple monitors. + LOG_COLLECT_CONCURRENTLY(cause, "whitebox control stall"); + MonitorLocker ml(ConcurrentGCBreakpoints::monitor()); + if (ConcurrentGCBreakpoints::is_controlled()) { + ml.wait(); + } + return true; + } + return false; +} + bool G1CollectedHeap::try_collect_concurrently(GCCause::Cause cause, uint gc_counter, uint old_marking_started_before) { @@ -1750,7 +1878,45 @@ bool G1CollectedHeap::try_collect_concurrently(GCCause::Cause cause, LOG_COLLECT_CONCURRENTLY(cause, "ignoring STW full GC"); old_marking_started_before = old_marking_started_after; } + } else if (GCCause::is_codecache_requested_gc(cause)) { + // For a CodeCache requested GC, before marking, progress is ensured as the + // following Remark pause unloads code (and signals the requester such). + // Otherwise we must ensure that it is restarted. + // + // For a CodeCache requested GC, a successful GC operation means that + // (1) marking is in progress. I.e. the VMOp started the marking or a + // Remark pause is pending from a different VM op; we will potentially + // abort a mixed phase if needed. + // (2) a new cycle was started (by this thread or some other), or + // (3) a Full GC was performed. + // + // Cases (2) and (3) are detected together by a change to + // _old_marking_cycles_started. + // + // Compared to other "automatic" GCs (see below), we do not consider being + // in whitebox as sufficient too because we might be anywhere within that + // cycle and we need to make progress. + if (op.mark_in_progress() || + (old_marking_started_before != old_marking_started_after)) { + LOG_COLLECT_CONCURRENTLY_COMPLETE(cause, true); + return true; + } + + if (wait_full_mark_finished(cause, + old_marking_started_before, + old_marking_started_after, + old_marking_completed_after)) { + return true; + } + + if (should_retry_vm_op(cause, &op)) { + continue; + } } else if (!GCCause::is_user_requested_gc(cause)) { + assert(cause == GCCause::_g1_humongous_allocation || + cause == GCCause::_g1_periodic_collection, + "Unsupported cause %s", GCCause::to_string(cause)); + // For an "automatic" (not user-requested) collection, we just need to // ensure that progress is made. // @@ -1762,11 +1928,6 @@ bool G1CollectedHeap::try_collect_concurrently(GCCause::Cause cause, // (5) a Full GC was performed. // Cases (4) and (5) are detected together by a change to // _old_marking_cycles_started. - // - // Note that (1) does not imply (4). If we're still in the mixed - // phase of an earlier concurrent collection, the request to make the - // collection a concurrent start won't be honored. If we don't check for - // both conditions we'll spin doing back-to-back collections. if (op.gc_succeeded() || op.cycle_already_in_progress() || op.whitebox_attached() || @@ -1790,56 +1951,20 @@ bool G1CollectedHeap::try_collect_concurrently(GCCause::Cause cause, BOOL_TO_STR(op.gc_succeeded()), old_marking_started_before, old_marking_started_after); - // Request is finished if a full collection (concurrent or stw) - // was started after this request and has completed, e.g. - // started_before < completed_after. - if (gc_counter_less_than(old_marking_started_before, - old_marking_completed_after)) { - LOG_COLLECT_CONCURRENTLY_COMPLETE(cause, true); + if (wait_full_mark_finished(cause, + old_marking_started_before, + old_marking_started_after, + old_marking_completed_after)) { return true; } - if (old_marking_started_after != old_marking_completed_after) { - // If there is an in-progress cycle (possibly started by us), then - // wait for that cycle to complete, e.g. - // while completed_now < started_after. - LOG_COLLECT_CONCURRENTLY(cause, "wait"); - MonitorLocker ml(G1OldGCCount_lock); - while (gc_counter_less_than(_old_marking_cycles_completed, - old_marking_started_after)) { - ml.wait(); - } - // Request is finished if the collection we just waited for was - // started after this request. - if (old_marking_started_before != old_marking_started_after) { - LOG_COLLECT_CONCURRENTLY(cause, "complete after wait"); - return true; - } - } - // If VMOp was successful then it started a new cycle that the above // wait &etc should have recognized as finishing this request. This // differs from a non-user-request, where gc_succeeded does not imply // a new cycle was started. assert(!op.gc_succeeded(), "invariant"); - if (op.cycle_already_in_progress()) { - // If VMOp failed because a cycle was already in progress, it - // is now complete. But it didn't finish this user-requested - // GC, so try again. - LOG_COLLECT_CONCURRENTLY(cause, "retry after in-progress"); - continue; - } else if (op.whitebox_attached()) { - // If WhiteBox wants control, wait for notification of a state - // change in the controller, then try again. Don't wait for - // release of control, since collections may complete while in - // control. Note: This won't recognize a STW full collection - // while waiting; we can't wait on multiple monitors. - LOG_COLLECT_CONCURRENTLY(cause, "whitebox control stall"); - MonitorLocker ml(ConcurrentGCBreakpoints::monitor()); - if (ConcurrentGCBreakpoints::is_controlled()) { - ml.wait(); - } + if (should_retry_vm_op(cause, &op)) { continue; } } diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index fbd1fe6165f..c74d77aefce 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -169,6 +169,17 @@ class G1CollectedHeap : public CollectedHeap { friend class G1CheckRegionAttrTableClosure; private: + // GC Overhead Limit functionality related members. + // + // The goal is to return null for allocations prematurely (before really going + // OOME) in case both GC CPU usage (>= GCTimeLimit) and not much available free + // memory (<= GCHeapFreeLimit) so that applications can exit gracefully or try + // to keep running by easing off memory. + uintx _gc_overhead_counter; // The number of consecutive garbage collections we were over the limits. + + void update_gc_overhead_counter(); + bool gc_overhead_limit_exceeded(); + G1ServiceThread* _service_thread; G1ServiceTask* _periodic_gc_task; G1MonotonicArenaFreeMemoryTask* _free_arena_memory_task; @@ -274,6 +285,14 @@ class G1CollectedHeap : public CollectedHeap { // (e) cause == _g1_periodic_collection and +G1PeriodicGCInvokesConcurrent. bool should_do_concurrent_full_gc(GCCause::Cause cause); + // Wait until a full mark (either currently in progress or one that completed + // after the current request) has finished. Returns whether that full mark started + // after this request. If so, we typically do not need another one. + bool wait_full_mark_finished(GCCause::Cause cause, + uint old_marking_started_before, + uint old_marking_started_after, + uint old_marking_completed_after); + // Attempt to start a concurrent cycle with the indicated cause. // precondition: should_do_concurrent_full_gc(cause) bool try_collect_concurrently(GCCause::Cause cause, @@ -417,18 +436,14 @@ class G1CollectedHeap : public CollectedHeap { // // * If either call cannot satisfy the allocation request using the // current allocating region, they will try to get a new one. If - // this fails, they will attempt to do an evacuation pause and - // retry the allocation. - // - // * If all allocation attempts fail, even after trying to schedule - // an evacuation pause, allocate_new_tlab() will return null, - // whereas mem_allocate() will attempt a heap expansion and/or - // schedule a Full GC. + // this fails, (only) mem_allocate() will attempt to do an evacuation + // pause and retry the allocation. Allocate_new_tlab() will return null, + // deferring to the following mem_allocate(). // // * We do not allow humongous-sized TLABs. So, allocate_new_tlab // should never be called with word_size being humongous. All // humongous allocation requests should go to mem_allocate() which - // will satisfy them with a special path. + // will satisfy them in a special path. HeapWord* allocate_new_tlab(size_t min_size, size_t requested_size, @@ -442,12 +457,13 @@ class G1CollectedHeap : public CollectedHeap { // should only be used for non-humongous allocations. inline HeapWord* attempt_allocation(size_t min_word_size, size_t desired_word_size, - size_t* actual_word_size); - + size_t* actual_word_size, + bool allow_gc); // Second-level mutator allocation attempt: take the Heap_lock and // retry the allocation attempt, potentially scheduling a GC - // pause. This should only be used for non-humongous allocations. - HeapWord* attempt_allocation_slow(uint node_index, size_t word_size); + // pause if allow_gc is set. This should only be used for non-humongous + // allocations. + HeapWord* attempt_allocation_slow(uint node_index, size_t word_size, bool allow_gc); // Takes the Heap_lock and attempts a humongous allocation. It can // potentially schedule a GC pause. diff --git a/src/hotspot/share/gc/g1/g1CollectorState.hpp b/src/hotspot/share/gc/g1/g1CollectorState.hpp index f9f1839c7be..54b85543449 100644 --- a/src/hotspot/share/gc/g1/g1CollectorState.hpp +++ b/src/hotspot/share/gc/g1/g1CollectorState.hpp @@ -60,6 +60,9 @@ class G1CollectorState { // do the concurrent start phase work. volatile bool _initiate_conc_mark_if_possible; + // Marking is in progress. Set from start of the concurrent start pause to the + // end of the Remark pause. + bool _mark_in_progress; // Marking or rebuilding remembered set work is in progress. Set from the end // of the concurrent start pause to the end of the Cleanup pause. bool _mark_or_rebuild_in_progress; @@ -78,6 +81,7 @@ class G1CollectorState { _in_concurrent_start_gc(false), _initiate_conc_mark_if_possible(false), + _mark_in_progress(false), _mark_or_rebuild_in_progress(false), _clearing_bitmap(false), _in_full_gc(false) { } @@ -92,6 +96,7 @@ class G1CollectorState { void set_initiate_conc_mark_if_possible(bool v) { _initiate_conc_mark_if_possible = v; } + void set_mark_in_progress(bool v) { _mark_in_progress = v; } void set_mark_or_rebuild_in_progress(bool v) { _mark_or_rebuild_in_progress = v; } void set_clearing_bitmap(bool v) { _clearing_bitmap = v; } @@ -106,6 +111,7 @@ class G1CollectorState { bool initiate_conc_mark_if_possible() const { return _initiate_conc_mark_if_possible; } + bool mark_in_progress() const { return _mark_in_progress; } bool mark_or_rebuild_in_progress() const { return _mark_or_rebuild_in_progress; } bool clearing_bitmap() const { return _clearing_bitmap; } diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp index f7b0cb23b65..18e0e40c54a 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp @@ -570,8 +570,8 @@ void G1GCPhaseTimes::print(bool evacuation_failed) { accounted_ms += print_evacuate_optional_collection_set(); accounted_ms += print_post_evacuate_collection_set(evacuation_failed); - assert(_gc_pause_time_ms >= accounted_ms, "GC pause time(%.3lfms) cannot be " - "smaller than the sum of each phase(%.3lfms).", _gc_pause_time_ms, accounted_ms); + assert(_gc_pause_time_ms >= accounted_ms, "GC pause time(%.15lf ms) cannot be " + "smaller than the sum of each phase(%.15lf ms).", _gc_pause_time_ms, accounted_ms); print_other(accounted_ms); diff --git a/src/hotspot/share/gc/g1/g1Policy.cpp b/src/hotspot/share/gc/g1/g1Policy.cpp index 92b56953067..36cd8a7fcda 100644 --- a/src/hotspot/share/gc/g1/g1Policy.cpp +++ b/src/hotspot/share/gc/g1/g1Policy.cpp @@ -593,6 +593,7 @@ void G1Policy::record_full_collection_end() { collector_state()->set_in_young_gc_before_mixed(false); collector_state()->set_initiate_conc_mark_if_possible(need_to_start_conc_mark("end of Full GC")); collector_state()->set_in_concurrent_start_gc(false); + collector_state()->set_mark_in_progress(false); collector_state()->set_mark_or_rebuild_in_progress(false); collector_state()->set_clearing_bitmap(false); @@ -704,6 +705,7 @@ void G1Policy::record_concurrent_mark_remark_end() { double elapsed_time_ms = (end_time_sec - _mark_remark_start_sec)*1000.0; _analytics->report_concurrent_mark_remark_times_ms(elapsed_time_ms); record_pause(G1GCPauseType::Remark, _mark_remark_start_sec, end_time_sec); + collector_state()->set_mark_in_progress(false); } void G1Policy::record_concurrent_mark_cleanup_start() { @@ -941,6 +943,7 @@ void G1Policy::record_young_collection_end(bool concurrent_operation_is_full_mar assert(!(G1GCPauseTypeHelper::is_concurrent_start_pause(this_pause) && collector_state()->mark_or_rebuild_in_progress()), "If the last pause has been concurrent start, we should not have been in the marking window"); if (G1GCPauseTypeHelper::is_concurrent_start_pause(this_pause)) { + collector_state()->set_mark_in_progress(concurrent_operation_is_full_mark); collector_state()->set_mark_or_rebuild_in_progress(concurrent_operation_is_full_mark); } @@ -1227,6 +1230,17 @@ void G1Policy::initiate_conc_mark() { collector_state()->set_initiate_conc_mark_if_possible(false); } +static const char* requester_for_mixed_abort(GCCause::Cause cause) { + if (cause == GCCause::_wb_breakpoint) { + return "run_to breakpoint"; + } else if (GCCause::is_codecache_requested_gc(cause)) { + return "codecache"; + } else { + assert(G1CollectedHeap::heap()->is_user_requested_concurrent_full_gc(cause), "must be"); + return "user"; + } +} + void G1Policy::decide_on_concurrent_start_pause() { // We are about to decide on whether this pause will be a // concurrent start pause. @@ -1259,8 +1273,7 @@ void G1Policy::decide_on_concurrent_start_pause() { initiate_conc_mark(); log_debug(gc, ergo)("Initiate concurrent cycle (concurrent cycle initiation requested)"); } else if (_g1h->is_user_requested_concurrent_full_gc(cause) || - (cause == GCCause::_codecache_GC_threshold) || - (cause == GCCause::_codecache_GC_aggressive) || + GCCause::is_codecache_requested_gc(cause) || (cause == GCCause::_wb_breakpoint)) { // Initiate a concurrent start. A concurrent start must be a young only // GC, so the collector state must be updated to reflect this. @@ -1275,7 +1288,7 @@ void G1Policy::decide_on_concurrent_start_pause() { abort_time_to_mixed_tracking(); initiate_conc_mark(); log_debug(gc, ergo)("Initiate concurrent cycle (%s requested concurrent cycle)", - (cause == GCCause::_wb_breakpoint) ? "run_to breakpoint" : "user"); + requester_for_mixed_abort(cause)); } else { // The concurrent marking thread is still finishing up the // previous cycle. If we start one right now the two cycles diff --git a/src/hotspot/share/gc/g1/g1VMOperations.cpp b/src/hotspot/share/gc/g1/g1VMOperations.cpp index 69cdd8d5ca6..f57ce756443 100644 --- a/src/hotspot/share/gc/g1/g1VMOperations.cpp +++ b/src/hotspot/share/gc/g1/g1VMOperations.cpp @@ -59,6 +59,7 @@ VM_G1TryInitiateConcMark::VM_G1TryInitiateConcMark(uint gc_count_before, GCCause::Cause gc_cause) : VM_GC_Operation(gc_count_before, gc_cause), _transient_failure(false), + _mark_in_progress(false), _cycle_already_in_progress(false), _whitebox_attached(false), _terminating(false), @@ -83,6 +84,9 @@ void VM_G1TryInitiateConcMark::doit() { // Record for handling by caller. _terminating = g1h->concurrent_mark_is_terminating(); + _mark_in_progress = g1h->collector_state()->mark_in_progress(); + _cycle_already_in_progress = g1h->concurrent_mark()->cm_thread()->in_progress(); + if (_terminating && GCCause::is_user_requested_gc(_gc_cause)) { // When terminating, the request to initiate a concurrent cycle will be // ignored by do_collection_pause_at_safepoint; instead it will just do @@ -91,9 +95,8 @@ void VM_G1TryInitiateConcMark::doit() { // requests the alternative GC might still be needed. } else if (!g1h->policy()->force_concurrent_start_if_outside_cycle(_gc_cause)) { // Failure to force the next GC pause to be a concurrent start indicates - // there is already a concurrent marking cycle in progress. Set flag - // to notify the caller and return immediately. - _cycle_already_in_progress = true; + // there is already a concurrent marking cycle in progress. Flags to indicate + // that were already set, so return immediately. } else if ((_gc_cause != GCCause::_wb_breakpoint) && ConcurrentGCBreakpoints::is_controlled()) { // WhiteBox wants to be in control of concurrent cycles, so don't try to diff --git a/src/hotspot/share/gc/g1/g1VMOperations.hpp b/src/hotspot/share/gc/g1/g1VMOperations.hpp index a201d57db76..8bac6263265 100644 --- a/src/hotspot/share/gc/g1/g1VMOperations.hpp +++ b/src/hotspot/share/gc/g1/g1VMOperations.hpp @@ -45,6 +45,7 @@ class VM_G1CollectFull : public VM_GC_Operation { class VM_G1TryInitiateConcMark : public VM_GC_Operation { bool _transient_failure; + bool _mark_in_progress; bool _cycle_already_in_progress; bool _whitebox_attached; bool _terminating; @@ -59,6 +60,7 @@ class VM_G1TryInitiateConcMark : public VM_GC_Operation { virtual bool doit_prologue(); virtual void doit(); bool transient_failure() const { return _transient_failure; } + bool mark_in_progress() const { return _mark_in_progress; } bool cycle_already_in_progress() const { return _cycle_already_in_progress; } bool whitebox_attached() const { return _whitebox_attached; } bool terminating() const { return _terminating; } diff --git a/src/hotspot/share/gc/shared/collectedHeap.cpp b/src/hotspot/share/gc/shared/collectedHeap.cpp index 2d23dce9488..5e83c8b76d8 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.cpp +++ b/src/hotspot/share/gc/shared/collectedHeap.cpp @@ -67,7 +67,7 @@ Klass* CollectedHeap::_filler_object_klass = nullptr; size_t CollectedHeap::_filler_array_max_size = 0; size_t CollectedHeap::_stack_chunk_max_size = 0; -class GCLogMessage : public FormatBuffer<512> {}; +class GCLogMessage : public FormatBuffer<1024> {}; template <> void EventLogBase::print(outputStream* st, GCLogMessage& m) { diff --git a/src/hotspot/share/gc/shared/gcCause.hpp b/src/hotspot/share/gc/shared/gcCause.hpp index ef96bf21567..9a918243db4 100644 --- a/src/hotspot/share/gc/shared/gcCause.hpp +++ b/src/hotspot/share/gc/shared/gcCause.hpp @@ -106,6 +106,11 @@ class GCCause : public AllStatic { cause == GCCause::_heap_dump); } + inline static bool is_codecache_requested_gc(GCCause::Cause cause) { + return (cause == _codecache_GC_threshold || + cause == _codecache_GC_aggressive); + } + // Causes for collection of the tenured gernation inline static bool is_tenured_allocation_failure_gc(GCCause::Cause cause) { // _allocation_failure is the generic cause a collection which could result diff --git a/src/hotspot/share/gc/shared/gc_globals.hpp b/src/hotspot/share/gc/shared/gc_globals.hpp index f693ab910ba..4b3cbf04b40 100644 --- a/src/hotspot/share/gc/shared/gc_globals.hpp +++ b/src/hotspot/share/gc/shared/gc_globals.hpp @@ -414,7 +414,7 @@ "Initial ratio of young generation/survivor space size") \ range(3, max_uintx) \ \ - product(bool, UseGCOverheadLimit, true, \ + product(bool, UseGCOverheadLimit, falseInDebug, \ "Use policy to limit of proportion of time spent in GC " \ "before an OutOfMemory error is thrown") \ \ diff --git a/src/hotspot/share/gc/shared/stringdedup/stringDedupStat.cpp b/src/hotspot/share/gc/shared/stringdedup/stringDedupStat.cpp index 28e5e9adf20..9da11518c3e 100644 --- a/src/hotspot/share/gc/shared/stringdedup/stringDedupStat.cpp +++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupStat.cpp @@ -100,13 +100,17 @@ void StringDedup::Stat::log_summary(const Stat* last_stat, const Stat* total_sta log_info(stringdedup)( "Concurrent String Deduplication " - "%zu/" STRDEDUP_BYTES_FORMAT_NS " (new), " + "%zu (inspected), " + "%zu/" STRDEDUP_BYTES_FORMAT_NS " (new unknown), " "%zu/" STRDEDUP_BYTES_FORMAT_NS " (deduped), " - "avg " STRDEDUP_PERCENT_FORMAT_NS ", " + "total avg deduped/new unknown bytes " STRDEDUP_PERCENT_FORMAT_NS ", " + STRDEDUP_BYTES_FORMAT_NS " (total deduped)," STRDEDUP_BYTES_FORMAT_NS " (total new unknown), " STRDEDUP_ELAPSED_FORMAT_MS " of " STRDEDUP_ELAPSED_FORMAT_MS, + last_stat->_inspected, last_stat->_new, STRDEDUP_BYTES_PARAM(last_stat->_new_bytes), last_stat->_deduped, STRDEDUP_BYTES_PARAM(last_stat->_deduped_bytes), total_deduped_bytes_percent, + STRDEDUP_BYTES_PARAM(total_stat->_deduped_bytes), STRDEDUP_BYTES_PARAM(total_stat->_new_bytes), strdedup_elapsed_param_ms(last_stat->_process_elapsed), strdedup_elapsed_param_ms(last_stat->_active_elapsed)); } @@ -217,14 +221,14 @@ void StringDedup::Stat::log_statistics(bool total) const { double replaced_percent = percent_of(_replaced, _new); double deleted_percent = percent_of(_deleted, _new); log_times(total ? "Total" : "Last"); - log_debug(stringdedup)(" Inspected: %12zu", _inspected); - log_debug(stringdedup)(" Known: %12zu(%5.1f%%)", _known, known_percent); - log_debug(stringdedup)(" Shared: %12zu(%5.1f%%)", _known_shared, known_shared_percent); - log_debug(stringdedup)(" New: %12zu(%5.1f%%)" STRDEDUP_BYTES_FORMAT, + log_debug(stringdedup)(" Inspected: %12zu", _inspected); + log_debug(stringdedup)(" Known: %12zu(%5.1f%%)", _known, known_percent); + log_debug(stringdedup)(" Shared: %12zu(%5.1f%%)", _known_shared, known_shared_percent); + log_debug(stringdedup)(" New unknown: %12zu(%5.1f%%)" STRDEDUP_BYTES_FORMAT, _new, new_percent, STRDEDUP_BYTES_PARAM(_new_bytes)); - log_debug(stringdedup)(" Replaced: %12zu(%5.1f%%)", _replaced, replaced_percent); - log_debug(stringdedup)(" Deleted: %12zu(%5.1f%%)", _deleted, deleted_percent); - log_debug(stringdedup)(" Deduplicated: %12zu(%5.1f%%)" STRDEDUP_BYTES_FORMAT "(%5.1f%%)", + log_debug(stringdedup)(" Replaced: %12zu(%5.1f%%)", _replaced, replaced_percent); + log_debug(stringdedup)(" Deleted: %12zu(%5.1f%%)", _deleted, deleted_percent); + log_debug(stringdedup)(" Deduplicated: %12zu(%5.1f%%)" STRDEDUP_BYTES_FORMAT "(%5.1f%%)", _deduped, deduped_percent, STRDEDUP_BYTES_PARAM(_deduped_bytes), deduped_bytes_percent); log_debug(stringdedup)(" Skipped: %zu (dead), %zu (incomplete), %zu (shared)", _skipped_dead, _skipped_incomplete, _skipped_shared); diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp index 807d4197b12..8210718126b 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, 2021, Red Hat, Inc. All rights reserved. - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp index eb87a9dc4c1..3ec42478282 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp @@ -91,7 +91,7 @@ void ShenandoahAdaptiveHeuristics::choose_collection_set_from_regiondata(Shenand // we hit max_cset. When max_cset is hit, we terminate the cset selection. Note that in this scheme, // ShenandoahGarbageThreshold is the soft threshold which would be ignored until min_garbage is hit. - size_t capacity = _space_info->soft_max_capacity(); + size_t capacity = ShenandoahHeap::heap()->soft_max_capacity(); size_t max_cset = (size_t)((1.0 * capacity / 100 * ShenandoahEvacReserve) / ShenandoahEvacWaste); size_t free_target = (capacity / 100 * ShenandoahMinFreeThreshold) + max_cset; size_t min_garbage = (free_target > actual_free ? (free_target - actual_free) : 0); @@ -233,7 +233,7 @@ static double saturate(double value, double min, double max) { // in operation mode. We want some way to decide that the average rate has changed, while keeping average // allocation rate computation independent. bool ShenandoahAdaptiveHeuristics::should_start_gc() { - size_t capacity = _space_info->soft_max_capacity(); + size_t capacity = ShenandoahHeap::heap()->soft_max_capacity(); size_t available = _space_info->soft_available(); size_t allocated = _space_info->bytes_allocated_since_gc_start(); diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp index 403405b984d..592bba67757 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp @@ -47,7 +47,7 @@ ShenandoahCompactHeuristics::ShenandoahCompactHeuristics(ShenandoahSpaceInfo* sp bool ShenandoahCompactHeuristics::should_start_gc() { size_t max_capacity = _space_info->max_capacity(); - size_t capacity = _space_info->soft_max_capacity(); + size_t capacity = ShenandoahHeap::heap()->soft_max_capacity(); size_t available = _space_info->available(); // Make sure the code below treats available without the soft tail. diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp index 08fd4599346..dfae9040242 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp @@ -28,7 +28,7 @@ #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahEvacInfo.hpp" #include "gc/shenandoah/shenandoahGeneration.hpp" -#include "gc/shenandoah/shenandoahGenerationalHeap.hpp" +#include "gc/shenandoah/shenandoahGenerationalHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" #include "gc/shenandoah/shenandoahTrace.hpp" @@ -65,8 +65,6 @@ void ShenandoahGenerationalHeuristics::choose_collection_set(ShenandoahCollectio size_t free = 0; size_t free_regions = 0; - const uint tenuring_threshold = heap->age_census()->tenuring_threshold(); - // This counts number of humongous regions that we intend to promote in this cycle. size_t humongous_regions_promoted = 0; // This counts number of regular regions that will be promoted in place. @@ -98,12 +96,12 @@ void ShenandoahGenerationalHeuristics::choose_collection_set(ShenandoahCollectio bool is_candidate; // This is our candidate for later consideration. if (collection_set->is_preselected(i)) { - assert(region->age() >= tenuring_threshold, "Preselection filter"); + assert(heap->is_tenurable(region), "Preselection filter"); is_candidate = true; preselected_candidates++; // Set garbage value to maximum value to force this into the sorted collection set. garbage = region_size_bytes; - } else if (region->is_young() && (region->age() >= tenuring_threshold)) { + } else if (region->is_young() && heap->is_tenurable(region)) { // Note that for GLOBAL GC, region may be OLD, and OLD regions do not qualify for pre-selection // This region is old enough to be promoted but it was not preselected, either because its garbage is below @@ -142,7 +140,7 @@ void ShenandoahGenerationalHeuristics::choose_collection_set(ShenandoahCollectio immediate_regions++; immediate_garbage += garbage; } else { - if (region->is_young() && region->age() >= tenuring_threshold) { + if (region->is_young() && heap->is_tenurable(region)) { oop obj = cast_to_oop(region->bottom()); size_t humongous_regions = ShenandoahHeapRegion::required_regions(obj->size() * HeapWordSize); humongous_regions_promoted += humongous_regions; @@ -246,10 +244,6 @@ void ShenandoahGenerationalHeuristics::choose_collection_set(ShenandoahCollectio size_t ShenandoahGenerationalHeuristics::add_preselected_regions_to_collection_set(ShenandoahCollectionSet* cset, const RegionData* data, size_t size) const { -#ifdef ASSERT - const uint tenuring_threshold = ShenandoahGenerationalHeap::heap()->age_census()->tenuring_threshold(); -#endif - // cur_young_garbage represents the amount of memory to be reclaimed from young-gen. In the case that live objects // are known to be promoted out of young-gen, we count this as cur_young_garbage because this memory is reclaimed // from young-gen and becomes available to serve future young-gen allocation requests. @@ -257,7 +251,7 @@ size_t ShenandoahGenerationalHeuristics::add_preselected_regions_to_collection_s for (size_t idx = 0; idx < size; idx++) { ShenandoahHeapRegion* r = data[idx].get_region(); if (cset->is_preselected(r->index())) { - assert(r->age() >= tenuring_threshold, "Preselected regions must have tenure age"); + assert(ShenandoahGenerationalHeap::heap()->is_tenurable(r), "Preselected regions must have tenure age"); // Entire region will be promoted, This region does not impact young-gen or old-gen evacuation reserve. // This region has been pre-selected and its impact on promotion reserve is already accounted for. diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp index b8d85de0487..b4f46955730 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp @@ -25,7 +25,7 @@ #include "gc/shenandoah/heuristics/shenandoahGlobalHeuristics.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" -#include "gc/shenandoah/shenandoahGenerationalHeap.hpp" +#include "gc/shenandoah/shenandoahGenerationalHeap.inline.hpp" #include "gc/shenandoah/shenandoahGlobalGeneration.hpp" #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" #include "utilities/quickSort.hpp" @@ -56,7 +56,6 @@ void ShenandoahGlobalHeuristics::choose_global_collection_set(ShenandoahCollecti size_t capacity = heap->young_generation()->max_capacity(); size_t garbage_threshold = region_size_bytes * ShenandoahGarbageThreshold / 100; size_t ignore_threshold = region_size_bytes * ShenandoahIgnoreGarbageThreshold / 100; - const uint tenuring_threshold = heap->age_census()->tenuring_threshold(); size_t young_evac_reserve = heap->young_generation()->get_evacuation_reserve(); size_t old_evac_reserve = heap->old_generation()->get_evacuation_reserve(); @@ -100,7 +99,7 @@ void ShenandoahGlobalHeuristics::choose_global_collection_set(ShenandoahCollecti ShenandoahHeapRegion* r = data[idx].get_region(); assert(!cset->is_preselected(r->index()), "There should be no preselected regions during GLOBAL GC"); bool add_region = false; - if (r->is_old() || (r->age() >= tenuring_threshold)) { + if (r->is_old() || heap->is_tenurable(r)) { size_t new_cset = old_cur_cset + r->get_live_data_bytes(); if ((r->garbage() > garbage_threshold)) { while ((new_cset > max_old_cset) && (unaffiliated_young_regions > 0)) { @@ -114,7 +113,7 @@ void ShenandoahGlobalHeuristics::choose_global_collection_set(ShenandoahCollecti old_cur_cset = new_cset; } } else { - assert(r->is_young() && (r->age() < tenuring_threshold), "DeMorgan's law (assuming r->is_affiliated)"); + assert(r->is_young() && !heap->is_tenurable(r), "DeMorgan's law (assuming r->is_affiliated)"); size_t new_cset = young_cur_cset + r->get_live_data_bytes(); size_t region_garbage = r->garbage(); size_t new_garbage = cur_young_garbage + region_garbage; diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp index 29b94e2f68f..2131f95b413 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp @@ -37,7 +37,6 @@ class ShenandoahSpaceInfo { public: virtual const char* name() const = 0; - virtual size_t soft_max_capacity() const = 0; virtual size_t max_capacity() const = 0; virtual size_t soft_available() const = 0; virtual size_t available() const = 0; diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp index e6f60dc1c83..205135751aa 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp @@ -42,7 +42,7 @@ ShenandoahStaticHeuristics::~ShenandoahStaticHeuristics() {} bool ShenandoahStaticHeuristics::should_start_gc() { size_t max_capacity = _space_info->max_capacity(); - size_t capacity = _space_info->soft_max_capacity(); + size_t capacity = ShenandoahHeap::heap()->soft_max_capacity(); size_t available = _space_info->available(); // Make sure the code below treats available without the soft tail. diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp index 3aca436104b..d236be8c9e6 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp @@ -26,7 +26,7 @@ #include "gc/shenandoah/heuristics/shenandoahOldHeuristics.hpp" #include "gc/shenandoah/heuristics/shenandoahYoungHeuristics.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" -#include "gc/shenandoah/shenandoahGenerationalHeap.hpp" +#include "gc/shenandoah/shenandoahGenerationalHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" #include "gc/shenandoah/shenandoahYoungGeneration.hpp" @@ -64,19 +64,18 @@ void ShenandoahYoungHeuristics::choose_young_collection_set(ShenandoahCollection size_t size, size_t actual_free, size_t cur_young_garbage) const { - auto heap = ShenandoahGenerationalHeap::heap(); + const auto heap = ShenandoahGenerationalHeap::heap(); - size_t capacity = heap->young_generation()->max_capacity(); - size_t garbage_threshold = ShenandoahHeapRegion::region_size_bytes() * ShenandoahGarbageThreshold / 100; - size_t ignore_threshold = ShenandoahHeapRegion::region_size_bytes() * ShenandoahIgnoreGarbageThreshold / 100; - const uint tenuring_threshold = heap->age_census()->tenuring_threshold(); + const size_t capacity = heap->soft_max_capacity(); + const size_t garbage_threshold = ShenandoahHeapRegion::region_size_bytes() * ShenandoahGarbageThreshold / 100; + const size_t ignore_threshold = ShenandoahHeapRegion::region_size_bytes() * ShenandoahIgnoreGarbageThreshold / 100; // This is young-gen collection or a mixed evacuation. // If this is mixed evacuation, the old-gen candidate regions have already been added. - size_t max_cset = (size_t) (heap->young_generation()->get_evacuation_reserve() / ShenandoahEvacWaste); size_t cur_cset = 0; - size_t free_target = (capacity * ShenandoahMinFreeThreshold) / 100 + max_cset; - size_t min_garbage = (free_target > actual_free) ? (free_target - actual_free) : 0; + const size_t max_cset = (size_t) (heap->young_generation()->get_evacuation_reserve() / ShenandoahEvacWaste); + const size_t free_target = (capacity * ShenandoahMinFreeThreshold) / 100 + max_cset; + const size_t min_garbage = (free_target > actual_free) ? (free_target - actual_free) : 0; log_info(gc, ergo)( @@ -89,11 +88,15 @@ void ShenandoahYoungHeuristics::choose_young_collection_set(ShenandoahCollection if (cset->is_preselected(r->index())) { continue; } - if (r->age() < tenuring_threshold) { - size_t new_cset = cur_cset + r->get_live_data_bytes(); - size_t region_garbage = r->garbage(); - size_t new_garbage = cur_young_garbage + region_garbage; - bool add_regardless = (region_garbage > ignore_threshold) && (new_garbage < min_garbage); + + // Note that we do not add tenurable regions if they were not pre-selected. They were not preselected + // because there is insufficient room in old-gen to hold their to-be-promoted live objects or because + // they are to be promoted in place. + if (!heap->is_tenurable(r)) { + const size_t new_cset = cur_cset + r->get_live_data_bytes(); + const size_t region_garbage = r->garbage(); + const size_t new_garbage = cur_young_garbage + region_garbage; + const bool add_regardless = (region_garbage > ignore_threshold) && (new_garbage < min_garbage); assert(r->is_young(), "Only young candidates expected in the data array"); if ((new_cset <= max_cset) && (add_regardless || (region_garbage > garbage_threshold))) { cur_cset = new_cset; @@ -101,9 +104,6 @@ void ShenandoahYoungHeuristics::choose_young_collection_set(ShenandoahCollection cset->add_region(r); } } - // Note that we do not add aged regions if they were not pre-selected. The reason they were not preselected - // is because there is not sufficient room in old-gen to hold their to-be-promoted live objects or because - // they are to be promoted in place. } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp b/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp index 94c98b78f1b..bd66f55bd8f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp @@ -27,8 +27,15 @@ #include "gc/shenandoah/shenandoahAgeCensus.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" -ShenandoahAgeCensus::ShenandoahAgeCensus() { +ShenandoahAgeCensus::ShenandoahAgeCensus() + : ShenandoahAgeCensus(ShenandoahHeap::heap()->max_workers()) +{ assert(ShenandoahHeap::heap()->mode()->is_generational(), "Only in generational mode"); +} + +ShenandoahAgeCensus::ShenandoahAgeCensus(uint max_workers) + : _max_workers(max_workers) +{ if (ShenandoahGenerationalMinTenuringAge > ShenandoahGenerationalMaxTenuringAge) { vm_exit_during_initialization( err_msg("ShenandoahGenerationalMinTenuringAge=%zu" @@ -39,6 +46,9 @@ ShenandoahAgeCensus::ShenandoahAgeCensus() { _global_age_table = NEW_C_HEAP_ARRAY(AgeTable*, MAX_SNAPSHOTS, mtGC); CENSUS_NOISE(_global_noise = NEW_C_HEAP_ARRAY(ShenandoahNoiseStats, MAX_SNAPSHOTS, mtGC);) _tenuring_threshold = NEW_C_HEAP_ARRAY(uint, MAX_SNAPSHOTS, mtGC); + CENSUS_NOISE(_skipped = 0); + NOT_PRODUCT(_counted = 0); + NOT_PRODUCT(_total = 0); for (int i = 0; i < MAX_SNAPSHOTS; i++) { // Note that we don't now get perfdata from age_table @@ -48,10 +58,9 @@ ShenandoahAgeCensus::ShenandoahAgeCensus() { _tenuring_threshold[i] = MAX_COHORTS; } if (ShenandoahGenerationalAdaptiveTenuring && !ShenandoahGenerationalCensusAtEvac) { - size_t max_workers = ShenandoahHeap::heap()->max_workers(); - _local_age_table = NEW_C_HEAP_ARRAY(AgeTable*, max_workers, mtGC); + _local_age_table = NEW_C_HEAP_ARRAY(AgeTable*, _max_workers, mtGC); CENSUS_NOISE(_local_noise = NEW_C_HEAP_ARRAY(ShenandoahNoiseStats, max_workers, mtGC);) - for (uint i = 0; i < max_workers; i++) { + for (uint i = 0; i < _max_workers; i++) { _local_age_table[i] = new AgeTable(false); CENSUS_NOISE(_local_noise[i].clear();) } @@ -61,6 +70,22 @@ ShenandoahAgeCensus::ShenandoahAgeCensus() { _epoch = MAX_SNAPSHOTS - 1; // see update_epoch() } +ShenandoahAgeCensus::~ShenandoahAgeCensus() { + for (uint i = 0; i < MAX_SNAPSHOTS; i++) { + delete _global_age_table[i]; + } + FREE_C_HEAP_ARRAY(AgeTable*, _global_age_table); + FREE_C_HEAP_ARRAY(uint, _tenuring_threshold); + CENSUS_NOISE(FREE_C_HEAP_ARRAY(ShenandoahNoiseStats, _global_noise)); + if (_local_age_table) { + for (uint i = 0; i < _max_workers; i++) { + delete _local_age_table[i]; + } + FREE_C_HEAP_ARRAY(AgeTable*, _local_age_table); + CENSUS_NOISE(FREE_C_HEAP_ARRAY(ShenandoahNoiseStats, _local_noise)); + } +} + CENSUS_NOISE(void ShenandoahAgeCensus::add(uint obj_age, uint region_age, uint region_youth, size_t size, uint worker_id) {) NO_CENSUS_NOISE(void ShenandoahAgeCensus::add(uint obj_age, uint region_age, size_t size, uint worker_id) {) if (obj_age <= markWord::max_age) { @@ -131,12 +156,11 @@ void ShenandoahAgeCensus::update_census(size_t age0_pop, AgeTable* pv1, AgeTable assert(pv1 == nullptr && pv2 == nullptr, "Error, check caller"); // Seed cohort 0 with population that may have been missed during // regular census. - _global_age_table[_epoch]->add((uint)0, age0_pop); + _global_age_table[_epoch]->add(0u, age0_pop); - size_t max_workers = ShenandoahHeap::heap()->max_workers(); // Merge data from local age tables into the global age table for the epoch, // clearing the local tables. - for (uint i = 0; i < max_workers; i++) { + for (uint i = 0; i < _max_workers; i++) { // age stats _global_age_table[_epoch]->merge(_local_age_table[i]); _local_age_table[i]->clear(); // clear for next census @@ -177,8 +201,7 @@ void ShenandoahAgeCensus::reset_local() { assert(_local_age_table == nullptr, "Error"); return; } - size_t max_workers = ShenandoahHeap::heap()->max_workers(); - for (uint i = 0; i < max_workers; i++) { + for (uint i = 0; i < _max_workers; i++) { _local_age_table[i]->clear(); CENSUS_NOISE(_local_noise[i].clear();) } @@ -204,8 +227,7 @@ bool ShenandoahAgeCensus::is_clear_local() { assert(_local_age_table == nullptr, "Error"); return true; } - size_t max_workers = ShenandoahHeap::heap()->max_workers(); - for (uint i = 0; i < max_workers; i++) { + for (uint i = 0; i < _max_workers; i++) { bool clear = _local_age_table[i]->is_clear(); CENSUS_NOISE(clear |= _local_noise[i].is_clear();) if (!clear) { @@ -246,7 +268,7 @@ void ShenandoahAgeCensus::update_tenuring_threshold() { _tenuring_threshold[_epoch] = tt; } print(); - log_trace(gc, age)("New tenuring threshold %zu (min %zu, max %zu)", + log_info(gc, age)("New tenuring threshold %zu (min %zu, max %zu)", (uintx) _tenuring_threshold[_epoch], ShenandoahGenerationalMinTenuringAge, ShenandoahGenerationalMaxTenuringAge); } @@ -279,13 +301,14 @@ uint ShenandoahAgeCensus::compute_tenuring_threshold() { uint upper_bound = ShenandoahGenerationalMaxTenuringAge; const uint prev_tt = previous_tenuring_threshold(); if (ShenandoahGenerationalCensusIgnoreOlderCohorts && prev_tt > 0) { - // We stay below the computed tenuring threshold for the last cycle plus 1, - // ignoring the mortality rates of any older cohorts. - upper_bound = MIN2(upper_bound, prev_tt + 1); + // We stay below the computed tenuring threshold for the last cycle, + // ignoring the mortality rates of any older cohorts (which may see + // higher mortality rates due to promotions). + upper_bound = MIN2(upper_bound, prev_tt); } upper_bound = MIN2(upper_bound, markWord::max_age); - const uint lower_bound = MAX2((uint)ShenandoahGenerationalMinTenuringAge, (uint)1); + const uint lower_bound = MAX2((uint)ShenandoahGenerationalMinTenuringAge, 1u); uint tenuring_threshold = upper_bound; for (uint i = upper_bound; i >= lower_bound; i--) { @@ -303,9 +326,9 @@ uint ShenandoahAgeCensus::compute_tenuring_threshold() { // cohorts are considered eligible for tenuring when all older // cohorts are. We return the next higher age as the tenuring threshold // so that we do not prematurely promote objects of this age. - assert(tenuring_threshold == i+1 || tenuring_threshold == upper_bound, "Error"); + assert(tenuring_threshold == i + 1 || tenuring_threshold == upper_bound, "Error"); assert(tenuring_threshold >= lower_bound && tenuring_threshold <= upper_bound, "Error"); - return tenuring_threshold; + return i + 1; } // Remember that we passed over this cohort, looking for younger cohorts // showing high mortality. We want to tenure cohorts of this age. @@ -335,6 +358,14 @@ double ShenandoahAgeCensus::mortality_rate(size_t prev_pop, size_t cur_pop) { } void ShenandoahAgeCensus::print() { + + const LogTarget(Debug, gc, age) lt; + if (!lt.is_enabled()) { + return; + } + + LogStream ls(lt); + // Print the population vector for the current epoch, and // for the previous epoch, as well as the computed mortality // ratio for each extant cohort. @@ -350,33 +381,32 @@ void ShenandoahAgeCensus::print() { for (uint i = 1; i < MAX_COHORTS; i++) { const size_t prev_pop = prev_pv->sizes[i-1]; // (i-1) OK because i >= 1 const size_t cur_pop = cur_pv->sizes[i]; - double mr = mortality_rate(prev_pop, cur_pop); + const double mr = mortality_rate(prev_pop, cur_pop); // Suppress printing when everything is zero if (prev_pop + cur_pop > 0) { - log_info(gc, age) - (" - age %3u: prev %10zu bytes, curr %10zu bytes, mortality %.2f ", - i, prev_pop*oopSize, cur_pop*oopSize, mr); + ls.print_cr(" - age %3u: prev %10zu bytes, curr %10zu bytes, mortality %.2f ", + i, prev_pop * oopSize, cur_pop * oopSize, mr); } total += cur_pop; if (i == tt) { // Underline the cohort for tenuring threshold (if < MAX_COHORTS) - log_info(gc, age)("----------------------------------------------------------------------------"); + ls.print_cr("----------------------------------------------------------------------------"); } } - CENSUS_NOISE(_global_noise[cur_epoch].print(total);) + CENSUS_NOISE(_global_noise[cur_epoch].print(ls, total);) } #ifdef SHENANDOAH_CENSUS_NOISE -void ShenandoahNoiseStats::print(size_t total) { +void ShenandoahNoiseStats::print(LogStream& ls, const size_t total) { if (total > 0) { - float f_skipped = (float)skipped/(float)total; - float f_aged = (float)aged/(float)total; - float f_clamped = (float)clamped/(float)total; - float f_young = (float)young/(float)total; - log_info(gc, age)("Skipped: %10zu (%.2f), R-Aged: %10zu (%.2f), " - "Clamped: %10zu (%.2f), R-Young: %10zu (%.2f)", - skipped*oopSize, f_skipped, aged*oopSize, f_aged, - clamped*oopSize, f_clamped, young*oopSize, f_young); + const float f_skipped = (float)skipped/(float)total; + const float f_aged = (float)aged/(float)total; + const float f_clamped = (float)clamped/(float)total; + const float f_young = (float)young/(float)total; + ls.print_cr("Skipped: %10zu (%.2f), R-Aged: %10zu (%.2f), " + "Clamped: %10zu (%.2f), R-Young: %10zu (%.2f)", + skipped*oopSize, f_skipped, aged*oopSize, f_aged, + clamped*oopSize, f_clamped, young*oopSize, f_young); } } #endif // SHENANDOAH_CENSUS_NOISE diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.hpp b/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.hpp index 89c68f7120b..90d188e1fca 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.hpp @@ -37,6 +37,8 @@ #define CENSUS_NOISE(x) x #define NO_CENSUS_NOISE(x) +class LogStream; + struct ShenandoahNoiseStats { size_t skipped; // Volume of objects skipped size_t aged; // Volume of objects from aged regions @@ -67,7 +69,7 @@ struct ShenandoahNoiseStats { young += other.young; } - void print(size_t total); + void print(LogStream& ls, size_t total); }; #else // SHENANDOAH_CENSUS_NOISE #define CENSUS_NOISE(x) @@ -91,7 +93,7 @@ struct ShenandoahNoiseStats { // // In addition, this class also maintains per worker population vectors into which // census for the current minor GC is accumulated (during marking or, optionally, during -// evacuation). These are cleared after each marking (resectively, evacuation) cycle, +// evacuation). These are cleared after each marking (respectively, evacuation) cycle, // once the per-worker data is consolidated into the appropriate population vector // per minor collection. The _local_age_table is thus C x N, for N GC workers. class ShenandoahAgeCensus: public CHeapObj { @@ -111,10 +113,12 @@ class ShenandoahAgeCensus: public CHeapObj { size_t _total; // net size of objects encountered (counted or skipped) in census #endif - uint _epoch; // Current epoch (modulo max age) - uint *_tenuring_threshold; // An array of the last N tenuring threshold values we + uint _epoch; // Current epoch (modulo max age) + uint* _tenuring_threshold; // An array of the last N tenuring threshold values we // computed. + uint _max_workers; // Maximum number of workers for parallel tasks + // Mortality rate of a cohort, given its population in // previous and current epochs double mortality_rate(size_t prev_pop, size_t cur_pop); @@ -165,11 +169,22 @@ class ShenandoahAgeCensus: public CHeapObj { }; ShenandoahAgeCensus(); + ShenandoahAgeCensus(uint max_workers); + ~ShenandoahAgeCensus(); // Return the local age table (population vector) for worker_id. // Only used in the case of (ShenandoahGenerationalAdaptiveTenuring && !ShenandoahGenerationalCensusAtEvac) - AgeTable* get_local_age_table(uint worker_id) { - return (AgeTable*) _local_age_table[worker_id]; + AgeTable* get_local_age_table(uint worker_id) const { + return _local_age_table[worker_id]; + } + + // Return the most recently computed tenuring threshold. + // Visible for testing. Use is_tenurable for consistent tenuring comparisons. + uint tenuring_threshold() const { return _tenuring_threshold[_epoch]; } + + // Return true if this age is at or above the tenuring threshold. + bool is_tenurable(uint age) const { + return age >= tenuring_threshold(); } // Update the local age table for worker_id by size for @@ -201,9 +216,6 @@ class ShenandoahAgeCensus: public CHeapObj { // is 0, because the evacuated objects have all had their ages incremented. void update_census(size_t age0_pop, AgeTable* pv1 = nullptr, AgeTable* pv2 = nullptr); - // Return the most recently computed tenuring threshold - uint tenuring_threshold() const { return _tenuring_threshold[_epoch]; } - // Reset the epoch, clearing accumulated census history // Note: this isn't currently used, but reserved for planned // future usage. diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAllocRequest.hpp b/src/hotspot/share/gc/shenandoah/shenandoahAllocRequest.hpp index 6ac62e8e9ed..78ae78f4c24 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahAllocRequest.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahAllocRequest.hpp @@ -34,6 +34,7 @@ class ShenandoahAllocRequest : StackObj { enum Type { _alloc_shared, // Allocate common, outside of TLAB _alloc_shared_gc, // Allocate common, outside of GCLAB/PLAB + _alloc_cds, // Allocate for CDS _alloc_tlab, // Allocate TLAB _alloc_gclab, // Allocate GCLAB _alloc_plab, // Allocate PLAB @@ -46,6 +47,8 @@ class ShenandoahAllocRequest : StackObj { return "Shared"; case _alloc_shared_gc: return "Shared GC"; + case _alloc_cds: + return "CDS"; case _alloc_tlab: return "TLAB"; case _alloc_gclab: @@ -121,6 +124,10 @@ class ShenandoahAllocRequest : StackObj { return ShenandoahAllocRequest(0, requested_size, _alloc_shared, ShenandoahAffiliation::YOUNG_GENERATION); } + static inline ShenandoahAllocRequest for_cds(size_t requested_size) { + return ShenandoahAllocRequest(0, requested_size, _alloc_cds, ShenandoahAffiliation::YOUNG_GENERATION); + } + inline size_t size() const { return _requested_size; } @@ -163,6 +170,7 @@ class ShenandoahAllocRequest : StackObj { switch (_alloc_type) { case _alloc_tlab: case _alloc_shared: + case _alloc_cds: return true; case _alloc_gclab: case _alloc_plab: @@ -178,6 +186,7 @@ class ShenandoahAllocRequest : StackObj { switch (_alloc_type) { case _alloc_tlab: case _alloc_shared: + case _alloc_cds: return false; case _alloc_gclab: case _alloc_plab: @@ -197,6 +206,7 @@ class ShenandoahAllocRequest : StackObj { return true; case _alloc_shared: case _alloc_shared_gc: + case _alloc_cds: return false; default: ShouldNotReachHere(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp index ffafcc5840d..c23f30a55e9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp @@ -64,7 +64,9 @@ void ShenandoahAsserts::print_obj(ShenandoahMessageBuffer& msg, oop obj) { ShenandoahMarkingContext* const ctx = heap->marking_context(); - msg.append(" " PTR_FORMAT " - klass " PTR_FORMAT " %s\n", p2i(obj), p2i(obj->klass()), obj->klass()->external_name()); + Klass* obj_klass = ShenandoahForwarding::klass(obj); + + msg.append(" " PTR_FORMAT " - klass " PTR_FORMAT " %s\n", p2i(obj), p2i(obj_klass), obj_klass->external_name()); msg.append(" %3s allocated after mark start\n", ctx->allocated_after_mark_start(obj) ? "" : "not"); msg.append(" %3s after update watermark\n", cast_from_oop(obj) >= r->get_update_watermark() ? "" : "not"); msg.append(" %3s marked strong\n", ctx->is_marked_strong(obj) ? "" : "not"); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp index 25b900f8d77..35faa40af77 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp @@ -27,6 +27,7 @@ #include "gc/shenandoah/shenandoahAgeCensus.hpp" #include "gc/shenandoah/shenandoahCollectionSet.hpp" +#include "gc/shenandoah/shenandoahGenerationalHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegionSet.hpp" @@ -98,7 +99,7 @@ void ShenandoahCollectionSet::add_region(ShenandoahHeapRegion* r) { if (r->is_young()) { _young_bytes_to_evacuate += live; _young_available_bytes_collected += free; - if (ShenandoahHeap::heap()->mode()->is_generational() && r->age() >= ShenandoahGenerationalHeap::heap()->age_census()->tenuring_threshold()) { + if (ShenandoahHeap::heap()->mode()->is_generational() && ShenandoahGenerationalHeap::heap()->is_tenurable(r)) { _young_bytes_to_promote += live; } } else if (r->is_old()) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.cpp index 0169795d6f6..d79e7dcefb9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.cpp @@ -37,6 +37,7 @@ ShenandoahCollectorPolicy::ShenandoahCollectorPolicy() : _abbreviated_degenerated_gcs(0), _success_full_gcs(0), _consecutive_degenerated_gcs(0), + _consecutive_degenerated_gcs_without_progress(0), _consecutive_young_gcs(0), _mixed_gcs(0), _success_old_gcs(0), @@ -67,14 +68,14 @@ void ShenandoahCollectorPolicy::record_alloc_failure_to_degenerated(ShenandoahGC } void ShenandoahCollectorPolicy::record_degenerated_upgrade_to_full() { - _consecutive_degenerated_gcs = 0; + reset_consecutive_degenerated_gcs(); _alloc_failure_degenerated_upgrade_to_full++; } void ShenandoahCollectorPolicy::record_success_concurrent(bool is_young, bool is_abbreviated) { update_young(is_young); - _consecutive_degenerated_gcs = 0; + reset_consecutive_degenerated_gcs(); _success_concurrent_gcs++; if (is_abbreviated) { _abbreviated_concurrent_gcs++; @@ -95,11 +96,18 @@ void ShenandoahCollectorPolicy::record_interrupted_old() { _interrupted_old_gcs++; } -void ShenandoahCollectorPolicy::record_success_degenerated(bool is_young, bool is_abbreviated) { +void ShenandoahCollectorPolicy::record_degenerated(bool is_young, bool is_abbreviated, bool progress) { update_young(is_young); _success_degenerated_gcs++; _consecutive_degenerated_gcs++; + + if (progress) { + _consecutive_degenerated_gcs_without_progress = 0; + } else { + _consecutive_degenerated_gcs_without_progress++; + } + if (is_abbreviated) { _abbreviated_degenerated_gcs++; } @@ -114,7 +122,7 @@ void ShenandoahCollectorPolicy::update_young(bool is_young) { } void ShenandoahCollectorPolicy::record_success_full() { - _consecutive_degenerated_gcs = 0; + reset_consecutive_degenerated_gcs(); _consecutive_young_gcs = 0; _success_full_gcs++; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.hpp b/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.hpp index 68579508de5..5fe90f64f98 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.hpp @@ -42,6 +42,7 @@ class ShenandoahCollectorPolicy : public CHeapObj { // Written by control thread, read by mutators volatile size_t _success_full_gcs; uint _consecutive_degenerated_gcs; + uint _consecutive_degenerated_gcs_without_progress; volatile size_t _consecutive_young_gcs; size_t _mixed_gcs; size_t _success_old_gcs; @@ -55,8 +56,25 @@ class ShenandoahCollectorPolicy : public CHeapObj { ShenandoahSharedFlag _in_shutdown; ShenandoahTracer* _tracer; + void reset_consecutive_degenerated_gcs() { + _consecutive_degenerated_gcs = 0; + _consecutive_degenerated_gcs_without_progress = 0; + } public: + // The most common scenario for lack of good progress following a degenerated GC is an accumulation of floating + // garbage during the most recently aborted concurrent GC effort. With generational GC, it is far more effective to + // reclaim this floating garbage with another degenerated cycle (which focuses on young generation and might require + // a pause of 200 ms) rather than a full GC cycle (which may require over 2 seconds with a 10 GB old generation). + // + // In generational mode, we'll only upgrade to full GC if we've done two degen cycles in a row and both indicated + // bad progress. In non-generational mode, we'll preserve the original behavior, which is to upgrade to full + // immediately following a degenerated cycle with bad progress. This preserves original behavior of non-generational + // Shenandoah to avoid introducing "surprising new behavior." It also makes less sense with non-generational + // Shenandoah to replace a full GC with a degenerated GC, because both have similar pause times in non-generational + // mode. + static constexpr size_t GENERATIONAL_CONSECUTIVE_BAD_DEGEN_PROGRESS_THRESHOLD = 2; + ShenandoahCollectorPolicy(); void record_mixed_cycle(); @@ -69,7 +87,12 @@ class ShenandoahCollectorPolicy : public CHeapObj { // cycles are very efficient and are worth tracking. Note that both degenerated and // concurrent cycles can be abbreviated. void record_success_concurrent(bool is_young, bool is_abbreviated); - void record_success_degenerated(bool is_young, bool is_abbreviated); + + // Record that a degenerated cycle has been completed. Note that such a cycle may or + // may not make "progress". We separately track the total number of degenerated cycles, + // the number of consecutive degenerated cycles and the number of consecutive cycles that + // fail to make good progress. + void record_degenerated(bool is_young, bool is_abbreviated, bool progress); void record_success_full(); void record_alloc_failure_to_degenerated(ShenandoahGC::ShenandoahDegenPoint point); void record_alloc_failure_to_full(); @@ -94,6 +117,11 @@ class ShenandoahCollectorPolicy : public CHeapObj { return _consecutive_degenerated_gcs; } + // Genshen will only upgrade to a full gc after the configured number of futile degenerated cycles. + bool generational_should_upgrade_degenerated_gc() const { + return _consecutive_degenerated_gcs_without_progress >= GENERATIONAL_CONSECUTIVE_BAD_DEGEN_PROGRESS_THRESHOLD; + } + static bool is_allocation_failure(GCCause::Cause cause); static bool is_shenandoah_gc(GCCause::Cause cause); static bool is_requested_gc(GCCause::Cause cause); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp index fda97c4836e..64093a7c4bf 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp @@ -831,7 +831,6 @@ bool ShenandoahConcurrentGC::has_in_place_promotions(ShenandoahHeap* heap) { return heap->mode()->is_generational() && heap->old_generation()->has_in_place_promotions(); } -template class ShenandoahConcurrentEvacThreadClosure : public ThreadClosure { private: OopClosure* const _oops; @@ -841,13 +840,9 @@ class ShenandoahConcurrentEvacThreadClosure : public ThreadClosure { void do_thread(Thread* thread) override { JavaThread* const jt = JavaThread::cast(thread); StackWatermarkSet::finish_processing(jt, _oops, StackWatermarkKind::gc); - if (GENERATIONAL) { - ShenandoahThreadLocalData::enable_plab_promotions(thread); - } } }; -template class ShenandoahConcurrentEvacUpdateThreadTask : public WorkerTask { private: ShenandoahJavaThreadsIterator _java_threads; @@ -859,30 +854,20 @@ class ShenandoahConcurrentEvacUpdateThreadTask : public WorkerTask { } void work(uint worker_id) override { - if (GENERATIONAL) { - Thread* worker_thread = Thread::current(); - ShenandoahThreadLocalData::enable_plab_promotions(worker_thread); - } - // ShenandoahEvacOOMScope has to be setup by ShenandoahContextEvacuateUpdateRootsClosure. // Otherwise, may deadlock with watermark lock ShenandoahContextEvacuateUpdateRootsClosure oops_cl; - ShenandoahConcurrentEvacThreadClosure thr_cl(&oops_cl); + ShenandoahConcurrentEvacThreadClosure thr_cl(&oops_cl); _java_threads.threads_do(&thr_cl, worker_id); } }; void ShenandoahConcurrentGC::op_thread_roots() { - ShenandoahHeap* const heap = ShenandoahHeap::heap(); + const ShenandoahHeap* const heap = ShenandoahHeap::heap(); assert(heap->is_evacuation_in_progress(), "Checked by caller"); ShenandoahGCWorkerPhase worker_phase(ShenandoahPhaseTimings::conc_thread_roots); - if (heap->mode()->is_generational()) { - ShenandoahConcurrentEvacUpdateThreadTask task(heap->workers()->active_workers()); - heap->workers()->run_task(&task); - } else { - ShenandoahConcurrentEvacUpdateThreadTask task(heap->workers()->active_workers()); - heap->workers()->run_task(&task); - } + ShenandoahConcurrentEvacUpdateThreadTask task(heap->workers()->active_workers()); + heap->workers()->run_task(&task); } void ShenandoahConcurrentGC::op_weak_refs() { @@ -1213,6 +1198,7 @@ void ShenandoahConcurrentGC::op_final_update_refs() { // We are not concerned about skipping this step in abbreviated cycles because regions // with no live objects cannot have been written to and so cannot have entries in the SATB // buffers. + ShenandoahGCPhase phase(ShenandoahPhaseTimings::final_update_refs_transfer_satb); heap->old_generation()->transfer_pointers_from_satb(); // Aging_cycle is only relevant during evacuation cycle for individual objects and during final mark for diff --git a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp index d8eb8e0a4e1..9cab6807bd0 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2013, 2021, Red Hat, Inc. All rights reserved. - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp index c941379d576..8a0eba5cd9f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp @@ -49,8 +49,7 @@ ShenandoahDegenGC::ShenandoahDegenGC(ShenandoahDegenPoint degen_point, Shenandoa ShenandoahGC(), _degen_point(degen_point), _generation(generation), - _abbreviated(false), - _consecutive_degen_with_bad_progress(0) { + _abbreviated(false) { } bool ShenandoahDegenGC::collect(GCCause::Cause cause) { @@ -247,7 +246,6 @@ void ShenandoahDegenGC::op_degenerated() { ShenandoahHeapRegion* r; while ((r = heap->collection_set()->next()) != nullptr) { if (r->is_pinned()) { - heap->cancel_gc(GCCause::_shenandoah_upgrade_to_full_gc); op_degenerated_fail(); return; } @@ -312,30 +310,14 @@ void ShenandoahDegenGC::op_degenerated() { metrics.snap_after(); - // The most common scenario for lack of good progress following a degenerated GC is an accumulation of floating - // garbage during the most recently aborted concurrent GC effort. With generational GC, it is far more effective to - // reclaim this floating garbage with another degenerated cycle (which focuses on young generation and might require - // a pause of 200 ms) rather than a full GC cycle (which may require over 2 seconds with a 10 GB old generation). - // - // In generational mode, we'll only upgrade to full GC if we've done two degen cycles in a row and both indicated - // bad progress. In non-generational mode, we'll preserve the original behavior, which is to upgrade to full - // immediately following a degenerated cycle with bad progress. This preserves original behavior of non-generational - // Shenandoah so as to avoid introducing "surprising new behavior." It also makes less sense with non-generational - // Shenandoah to replace a full GC with a degenerated GC, because both have similar pause times in non-generational - // mode. - if (!metrics.is_good_progress(_generation)) { - _consecutive_degen_with_bad_progress++; - } else { - _consecutive_degen_with_bad_progress = 0; - } - if (!heap->mode()->is_generational() || - ((heap->shenandoah_policy()->consecutive_degenerated_gc_count() > 1) && (_consecutive_degen_with_bad_progress >= 2))) { - heap->cancel_gc(GCCause::_shenandoah_upgrade_to_full_gc); - op_degenerated_futile(); - } else { + // Decide if this cycle made good progress, and, if not, should it upgrade to a full GC. + const bool progress = metrics.is_good_progress(_generation); + ShenandoahCollectorPolicy* policy = heap->shenandoah_policy(); + policy->record_degenerated(_generation->is_young(), _abbreviated, progress); + if (progress) { heap->notify_gc_progress(); - heap->shenandoah_policy()->record_success_degenerated(_generation->is_young(), _abbreviated); - _generation->heuristics()->record_success_degenerated(); + } else if (!heap->mode()->is_generational() || policy->generational_should_upgrade_degenerated_gc()) { + op_degenerated_futile(); } } @@ -482,7 +464,9 @@ const char* ShenandoahDegenGC::degen_event_message(ShenandoahDegenPoint point) c void ShenandoahDegenGC::upgrade_to_full() { log_info(gc)("Degenerated GC upgrading to Full GC"); - ShenandoahHeap::heap()->shenandoah_policy()->record_degenerated_upgrade_to_full(); + ShenandoahHeap* heap = ShenandoahHeap::heap(); + heap->cancel_gc(GCCause::_shenandoah_upgrade_to_full_gc); + heap->shenandoah_policy()->record_degenerated_upgrade_to_full(); ShenandoahFullGC full_gc; full_gc.op_full(GCCause::_shenandoah_upgrade_to_full_gc); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.hpp b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.hpp index a2598fe4e8e..971bd67eb0d 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.hpp @@ -36,7 +36,6 @@ class ShenandoahDegenGC : public ShenandoahGC { const ShenandoahDegenPoint _degen_point; ShenandoahGeneration* _generation; bool _abbreviated; - size_t _consecutive_degen_with_bad_progress; public: ShenandoahDegenGC(ShenandoahDegenPoint degen_point, ShenandoahGeneration* generation); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp index 1acb6a23e7a..87c4943b238 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp @@ -816,6 +816,7 @@ HeapWord* ShenandoahFreeSet::allocate_single(ShenandoahAllocRequest& req, bool& switch (req.type()) { case ShenandoahAllocRequest::_alloc_tlab: case ShenandoahAllocRequest::_alloc_shared: + case ShenandoahAllocRequest::_alloc_cds: return allocate_for_mutator(req, in_new_region); case ShenandoahAllocRequest::_alloc_gclab: case ShenandoahAllocRequest::_alloc_plab: @@ -880,7 +881,7 @@ HeapWord* ShenandoahFreeSet::allocate_from_regions(Iter& iterator, ShenandoahAll for (idx_t idx = iterator.current(); iterator.has_next(); idx = iterator.next()) { ShenandoahHeapRegion* r = _heap->get_region(idx); size_t min_size = (req.type() == ShenandoahAllocRequest::_alloc_tlab) ? req.min_size() : req.size(); - if (alloc_capacity(r) >= min_size) { + if (alloc_capacity(r) >= min_size * HeapWordSize) { HeapWord* result = try_allocate_in(r, req, in_new_region); if (result != nullptr) { return result; @@ -1169,8 +1170,8 @@ HeapWord* ShenandoahFreeSet::try_allocate_in(ShenandoahHeapRegion* r, Shenandoah return result; } -HeapWord* ShenandoahFreeSet::allocate_contiguous(ShenandoahAllocRequest& req) { - assert(req.is_mutator_alloc(), "All humongous allocations are performed by mutator"); +HeapWord* ShenandoahFreeSet::allocate_contiguous(ShenandoahAllocRequest& req, bool is_humongous) { + assert(req.is_mutator_alloc(), "All contiguous allocations are performed by mutator"); shenandoah_assert_heaplocked(); size_t words_size = req.size(); @@ -1244,10 +1245,16 @@ HeapWord* ShenandoahFreeSet::allocate_contiguous(ShenandoahAllocRequest& req) { assert(i == beg || _heap->get_region(i - 1)->index() + 1 == r->index(), "Should be contiguous"); assert(r->is_empty(), "Should be empty"); - if (i == beg) { - r->make_humongous_start(); + r->set_affiliation(req.affiliation()); + + if (is_humongous) { + if (i == beg) { + r->make_humongous_start(); + } else { + r->make_humongous_cont(); + } } else { - r->make_humongous_cont(); + r->make_regular_allocation(req.affiliation()); } // Trailing region may be non-full, record the remainder there @@ -1257,8 +1264,6 @@ HeapWord* ShenandoahFreeSet::allocate_contiguous(ShenandoahAllocRequest& req) { } else { used_words = ShenandoahHeapRegion::region_size_words(); } - - r->set_affiliation(req.affiliation()); r->set_update_watermark(r->bottom()); r->set_top(r->bottom() + used_words); } @@ -1268,14 +1273,26 @@ HeapWord* ShenandoahFreeSet::allocate_contiguous(ShenandoahAllocRequest& req) { _heap->notify_mutator_alloc_words(ShenandoahHeapRegion::region_size_words() - remainder, true); } - // retire_range_from_partition() will adjust bounds on Mutator free set if appropriate - _partitions.retire_range_from_partition(ShenandoahFreeSetPartitionId::Mutator, beg, end); - - size_t total_humongous_size = ShenandoahHeapRegion::region_size_bytes() * num; - _partitions.increase_used(ShenandoahFreeSetPartitionId::Mutator, total_humongous_size); + size_t total_used = 0; + if (is_humongous) { + // Humongous allocation retires all regions at once: no allocation is possible anymore. + _partitions.retire_range_from_partition(ShenandoahFreeSetPartitionId::Mutator, beg, end); + total_used = ShenandoahHeapRegion::region_size_bytes() * num; + } else { + // Non-humongous allocation retires only the regions that cannot be used for allocation anymore. + for (idx_t i = beg; i <= end; i++) { + ShenandoahHeapRegion* r = _heap->get_region(i); + if (r->free() < PLAB::min_size() * HeapWordSize) { + _partitions.retire_from_partition(ShenandoahFreeSetPartitionId::Mutator, i, r->used()); + } + total_used += r->used(); + } + } + _partitions.increase_used(ShenandoahFreeSetPartitionId::Mutator, total_used); _partitions.assert_bounds(); + req.set_actual_size(words_size); - if (remainder != 0) { + if (remainder != 0 && is_humongous) { req.set_waste(ShenandoahHeapRegion::region_size_words() - remainder); } return _heap->get_region(beg)->bottom(); @@ -2064,7 +2081,10 @@ HeapWord* ShenandoahFreeSet::allocate(ShenandoahAllocRequest& req, bool& in_new_ case ShenandoahAllocRequest::_alloc_shared: case ShenandoahAllocRequest::_alloc_shared_gc: in_new_region = true; - return allocate_contiguous(req); + return allocate_contiguous(req, /* is_humongous = */ true); + case ShenandoahAllocRequest::_alloc_cds: + in_new_region = true; + return allocate_contiguous(req, /* is_humongous = */ false); case ShenandoahAllocRequest::_alloc_plab: case ShenandoahAllocRequest::_alloc_gclab: case ShenandoahAllocRequest::_alloc_tlab: diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp index 55f23480618..8ad7055b3d6 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp @@ -345,7 +345,7 @@ class ShenandoahFreeSet : public CHeapObj { // object. No other objects are packed into these regions. // // Precondition: ShenandoahHeapRegion::requires_humongous(req.size()) - HeapWord* allocate_contiguous(ShenandoahAllocRequest& req); + HeapWord* allocate_contiguous(ShenandoahAllocRequest& req, bool is_humongous); // Change region r from the Mutator partition to the GC's Collector or OldCollector partition. This requires that the // region is entirely empty. diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp index 9a511de939c..7b3839dc198 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp @@ -28,9 +28,8 @@ #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahGeneration.hpp" -#include "gc/shenandoah/shenandoahGenerationalHeap.hpp" +#include "gc/shenandoah/shenandoahGenerationalHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegionClosures.hpp" -#include "gc/shenandoah/shenandoahMonitoringSupport.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" #include "gc/shenandoah/shenandoahReferenceProcessor.hpp" #include "gc/shenandoah/shenandoahScanRemembered.inline.hpp" @@ -183,7 +182,7 @@ void ShenandoahGeneration::log_status(const char *msg) const { // byte size in proper unit and proper unit for byte size are consistent. const size_t v_used = used(); const size_t v_used_regions = used_regions_size(); - const size_t v_soft_max_capacity = soft_max_capacity(); + const size_t v_soft_max_capacity = ShenandoahHeap::heap()->soft_max_capacity(); const size_t v_max_capacity = max_capacity(); const size_t v_available = available(); const size_t v_humongous_waste = get_humongous_waste(); @@ -534,7 +533,6 @@ size_t ShenandoahGeneration::select_aged_regions(size_t old_available) { bool* const candidate_regions_for_promotion_by_copy = heap->collection_set()->preselected_regions(); ShenandoahMarkingContext* const ctx = heap->marking_context(); - const uint tenuring_threshold = heap->age_census()->tenuring_threshold(); const size_t old_garbage_threshold = (ShenandoahHeapRegion::region_size_bytes() * ShenandoahOldGarbageThreshold) / 100; size_t old_consumed = 0; @@ -558,7 +556,7 @@ size_t ShenandoahGeneration::select_aged_regions(size_t old_available) { // skip over regions that aren't regular young with some live data continue; } - if (r->age() >= tenuring_threshold) { + if (heap->is_tenurable(r)) { if ((r->garbage() < old_garbage_threshold)) { // This tenure-worthy region has too little garbage, so we do not want to expend the copying effort to // reclaim the garbage; instead this region may be eligible for promotion-in-place to the @@ -613,7 +611,7 @@ size_t ShenandoahGeneration::select_aged_regions(size_t old_available) { // these regions. The likely outcome is that these regions will not be selected for evacuation or promotion // in the current cycle and we will anticipate that they will be promoted in the next cycle. This will cause // us to reserve more old-gen memory so that these objects can be promoted in the subsequent cycle. - if (heap->is_aging_cycle() && (r->age() + 1 == tenuring_threshold)) { + if (heap->is_aging_cycle() && heap->age_census()->is_tenurable(r->age() + 1)) { if (r->garbage() >= old_garbage_threshold) { promo_potential += r->get_live_data_bytes(); } @@ -799,14 +797,13 @@ void ShenandoahGeneration::cancel_marking() { ShenandoahGeneration::ShenandoahGeneration(ShenandoahGenerationType type, uint max_workers, - size_t max_capacity, - size_t soft_max_capacity) : + size_t max_capacity) : _type(type), _task_queues(new ShenandoahObjToScanQueueSet(max_workers)), _ref_processor(new ShenandoahReferenceProcessor(MAX2(max_workers, 1U))), _affiliated_region_count(0), _humongous_waste(0), _evacuation_reserve(0), _used(0), _bytes_allocated_since_gc_start(0), - _max_capacity(max_capacity), _soft_max_capacity(soft_max_capacity), + _max_capacity(max_capacity), _heuristics(nullptr) { _is_marking_complete.set(); @@ -952,7 +949,7 @@ size_t ShenandoahGeneration::available_with_reserve() const { } size_t ShenandoahGeneration::soft_available() const { - return available(soft_max_capacity()); + return available(ShenandoahHeap::heap()->soft_max_capacity()); } size_t ShenandoahGeneration::available(size_t capacity) const { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp index 242acbdea8c..2b7aca342da 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp @@ -71,7 +71,6 @@ class ShenandoahGeneration : public CHeapObj, public ShenandoahSpaceInfo { volatile size_t _used; volatile size_t _bytes_allocated_since_gc_start; size_t _max_capacity; - size_t _soft_max_capacity; ShenandoahHeuristics* _heuristics; @@ -105,8 +104,7 @@ class ShenandoahGeneration : public CHeapObj, public ShenandoahSpaceInfo { public: ShenandoahGeneration(ShenandoahGenerationType type, uint max_workers, - size_t max_capacity, - size_t soft_max_capacity); + size_t max_capacity); ~ShenandoahGeneration(); bool is_young() const { return _type == YOUNG; } @@ -126,7 +124,6 @@ class ShenandoahGeneration : public CHeapObj, public ShenandoahSpaceInfo { virtual ShenandoahHeuristics* initialize_heuristics(ShenandoahMode* gc_mode); - size_t soft_max_capacity() const override { return _soft_max_capacity; } size_t max_capacity() const override { return _max_capacity; } virtual size_t used_regions() const; virtual size_t used_regions_size() const; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp index 6b33d5207d0..2555f73d018 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2013, 2021, Red Hat, Inc. All rights reserved. - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp index ba9ef5979a8..b538f7b1417 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp @@ -26,7 +26,7 @@ #include "gc/shenandoah/shenandoahAsserts.hpp" #include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahGenerationalEvacuationTask.hpp" -#include "gc/shenandoah/shenandoahGenerationalHeap.hpp" +#include "gc/shenandoah/shenandoahGenerationalHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" #include "gc/shenandoah/shenandoahPacer.hpp" @@ -57,11 +57,9 @@ ShenandoahGenerationalEvacuationTask::ShenandoahGenerationalEvacuationTask(Shena _heap(heap), _regions(iterator), _concurrent(concurrent), - _only_promote_regions(only_promote_regions), - _tenuring_threshold(0) + _only_promote_regions(only_promote_regions) { shenandoah_assert_generational(); - _tenuring_threshold = _heap->age_census()->tenuring_threshold(); } void ShenandoahGenerationalEvacuationTask::work(uint worker_id) { @@ -142,7 +140,7 @@ void ShenandoahGenerationalEvacuationTask::evacuate_and_promote_regions() { void ShenandoahGenerationalEvacuationTask::maybe_promote_region(ShenandoahHeapRegion* r) { - if (r->is_young() && r->is_active() && (r->age() >= _tenuring_threshold)) { + if (r->is_young() && r->is_active() && _heap->is_tenurable(r)) { if (r->is_humongous_start()) { // We promote humongous_start regions along with their affiliated continuations during evacuation rather than // doing this work during a safepoint. We cannot put humongous regions into the collection set because that @@ -180,7 +178,7 @@ void ShenandoahGenerationalEvacuationTask::promote_in_place(ShenandoahHeapRegion assert(region->garbage_before_padded_for_promote() < old_garbage_threshold, "Region %zu has too much garbage for promotion", region->index()); assert(region->is_young(), "Only young regions can be promoted"); assert(region->is_regular(), "Use different service to promote humongous regions"); - assert(region->age() >= _tenuring_threshold, "Only promote regions that are sufficiently aged"); + assert(_heap->is_tenurable(region), "Only promote regions that are sufficiently aged"); assert(region->get_top_before_promote() == tams, "Region %zu has been used for allocations before promotion", region->index()); } @@ -263,7 +261,7 @@ void ShenandoahGenerationalEvacuationTask::promote_humongous(ShenandoahHeapRegio shenandoah_assert_generations_reconciled(); assert(region->is_young(), "Only young regions can be promoted"); assert(region->is_humongous_start(), "Should not promote humongous continuation in isolation"); - assert(region->age() >= _tenuring_threshold, "Only promote regions that are sufficiently aged"); + assert(_heap->is_tenurable(region), "Only promote regions that are sufficiently aged"); assert(marking_context->is_marked(obj), "promoted humongous object should be alive"); const size_t used_bytes = obj->size() * HeapWordSize; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.hpp index abe2fc0110c..0c402d6c90a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.hpp @@ -39,7 +39,6 @@ class ShenandoahGenerationalEvacuationTask : public WorkerTask { ShenandoahRegionIterator* _regions; bool _concurrent; bool _only_promote_regions; - uint _tenuring_threshold; public: ShenandoahGenerationalEvacuationTask(ShenandoahGenerationalHeap* sh, diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp index e2e3f0a4677..c4a7408e032 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp @@ -193,7 +193,6 @@ ShenandoahPrepareForGenerationalCompactionObjectClosure::ShenandoahPrepareForGen ShenandoahHeapRegion* from_region, uint worker_id) : _preserved_marks(preserved_marks), _heap(ShenandoahGenerationalHeap::heap()), - _tenuring_threshold(0), _empty_regions(empty_regions), _empty_regions_pos(0), _old_to_region(nullptr), @@ -212,8 +211,6 @@ ShenandoahPrepareForGenerationalCompactionObjectClosure::ShenandoahPrepareForGen _young_to_region = from_region; _young_compact_point = from_region->bottom(); } - - _tenuring_threshold = _heap->age_census()->tenuring_threshold(); } void ShenandoahPrepareForGenerationalCompactionObjectClosure::set_from_region(ShenandoahHeapRegion* from_region) { @@ -279,7 +276,7 @@ void ShenandoahPrepareForGenerationalCompactionObjectClosure::do_object(oop p) { bool promote_object = false; if ((_from_affiliation == ShenandoahAffiliation::YOUNG_GENERATION) && - (from_region_age + object_age >= _tenuring_threshold)) { + _heap->age_census()->is_tenurable(from_region_age + object_age)) { if ((_old_to_region != nullptr) && (_old_compact_point + obj_size > _old_to_region->end())) { finish_old_region(); _old_to_region = nullptr; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.hpp index 9240a056105..06080286f22 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.hpp @@ -90,7 +90,6 @@ class ShenandoahPrepareForGenerationalCompactionObjectClosure : public ObjectClo private: PreservedMarks* const _preserved_marks; ShenandoahGenerationalHeap* const _heap; - uint _tenuring_threshold; // _empty_regions is a thread-local list of heap regions that have been completely emptied by this worker thread's // compaction efforts. The worker thread that drives these efforts adds compacted regions to this list if the diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp index 731868310f4..feb82dd0527 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp @@ -53,21 +53,6 @@ class ShenandoahGenerationalInitLogger : public ShenandoahInitLogger { ShenandoahGenerationalInitLogger logger; logger.print_all(); } - - void print_heap() override { - ShenandoahInitLogger::print_heap(); - - ShenandoahGenerationalHeap* heap = ShenandoahGenerationalHeap::heap(); - - ShenandoahYoungGeneration* young = heap->young_generation(); - log_info(gc, init)("Young Generation Soft Size: " EXACTFMT, EXACTFMTARGS(young->soft_max_capacity())); - log_info(gc, init)("Young Generation Max: " EXACTFMT, EXACTFMTARGS(young->max_capacity())); - - ShenandoahOldGeneration* old = heap->old_generation(); - log_info(gc, init)("Old Generation Soft Size: " EXACTFMT, EXACTFMTARGS(old->soft_max_capacity())); - log_info(gc, init)("Old Generation Max: " EXACTFMT, EXACTFMTARGS(old->max_capacity())); - } - protected: void print_gc_specific() override { ShenandoahInitLogger::print_gc_specific(); @@ -141,8 +126,8 @@ void ShenandoahGenerationalHeap::initialize_heuristics() { size_t initial_capacity_old = max_capacity() - max_capacity_young; size_t max_capacity_old = max_capacity() - initial_capacity_young; - _young_generation = new ShenandoahYoungGeneration(max_workers(), max_capacity_young, initial_capacity_young); - _old_generation = new ShenandoahOldGeneration(max_workers(), max_capacity_old, initial_capacity_old); + _young_generation = new ShenandoahYoungGeneration(max_workers(), max_capacity_young); + _old_generation = new ShenandoahOldGeneration(max_workers(), max_capacity_old); _young_generation->initialize_heuristics(mode()); _old_generation->initialize_heuristics(mode()); } @@ -244,7 +229,7 @@ oop ShenandoahGenerationalHeap::evacuate_object(oop p, Thread* thread) { if (mark.has_displaced_mark_helper()) { // We don't want to deal with MT here just to ensure we read the right mark word. // Skip the potential promotion attempt for this one. - } else if (r->age() + mark.age() >= age_census()->tenuring_threshold()) { + } else if (age_census()->is_tenurable(r->age() + mark.age())) { oop result = try_evacuate_object(p, thread, r, OLD_GENERATION); if (result != nullptr) { return result; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp index ed5a6f3d9a5..fb356873356 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp @@ -81,6 +81,8 @@ class ShenandoahGenerationalHeap : public ShenandoahHeap { return _age_census; } + inline bool is_tenurable(const ShenandoahHeapRegion* r) const; + ShenandoahEvacuationTracker* evac_tracker() const { return _evac_tracker; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.inline.hpp new file mode 100644 index 00000000000..8289b48185b --- /dev/null +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.inline.hpp @@ -0,0 +1,37 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHGENERATIONALHEAP_INLINE_HPP +#define SHARE_GC_SHENANDOAH_SHENANDOAHGENERATIONALHEAP_INLINE_HPP + +#include "gc/shenandoah/shenandoahGenerationalHeap.hpp" + +#include "gc/shenandoah/shenandoahAgeCensus.hpp" +#include "gc/shenandoah/shenandoahHeapRegion.hpp" + +inline bool ShenandoahGenerationalHeap::is_tenurable(const ShenandoahHeapRegion* r) const { + return _age_census->is_tenurable(r->age()); +} + +#endif // SHARE_GC_SHENANDOAH_SHENANDOAHGENERATIONALHEAP_INLINE_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp index c6277e3898e..6099c41f262 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp @@ -50,10 +50,6 @@ size_t ShenandoahGlobalGeneration::used_regions_size() const { return ShenandoahHeap::heap()->capacity(); } -size_t ShenandoahGlobalGeneration::soft_max_capacity() const { - return ShenandoahHeap::heap()->soft_max_capacity(); -} - size_t ShenandoahGlobalGeneration::available() const { // The collector reserve may eat into what the mutator is allowed to use. Make sure we are looking // at what is available to the mutator when reporting how much memory is available. @@ -65,8 +61,8 @@ size_t ShenandoahGlobalGeneration::soft_available() const { size_t available = this->available(); // Make sure the code below treats available without the soft tail. - assert(max_capacity() >= soft_max_capacity(), "Max capacity must be greater than soft max capacity."); - size_t soft_tail = max_capacity() - soft_max_capacity(); + assert(max_capacity() >= ShenandoahHeap::heap()->soft_max_capacity(), "Max capacity must be greater than soft max capacity."); + size_t soft_tail = max_capacity() - ShenandoahHeap::heap()->soft_max_capacity(); return (available > soft_tail) ? (available - soft_tail) : 0; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp index 5857170d4cc..a823784a459 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp @@ -32,14 +32,13 @@ // A "generation" that represents the whole heap. class ShenandoahGlobalGeneration : public ShenandoahGeneration { public: - ShenandoahGlobalGeneration(bool generational, uint max_queues, size_t max_capacity, size_t soft_max_capacity) - : ShenandoahGeneration(generational ? GLOBAL : NON_GEN, max_queues, max_capacity, soft_max_capacity) { } + ShenandoahGlobalGeneration(bool generational, uint max_queues, size_t max_capacity) + : ShenandoahGeneration(generational ? GLOBAL : NON_GEN, max_queues, max_capacity) { } public: const char* name() const override; size_t max_capacity() const override; - size_t soft_max_capacity() const override; size_t used_regions() const override; size_t used_regions_size() const override; size_t available() const override; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index 0fc7ba39cfa..a56ada222d7 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -32,6 +32,7 @@ #include "gc/shared/gcArguments.hpp" #include "gc/shared/gcTimer.hpp" #include "gc/shared/gcTraceTime.inline.hpp" +#include "gc/shared/gc_globals.hpp" #include "gc/shared/locationPrinter.inline.hpp" #include "gc/shared/memAllocator.hpp" #include "gc/shared/plab.hpp" @@ -201,8 +202,7 @@ jint ShenandoahHeap::initialize() { assert(num_min_regions <= _num_regions, "sanity"); _minimum_size = num_min_regions * reg_size_bytes; - // Default to max heap size. - _soft_max_size = _num_regions * reg_size_bytes; + _soft_max_size = SoftMaxHeapSize; _committed = _initial_size; @@ -524,7 +524,7 @@ void ShenandoahHeap::initialize_mode() { } void ShenandoahHeap::initialize_heuristics() { - _global_generation = new ShenandoahGlobalGeneration(mode()->is_generational(), max_workers(), max_capacity(), max_capacity()); + _global_generation = new ShenandoahGlobalGeneration(mode()->is_generational(), max_workers(), max_capacity()); _global_generation->initialize_heuristics(mode()); } @@ -1238,6 +1238,11 @@ class ShenandoahRetireGCLABClosure : public ThreadClosure { // 1. We need to make the plab memory parsable by remembered-set scanning. // 2. We need to establish a trustworthy UpdateWaterMark value within each old-gen heap region ShenandoahGenerationalHeap::heap()->retire_plab(plab, thread); + + // Re-enable promotions for the next evacuation phase. + ShenandoahThreadLocalData::enable_plab_promotions(thread); + + // Reset the fill size for next evacuation phase. if (_resize && ShenandoahThreadLocalData::plab_size(thread) > 0) { ShenandoahThreadLocalData::set_plab_size(thread, 0); } @@ -2791,41 +2796,15 @@ bool ShenandoahHeap::requires_barriers(stackChunkOop obj) const { HeapWord* ShenandoahHeap::allocate_loaded_archive_space(size_t size) { #if INCLUDE_CDS_JAVA_HEAP - // CDS wants a continuous memory range to load a bunch of objects. - // This effectively bypasses normal allocation paths, and requires - // a bit of massaging to unbreak GC invariants. - - ShenandoahAllocRequest req = ShenandoahAllocRequest::for_shared(size); - - // Easy case: a single regular region, no further adjustments needed. - if (!ShenandoahHeapRegion::requires_humongous(size)) { - return allocate_memory(req); - } - - // Hard case: the requested size would cause a humongous allocation. - // We need to make sure it looks like regular allocation to the rest of GC. - - // CDS code would guarantee no objects straddle multiple regions, as long as - // regions are as large as MIN_GC_REGION_ALIGNMENT. It is impractical at this - // point to deal with case when Shenandoah runs with smaller regions. - // TODO: This check can be dropped once MIN_GC_REGION_ALIGNMENT agrees more with Shenandoah. - if (ShenandoahHeapRegion::region_size_bytes() < ArchiveHeapWriter::MIN_GC_REGION_ALIGNMENT) { - return nullptr; - } - - HeapWord* mem = allocate_memory(req); - size_t start_idx = heap_region_index_containing(mem); - size_t num_regions = ShenandoahHeapRegion::required_regions(size * HeapWordSize); - - // Flip humongous -> regular. - { - ShenandoahHeapLocker locker(lock(), false); - for (size_t c = start_idx; c < start_idx + num_regions; c++) { - get_region(c)->make_regular_bypass(); - } - } + // CDS wants a raw continuous memory range to load a bunch of objects itself. + // This is an unusual request, since all requested regions should be regular, not humongous. + // + // CDS would guarantee no objects straddle multiple regions, as long as regions are as large + // as MIN_GC_REGION_ALIGNMENT. + guarantee(ShenandoahHeapRegion::region_size_bytes() >= ArchiveHeapWriter::MIN_GC_REGION_ALIGNMENT, "Must be"); - return mem; + ShenandoahAllocRequest req = ShenandoahAllocRequest::for_cds(size); + return allocate_memory(req); #else assert(false, "Archive heap loader should not be available, should not be here"); return nullptr; @@ -2852,17 +2831,25 @@ void ShenandoahHeap::complete_loaded_archive_space(MemRegion archive_space) { "Archive space should be fully used: " PTR_FORMAT " " PTR_FORMAT, p2i(cur), p2i(end)); - // Region bounds are good. - ShenandoahHeapRegion* begin_reg = heap_region_containing(start); - ShenandoahHeapRegion* end_reg = heap_region_containing(end); - assert(begin_reg->is_regular(), "Must be"); - assert(end_reg->is_regular(), "Must be"); - assert(begin_reg->bottom() == start, - "Must agree: archive-space-start: " PTR_FORMAT ", begin-region-bottom: " PTR_FORMAT, - p2i(start), p2i(begin_reg->bottom())); - assert(end_reg->top() == end, - "Must agree: archive-space-end: " PTR_FORMAT ", end-region-top: " PTR_FORMAT, - p2i(end), p2i(end_reg->top())); + // All regions in contiguous space have good state. + size_t begin_reg_idx = heap_region_index_containing(start); + size_t end_reg_idx = heap_region_index_containing(end); + + for (size_t idx = begin_reg_idx; idx <= end_reg_idx; idx++) { + ShenandoahHeapRegion* r = get_region(idx); + assert(r->is_regular(), "Must be regular"); + assert(r->is_young(), "Must be young"); + assert(idx == end_reg_idx || r->top() == r->end(), + "All regions except the last one should be full: " PTR_FORMAT " " PTR_FORMAT, + p2i(r->top()), p2i(r->end())); + assert(idx != begin_reg_idx || r->bottom() == start, + "Archive space start should be at the bottom of first region: " PTR_FORMAT " " PTR_FORMAT, + p2i(r->bottom()), p2i(start)); + assert(idx != end_reg_idx || r->top() == end, + "Archive space end should be at the top of last region: " PTR_FORMAT " " PTR_FORMAT, + p2i(r->top()), p2i(end)); + } + #endif } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp index 9f5f384cc29..509ba1db9c2 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -293,6 +293,7 @@ class ShenandoahHeap : public CollectedHeap { public: inline HeapWord* base() const { return _heap_region.start(); } + inline HeapWord* end() const { return _heap_region.end(); } inline size_t num_regions() const { return _num_regions; } inline bool is_heap_region_special() { return _heap_region_special; } @@ -680,7 +681,7 @@ class ShenandoahHeap : public CollectedHeap { // ---------- CDS archive support - bool can_load_archived_objects() const override { return !ShenandoahCardBarrier; } + bool can_load_archived_objects() const override { return true; } HeapWord* allocate_loaded_archive_space(size_t size) override; void complete_loaded_archive_space(MemRegion archive_space) override; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp index d00a99ee728..b959494ae99 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp @@ -142,27 +142,17 @@ void ShenandoahHeapRegion::make_affiliated_maybe() { void ShenandoahHeapRegion::make_regular_bypass() { shenandoah_assert_heaplocked(); - assert (!Universe::is_fully_initialized() || - ShenandoahHeap::heap()->is_full_gc_in_progress() || + assert (ShenandoahHeap::heap()->is_full_gc_in_progress() || ShenandoahHeap::heap()->is_degenerated_gc_in_progress(), - "Only for STW GC or when Universe is initializing (CDS)"); + "Only for STW GC"); reset_age(); - auto cur_state = state(); - switch (cur_state) { + switch (state()) { case _empty_uncommitted: do_commit(); case _empty_committed: case _cset: case _humongous_start: case _humongous_cont: - if (cur_state == _humongous_start || cur_state == _humongous_cont) { - // CDS allocates chunks of the heap to fill with regular objects. The allocator - // will dutifully track any waste in the unused portion of the last region. Once - // CDS has finished initializing the objects, it will convert these regions to - // regular regions. The 'waste' in the last region is no longer wasted at this point, - // so we must stop treating it as such. - decrement_humongous_waste(); - } set_state(_regular); return; case _pinned_cset: diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.inline.hpp index 0df482c1e2d..57a5391ffe9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.inline.hpp @@ -113,6 +113,7 @@ inline void ShenandoahHeapRegion::adjust_alloc_metadata(ShenandoahAllocRequest:: switch (type) { case ShenandoahAllocRequest::_alloc_shared: case ShenandoahAllocRequest::_alloc_shared_gc: + case ShenandoahAllocRequest::_alloc_cds: // Counted implicitly by tlab/gclab allocs break; case ShenandoahAllocRequest::_alloc_tlab: diff --git a/src/hotspot/share/gc/shenandoah/shenandoahInitLogger.cpp b/src/hotspot/share/gc/shenandoah/shenandoahInitLogger.cpp index b5e5e6fd698..421c001b510 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahInitLogger.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahInitLogger.cpp @@ -43,6 +43,7 @@ void ShenandoahInitLogger::print_heap() { log_info(gc, init)("Heap Region Count: %zu", ShenandoahHeapRegion::region_count()); log_info(gc, init)("Heap Region Size: " EXACTFMT, EXACTFMTARGS(ShenandoahHeapRegion::region_size_bytes())); log_info(gc, init)("TLAB Size Max: " EXACTFMT, EXACTFMTARGS(ShenandoahHeapRegion::max_tlab_size_bytes())); + log_info(gc, init)("Soft Max Heap Size: " EXACTFMT, EXACTFMTARGS(ShenandoahHeap::heap()->soft_max_capacity())); } void ShenandoahInitLogger::print_gc_specific() { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.cpp index 34e6af41b42..5318f38d8ef 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.cpp @@ -57,6 +57,26 @@ bool ShenandoahMarkBitMap::is_bitmap_clear_range(const HeapWord* start, const He return (result == end); } +HeapWord* ShenandoahMarkBitMap::get_prev_marked_addr(const HeapWord* limit, + const HeapWord* addr) const { +#ifdef ASSERT + ShenandoahHeap* heap = ShenandoahHeap::heap(); + ShenandoahHeapRegion* r = heap->heap_region_containing(addr); + ShenandoahMarkingContext* ctx = heap->marking_context(); + HeapWord* tams = ctx->top_at_mark_start(r); + assert(limit != nullptr, "limit must not be null"); + assert(limit >= r->bottom(), "limit must be more than bottom"); + assert(addr <= tams, "addr must be less than TAMS"); +#endif + + // Round addr down to a possible object boundary to be safe. + size_t const addr_offset = address_to_index(align_down(addr, HeapWordSize << LogMinObjAlignment)); + size_t const limit_offset = address_to_index(limit); + size_t const last_offset = get_prev_one_offset(limit_offset, addr_offset); + + // cast required to remove const-ness of the value pointed to. We won't modify that object, but my caller might. + return (last_offset > addr_offset)? (HeapWord*) addr + 1: index_to_address(last_offset); +} HeapWord* ShenandoahMarkBitMap::get_next_marked_addr(const HeapWord* addr, const HeapWord* limit) const { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.hpp index 56daf4c5956..4c3177d0e81 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.hpp @@ -119,9 +119,21 @@ class ShenandoahMarkBitMap { template inline idx_t get_next_bit_impl(idx_t l_index, idx_t r_index) const; - inline idx_t get_next_one_offset (idx_t l_index, idx_t r_index) const; + // Helper for get_prev_{zero,one}_bit variants. + // - flip designates whether searching for 1s or 0s. Must be one of + // find_{zeros,ones}_flip. + // - aligned_left is true if l_index is a priori on a bm_word_t boundary. + template + inline idx_t get_prev_bit_impl(idx_t l_index, idx_t r_index) const; + + // Search for the first marked address in the range [l_index, r_index), or r_index if none found. + inline idx_t get_next_one_offset(idx_t l_index, idx_t r_index) const; - void clear_large_range (idx_t beg, idx_t end); + // Search for last one in the range [l_index, r_index). Return r_index if not found. + inline idx_t get_prev_one_offset(idx_t l_index, idx_t r_index) const; + + // Clear the strong and weak mark bits for all index positions >= l_index and < r_index. + void clear_large_range(idx_t beg, idx_t end); // Verify bit is less than size(). void verify_index(idx_t bit) const NOT_DEBUG_RETURN; @@ -162,12 +174,14 @@ class ShenandoahMarkBitMap { bool is_bitmap_clear_range(const HeapWord* start, const HeapWord* end) const; - // Return the address corresponding to the next marked bit at or after - // "addr", and before "limit", if "limit" is non-null. If there is no - // such bit, returns "limit" if that is non-null, or else "endWord()". + // Return the first marked address in the range [addr, limit), or limit if none found. HeapWord* get_next_marked_addr(const HeapWord* addr, const HeapWord* limit) const; + // Return the last marked address in the range [limit, addr], or addr+1 if none found. + HeapWord* get_prev_marked_addr(const HeapWord* limit, + const HeapWord* addr) const; + bm_word_t inverted_bit_mask_for_range(idx_t beg, idx_t end) const; void clear_range_within_word (idx_t beg, idx_t end); void clear_range (idx_t beg, idx_t end); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.inline.hpp index f0a9752b614..21b526f9995 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.inline.hpp @@ -29,6 +29,7 @@ #include "gc/shenandoah/shenandoahMarkBitMap.hpp" #include "runtime/atomic.hpp" +#include "utilities/count_leading_zeros.hpp" #include "utilities/count_trailing_zeros.hpp" inline size_t ShenandoahMarkBitMap::address_to_index(const HeapWord* addr) const { @@ -171,10 +172,99 @@ inline ShenandoahMarkBitMap::idx_t ShenandoahMarkBitMap::get_next_bit_impl(idx_t return r_index; } +template +inline ShenandoahMarkBitMap::idx_t ShenandoahMarkBitMap::get_prev_bit_impl(idx_t l_index, idx_t r_index) const { + STATIC_ASSERT(flip == find_ones_flip || flip == find_zeros_flip); + verify_range(l_index, r_index); + assert(!aligned_left || is_aligned(l_index, BitsPerWord), "l_index not aligned"); + + // The first word often contains an interesting bit, either due to + // density or because of features of the calling algorithm. So it's + // important to examine that first word with a minimum of fuss, + // minimizing setup time for later words that will be wasted if the + // first word is indeed interesting. + + // The benefit from aligned_left being true is relatively small. + // It saves an operation in the setup for the word search loop. + // It also eliminates the range check on the final result. + // However, callers often have a comparison with l_index, and + // inlining often allows the two comparisons to be combined; it is + // important when !aligned_left that return paths either return + // l_index or a value dominating a comparison with l_index. + // aligned_left is still helpful when the caller doesn't have a + // range check because features of the calling algorithm guarantee + // an interesting bit will be present. + + if (l_index < r_index) { + // Get the word containing r_index, and shift out the high-order bits (representing objects that come after r_index) + idx_t index = to_words_align_down(r_index); + assert(BitsPerWord - 2 >= bit_in_word(r_index), "sanity"); + size_t shift = BitsPerWord - 2 - bit_in_word(r_index); + bm_word_t cword = (map(index) ^ flip) << shift; + // After this shift, the highest order bits correspond to r_index. + + // We give special handling if either of the two most significant bits (Weak or Strong) is set. With 64-bit + // words, the mask of interest is 0xc000_0000_0000_0000. Symbolically, this constant is represented by: + const bm_word_t first_object_mask = ((bm_word_t) 0x3) << (BitsPerWord - 2); + if ((cword & first_object_mask) != 0) { + // The first object is similarly often interesting. When it matters + // (density or features of the calling algorithm make it likely + // the first bit is set), going straight to the next clause compares + // poorly with doing this check first; count_leading_zeros can be + // relatively expensive, plus there is the additional range check. + // But when the first bit isn't set, the cost of having tested for + // it is relatively small compared to the rest of the search. + return r_index; + } else if (cword != 0) { + // Note that there are 2 bits corresponding to every index value (Weak and Strong), and every odd index value + // corresponds to the same object as index-1 + // Flipped and shifted first word is non-zero. If leading_zeros is 0 or 1, we return r_index (above). + // if leading zeros is 2 or 3, we return (r_index - 1) or (r_index - 2), and so forth + idx_t result = r_index + 1 - count_leading_zeros(cword); + if (aligned_left || (result >= l_index)) return result; + else { + // Sentinel value means no object found within specified range. + return r_index + 2; + } + } else { + // Flipped and shifted first word is zero. Word search through + // aligned up r_index for a non-zero flipped word. + idx_t limit = aligned_left + ? to_words_align_down(l_index) // Minuscule savings when aligned. + : to_words_align_up(l_index); + // Unsigned index is always >= unsigned limit if limit equals zero, so test for strictly greater than before decrement. + while (index-- > limit) { + cword = map(index) ^ flip; + if (cword != 0) { + // cword hods bits: + // 0x03 for the object corresponding to index (and index+1) (count_leading_zeros is 62 or 63) + // 0x0c for the object corresponding to index + 2 (and index+3) (count_leading_zeros is 60 or 61) + // and so on. + idx_t result = bit_index(index + 1) - (count_leading_zeros(cword) + 1); + if (aligned_left || (result >= l_index)) return result; + else { + // Sentinel value means no object found within specified range. + return r_index + 2; + } + } + } + // No bits in range; return r_index+2. + return r_index + 2; + } + } + else { + return r_index + 2; + } +} + inline ShenandoahMarkBitMap::idx_t ShenandoahMarkBitMap::get_next_one_offset(idx_t l_offset, idx_t r_offset) const { return get_next_bit_impl(l_offset, r_offset); } +inline ShenandoahMarkBitMap::idx_t ShenandoahMarkBitMap::get_prev_one_offset(idx_t l_offset, idx_t r_offset) const { + return get_prev_bit_impl(l_offset, r_offset); +} + // Returns a bit mask for a range of bits [beg, end) within a single word. Each // bit in the mask is 0 if the bit is in the range, 1 if not in the range. The // returned mask can be used directly to clear the range, or inverted to set the diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.hpp index 8a52042e513..d8e0c74ea4e 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.hpp @@ -67,8 +67,12 @@ class ShenandoahMarkingContext : public CHeapObj { inline bool is_marked_or_old(oop obj) const; inline bool is_marked_strong_or_old(oop obj) const; + // Return address of the first marked address in the range [addr,limit), or limit if no marked object found inline HeapWord* get_next_marked_addr(const HeapWord* addr, const HeapWord* limit) const; + // Return address of the last marked object in range [limit, start], returning start+1 if no marked object found + inline HeapWord* get_prev_marked_addr(const HeapWord* limit, const HeapWord* start) const; + inline bool allocated_after_mark_start(const oop obj) const; inline bool allocated_after_mark_start(const HeapWord* addr) const; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp index e3ba774283c..fe98413a8cc 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp @@ -72,6 +72,10 @@ inline HeapWord* ShenandoahMarkingContext::get_next_marked_addr(const HeapWord* return _mark_bit_map.get_next_marked_addr(start, limit); } +inline HeapWord* ShenandoahMarkingContext::get_prev_marked_addr(const HeapWord* limit, const HeapWord* start) const { + return _mark_bit_map.get_prev_marked_addr(limit, start); +} + inline bool ShenandoahMarkingContext::allocated_after_mark_start(oop obj) const { const HeapWord* addr = cast_from_oop(obj); return allocated_after_mark_start(addr); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp index 35d963f1801..5cccd395d38 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp @@ -196,8 +196,8 @@ class ShenandoahConcurrentCoalesceAndFillTask : public WorkerTask { } }; -ShenandoahOldGeneration::ShenandoahOldGeneration(uint max_queues, size_t max_capacity, size_t soft_max_capacity) - : ShenandoahGeneration(OLD, max_queues, max_capacity, soft_max_capacity), +ShenandoahOldGeneration::ShenandoahOldGeneration(uint max_queues, size_t max_capacity) + : ShenandoahGeneration(OLD, max_queues, max_capacity), _coalesce_and_fill_region_array(NEW_C_HEAP_ARRAY(ShenandoahHeapRegion*, ShenandoahHeap::heap()->num_regions(), mtGC)), _old_heuristics(nullptr), _region_balance(0), diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp index b70a8d33b95..abc865c31cd 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp @@ -88,7 +88,7 @@ class ShenandoahOldGeneration : public ShenandoahGeneration { bool coalesce_and_fill(); public: - ShenandoahOldGeneration(uint max_queues, size_t max_capacity, size_t soft_max_capacity); + ShenandoahOldGeneration(uint max_queues, size_t max_capacity); ShenandoahHeuristics* initialize_heuristics(ShenandoahMode* gc_mode) override; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp index 0a456151318..c68f0b78dab 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp @@ -126,6 +126,7 @@ class outputStream; f(final_update_refs, "Pause Final Update Refs (N)") \ f(final_update_refs_verify, " Verify") \ f(final_update_refs_update_region_states, " Update Region States") \ + f(final_update_refs_transfer_satb, " Transfer Old From SATB") \ f(final_update_refs_trash_cset, " Trash Collection Set") \ f(final_update_refs_rebuild_freeset, " Rebuild Free Set") \ f(final_update_refs_propagate_gc_state, " Propagate GC State") \ diff --git a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp index 23c705348c4..ea94c2926e8 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp @@ -125,9 +125,8 @@ void ShenandoahDirectCardMarkRememberedSet::mark_read_table_as_clean() { // No lock required because arguments align with card boundaries. void ShenandoahCardCluster::reset_object_range(HeapWord* from, HeapWord* to) { - assert(((((unsigned long long) from) & (CardTable::card_size() - 1)) == 0) && - ((((unsigned long long) to) & (CardTable::card_size() - 1)) == 0), - "reset_object_range bounds must align with card boundaries"); + assert(CardTable::is_card_aligned(from) && CardTable::is_card_aligned(to), + "Must align with card boundaries"); size_t card_at_start = _rs->card_index_for_addr(from); size_t num_cards = (to - from) / CardTable::card_size_in_words(); @@ -222,31 +221,88 @@ size_t ShenandoahCardCluster::get_last_start(size_t card_index) const { return _object_starts[card_index].offsets.last; } -// Given a card_index, return the starting address of the first block in the heap -// that straddles into this card. If this card is co-initial with an object, then -// this would return the first address of the range that this card covers, which is -// where the card's first object also begins. -HeapWord* ShenandoahCardCluster::block_start(const size_t card_index) const { +HeapWord* ShenandoahCardCluster::first_object_start(const size_t card_index, const ShenandoahMarkingContext* const ctx, + HeapWord* tams, HeapWord* end_range_of_interest) const { HeapWord* left = _rs->addr_for_card_index(card_index); + assert(left < end_range_of_interest, "No meaningful work to do"); + ShenandoahHeapRegion* region = ShenandoahHeap::heap()->heap_region_containing(left); #ifdef ASSERT assert(ShenandoahHeap::heap()->mode()->is_generational(), "Do not use in non-generational mode"); - ShenandoahHeapRegion* region = ShenandoahHeap::heap()->heap_region_containing(left); assert(region->is_old(), "Do not use for young regions"); // For HumongousRegion:s it's more efficient to jump directly to the // start region. assert(!region->is_humongous(), "Use region->humongous_start_region() instead"); #endif + + HeapWord* right = MIN2(region->top(), end_range_of_interest); + HeapWord* end_of_search_next = MIN2(right, tams); + // Since end_range_of_interest may not align on a card boundary, last_relevant_card_index is conservative. Not all of the + // memory within the last relevant card's span is < right. + size_t last_relevant_card_index; + if (end_range_of_interest == _end_of_heap) { + last_relevant_card_index = _rs->card_index_for_addr(end_range_of_interest - 1); + } else { + last_relevant_card_index = _rs->card_index_for_addr(end_range_of_interest); + if (_rs->addr_for_card_index(last_relevant_card_index) == end_range_of_interest) { + last_relevant_card_index--; + } + } + assert(card_index <= last_relevant_card_index, "sanity: card_index: %zu, last_relevant: %zu, left: " PTR_FORMAT + ", end_of_range: " PTR_FORMAT, card_index, last_relevant_card_index, p2i(left), p2i(end_range_of_interest)); + + // if marking context is valid and we are below tams, we use the marking bit map to find the first marked object that + // intersects with this card. If no such object exists, we return the first marked object that follows the start + // of this card's memory range if such an object is found at or before last_relevant_card_index. If there are no + // marked objects in this range, we return nullptr. + if ((ctx != nullptr) && (left < tams)) { + if (ctx->is_marked(left)) { + oop obj = cast_to_oop(left); + assert(oopDesc::is_oop(obj), "Should be an object"); + return left; + } + // get the previous marked object, if any + if (region->bottom() < left) { + // In the case that this region was most recently marked as young, the fact that this region has been promoted in place + // denotes that final mark (Young) has completed. In the case that this region was most recently marked as old, the + // fact that (ctx != nullptr) denotes that old marking has completed. Otherwise, ctx would equal null. + HeapWord* prev = ctx->get_prev_marked_addr(region->bottom(), left - 1); + if (prev < left) { + oop obj = cast_to_oop(prev); + assert(oopDesc::is_oop(obj), "Should be an object"); + HeapWord* obj_end = prev + obj->size(); + if (obj_end > left) { + return prev; + } + } + } + // Either prev >= left (no previous object found), or the previous object that was found ends before my card range begins. + // In eiher case, find the next marked object if any on this or a following card + assert(!ctx->is_marked(left), "Was dealt with above"); + assert(right > left, "We don't expect to be examining cards above the smaller of TAMS or top"); + HeapWord* next = ctx->get_next_marked_addr(left, end_of_search_next); + // If end_of_search_next < right, we may return tams here, which is "marked" by default + if (next < right) { + oop obj = cast_to_oop(next); + assert(oopDesc::is_oop(obj), "Should be an object"); + return next; + } else { + return nullptr; + } + } + + assert((ctx == nullptr) || (left >= tams), "Should have returned above"); + + // The following code assumes that all data in region at or above left holds parsable objects + assert((left >= tams) || ShenandoahGenerationalHeap::heap()->old_generation()->is_parsable(), + "The code that follows expects a parsable heap"); if (starts_object(card_index) && get_first_start(card_index) == 0) { - // This card contains a co-initial object; a fortiori, it covers - // also the case of a card being the first in a region. + // This card contains a co-initial object; a fortiori, it covers also the case of a card being the first in a region. assert(oopDesc::is_oop(cast_to_oop(left)), "Should be an object"); return left; } - HeapWord* p = nullptr; - oop obj = cast_to_oop(p); ssize_t cur_index = (ssize_t)card_index; assert(cur_index >= 0, "Overflow"); assert(cur_index > 0, "Should have returned above"); @@ -256,37 +312,75 @@ HeapWord* ShenandoahCardCluster::block_start(const size_t card_index) const { } // cur_index should start an object: we should not have walked // past the left end of the region. - assert(cur_index >= 0 && (cur_index <= (ssize_t)card_index), "Error"); + assert(cur_index >= 0 && (cur_index <= (ssize_t) card_index), "Error"); assert(region->bottom() <= _rs->addr_for_card_index(cur_index), "Fell off the bottom of containing region"); assert(starts_object(cur_index), "Error"); size_t offset = get_last_start(cur_index); // can avoid call via card size arithmetic below instead - p = _rs->addr_for_card_index(cur_index) + offset; + HeapWord* p = _rs->addr_for_card_index(cur_index) + offset; + if ((ctx != nullptr) && (p < tams)) { + if (ctx->is_marked(p)) { + oop obj = cast_to_oop(p); + assert(oopDesc::is_oop(obj), "Should be an object"); + assert(Klass::is_valid(obj->klass()), "Not a valid klass ptr"); + assert(p + obj->size() > left, "This object should span start of card"); + assert(p < right, "Result must precede right"); + return p; + } else { + // Object that spans start of card is dead, so should not be scanned + assert((ctx == nullptr) || (left + get_first_start(card_index) >= tams), "Should have handled this case above"); + if (starts_object(card_index)) { + assert(left + get_first_start(card_index) < right, "Result must precede right"); + return left + get_first_start(card_index); + } else { + // Spanning object is dead and this card does not start an object, so the start object is in some card that follows + size_t following_card_index = card_index; + do { + following_card_index++; + if (following_card_index > last_relevant_card_index) { + return nullptr; + } + } while (!starts_object(following_card_index)); + HeapWord* result_candidate = _rs->addr_for_card_index(following_card_index) + get_first_start(following_card_index); + return (result_candidate >= right)? nullptr: result_candidate; + } + } + } + // Recall that we already dealt with the co-initial object case above assert(p < left, "obj should start before left"); // While it is safe to ask an object its size in the loop that // follows, the (ifdef'd out) loop should never be needed. - // 1. we ask this question only for regions in the old generation + // 1. we ask this question only for regions in the old generation, and those + // that are not humongous regions // 2. there is no direct allocation ever by mutators in old generation - // regions. Only GC will ever allocate in old regions, and then - // too only during promotion/evacuation phases. Thus there is no danger + // regions walked by this code. Only GC will ever allocate in old regions, + // and then too only during promotion/evacuation phases. Thus there is no danger // of races between reading from and writing to the object start array, // or of asking partially initialized objects their size (in the loop below). + // Furthermore, humongous regions (and their dirty cards) are never processed + // by this code. // 3. only GC asks this question during phases when it is not concurrently // evacuating/promoting, viz. during concurrent root scanning (before // the evacuation phase) and during concurrent update refs (after the // evacuation phase) of young collections. This is never called - // during old or global collections. + // during global collections during marking or update refs.. // 4. Every allocation under TAMS updates the object start array. - NOT_PRODUCT(obj = cast_to_oop(p);) +#ifdef ASSERT + oop obj = cast_to_oop(p); assert(oopDesc::is_oop(obj), "Should be an object"); -#define WALK_FORWARD_IN_BLOCK_START false - while (WALK_FORWARD_IN_BLOCK_START && p + obj->size() < left) { + while (p + obj->size() < left) { p += obj->size(); + obj = cast_to_oop(p); + assert(oopDesc::is_oop(obj), "Should be an object"); + assert(Klass::is_valid(obj->klass()), "Not a valid klass ptr"); + // Check assumptions in previous block comment if this assert fires + fatal("Should never need forward walk in block start"); } -#undef WALK_FORWARD_IN_BLOCK_START // false - assert(p + obj->size() > left, "obj should end after left"); + assert(p <= left, "p should start at or before left end of card"); + assert(p + obj->size() > left, "obj should end after left end of card"); +#endif // ASSERT return p; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.hpp b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.hpp index 5df34159c0f..08fcd74a460 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.hpp @@ -351,6 +351,7 @@ class ShenandoahCardCluster: public CHeapObj { private: ShenandoahDirectCardMarkRememberedSet* _rs; + const HeapWord* _end_of_heap; public: static const size_t CardsPerCluster = 64; @@ -404,6 +405,7 @@ class ShenandoahCardCluster: public CHeapObj { ShenandoahCardCluster(ShenandoahDirectCardMarkRememberedSet* rs) { _rs = rs; + _end_of_heap = ShenandoahHeap::heap()->end(); _object_starts = NEW_C_HEAP_ARRAY(crossing_info, rs->total_cards() + 1, mtGC); // the +1 is to account for card table guarding entry for (size_t i = 0; i < rs->total_cards(); i++) { _object_starts[i].short_word = 0; @@ -650,12 +652,31 @@ class ShenandoahCardCluster: public CHeapObj { size_t get_last_start(size_t card_index) const; - // Given a card_index, return the starting address of the first block in the heap - // that straddles into the card. If the card is co-initial with an object, then - // this would return the starting address of the heap that this card covers. - // Expects to be called for a card affiliated with the old generation in - // generational mode. - HeapWord* block_start(size_t card_index) const; + // Given a card_index, return the starting address of the first live object in the heap + // that intersects with or follows this card. This must be a valid, parsable object, and must + // be the first such object that intersects with this card. The object may start before, + // at, or after the start of the card identified by card_index, and may end in or after the card. + // + // The tams argument represents top for the enclosing region at the start of the most recently + // initiated concurrent old marking effort. If ctx is non-null, we use the marking context to identify + // marked objects below tams. Above tams, we know that every object is marked and that the memory is + // parsable (so we can add an object's size to its address to find the next object). If ctx is null, + // we use crossing maps to find where object's start, and use object sizes to walk individual objects. + // The region must be parsable if ctx is null. + // + // The end_range_of_interest pointer argument represents an upper bound on how far we look in the forward direction + // for the first object in the heap that intersects or follows this card. If there are no live objects found at + // an address less than end_range_of_interest returns nullptr. + // + // Expects to be called for a card in a region affiliated with the old generation of the + // generational heap, otherwise behavior is undefined. + // + // If not null, ctx holds the complete marking context of the old generation. If null, + // we expect that the marking context isn't available and the crossing maps are valid. + // Note that crossing maps may be invalid following class unloading and before dead + // or unloaded objects have been coalesced and filled. Coalesce and fill updates the crossing maps. + HeapWord* first_object_start(size_t card_index, const ShenandoahMarkingContext* const ctx, + HeapWord* tams, HeapWord* end_range_of_interest) const; }; // ShenandoahScanRemembered is a concrete class representing the diff --git a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp index 68bec5c2071..82022420a2a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp @@ -50,7 +50,7 @@ // degenerated execution, leading to dangling references. template void ShenandoahScanRemembered::process_clusters(size_t first_cluster, size_t count, HeapWord* end_of_range, - ClosureType* cl, bool use_write_table, uint worker_id) { + ClosureType* cl, bool use_write_table, uint worker_id) { assert(ShenandoahHeap::heap()->old_generation()->is_parsable(), "Old generation regions must be parsable for remembered set scan"); // If old-gen evacuation is active, then MarkingContext for old-gen heap regions is valid. We use the MarkingContext @@ -102,7 +102,7 @@ void ShenandoahScanRemembered::process_clusters(size_t first_cluster, size_t cou // tams and ctx below are for old generation marking. As such, young gen roots must // consider everything above tams, since it doesn't represent a TAMS for young gen's // SATB marking. - const HeapWord* tams = (ctx == nullptr ? region->bottom() : ctx->top_at_mark_start(region)); + HeapWord* const tams = (ctx == nullptr ? region->bottom() : ctx->top_at_mark_start(region)); NOT_PRODUCT(ShenandoahCardStats stats(whole_cards, card_stats(worker_id));) @@ -162,19 +162,37 @@ void ShenandoahScanRemembered::process_clusters(size_t first_cluster, size_t cou // [left, right) is a maximal right-open interval of dirty cards HeapWord* left = _rs->addr_for_card_index(dirty_l); // inclusive HeapWord* right = _rs->addr_for_card_index(dirty_r + 1); // exclusive + if (end_addr <= left) { + // The range of addresses to be scanned is empty + continue; + } // Clip right to end_addr established above (still exclusive) right = MIN2(right, end_addr); assert(right <= region->top() && end_addr <= region->top(), "Busted bounds"); const MemRegion mr(left, right); - // NOTE: We'll not call block_start() repeatedly - // on a very large object if its head card is dirty. If not, - // (i.e. the head card is clean) we'll call it each time we - // process a new dirty range on the object. This is always - // the case for large object arrays, which are typically more + // NOTE: We'll not call first_object_start() repeatedly + // on a very large object, i.e. one spanning multiple cards, + // if its head card is dirty. If not, (i.e. its head card is clean) + // we'll call it each time we process a new dirty range on the object. + // This is always the case for large object arrays, which are typically more // common. - HeapWord* p = _scc->block_start(dirty_l); + assert(ctx != nullptr || heap->old_generation()->is_parsable(), "Error"); + HeapWord* p = _scc->first_object_start(dirty_l, ctx, tams, right); + assert((p == nullptr) || (p < right), "No first object found is denoted by nullptr, p: " + PTR_FORMAT ", right: " PTR_FORMAT ", end_addr: " PTR_FORMAT ", next card addr: " PTR_FORMAT, + p2i(p), p2i(right), p2i(end_addr), p2i(_rs->addr_for_card_index(dirty_r + 1))); + if (p == nullptr) { + // There are no live objects to be scanned in this dirty range. cur_index identifies first card in this + // uninteresting dirty range. At top of next loop iteration, we will either end the looop + // (because cur_index < start_card_index) or we will begin the search for a range of clean cards. + continue; + } + oop obj = cast_to_oop(p); + assert(oopDesc::is_oop(obj), "Not an object at " PTR_FORMAT ", left: " PTR_FORMAT ", right: " PTR_FORMAT, + p2i(p), p2i(left), p2i(right)); + assert(ctx==nullptr || ctx->is_marked(obj), "Error"); // PREFIX: The object that straddles into this range of dirty cards // from the left may be subject to special treatment unless diff --git a/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp index daf5d456af5..849ab691dcf 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp @@ -30,8 +30,8 @@ #include "gc/shenandoah/shenandoahUtils.hpp" #include "gc/shenandoah/shenandoahYoungGeneration.hpp" -ShenandoahYoungGeneration::ShenandoahYoungGeneration(uint max_queues, size_t max_capacity, size_t soft_max_capacity) : - ShenandoahGeneration(YOUNG, max_queues, max_capacity, soft_max_capacity), +ShenandoahYoungGeneration::ShenandoahYoungGeneration(uint max_queues, size_t max_capacity) : + ShenandoahGeneration(YOUNG, max_queues, max_capacity), _old_gen_task_queues(nullptr) { } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.hpp index a8ebab507b6..14f9a9b3004 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.hpp @@ -34,7 +34,7 @@ class ShenandoahYoungGeneration : public ShenandoahGeneration { ShenandoahYoungHeuristics* _young_heuristics; public: - ShenandoahYoungGeneration(uint max_queues, size_t max_capacity, size_t max_soft_capacity); + ShenandoahYoungGeneration(uint max_queues, size_t max_capacity); ShenandoahHeuristics* initialize_heuristics(ShenandoahMode* gc_mode) override; diff --git a/src/hotspot/share/gc/z/zPageAllocator.cpp b/src/hotspot/share/gc/z/zPageAllocator.cpp index 80a53feed71..c16354106d8 100644 --- a/src/hotspot/share/gc/z/zPageAllocator.cpp +++ b/src/hotspot/share/gc/z/zPageAllocator.cpp @@ -1087,7 +1087,8 @@ void ZPartition::free_memory_alloc_failed(ZMemoryAllocation* allocation) { freed += vmem.size(); _cache.insert(vmem); } - assert(allocation->harvested() + allocation->committed_capacity() == freed, "must have freed all"); + assert(allocation->harvested() + allocation->committed_capacity() == freed, "must have freed all" + " %zu + %zu == %zu", allocation->harvested(), allocation->committed_capacity(), freed); // Adjust capacity to reflect the failed capacity increase const size_t remaining = allocation->size() - freed; @@ -1904,23 +1905,27 @@ void ZPageAllocator::cleanup_failed_commit_single_partition(ZSinglePartitionAllo ZMemoryAllocation* const allocation = single_partition_allocation->allocation(); assert(allocation->commit_failed(), "Must have failed to commit"); + assert(allocation->partial_vmems()->is_empty(), "Invariant for single partition commit failure"); - const size_t committed = allocation->committed_capacity(); - const ZVirtualMemory non_harvested_vmem = vmem.last_part(allocation->harvested()); - const ZVirtualMemory committed_vmem = non_harvested_vmem.first_part(committed); - const ZVirtualMemory non_committed_vmem = non_harvested_vmem.last_part(committed); + // For a single partition we have unmapped the harvested memory before we + // started committing, and moved its physical memory association to the start + // of the vmem. As such, the partial_vmems is empty. All the harvested and + // partially successfully committed memory is mapped in the first part of vmem. + const size_t harvested_and_committed_capacity = allocation->harvested() + allocation->committed_capacity(); + const ZVirtualMemory succeeded_vmem = vmem.first_part(harvested_and_committed_capacity); + const ZVirtualMemory failed_vmem = vmem.last_part(harvested_and_committed_capacity); - if (committed_vmem.size() > 0) { + if (succeeded_vmem.size() > 0) { // Register the committed and mapped memory. We insert the committed // memory into partial_vmems so that it will be inserted into the cache // in a subsequent step. - allocation->partial_vmems()->append(committed_vmem); + allocation->partial_vmems()->append(succeeded_vmem); } // Free the virtual and physical memory we fetched to use but failed to commit ZPartition& partition = allocation->partition(); - partition.free_physical(non_committed_vmem); - partition.free_virtual(non_committed_vmem); + partition.free_physical(failed_vmem); + partition.free_virtual(failed_vmem); } void ZPageAllocator::cleanup_failed_commit_multi_partition(ZMultiPartitionAllocation* multi_partition_allocation, const ZVirtualMemory& vmem) { @@ -1936,7 +1941,7 @@ void ZPageAllocator::cleanup_failed_commit_multi_partition(ZMultiPartitionAlloca } const size_t committed = allocation->committed_capacity(); - const ZVirtualMemory non_harvested_vmem = vmem.last_part(allocation->harvested()); + const ZVirtualMemory non_harvested_vmem = partial_vmem.last_part(allocation->harvested()); const ZVirtualMemory committed_vmem = non_harvested_vmem.first_part(committed); const ZVirtualMemory non_committed_vmem = non_harvested_vmem.last_part(committed); diff --git a/src/hotspot/share/gc/z/zPhysicalMemoryManager.cpp b/src/hotspot/share/gc/z/zPhysicalMemoryManager.cpp index 2c2f9988d4b..54477d19a27 100644 --- a/src/hotspot/share/gc/z/zPhysicalMemoryManager.cpp +++ b/src/hotspot/share/gc/z/zPhysicalMemoryManager.cpp @@ -214,9 +214,20 @@ void ZPhysicalMemoryManager::free(const ZVirtualMemory& vmem, uint32_t numa_id) }); } +static size_t inject_commit_limit(const ZVirtualMemory& vmem) { + // To facilitate easier interoperability with multi partition allocations we + // divide by ZNUMA::count(). Users of ZFailLargerCommits need to be aware of + // this when writing tests. In the future we could probe the VirtualMemoryManager + // and condition this division on whether the vmem is in the multi partition + // address space. + return align_up(MIN2(ZFailLargerCommits / ZNUMA::count(), vmem.size()), ZGranuleSize); +} + size_t ZPhysicalMemoryManager::commit(const ZVirtualMemory& vmem, uint32_t numa_id) { zbacking_index* const pmem = _physical_mappings.addr(vmem.start()); - const size_t size = vmem.size(); + const size_t size = ZFailLargerCommits > 0 + ? inject_commit_limit(vmem) + : vmem.size(); size_t total_committed = 0; diff --git a/src/hotspot/share/gc/z/z_globals.hpp b/src/hotspot/share/gc/z/z_globals.hpp index e1f525e5372..4e5d725a5fd 100644 --- a/src/hotspot/share/gc/z/z_globals.hpp +++ b/src/hotspot/share/gc/z/z_globals.hpp @@ -118,6 +118,11 @@ develop(bool, ZVerifyOops, false, \ "Verify accessed oops") \ \ + develop(size_t, ZFailLargerCommits, 0, \ + "Commits larger than ZFailLargerCommits will be truncated, " \ + "used to stress page allocation commit failure paths " \ + "(0: Disabled)") \ + \ develop(uint, ZFakeNUMA, 1, \ "ZFakeNUMA is used to test the internal NUMA memory support " \ "without the need for UseNUMA") \ diff --git a/src/hotspot/share/interpreter/bytecodeStream.hpp b/src/hotspot/share/interpreter/bytecodeStream.hpp index 89d97053b45..412951691c5 100644 --- a/src/hotspot/share/interpreter/bytecodeStream.hpp +++ b/src/hotspot/share/interpreter/bytecodeStream.hpp @@ -100,8 +100,23 @@ class BaseBytecodeStream: StackObj { 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. u1 get_index_u1() const { assert_raw_index_size(1); return *(jubyte*)(bcp()+1); } diff --git a/src/hotspot/share/jfr/jfr.cpp b/src/hotspot/share/jfr/jfr.cpp index 4bd57b3c324..bd5797be0a0 100644 --- a/src/hotspot/share/jfr/jfr.cpp +++ b/src/hotspot/share/jfr/jfr.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ #include "jfr/recorder/repository/jfrEmergencyDump.hpp" #include "jfr/recorder/service/jfrOptionSet.hpp" #include "jfr/recorder/service/jfrOptionSet.hpp" +#include "jfr/recorder/service/jfrRecorderService.hpp" #include "jfr/recorder/repository/jfrRepository.hpp" #include "jfr/support/jfrKlassExtension.hpp" #include "jfr/support/jfrResolution.hpp" @@ -43,6 +44,7 @@ #include "runtime/java.hpp" #include "runtime/javaThread.hpp" + bool Jfr::is_enabled() { return JfrRecorder::is_enabled(); } @@ -151,9 +153,9 @@ void Jfr::on_resolution(const Method* caller, const Method* target, TRAPS) { } #endif -void Jfr::on_vm_shutdown(bool exception_handler, bool halt) { +void Jfr::on_vm_shutdown(bool exception_handler /* false */, bool halt /* false */, bool oom /* false */) { if (!halt && JfrRecorder::is_recording()) { - JfrEmergencyDump::on_vm_shutdown(exception_handler); + JfrEmergencyDump::on_vm_shutdown(exception_handler, oom); } } @@ -170,3 +172,9 @@ bool Jfr::on_flight_recorder_option(const JavaVMOption** option, char* delimiter bool Jfr::on_start_flight_recording_option(const JavaVMOption** option, char* delimiter) { return JfrOptionSet::parse_start_flight_recording_option(option, delimiter); } + +void Jfr::on_report_java_out_of_memory() { + if (CrashOnOutOfMemoryError && JfrRecorder::is_recording()) { + JfrRecorderService::emit_leakprofiler_events_on_oom(); + } +} diff --git a/src/hotspot/share/jfr/jfr.hpp b/src/hotspot/share/jfr/jfr.hpp index b053c6445ef..a7565620bbd 100644 --- a/src/hotspot/share/jfr/jfr.hpp +++ b/src/hotspot/share/jfr/jfr.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,7 +70,7 @@ class Jfr : AllStatic { static void on_resolution(const Method* caller, const Method* target, TRAPS); static void on_java_thread_start(JavaThread* starter, JavaThread* startee); static void on_set_current_thread(JavaThread* jt, oop thread); - static void on_vm_shutdown(bool exception_handler = false, bool halt = false); + static void on_vm_shutdown(bool exception_handler = false, bool halt = false, bool oom = false); static void on_vm_error_report(outputStream* st); static bool on_flight_recorder_option(const JavaVMOption** option, char* delimiter); static bool on_start_flight_recording_option(const JavaVMOption** option, char* delimiter); @@ -78,6 +78,7 @@ class Jfr : AllStatic { static void initialize_main_thread(JavaThread* jt); static bool has_sample_request(JavaThread* jt); static void check_and_process_sample_request(JavaThread* jt); + static void on_report_java_out_of_memory(); }; #endif // SHARE_JFR_JFR_HPP diff --git a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp index a09da529b1b..0b4ab532064 100644 --- a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp +++ b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -364,8 +364,7 @@ JVM_ENTRY_NO_ENV(void, jfr_set_force_instrumentation(JNIEnv* env, jclass jvm, jb JVM_END NO_TRANSITION(void, jfr_emit_old_object_samples(JNIEnv* env, jclass jvm, jlong cutoff_ticks, jboolean emit_all, jboolean skip_bfs)) - JfrRecorderService service; - service.emit_leakprofiler_events(cutoff_ticks, emit_all == JNI_TRUE, skip_bfs == JNI_TRUE); + JfrRecorderService::emit_leakprofiler_events(cutoff_ticks, emit_all == JNI_TRUE, skip_bfs == JNI_TRUE); NO_TRANSITION_END JVM_ENTRY_NO_ENV(void, jfr_exclude_thread(JNIEnv* env, jclass jvm, jobject t)) diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp index 2793a1fb984..a59503f50d8 100644 --- a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp +++ b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp @@ -25,7 +25,6 @@ #include "jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp" #include "logging/log.hpp" - #if defined(LINUX) #include "jfr/periodic/sampling/jfrThreadSampling.hpp" #include "jfr/support/jfrThreadLocal.hpp" @@ -68,7 +67,7 @@ static JavaThread* get_java_thread_if_valid() { } JfrCPUTimeTraceQueue::JfrCPUTimeTraceQueue(u4 capacity) : - _data(nullptr), _capacity(capacity), _head(0), _lost_samples(0) { + _data(nullptr), _capacity(capacity), _head(0), _lost_samples(0), _lost_samples_due_to_queue_full(0) { if (capacity != 0) { _data = JfrCHeapObj::new_array(capacity); } @@ -111,10 +110,13 @@ void JfrCPUTimeTraceQueue::set_size(u4 size) { } u4 JfrCPUTimeTraceQueue::capacity() const { - return _capacity; + return Atomic::load_acquire(&_capacity); } void JfrCPUTimeTraceQueue::set_capacity(u4 capacity) { + if (capacity == Atomic::load(&_capacity)) { + return; + } _head = 0; if (_data != nullptr) { assert(_capacity != 0, "invariant"); @@ -125,7 +127,7 @@ void JfrCPUTimeTraceQueue::set_capacity(u4 capacity) { } else { _data = nullptr; } - _capacity = capacity; + Atomic::release_store(&_capacity, capacity); } bool JfrCPUTimeTraceQueue::is_empty() const { @@ -141,28 +143,51 @@ void JfrCPUTimeTraceQueue::increment_lost_samples() { Atomic::inc(&_lost_samples); } +void JfrCPUTimeTraceQueue::increment_lost_samples_due_to_queue_full() { + Atomic::inc(&_lost_samples_due_to_queue_full); +} + u4 JfrCPUTimeTraceQueue::get_and_reset_lost_samples() { return Atomic::xchg(&_lost_samples, (u4)0); } -void JfrCPUTimeTraceQueue::resize(u4 capacity) { - if (capacity != _capacity) { - set_capacity(capacity); - } +u4 JfrCPUTimeTraceQueue::get_and_reset_lost_samples_due_to_queue_full() { + return Atomic::xchg(&_lost_samples_due_to_queue_full, (u4)0); } -void JfrCPUTimeTraceQueue::resize_for_period(u4 period_millis) { - u4 capacity = CPU_TIME_QUEUE_CAPACITY; - if (period_millis > 0 && period_millis < 10) { - capacity = (u4) ((double) capacity * 10 / period_millis); - } - resize(capacity); +void JfrCPUTimeTraceQueue::init() { + set_capacity(JfrCPUTimeTraceQueue::CPU_TIME_QUEUE_INITIAL_CAPACITY); } void JfrCPUTimeTraceQueue::clear() { Atomic::release_store(&_head, (u4)0); } +void JfrCPUTimeTraceQueue::resize_if_needed() { + u4 lost_samples_due_to_queue_full = get_and_reset_lost_samples_due_to_queue_full(); + if (lost_samples_due_to_queue_full == 0) { + return; + } + u4 capacity = Atomic::load(&_capacity); + if (capacity < CPU_TIME_QUEUE_MAX_CAPACITY) { + float ratio = (float)lost_samples_due_to_queue_full / (float)capacity; + int factor = 1; + if (ratio > 8) { // idea is to quickly scale the queue in the worst case + factor = ratio; + } else if (ratio > 2) { + factor = 8; + } else if (ratio > 0.5) { + factor = 4; + } else if (ratio > 0.01) { + factor = 2; + } + if (factor > 1) { + u4 new_capacity = MIN2(CPU_TIME_QUEUE_MAX_CAPACITY, capacity * factor); + set_capacity(new_capacity); + } + } +} + // A throttle is either a rate or a fixed period class JfrCPUSamplerThrottle { @@ -206,6 +231,8 @@ class JfrCPUSamplerThread : public NonJavaThread { volatile bool _is_async_processing_of_cpu_time_jfr_requests_triggered; volatile bool _warned_about_timer_creation_failure; volatile bool _signal_handler_installed; + DEBUG_ONLY(volatile bool _out_of_stack_walking_enabled;) + DEBUG_ONLY(volatile u8 _out_of_stack_walking_iterations;) static const u4 STOP_SIGNAL_BIT = 0x80000000; @@ -249,8 +276,19 @@ class JfrCPUSamplerThread : public NonJavaThread { void handle_timer_signal(siginfo_t* info, void* context); bool init_timers(); void stop_timer(); + virtual void print_on(outputStream* st) const; void trigger_async_processing_of_cpu_time_jfr_requests(); + + #ifdef ASSERT + void set_out_of_stack_walking_enabled(bool runnable) { + Atomic::release_store(&_out_of_stack_walking_enabled, runnable); + } + + u8 out_of_stack_walking_iterations() const { + return Atomic::load(&_out_of_stack_walking_iterations); + } + #endif }; JfrCPUSamplerThread::JfrCPUSamplerThread(JfrCPUSamplerThrottle& throttle) : @@ -276,7 +314,7 @@ void JfrCPUSamplerThread::on_javathread_create(JavaThread* thread) { } JfrThreadLocal* tl = thread->jfr_thread_local(); assert(tl != nullptr, "invariant"); - tl->cpu_time_jfr_queue().resize_for_period(_current_sampling_period_ns / 1000000); + tl->cpu_time_jfr_queue().init(); timer_t timerid; if (create_timer_for_thread(thread, timerid)) { tl->set_cpu_timer(&timerid); @@ -295,12 +333,14 @@ void JfrCPUSamplerThread::on_javathread_terminate(JavaThread* thread) { if (timer == nullptr) { return; // no timer was created for this thread } + tl->acquire_cpu_time_jfr_dequeue_lock(); tl->unset_cpu_timer(); tl->deallocate_cpu_time_jfr_queue(); s4 lost_samples = tl->cpu_time_jfr_queue().lost_samples(); if (lost_samples > 0) { JfrCPUTimeThreadSampling::send_lost_event(JfrTicks::now(), JfrThreadLocal::thread_id(thread), lost_samples); } + tl->release_cpu_time_jfr_queue_lock(); } void JfrCPUSamplerThread::start_thread() { @@ -353,10 +393,12 @@ void JfrCPUSamplerThread::run() { recompute_period_if_needed(); last_recompute_check = os::javaTimeNanos(); } - - if (Atomic::cmpxchg(&_is_async_processing_of_cpu_time_jfr_requests_triggered, true, false)) { - stackwalk_threads_in_native(); - } + DEBUG_ONLY(if (Atomic::load_acquire(&_out_of_stack_walking_enabled)) {) + if (Atomic::cmpxchg(&_is_async_processing_of_cpu_time_jfr_requests_triggered, true, false)) { + DEBUG_ONLY(Atomic::inc(&_out_of_stack_walking_iterations);) + stackwalk_threads_in_native(); + } + DEBUG_ONLY(}) os::naked_sleep(100); } } @@ -546,6 +588,21 @@ void JfrCPUTimeThreadSampling::handle_timer_signal(siginfo_t* info, void* contex _sampler->decrement_signal_handler_count(); } +#ifdef ASSERT +void JfrCPUTimeThreadSampling::set_out_of_stack_walking_enabled(bool runnable) { + if (_instance != nullptr && _instance->_sampler != nullptr) { + _instance->_sampler->set_out_of_stack_walking_enabled(runnable); + } +} + +u8 JfrCPUTimeThreadSampling::out_of_stack_walking_iterations() { + if (_instance != nullptr && _instance->_sampler != nullptr) { + return _instance->_sampler->out_of_stack_walking_iterations(); + } + return 0; +} +#endif + void JfrCPUSamplerThread::sample_thread(JfrSampleRequest& request, void* ucontext, JavaThread* jt, JfrThreadLocal* tl, JfrTicks& now) { JfrSampleRequestBuilder::build_cpu_time_sample_request(request, ucontext, jt, jt->jfr_thread_local(), now); } @@ -591,6 +648,7 @@ void JfrCPUSamplerThread::handle_timer_signal(siginfo_t* info, void* context) { } } else { queue.increment_lost_samples(); + queue.increment_lost_samples_due_to_queue_full(); } if (jt->thread_state() == _thread_in_native) { @@ -732,6 +790,12 @@ void JfrCPUSamplerThread::stop_timer() { VMThread::execute(&op); } +void JfrCPUSamplerThread::print_on(outputStream* st) const { + st->print("\"%s\" ", name()); + Thread::print_on(st); + st->cr(); +} + void JfrCPUSamplerThread::recompute_period_if_needed() { int64_t current_period = get_sampling_period(); int64_t period = _throttle.compute_sampling_period(); @@ -808,4 +872,10 @@ void JfrCPUTimeThreadSampling::on_javathread_create(JavaThread* thread) { void JfrCPUTimeThreadSampling::on_javathread_terminate(JavaThread* thread) { } +#ifdef ASSERT +static void set_out_of_stack_walking_enabled(bool runnable) { + warn(); +} +#endif + #endif // defined(LINUX) && defined(INCLUDE_JFR) diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp index dae0be5c3a7..e17e63fc3ed 100644 --- a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp +++ b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp @@ -50,12 +50,15 @@ class JfrCPUTimeTraceQueue { static const u4 CPU_TIME_QUEUE_CAPACITY = 500; JfrCPUTimeSampleRequest* _data; - u4 _capacity; + volatile u4 _capacity; // next unfilled index volatile u4 _head; volatile u4 _lost_samples; + volatile u4 _lost_samples_due_to_queue_full; + static const u4 CPU_TIME_QUEUE_INITIAL_CAPACITY = 20; + static const u4 CPU_TIME_QUEUE_MAX_CAPACITY = 2000; public: JfrCPUTimeTraceQueue(u4 capacity); @@ -81,12 +84,17 @@ class JfrCPUTimeTraceQueue { void increment_lost_samples(); + void increment_lost_samples_due_to_queue_full(); + // returns the previous lost samples count u4 get_and_reset_lost_samples(); - void resize(u4 capacity); + u4 get_and_reset_lost_samples_due_to_queue_full(); + + void resize_if_needed(); - void resize_for_period(u4 period_millis); + // init the queue capacity + void init(); void clear(); @@ -130,6 +138,10 @@ class JfrCPUTimeThreadSampling : public JfrCHeapObj { static void send_lost_event(const JfrTicks& time, traceid tid, s4 lost_samples); static void trigger_async_processing_of_cpu_time_jfr_requests(); + + DEBUG_ONLY(static void set_out_of_stack_walking_enabled(bool runnable);) + + DEBUG_ONLY(static u8 out_of_stack_walking_iterations();) }; #else @@ -150,6 +162,8 @@ class JfrCPUTimeThreadSampling : public JfrCHeapObj { static void on_javathread_create(JavaThread* thread); static void on_javathread_terminate(JavaThread* thread); + DEBUG_ONLY(static void set_out_of_stack_walking_enabled(bool runnable)); + DEBUG_ONLY(static u8 out_of_stack_walking_iterations();) }; #endif // defined(LINUX) diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp index 4c44c43772d..596702a53dd 100644 --- a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp +++ b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,6 +85,7 @@ class JfrSamplerThread : public NonJavaThread { bool is_JfrSampler_thread() const { return true; } int64_t java_period() const { return Atomic::load(&_java_period_millis); }; int64_t native_period() const { return Atomic::load(&_native_period_millis); }; + virtual void print_on(outputStream* st) const; }; JfrSamplerThread::JfrSamplerThread(int64_t java_period_millis, int64_t native_period_millis, u4 max_frames) : @@ -231,41 +232,50 @@ void JfrSamplerThread::task_stacktrace(JfrSampleRequestType type, JavaThread** l JavaThread* start = nullptr; elapsedTimer sample_time; sample_time.start(); - ThreadsListHandle tlh; - // Resolve a sample session relative start position index into the thread list array. - // In cases where the last sampled thread is null or not-null but stale, find_index() returns -1. - _cur_index = tlh.list()->find_index_of_JavaThread(*last_thread); - JavaThread* current = _cur_index != -1 ? *last_thread : nullptr; - - while (num_samples < sample_limit) { - current = next_thread(tlh.list(), start, current); - if (current == nullptr) { - break; - } - if (is_excluded(current)) { - continue; - } - if (start == nullptr) { - start = current; // remember the thread where we started to attempt sampling - } - bool success; - if (JAVA_SAMPLE == type) { - success = sample_java_thread(current); - } else { - assert(type == NATIVE_SAMPLE, "invariant"); - success = sample_native_thread(current); - } - if (success) { - num_samples++; - } - if (SafepointSynchronize::is_at_safepoint()) { - // For _thread_in_native, we cannot get the Threads_lock. - // For _thread_in_Java, well, there are none. - break; + { + /* + * Take the Threads_lock for three purposes: + * + * 1) Avoid sampling right through a safepoint, + * which could result in touching oops in case of virtual threads. + * 2) Prevent JFR from issuing an epoch rotation while the sampler thread + * is actively processing a thread in state native, as both threads are outside the safepoint protocol. + * 3) Some operating systems (BSD / Mac) require a process lock when sending a signal with pthread_kill. + * Holding the Threads_lock prevents a JavaThread from calling os::create_thread(), which also takes the process lock. + * In a sense, we provide a coarse signal mask, so we can always send the resume signal. + */ + MutexLocker tlock(Threads_lock); + ThreadsListHandle tlh; + // Resolve a sample session relative start position index into the thread list array. + // In cases where the last sampled thread is null or not-null but stale, find_index() returns -1. + _cur_index = tlh.list()->find_index_of_JavaThread(*last_thread); + JavaThread* current = _cur_index != -1 ? *last_thread : nullptr; + + while (num_samples < sample_limit) { + current = next_thread(tlh.list(), start, current); + if (current == nullptr) { + break; + } + if (is_excluded(current)) { + continue; + } + if (start == nullptr) { + start = current; // remember the thread where we started to attempt sampling + } + bool success; + if (JAVA_SAMPLE == type) { + success = sample_java_thread(current); + } else { + assert(type == NATIVE_SAMPLE, "invariant"); + success = sample_native_thread(current); + } + if (success) { + num_samples++; + } } - } - *last_thread = current; // remember the thread we last attempted to sample + *last_thread = current; // remember the thread we last attempted to sample + } sample_time.stop(); log_trace(jfr)("JFR thread sampling done in %3.7f secs with %d java %d native samples", sample_time.seconds(), type == JAVA_SAMPLE ? num_samples : 0, type == NATIVE_SAMPLE ? num_samples : 0); @@ -296,6 +306,7 @@ class OSThreadSampler : public SuspendedThreadTask { // Sampling a thread in state _thread_in_Java // involves a platform-specific thread suspend and CPU context retrieval. bool JfrSamplerThread::sample_java_thread(JavaThread* jt) { + assert_lock_strong(Threads_lock); if (jt->thread_state() != _thread_in_Java) { return false; } @@ -327,6 +338,7 @@ static JfrSamplerThread* _sampler_thread = nullptr; // without thread suspension and CPU context retrieval, // if we carefully order the loads of the thread state. bool JfrSamplerThread::sample_native_thread(JavaThread* jt) { + assert_lock_strong(Threads_lock); if (jt->thread_state() != _thread_in_native) { return false; } @@ -342,24 +354,14 @@ bool JfrSamplerThread::sample_native_thread(JavaThread* jt) { SafepointMechanism::arm_local_poll_release(jt); - // Take the Threads_lock for two purposes: - // 1) Avoid sampling through a safepoint which could result - // in touching oops in case of virtual threads. - // 2) Prevent JFR from issuing an epoch rotation while the sampler thread - // is actively processing a thread in native, as both threads are now - // outside the safepoint protocol. - - // OrderAccess::fence() as part of acquiring the lock prevents loads from floating up. - JfrMutexTryLock threads_lock(Threads_lock); - - if (!threads_lock.acquired() || !jt->has_last_Java_frame()) { - // Remove the native sample request and release the potentially waiting thread. - JfrSampleMonitor jsm(tl); - return false; + // Separate the arming of the poll (above) from the reading of JavaThread state (below). + if (UseSystemMemoryBarrier) { + SystemMemoryBarrier::emit(); + } else { + OrderAccess::fence(); } - if (jt->thread_state() != _thread_in_native) { - assert_lock_strong(Threads_lock); + if (jt->thread_state() != _thread_in_native || !jt->has_last_Java_frame()) { JfrSampleMonitor jsm(tl); if (jsm.is_waiting()) { // The thread has already returned from native, @@ -384,6 +386,12 @@ void JfrSamplerThread::set_native_period(int64_t period_millis) { Atomic::store(&_native_period_millis, period_millis); } +void JfrSamplerThread::print_on(outputStream* st) const { + st->print("\"%s\" ", name()); + Thread::print_on(st); + st->cr(); +} + // JfrThreadSampler; static JfrThreadSampler* _instance = nullptr; diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampling.cpp b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampling.cpp index ddc9d59b295..534c9996cfe 100644 --- a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampling.cpp +++ b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampling.cpp @@ -217,7 +217,8 @@ static bool compute_top_frame(const JfrSampleRequest& request, frame& top_frame, const PcDesc* const pc_desc = get_pc_desc(sampled_nm, sampled_pc); if (is_valid(pc_desc)) { intptr_t* const synthetic_sp = sender_sp - sampled_nm->frame_size(); - top_frame = frame(synthetic_sp, synthetic_sp, sender_sp, pc_desc->real_pc(sampled_nm), sampled_nm); + intptr_t* const synthetic_fp = sender_sp AARCH64_ONLY( - frame::sender_sp_offset); + top_frame = frame(synthetic_sp, synthetic_sp, synthetic_fp, pc_desc->real_pc(sampled_nm), sampled_nm); in_continuation = is_in_continuation(top_frame, jt); return true; } @@ -368,6 +369,7 @@ static void drain_enqueued_cpu_time_requests(const JfrTicks& now, JfrThreadLocal tl->set_has_cpu_time_jfr_requests(false); if (queue.lost_samples() > 0) { JfrCPUTimeThreadSampling::send_lost_event( now, JfrThreadLocal::thread_id(jt), queue.get_and_reset_lost_samples()); + queue.resize_if_needed(); } if (lock) { tl->release_cpu_time_jfr_queue_lock(); diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdKlassQueue.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdKlassQueue.cpp index e821b528707..9c57374d6c6 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdKlassQueue.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdKlassQueue.cpp @@ -29,6 +29,7 @@ #include "jfr/support/jfrThreadLocal.hpp" #include "jfr/utilities/jfrEpochQueue.inline.hpp" #include "jfr/utilities/jfrTypes.hpp" +#include "memory/metaspace.hpp" #include "oops/compressedKlass.inline.hpp" #include "utilities/macros.hpp" @@ -73,14 +74,13 @@ static size_t element_size(bool compressed) { return compressed ? NARROW_ELEMENT_SIZE : ELEMENT_SIZE; } -static bool can_compress_element(const Klass* klass) { - return CompressedKlassPointers::is_encodable(klass) && - JfrTraceId::load_raw(klass) < uncompressed_threshold; +static bool can_compress_element(traceid id) { + return Metaspace::using_class_space() && id < uncompressed_threshold; } static size_t element_size(const Klass* klass) { assert(klass != nullptr, "invariant"); - return element_size(can_compress_element(klass)); + return element_size(can_compress_element(JfrTraceId::load_raw(klass))); } static bool is_unloaded(traceid id, bool previous_epoch) { @@ -136,8 +136,7 @@ static inline void store_traceid(JfrEpochQueueNarrowKlassElement* element, trace } static void store_compressed_element(traceid id, const Klass* klass, u1* pos) { - assert(can_compress_element(klass), "invariant"); - assert(id == JfrTraceId::load_raw(klass), "invariant"); + assert(can_compress_element(id), "invariant"); JfrEpochQueueNarrowKlassElement* const element = new (pos) JfrEpochQueueNarrowKlassElement(); store_traceid(element, id); element->compressed_klass = encode(klass); @@ -153,7 +152,7 @@ static void store_element(const Klass* klass, u1* pos) { assert(pos != nullptr, "invariant"); assert(klass != nullptr, "invariant"); const traceid id = JfrTraceId::load_raw(klass); - if (can_compress_element(klass)) { + if (can_compress_element(id)) { store_compressed_element(id, klass, pos); return; } diff --git a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp index b49ce4556c7..e0c5d36a3c7 100644 --- a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp +++ b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,9 @@ #include "runtime/javaThread.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/os.hpp" +#include "runtime/thread.inline.hpp" +#include "runtime/vmOperations.hpp" +#include "runtime/vmThread.hpp" #include "utilities/growableArray.hpp" #include "utilities/ostream.hpp" @@ -450,25 +453,14 @@ const char* JfrEmergencyDump::chunk_path(const char* repository_path) { * * If we end up deadlocking in the attempt of dumping out jfr data, * we rely on the WatcherThread task "is_error_reported()", -* to exit the VM after a hard-coded timeout (disallow WatcherThread to emergency dump). +* to exit the VM after a hard-coded timeout (the reason +* for disallowing the WatcherThread to issue an emergency dump). * This "safety net" somewhat explains the aggressiveness in this attempt. * */ -static bool prepare_for_emergency_dump(Thread* thread) { +static void release_locks(Thread* thread) { assert(thread != nullptr, "invariant"); - if (thread->is_Watcher_thread()) { - // need WatcherThread as a safeguard against potential deadlocks - return false; - } - -#ifdef ASSERT - Mutex* owned_lock = thread->owned_locks(); - while (owned_lock != nullptr) { - Mutex* next = owned_lock->next(); - owned_lock->unlock(); - owned_lock = next; - } -#endif // ASSERT + assert(!thread->is_Java_thread() || JavaThread::cast(thread)->thread_state() == _thread_in_vm, "invariant"); if (Threads_lock->owned_by_self()) { Threads_lock->unlock(); @@ -517,24 +509,18 @@ static bool prepare_for_emergency_dump(Thread* thread) { if (JfrStacktrace_lock->owned_by_self()) { JfrStacktrace_lock->unlock(); } - return true; -} - -static volatile int jfr_shutdown_lock = 0; - -static bool guard_reentrancy() { - return Atomic::cmpxchg(&jfr_shutdown_lock, 0, 1) == 0; } class JavaThreadInVMAndNative : public StackObj { private: - JavaThread* const _jt; + JavaThread* _jt; JavaThreadState _original_state; public: - JavaThreadInVMAndNative(Thread* t) : _jt(t->is_Java_thread() ? JavaThread::cast(t) : nullptr), + JavaThreadInVMAndNative(Thread* t) : _jt(nullptr), _original_state(_thread_max_state) { - if (_jt != nullptr) { + if (t != nullptr && t->is_Java_thread()) { + _jt = JavaThread::cast(t); _original_state = _jt->thread_state(); if (_original_state != _thread_in_vm) { _jt->set_thread_state(_thread_in_vm); @@ -544,6 +530,7 @@ class JavaThreadInVMAndNative : public StackObj { ~JavaThreadInVMAndNative() { if (_original_state != _thread_max_state) { + assert(_jt != nullptr, "invariant"); _jt->set_thread_state(_original_state); } } @@ -556,35 +543,82 @@ class JavaThreadInVMAndNative : public StackObj { } }; -static void post_events(bool exception_handler, Thread* thread) { +static void post_events(bool exception_handler, bool oom, Thread * thread) { if (exception_handler) { EventShutdown e; - e.set_reason("VM Error"); + e.set_reason(oom ? "CrashOnOutOfMemoryError" : "VM Error"); e.commit(); - } else { - // OOM - LeakProfiler::emit_events(max_jlong, false, false); } EventDumpReason event; - event.set_reason(exception_handler ? "Crash" : "Out of Memory"); + event.set_reason(exception_handler && oom ? "CrashOnOutOfMemoryError" : exception_handler ? "Crash" : "Out of Memory"); event.set_recordingId(-1); event.commit(); } -void JfrEmergencyDump::on_vm_shutdown(bool exception_handler) { - if (!guard_reentrancy()) { - return; +static volatile traceid _jfr_shutdown_tid = 0; + +static bool guard_reentrancy() { + const traceid shutdown_tid = Atomic::load(&_jfr_shutdown_tid); + if (shutdown_tid == max_julong) { + // Someone tried but did not have a proper thread for the purpose. + return false; } - Thread* thread = Thread::current_or_null_safe(); - if (thread == nullptr) { + if (shutdown_tid == 0) { + Thread* const thread = Thread::current_or_null_safe(); + const traceid tid = thread != nullptr ? JFR_JVM_THREAD_ID(thread) : max_julong; + if (Atomic::cmpxchg(&_jfr_shutdown_tid, shutdown_tid, tid) != shutdown_tid) { + JavaThreadInVMAndNative jtivm(thread); + if (thread != nullptr) { + release_locks(thread); + } + log_info(jfr, system)("A jfr emergency dump is already in progress, waiting for thread id " UINT64_FORMAT_X, Atomic::load(&_jfr_shutdown_tid)); + // Transition to a safe safepoint state for the infinite sleep. A nop for non-java threads. + jtivm.transition_to_native(); + os::infinite_sleep(); // stay here until we exit normally or crash. + ShouldNotReachHere(); + } + return tid != max_julong; + } + // Recursive case + assert(JFR_JVM_THREAD_ID(Thread::current_or_null_safe()) == shutdown_tid, "invariant"); + return false; +} + +void JfrEmergencyDump::on_vm_shutdown(bool exception_handler, bool oom) { + if (!guard_reentrancy()) { return; } + + Thread* const thread = Thread::current_or_null_safe(); + assert(thread != nullptr, "invariant"); + // Ensure a JavaThread is _thread_in_vm when we make this call JavaThreadInVMAndNative jtivm(thread); - if (!prepare_for_emergency_dump(thread)) { + post_events(exception_handler, oom, thread); + + if (thread->is_Watcher_thread()) { + // We cannot attempt an emergency dump using the Watcher thread + // because we rely on the WatcherThread task "is_error_reported()", + // to exit the VM after a hardcoded timeout, should the relatively + // risky operation of an emergency dump fail (deadlock, livelock). + log_warning(jfr, system) + ("The Watcher thread crashed so no jfr emergency dump will be generated."); return; } - post_events(exception_handler, thread); + + if (thread->is_VM_thread()) { + const VM_Operation* const operation = VMThread::vm_operation(); + if (operation != nullptr && operation->type() == VM_Operation::VMOp_JFROldObject) { + // We will not be able to issue a rotation because the rotation lock + // is held by the JFR Recorder Thread that issued the VM_Operation. + log_warning(jfr, system) + ("The VM Thread crashed as part of emitting leak profiler events so no jfr emergency dump will be generated."); + return; + } + } + + release_locks(thread); + // if JavaThread, transition to _thread_in_native to issue a final flushpoint NoHandleMark nhm; jtivm.transition_to_native(); diff --git a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.hpp b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.hpp index 7db4b511746..b337d73364a 100644 --- a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.hpp +++ b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,7 @@ class JfrEmergencyDump : AllStatic { static const char* chunk_path(const char* repository_path); static void on_vm_error(const char* repository_path); static void on_vm_error_report(outputStream* st, const char* repository_path); - static void on_vm_shutdown(bool exception_handler); + static void on_vm_shutdown(bool exception_handler, bool oom); }; #endif // SHARE_JFR_RECORDER_REPOSITORY_JFREMERGENCYDUMP_HPP diff --git a/src/hotspot/share/jfr/recorder/service/jfrPostBox.cpp b/src/hotspot/share/jfr/recorder/service/jfrPostBox.cpp index b1bddfff466..0c4874e5c04 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrPostBox.cpp +++ b/src/hotspot/share/jfr/recorder/service/jfrPostBox.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,8 @@ (MSGBIT(MSG_START)) | \ (MSGBIT(MSG_CLONE_IN_MEMORY)) | \ (MSGBIT(MSG_VM_ERROR)) | \ - (MSGBIT(MSG_FLUSHPOINT)) \ + (MSGBIT(MSG_FLUSHPOINT)) | \ + (MSGBIT(MSG_EMIT_LEAKP_REFCHAINS)) \ ) static JfrPostBox* _instance = nullptr; @@ -165,7 +166,7 @@ void JfrPostBox::notify_waiters() { assert(JfrMsg_lock->owned_by_self(), "incrementing _msg_handled_serial is protected by JfrMsg_lock."); // Update made visible on release of JfrMsg_lock via fence instruction in Monitor::IUnlock. ++_msg_handled_serial; - JfrMsg_lock->notify(); + JfrMsg_lock->notify_all(); } // safeguard to ensure no threads are left waiting diff --git a/src/hotspot/share/jfr/recorder/service/jfrPostBox.hpp b/src/hotspot/share/jfr/recorder/service/jfrPostBox.hpp index 10457261643..92f70b1dc9b 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrPostBox.hpp +++ b/src/hotspot/share/jfr/recorder/service/jfrPostBox.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,6 +43,7 @@ enum JFR_Msg { MSG_SHUTDOWN, MSG_VM_ERROR, MSG_FLUSHPOINT, + MSG_EMIT_LEAKP_REFCHAINS, MSG_NO_OF_MSGS }; @@ -51,23 +52,25 @@ enum JFR_Msg { * * Synchronous messages (posting thread waits for message completion): * - * MSG_CLONE_IN_MEMORY (0) ; MSGBIT(MSG_CLONE_IN_MEMORY) == (1 << 0) == 0x1 - * MSG_START(1) ; MSGBIT(MSG_START) == (1 << 0x1) == 0x2 - * MSG_STOP (2) ; MSGBIT(MSG_STOP) == (1 << 0x2) == 0x4 - * MSG_ROTATE (3) ; MSGBIT(MSG_ROTATE) == (1 << 0x3) == 0x8 - * MSG_VM_ERROR (8) ; MSGBIT(MSG_VM_ERROR) == (1 << 0x8) == 0x100 - * MSG_FLUSHPOINT (9) ; MSGBIT(MSG_FLUSHPOINT) == (1 << 0x9) == 0x200 + * MSG_CLONE_IN_MEMORY (0) ; MSGBIT(MSG_CLONE_IN_MEMORY) == (1 << 0) == 0x1 + * MSG_START(1) ; MSGBIT(MSG_START) == (1 << 0x1) == 0x2 + * MSG_STOP (2) ; MSGBIT(MSG_STOP) == (1 << 0x2) == 0x4 + * MSG_ROTATE (3) ; MSGBIT(MSG_ROTATE) == (1 << 0x3) == 0x8 + * MSG_VM_ERROR (8) ; MSGBIT(MSG_VM_ERROR) == (1 << 0x8) == 0x100 + * MSG_FLUSHPOINT (9) ; MSGBIT(MSG_FLUSHPOINT) == (1 << 0x9) == 0x200 + * MSG_EMIT_LEAKP_REFCHAINS (10); MSGBIT(MSG_EMIT_LEAKP_REFCHAINS) == (1 << 0xa) == 0x400 * * Asynchronous messages (posting thread returns immediately upon deposit): * - * MSG_FULLBUFFER (4) ; MSGBIT(MSG_FULLBUFFER) == (1 << 0x4) == 0x10 - * MSG_CHECKPOINT (5) ; MSGBIT(CHECKPOINT) == (1 << 0x5) == 0x20 - * MSG_WAKEUP (6) ; MSGBIT(WAKEUP) == (1 << 0x6) == 0x40 - * MSG_SHUTDOWN (7) ; MSGBIT(MSG_SHUTDOWN) == (1 << 0x7) == 0x80 + * MSG_FULLBUFFER (4) ; MSGBIT(MSG_FULLBUFFER) == (1 << 0x4) == 0x10 + * MSG_CHECKPOINT (5) ; MSGBIT(CHECKPOINT) == (1 << 0x5) == 0x20 + * MSG_WAKEUP (6) ; MSGBIT(WAKEUP) == (1 << 0x6) == 0x40 + * MSG_SHUTDOWN (7) ; MSGBIT(MSG_SHUTDOWN) == (1 << 0x7) == 0x80 */ class JfrPostBox : public JfrCHeapObj { friend class JfrRecorder; + friend class JfrRecorderService; public: void post(JFR_Msg msg); diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp index f0170bac460..a136f8f1476 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp +++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,6 +54,7 @@ #include "runtime/safepoint.hpp" #include "runtime/vmOperations.hpp" #include "runtime/vmThread.hpp" +#include "utilities/growableArray.hpp" // incremented on each flushpoint static u8 flushpoint_id = 0; @@ -413,6 +414,7 @@ class JfrSafepointWriteVMOperation : public VM_Operation { JfrRecorderService::JfrRecorderService() : _checkpoint_manager(JfrCheckpointManager::instance()), _chunkwriter(JfrRepository::chunkwriter()), + _post_box(JfrPostBox::instance()), _repository(JfrRepository::instance()), _stack_trace_repository(JfrStackTraceRepository::instance()), _storage(JfrStorage::instance()), @@ -531,6 +533,7 @@ void JfrRecorderService::rotate(int msgs) { return; } if (msgs & MSGBIT(MSG_VM_ERROR)) { + stop(); vm_error_rotation(); return; } @@ -690,17 +693,173 @@ void JfrRecorderService::evaluate_chunk_size_for_rotation() { JfrChunkRotation::evaluate(_chunkwriter); } -void JfrRecorderService::emit_leakprofiler_events(int64_t cutoff_ticks, bool emit_all, bool skip_bfs) { - DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(JavaThread::current())); - // Take the rotation lock to exclude flush() during event emits. This is because event emit - // also creates a number checkpoint events. Those checkpoint events require a future typeset checkpoint - // event for completeness, i.e. to be generated before being flushed to a segment. +// LeakProfiler event serialization support. + +struct JfrLeakProfilerEmitRequest { + int64_t cutoff_ticks; + bool emit_all; + bool skip_bfs; + bool oom; +}; + +typedef GrowableArrayCHeap JfrLeakProfilerEmitRequestQueue; +static JfrLeakProfilerEmitRequestQueue* _queue = nullptr; +constexpr const static int64_t _no_path_to_gc_roots = 0; +static bool _oom_emit_request_posted = false; +static bool _oom_emit_request_delivered = false; + +static inline bool exclude_paths_to_gc_roots(int64_t cutoff_ticks) { + return cutoff_ticks <= _no_path_to_gc_roots; +} + +static void enqueue(const JfrLeakProfilerEmitRequest& request) { + assert(JfrRotationLock::is_owner(), "invariant"); + if (_queue == nullptr) { + _queue = new JfrLeakProfilerEmitRequestQueue(4); + } + assert(_queue != nullptr, "invariant"); + assert(!_oom_emit_request_posted, "invariant"); + if (request.oom) { + _oom_emit_request_posted = true; + } + _queue->append(request); +} + +static JfrLeakProfilerEmitRequest dequeue() { + assert(JfrRotationLock::is_owner(), "invariant"); + assert(_queue != nullptr, "invariant"); + assert(_queue->is_nonempty(), "invariant"); + const JfrLeakProfilerEmitRequest& request = _queue->first(); + _queue->remove_at(0); + return request; +} + +// This version of emit excludes path-to-gc-roots, i.e. it skips reference chains. +static void emit_leakprofiler_events(bool emit_all, bool skip_bfs, JavaThread* jt) { + assert(jt != nullptr, "invariant"); + DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt)); + // Take the rotation lock to exclude flush() during event emits. This is because the event emit operation + // also creates a number of checkpoint events. Those checkpoint events require a future typeset checkpoint + // event for completeness, i.e., to be generated before being flushed to a segment. // The upcoming flush() or rotation() after event emit completes this typeset checkpoint - // and serializes all event emit checkpoint events to the same segment. + // and serializes all checkpoint events to the same segment. JfrRotationLock lock; + // Take the rotation lock before the thread transition, to avoid blocking safepoints. + if (_oom_emit_request_posted) { + // A request to emit leakprofiler events in response to CrashOnOutOfMemoryError + // is pending or has already been completed. We are about to crash at any time now. + assert(CrashOnOutOfMemoryError, "invariant"); + return; + } + MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, jt)); + ThreadInVMfromNative transition(jt); + // Since we are not requesting path-to-gc-roots, i.e., reference chains, we need not issue a VM_Operation. + // Therefore, we can let the requesting thread process the request directly, since it already holds the requisite lock. + LeakProfiler::emit_events(_no_path_to_gc_roots, emit_all, skip_bfs); +} + +void JfrRecorderService::transition_and_post_leakprofiler_emit_msg(JavaThread* jt) { + assert(jt != nullptr, "invariant"); + DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt);) + assert(!JfrRotationLock::is_owner(), "invariant"); + // Transition to _thread_in_VM and post a synchronous message to the JFR Recorder Thread + // for it to process our enqueued request, which includes paths-to-gc-roots, i.e., reference chains. + MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, jt)); + ThreadInVMfromNative transition(jt); + _post_box.post(MSG_EMIT_LEAKP_REFCHAINS); +} + +// This version of emit includes path-to-gc-roots, i.e., it includes in the request traversing of reference chains. +// Traversing reference chains is performed as part of a VM_Operation, and we initiate it from the JFR Recorder Thread. +// Because multiple threads can concurrently report_on_java_out_of_memory(), having them all post a synchronous JFR msg, +// they rendezvous at a safepoint in a convenient state, ThreadBlockInVM. This mechanism prevents any thread from racing past +// this point and begin executing VMError::report_and_die(), until at least one oom request has been delivered. +void JfrRecorderService::emit_leakprofiler_events_paths_to_gc_roots(int64_t cutoff_ticks, + bool emit_all, + bool skip_bfs, + bool oom, + JavaThread* jt) { + assert(jt != nullptr, "invariant"); + DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt);) + assert(!exclude_paths_to_gc_roots(cutoff_ticks), "invariant"); + + { + JfrRotationLock lock; + // Take the rotation lock to read and post a request for the JFR Recorder Thread. + if (_oom_emit_request_posted) { + if (!oom) { + // A request to emit leakprofiler events in response to CrashOnOutOfMemoryError + // is pending or has already been completed. We are about to crash at any time now. + assert(CrashOnOutOfMemoryError, "invariant"); + return; + } + } else { + assert(!_oom_emit_request_posted, "invariant"); + JfrLeakProfilerEmitRequest request = { cutoff_ticks, emit_all, skip_bfs, oom }; + enqueue(request); + } + } + JfrRecorderService service; + service.transition_and_post_leakprofiler_emit_msg(jt); +} + +// Leakprofiler serialization request, the jdk.jfr.internal.JVM.emitOldObjectSamples() Java entry point. +void JfrRecorderService::emit_leakprofiler_events(int64_t cutoff_ticks, + bool emit_all, + bool skip_bfs) { + JavaThread* const jt = JavaThread::current(); + DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt);) + if (exclude_paths_to_gc_roots(cutoff_ticks)) { + ::emit_leakprofiler_events(emit_all, skip_bfs, jt); + return; + } + emit_leakprofiler_events_paths_to_gc_roots(cutoff_ticks, emit_all, skip_bfs, /* oom */ false, jt); +} + +// Leakprofiler serialization request, the report_on_java_out_of_memory VM entry point. +void JfrRecorderService::emit_leakprofiler_events_on_oom() { + assert(CrashOnOutOfMemoryError, "invariant"); + if (EventOldObjectSample::is_enabled()) { + JavaThread* const jt = JavaThread::current(); + DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt);) + ThreadToNativeFromVM transition(jt); + emit_leakprofiler_events_paths_to_gc_roots(max_jlong, false, false, /* oom */ true, jt); + } +} + +// The worker routine for the JFR Recorder Thread when processing MSG_EMIT_LEAKP_REFCHAINS messages. +void JfrRecorderService::emit_leakprofiler_events() { + JavaThread* const jt = JavaThread::current(); + DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt)); // Take the rotation lock before the transition. - JavaThread* current_thread = JavaThread::current(); - MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current_thread)); - ThreadInVMfromNative transition(current_thread); - LeakProfiler::emit_events(cutoff_ticks, emit_all, skip_bfs); + JfrRotationLock lock; + if (_oom_emit_request_delivered) { + // A request to emit leakprofiler events in response to CrashOnOutOfMemoryError + // has already been completed. We are about to crash at any time now. + assert(_oom_emit_request_posted, "invariant"); + assert(CrashOnOutOfMemoryError, "invariant"); + return; + } + + assert(_queue->is_nonempty(), "invariant"); + + { + MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, jt)); + ThreadInVMfromNative transition(jt); + while (_queue->is_nonempty()) { + const JfrLeakProfilerEmitRequest& request = dequeue(); + LeakProfiler::emit_events(request.cutoff_ticks, request.emit_all, request.skip_bfs); + if (_oom_emit_request_posted && request.oom) { + assert(CrashOnOutOfMemoryError, "invariant"); + _oom_emit_request_delivered = true; + break; + } + } + } + + // If processing involved an out-of-memory request, issue an immediate flush operation. + DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt)); + if (_chunkwriter.is_valid() && _oom_emit_request_delivered) { + invoke_flush(); + } } diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.hpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.hpp index e5b4500afc0..3759ff98828 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.hpp +++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,19 +27,23 @@ #include "jfr/utilities/jfrAllocation.hpp" +class JavaThread; class JfrCheckpointManager; class JfrChunkWriter; +class JfrPostBox; class JfrRepository; class JfrStackTraceRepository; class JfrStorage; class JfrStringPool; class JfrRecorderService : public StackObj { + friend class Jfr; friend class JfrSafepointClearVMOperation; friend class JfrSafepointWriteVMOperation; private: JfrCheckpointManager& _checkpoint_manager; JfrChunkWriter& _chunkwriter; + JfrPostBox& _post_box; JfrRepository& _repository; JfrStackTraceRepository& _stack_trace_repository; JfrStorage& _storage; @@ -64,6 +68,14 @@ class JfrRecorderService : public StackObj { void invoke_safepoint_write(); void post_safepoint_write(); + void transition_and_post_leakprofiler_emit_msg(JavaThread* jt); + + static void emit_leakprofiler_events_on_oom(); + static void emit_leakprofiler_events_paths_to_gc_roots(int64_t cutoff_ticks, + bool emit_all, + bool skip_bfs, + bool oom, + JavaThread* jt); public: JfrRecorderService(); void start(); @@ -72,8 +84,12 @@ class JfrRecorderService : public StackObj { void flushpoint(); void process_full_buffers(); void evaluate_chunk_size_for_rotation(); - void emit_leakprofiler_events(int64_t cutoff_ticks, bool emit_all, bool skip_bfs); + void emit_leakprofiler_events(); + static bool is_recording(); + static void emit_leakprofiler_events(int64_t cutoff_ticks, + bool emit_all, + bool skip_bfs); }; #endif // SHARE_JFR_RECORDER_SERVICE_JFRRECORDERSERVICE_HPP diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderThreadLoop.cpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderThreadLoop.cpp index 8aeb745b35e..c63cb37e367 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrRecorderThreadLoop.cpp +++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderThreadLoop.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,6 +45,7 @@ void recorderthread_entry(JavaThread* thread, JavaThread* unused) { #define ROTATE (msgs & (MSGBIT(MSG_ROTATE)|MSGBIT(MSG_STOP))) #define FLUSHPOINT (msgs & (MSGBIT(MSG_FLUSHPOINT))) #define PROCESS_FULL_BUFFERS (msgs & (MSGBIT(MSG_ROTATE)|MSGBIT(MSG_STOP)|MSGBIT(MSG_FULLBUFFER))) + #define LEAKPROFILER_REFCHAINS (msgs & MSGBIT(MSG_EMIT_LEAKP_REFCHAINS)) JfrPostBox& post_box = JfrRecorderThreadEntry::post_box(); log_debug(jfr, system)("Recorder thread STARTED"); @@ -71,6 +72,9 @@ void recorderthread_entry(JavaThread* thread, JavaThread* unused) { if (PROCESS_FULL_BUFFERS) { service.process_full_buffers(); } + if (LEAKPROFILER_REFCHAINS) { + service.emit_leakprofiler_events(); + } // Check amount of data written to chunk already // if it warrants asking for a new chunk. service.evaluate_chunk_size_for_rotation(); @@ -99,5 +103,5 @@ void recorderthread_entry(JavaThread* thread, JavaThread* unused) { #undef ROTATE #undef FLUSHPOINT #undef PROCESS_FULL_BUFFERS - #undef SCAVENGE + #undef LEAKPROFILER_REFCHAINS } diff --git a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp index 291169b9aa7..037faee1b9f 100644 --- a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp +++ b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp @@ -656,7 +656,7 @@ JfrCPUTimeTraceQueue& JfrThreadLocal::cpu_time_jfr_queue() { } void JfrThreadLocal::deallocate_cpu_time_jfr_queue() { - cpu_time_jfr_queue().resize(0); + cpu_time_jfr_queue().set_capacity(0); } void JfrThreadLocal::set_do_async_processing_of_cpu_time_jfr_requests(bool wants) { diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index d45036ced94..22ced5a4411 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -27,6 +27,7 @@ #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmClasses.hpp" +#include "code/nmethod.hpp" #include "code/scopeDesc.hpp" #include "compiler/compileBroker.hpp" #include "compiler/compilerEvent.hpp" @@ -1206,7 +1207,7 @@ C2V_VMENTRY_0(jint, installCode0, (JNIEnv *env, jobject, assert(JVMCIENV->isa_HotSpotNmethod(installed_code_handle), "wrong type"); // Clear the link to an old nmethod first JVMCIObject nmethod_mirror = installed_code_handle; - JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, true, JVMCI_CHECK_0); + JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, true, nmethod::InvalidationReason::JVMCI_REPLACED_WITH_NEW_CODE, JVMCI_CHECK_0); } else { assert(JVMCIENV->isa_InstalledCode(installed_code_handle), "wrong type"); } @@ -1217,6 +1218,14 @@ C2V_VMENTRY_0(jint, installCode0, (JNIEnv *env, jobject, return result; C2V_END +C2V_VMENTRY_0(jobject, getInvalidationReasonDescription, (JNIEnv *env, jobject, jint invalidation_reason)) + HandleMark hm(THREAD); + JNIHandleMark jni_hm(thread); + nmethod::InvalidationReason reason = static_cast(invalidation_reason); + JVMCIObject desc = JVMCIENV->create_string(nmethod::invalidation_reason_to_string(reason), JVMCI_CHECK_NULL); + return JVMCIENV->get_jobject(desc); +C2V_END + C2V_VMENTRY(void, resetCompilationStatistics, (JNIEnv* env, jobject)) JVMCICompiler* compiler = JVMCICompiler::instance(true, CHECK); CompilerStatistics* stats = compiler->stats(); @@ -1382,7 +1391,7 @@ C2V_VMENTRY(void, reprofile, (JNIEnv* env, jobject, ARGUMENT_PAIR(method))) nmethod* code = method->code(); if (code != nullptr) { - code->make_not_entrant("JVMCI reprofile"); + code->make_not_entrant(nmethod::InvalidationReason::JVMCI_REPROFILE); } MethodData* method_data = method->method_data(); @@ -1395,9 +1404,14 @@ C2V_VMENTRY(void, reprofile, (JNIEnv* env, jobject, ARGUMENT_PAIR(method))) C2V_END -C2V_VMENTRY(void, invalidateHotSpotNmethod, (JNIEnv* env, jobject, jobject hs_nmethod, jboolean deoptimize)) +C2V_VMENTRY(void, invalidateHotSpotNmethod, (JNIEnv* env, jobject, jobject hs_nmethod, jboolean deoptimize, jint invalidation_reason)) + int first = static_cast(nmethod::InvalidationReason::C1_CODEPATCH); + int last = static_cast(nmethod::InvalidationReason::INVALIDATION_REASONS_COUNT); + if (invalidation_reason < first || invalidation_reason >= last) { + JVMCI_THROW_MSG(IllegalArgumentException, err_msg("Invalid invalidation_reason: %d", invalidation_reason)); + } JVMCIObject nmethod_mirror = JVMCIENV->wrap(hs_nmethod); - JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, deoptimize, JVMCI_CHECK); + JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, deoptimize, static_cast(invalidation_reason), JVMCI_CHECK); C2V_END C2V_VMENTRY_NULL(jlongArray, collectCounters, (JNIEnv* env, jobject)) @@ -1822,7 +1836,7 @@ C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv* env, jobject, jobject _hs_ if (!fst.current()->is_compiled_frame()) { JVMCI_THROW_MSG(IllegalStateException, "compiled stack frame expected"); } - fst.current()->cb()->as_nmethod()->make_not_entrant("JVMCI materialize virtual objects"); + fst.current()->cb()->as_nmethod()->make_not_entrant(nmethod::InvalidationReason::JVMCI_MATERIALIZE_VIRTUAL_OBJECT); } Deoptimization::deoptimize(thread, *fst.current(), Deoptimization::Reason_none); // look for the frame again as it has been updated by deopt (pc, deopt state...) @@ -3351,6 +3365,7 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "getResolvedJavaType0", CC "(Ljava/lang/Object;JZ)" HS_KLASS, FN_PTR(getResolvedJavaType0)}, {CC "readConfiguration", CC "()[" OBJECT, FN_PTR(readConfiguration)}, {CC "installCode0", CC "(JJZ" HS_COMPILED_CODE "[" OBJECT INSTALLED_CODE "J[B)I", FN_PTR(installCode0)}, + {CC "getInvalidationReasonDescription", CC "(I)" STRING, FN_PTR(getInvalidationReasonDescription)}, {CC "getInstallCodeFlags", CC "()I", FN_PTR(getInstallCodeFlags)}, {CC "resetCompilationStatistics", CC "()V", FN_PTR(resetCompilationStatistics)}, {CC "disassembleCodeBlob", CC "(" INSTALLED_CODE ")" STRING, FN_PTR(disassembleCodeBlob)}, @@ -3359,7 +3374,7 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "getLocalVariableTableStart", CC "(" HS_METHOD2 ")J", FN_PTR(getLocalVariableTableStart)}, {CC "getLocalVariableTableLength", CC "(" HS_METHOD2 ")I", FN_PTR(getLocalVariableTableLength)}, {CC "reprofile", CC "(" HS_METHOD2 ")V", FN_PTR(reprofile)}, - {CC "invalidateHotSpotNmethod", CC "(" HS_NMETHOD "Z)V", FN_PTR(invalidateHotSpotNmethod)}, + {CC "invalidateHotSpotNmethod", CC "(" HS_NMETHOD "ZI)V", FN_PTR(invalidateHotSpotNmethod)}, {CC "collectCounters", CC "()[J", FN_PTR(collectCounters)}, {CC "getCountersSize", CC "()I", FN_PTR(getCountersSize)}, {CC "setCountersSize", CC "(I)Z", FN_PTR(setCountersSize)}, diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp index b8474552256..fd2b1dbd6b6 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.cpp +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp @@ -1750,7 +1750,7 @@ void JVMCIEnv::initialize_installed_code(JVMCIObject installed_code, CodeBlob* c } -void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, JVMCI_TRAPS) { +void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, nmethod::InvalidationReason invalidation_reason, JVMCI_TRAPS) { if (mirror.is_null()) { JVMCI_THROW(NullPointerException); } @@ -1773,7 +1773,7 @@ void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, JV if (!deoptimize) { // Prevent future executions of the nmethod but let current executions complete. - nm->make_not_entrant("JVMCI invalidate nmethod mirror"); + nm->make_not_entrant(invalidation_reason); // Do not clear the address field here as the Java code may still // want to later call this method with deoptimize == true. That requires @@ -1782,7 +1782,7 @@ void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, JV // Deoptimize the nmethod immediately. DeoptimizationScope deopt_scope; deopt_scope.mark(nm); - nm->make_not_entrant("JVMCI invalidate nmethod mirror"); + nm->make_not_entrant(invalidation_reason); nm->make_deoptimized(); deopt_scope.deoptimize_marked(); diff --git a/src/hotspot/share/jvmci/jvmciEnv.hpp b/src/hotspot/share/jvmci/jvmciEnv.hpp index 69f6647b0d6..b49bba88b6b 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.hpp +++ b/src/hotspot/share/jvmci/jvmciEnv.hpp @@ -462,7 +462,7 @@ class JVMCIEnv : public ResourceObj { // field of `mirror` to prevent it from being called. // If `deoptimize` is true, the nmethod is immediately deoptimized. // The HotSpotNmethod.address field is zero upon returning. - void invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimze, JVMCI_TRAPS); + void invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimze, nmethod::InvalidationReason invalidation_reason, JVMCI_TRAPS); void initialize_installed_code(JVMCIObject installed_code, CodeBlob* cb, JVMCI_TRAPS); diff --git a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp index d5fcd2aaaba..432fefe56d1 100644 --- a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp +++ b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp @@ -102,6 +102,7 @@ boolean_field(HotSpotNmethod, isDefault) \ long_field(HotSpotNmethod, compileIdSnapshot) \ object_field(HotSpotNmethod, method, "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;") \ + int_field(HotSpotNmethod, invalidationReason) \ jvmci_constructor(HotSpotNmethod, "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;Ljava/lang/String;ZJ)V") \ end_class \ start_class(HotSpotCompiledCode, jdk_vm_ci_hotspot_HotSpotCompiledCode) \ diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index bee5f4ea445..24ea4936822 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -797,7 +797,7 @@ void JVMCINMethodData::set_nmethod_mirror(nmethod* nm, oop new_mirror) { Universe::heap()->register_nmethod(nm); } -void JVMCINMethodData::invalidate_nmethod_mirror(nmethod* nm) { +void JVMCINMethodData::invalidate_nmethod_mirror(nmethod* nm, nmethod::InvalidationReason invalidation_reason) { oop nmethod_mirror = get_nmethod_mirror(nm); if (nmethod_mirror == nullptr) { return; @@ -816,12 +816,20 @@ void JVMCINMethodData::invalidate_nmethod_mirror(nmethod* nm) { HotSpotJVMCI::InstalledCode::set_address(jvmciEnv, nmethod_mirror, 0); HotSpotJVMCI::InstalledCode::set_entryPoint(jvmciEnv, nmethod_mirror, 0); HotSpotJVMCI::HotSpotInstalledCode::set_codeStart(jvmciEnv, nmethod_mirror, 0); + if (HotSpotJVMCI::HotSpotNmethod::invalidationReason(jvmciEnv, nmethod_mirror) == + static_cast(nmethod::InvalidationReason::NOT_INVALIDATED)) { + HotSpotJVMCI::HotSpotNmethod::set_invalidationReason(jvmciEnv, nmethod_mirror, static_cast(invalidation_reason)); + } } else if (nm->is_not_entrant()) { // Zero the entry point so any new invocation will fail but keep // the address link around that so that existing activations can // be deoptimized via the mirror (i.e. JVMCIEnv::invalidate_installed_code). HotSpotJVMCI::InstalledCode::set_entryPoint(jvmciEnv, nmethod_mirror, 0); HotSpotJVMCI::HotSpotInstalledCode::set_codeStart(jvmciEnv, nmethod_mirror, 0); + if (HotSpotJVMCI::HotSpotNmethod::invalidationReason(jvmciEnv, nmethod_mirror) == + static_cast(nmethod::InvalidationReason::NOT_INVALIDATED)) { + HotSpotJVMCI::HotSpotNmethod::set_invalidationReason(jvmciEnv, nmethod_mirror, static_cast(invalidation_reason)); + } } } @@ -2184,7 +2192,7 @@ JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV, tty->print_cr("Replacing method %s", method_name); } if (old != nullptr) { - old->make_not_entrant("JVMCI register method"); + old->make_not_entrant(nmethod::InvalidationReason::JVMCI_REPLACED_WITH_NEW_CODE); } LogTarget(Info, nmethod, install) lt; diff --git a/src/hotspot/share/jvmci/jvmciRuntime.hpp b/src/hotspot/share/jvmci/jvmciRuntime.hpp index b49e09a1884..95c7d32f928 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.hpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp @@ -121,7 +121,7 @@ class JVMCINMethodData : public ResourceObj { // Clears the HotSpotNmethod.address field in the mirror. If nm // is dead, the HotSpotNmethod.entryPoint field is also cleared. - void invalidate_nmethod_mirror(nmethod* nm); + void invalidate_nmethod_mirror(nmethod* nm, nmethod::InvalidationReason invalidation_reason); // Gets the mirror from nm's oops table. oop get_nmethod_mirror(nmethod* nm); diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index e26c815946d..eb2843008fd 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -564,7 +564,30 @@ declare_constant_with_value("LockStack::_end_offset", LockStack::end_offset()) \ declare_constant_with_value("OMCache::oop_to_oop_difference", OMCache::oop_to_oop_difference()) \ declare_constant_with_value("OMCache::oop_to_monitor_difference", OMCache::oop_to_monitor_difference()) \ - \ + \ + declare_constant(nmethod::InvalidationReason::NOT_INVALIDATED) \ + declare_constant(nmethod::InvalidationReason::C1_CODEPATCH) \ + declare_constant(nmethod::InvalidationReason::C1_DEOPTIMIZE) \ + declare_constant(nmethod::InvalidationReason::C1_DEOPTIMIZE_FOR_PATCHING) \ + declare_constant(nmethod::InvalidationReason::C1_PREDICATE_FAILED_TRAP) \ + declare_constant(nmethod::InvalidationReason::CI_REPLAY) \ + declare_constant(nmethod::InvalidationReason::UNLOADING) \ + declare_constant(nmethod::InvalidationReason::UNLOADING_COLD) \ + declare_constant(nmethod::InvalidationReason::JVMCI_INVALIDATE) \ + declare_constant(nmethod::InvalidationReason::JVMCI_MATERIALIZE_VIRTUAL_OBJECT) \ + declare_constant(nmethod::InvalidationReason::JVMCI_REPLACED_WITH_NEW_CODE) \ + declare_constant(nmethod::InvalidationReason::JVMCI_REPROFILE) \ + declare_constant(nmethod::InvalidationReason::MARKED_FOR_DEOPTIMIZATION) \ + declare_constant(nmethod::InvalidationReason::MISSING_EXCEPTION_HANDLER) \ + declare_constant(nmethod::InvalidationReason::NOT_USED) \ + declare_constant(nmethod::InvalidationReason::OSR_INVALIDATION_BACK_BRANCH) \ + declare_constant(nmethod::InvalidationReason::OSR_INVALIDATION_FOR_COMPILING_WITH_C1) \ + declare_constant(nmethod::InvalidationReason::OSR_INVALIDATION_OF_LOWER_LEVEL) \ + declare_constant(nmethod::InvalidationReason::SET_NATIVE_FUNCTION) \ + declare_constant(nmethod::InvalidationReason::UNCOMMON_TRAP) \ + declare_constant(nmethod::InvalidationReason::WHITEBOX_DEOPTIMIZATION) \ + declare_constant(nmethod::InvalidationReason::ZOMBIE) \ + \ declare_constant(CodeInstaller::VERIFIED_ENTRY) \ declare_constant(CodeInstaller::UNVERIFIED_ENTRY) \ declare_constant(CodeInstaller::OSR_ENTRY) \ @@ -809,7 +832,6 @@ \ AARCH64_ONLY(declare_constant(NMethodPatchingType::stw_instruction_and_data_patch)) \ AARCH64_ONLY(declare_constant(NMethodPatchingType::conc_instruction_and_data_patch)) \ - AARCH64_ONLY(declare_constant(NMethodPatchingType::conc_data_patch)) \ \ declare_constant(ObjectMonitor::NO_OWNER) \ declare_constant(ObjectMonitor::ANONYMOUS_OWNER) \ diff --git a/src/hotspot/share/logging/logAsyncWriter.cpp b/src/hotspot/share/logging/logAsyncWriter.cpp index cfb6a991c4c..d184827f582 100644 --- a/src/hotspot/share/logging/logAsyncWriter.cpp +++ b/src/hotspot/share/logging/logAsyncWriter.cpp @@ -318,13 +318,13 @@ void AsyncLogWriter::initialize() { AsyncLogWriter* self = new AsyncLogWriter(); if (self->_initialized) { - Atomic::release_store_fence(&AsyncLogWriter::_instance, self); - // All readers of _instance after the fence see non-null. // We use LogOutputList's RCU counters to ensure all synchronous logsites have completed. - // After that, we start AsyncLog Thread and it exclusively takes over all logging I/O. + // After that, we publish the initalized _instance to readers. + // Then we start the AsyncLog Thread and it exclusively takes over all logging I/O. for (LogTagSet* ts = LogTagSet::first(); ts != nullptr; ts = ts->next()) { ts->wait_until_no_readers(); } + Atomic::release_store_fence(&AsyncLogWriter::_instance, self); os::start_thread(self); log_debug(logging, thread)("Async logging thread started."); } else { diff --git a/src/hotspot/share/memory/allocation.cpp b/src/hotspot/share/memory/allocation.cpp index 0d99c1bea68..9941fdb0cfc 100644 --- a/src/hotspot/share/memory/allocation.cpp +++ b/src/hotspot/share/memory/allocation.cpp @@ -74,7 +74,7 @@ void* MetaspaceObj::operator new(size_t size, ClassLoaderData* loader_data, MetaspaceObj::Type type, TRAPS) throw() { // Klass has its own operator new assert(type != ClassType, "class has its own operator new"); - return Metaspace::allocate(loader_data, word_size, type, /*use_class_space*/ false, THREAD); + return Metaspace::allocate(loader_data, word_size, type, THREAD); } void* MetaspaceObj::operator new(size_t size, ClassLoaderData* loader_data, @@ -82,7 +82,7 @@ void* MetaspaceObj::operator new(size_t size, ClassLoaderData* loader_data, MetaspaceObj::Type type) throw() { assert(!Thread::current()->is_Java_thread(), "only allowed by non-Java thread"); assert(type != ClassType, "class has its own operator new"); - return Metaspace::allocate(loader_data, word_size, type, /*use_class_space*/ false); + return Metaspace::allocate(loader_data, word_size, type); } // This is used for allocating training data. We are allocating training data in many cases where a GC cannot be triggered. diff --git a/src/hotspot/share/memory/guardedMemory.hpp b/src/hotspot/share/memory/guardedMemory.hpp index a3bbf48b0cd..2b6d34e8e0a 100644 --- a/src/hotspot/share/memory/guardedMemory.hpp +++ b/src/hotspot/share/memory/guardedMemory.hpp @@ -42,9 +42,10 @@ * |Offset | Content | Description | * |------------------------------------------------------------ * |base_addr | 0xABABABABABABABAB | Head guard | - * |+16 | | User data size | - * |+sizeof(uintptr_t) | | Tag word | - * |+sizeof(uintptr_t) | | Tag word | + * |+GUARD_SIZE | | User data size | + * |+sizeof(size_t) | | Tag word | + * |+sizeof(void*) | | Tag word | + * |+sizeof(void*) | | Padding | * |+sizeof(void*) | 0xF1 ( | User data | * |+user_size | 0xABABABABABABABAB | Tail guard | * ------------------------------------------------------------- @@ -52,6 +53,8 @@ * Where: * - guard padding uses "badResourceValue" (0xAB) * - tag word and tag2 word are general purpose + * - padding is inserted as-needed by the compiler to ensure + * the user data is aligned on a 16-byte boundary * - user data * -- initially padded with "uninitBlockPad" (0xF1), * -- to "freeBlockPad" (0xBA), when freed @@ -132,12 +135,15 @@ class GuardedMemory : StackObj { // Wrapper on stack /** * Header guard and size + * + * NB: the size and placement of the GuardHeader must be such that the + * user-ptr is maximally aligned i.e. 16-byte alignment for x86 ABI for + * stack alignment and use of vector (xmm) instructions. We use alignas + * to achieve this. */ - class GuardHeader : Guard { + class alignas(16) GuardHeader : Guard { friend class GuardedMemory; protected: - // Take care in modifying fields here, will effect alignment - // e.g. x86 ABI 16 byte stack alignment union { uintptr_t __unused_full_word1; size_t _user_size; diff --git a/src/hotspot/share/memory/memoryReserver.cpp b/src/hotspot/share/memory/memoryReserver.cpp index 457818139cd..9d091795a4d 100644 --- a/src/hotspot/share/memory/memoryReserver.cpp +++ b/src/hotspot/share/memory/memoryReserver.cpp @@ -113,12 +113,13 @@ static char* reserve_memory_inner(char* requested_address, ReservedSpace MemoryReserver::reserve_memory(char* requested_address, size_t size, size_t alignment, + size_t page_size, bool exec, MemTag mem_tag) { char* base = reserve_memory_inner(requested_address, size, alignment, exec, mem_tag); if (base != nullptr) { - return ReservedSpace(base, size, alignment, os::vm_page_size(), exec, false /* special */); + return ReservedSpace(base, size, alignment, page_size, exec, false /* special */); } // Failed @@ -191,7 +192,7 @@ ReservedSpace MemoryReserver::reserve(char* requested_address, } // == Case 3 == - return reserve_memory(requested_address, size, alignment, executable, mem_tag); + return reserve_memory(requested_address, size, alignment, page_size, executable, mem_tag); } ReservedSpace MemoryReserver::reserve(char* requested_address, diff --git a/src/hotspot/share/memory/memoryReserver.hpp b/src/hotspot/share/memory/memoryReserver.hpp index f8f642cca95..fd052e5e283 100644 --- a/src/hotspot/share/memory/memoryReserver.hpp +++ b/src/hotspot/share/memory/memoryReserver.hpp @@ -34,6 +34,7 @@ class MemoryReserver : AllStatic { static ReservedSpace reserve_memory(char* requested_address, size_t size, size_t alignment, + size_t page_size, bool exec, MemTag mem_tag); diff --git a/src/hotspot/share/memory/metaspace.cpp b/src/hotspot/share/memory/metaspace.cpp index 7eca79142a6..3b2fb23677d 100644 --- a/src/hotspot/share/memory/metaspace.cpp +++ b/src/hotspot/share/memory/metaspace.cpp @@ -868,7 +868,7 @@ size_t Metaspace::max_allocation_word_size() { // is suitable for calling from non-Java threads. // Callers are responsible for checking null. MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size, - MetaspaceObj::Type type, bool use_class_space) { + MetaspaceObj::Type type) { assert(word_size <= Metaspace::max_allocation_word_size(), "allocation size too large (%zu)", word_size); @@ -878,7 +878,7 @@ MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size, // Deal with concurrent unloading failed allocation starvation MetaspaceCriticalAllocation::block_if_concurrent_purge(); - MetadataType mdtype = use_class_space ? ClassType : NonClassType; + MetadataType mdtype = (type == MetaspaceObj::ClassType) ? ClassType : NonClassType; // Try to allocate metadata. MetaWord* result = loader_data->metaspace_non_null()->allocate(word_size, mdtype); @@ -902,7 +902,7 @@ MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size, } MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size, - MetaspaceObj::Type type, bool use_class_space, TRAPS) { + MetaspaceObj::Type type, TRAPS) { if (HAS_PENDING_EXCEPTION) { assert(false, "Should not allocate with exception pending"); @@ -910,10 +910,10 @@ MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size, } assert(!THREAD->owns_locks(), "allocating metaspace while holding mutex"); - MetaWord* result = allocate(loader_data, word_size, type, use_class_space); + MetaWord* result = allocate(loader_data, word_size, type); if (result == nullptr) { - MetadataType mdtype = use_class_space ? ClassType : NonClassType; + MetadataType mdtype = (type == MetaspaceObj::ClassType) ? ClassType : NonClassType; tracer()->report_metaspace_allocation_failure(loader_data, word_size, type, mdtype); // Allocation failed. diff --git a/src/hotspot/share/memory/metaspace.hpp b/src/hotspot/share/memory/metaspace.hpp index 293782c0d75..86a89777cd4 100644 --- a/src/hotspot/share/memory/metaspace.hpp +++ b/src/hotspot/share/memory/metaspace.hpp @@ -120,12 +120,12 @@ class Metaspace : public AllStatic { static constexpr size_t min_allocation_word_size = min_allocation_alignment_words; static MetaWord* allocate(ClassLoaderData* loader_data, size_t word_size, - MetaspaceObj::Type type, bool use_class_space, TRAPS); + MetaspaceObj::Type type, TRAPS); // Non-TRAPS version of allocate which can be called by a non-Java thread, that returns // null on failure. static MetaWord* allocate(ClassLoaderData* loader_data, size_t word_size, - MetaspaceObj::Type type, bool use_class_space); + MetaspaceObj::Type type); // Returns true if the pointer points into class space, non-class metaspace, or the // metadata portion of the CDS archive. diff --git a/src/hotspot/share/nmt/mallocHeader.inline.hpp b/src/hotspot/share/nmt/mallocHeader.inline.hpp index 34ec891d33f..8b1862332fc 100644 --- a/src/hotspot/share/nmt/mallocHeader.inline.hpp +++ b/src/hotspot/share/nmt/mallocHeader.inline.hpp @@ -104,7 +104,7 @@ inline OutTypeParam MallocHeader::resolve_checked_impl(InTypeParam memblock) { OutTypeParam header_pointer = (OutTypeParam)memblock - 1; if (!header_pointer->check_block_integrity(msg, sizeof(msg), &corruption)) { header_pointer->print_block_on_error(tty, corruption != nullptr ? corruption : (address)header_pointer); - fatal("NMT corruption: Block at " PTR_FORMAT ": %s", p2i(memblock), msg); + fatal("NMT has detected a memory corruption bug. Block at " PTR_FORMAT ": %s", p2i(memblock), msg); } return header_pointer; } diff --git a/src/hotspot/share/nmt/mallocTracker.cpp b/src/hotspot/share/nmt/mallocTracker.cpp index 6a2da5f79cd..d919f3ce873 100644 --- a/src/hotspot/share/nmt/mallocTracker.cpp +++ b/src/hotspot/share/nmt/mallocTracker.cpp @@ -207,6 +207,12 @@ void* MallocTracker::record_free_block(void* memblock) { deaccount(header->free_info()); + if (ZapCHeap) { + // To do this zapping, we need to know the block size. + // This is why we have to do it here, and not in os::free. + memset(memblock, freeBlockPad, header->size()); + } + header->mark_block_as_dead(); return (void*)header; diff --git a/src/hotspot/share/oops/array.inline.hpp b/src/hotspot/share/oops/array.inline.hpp index 3fa7fd15fb3..30cf2e38f77 100644 --- a/src/hotspot/share/oops/array.inline.hpp +++ b/src/hotspot/share/oops/array.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * 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,14 +34,14 @@ template inline void* Array::operator new(size_t size, ClassLoaderData* loader_data, int length, TRAPS) throw() { size_t word_size = Array::size(length); return (void*) Metaspace::allocate(loader_data, word_size, - MetaspaceObj::array_type(sizeof(T)), false, THREAD); + MetaspaceObj::array_type(sizeof(T)), THREAD); } template inline void* Array::operator new(size_t size, ClassLoaderData* loader_data, int length) throw() { size_t word_size = Array::size(length); return (void*) Metaspace::allocate(loader_data, word_size, - MetaspaceObj::array_type(sizeof(T)), false); + MetaspaceObj::array_type(sizeof(T))); } template diff --git a/src/hotspot/share/oops/arrayKlass.cpp b/src/hotspot/share/oops/arrayKlass.cpp index 5f6f6ac674d..fcc683cac8b 100644 --- a/src/hotspot/share/oops/arrayKlass.cpp +++ b/src/hotspot/share/oops/arrayKlass.cpp @@ -41,10 +41,6 @@ #include "oops/oop.inline.hpp" #include "runtime/handles.inline.hpp" -void* ArrayKlass::operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, TRAPS) throw() { - return Metaspace::allocate(loader_data, word_size, MetaspaceObj::ClassType, true, THREAD); -} - ArrayKlass::ArrayKlass() { assert(CDSConfig::is_dumping_static_archive() || CDSConfig::is_using_archive(), "only for CDS"); } diff --git a/src/hotspot/share/oops/arrayKlass.hpp b/src/hotspot/share/oops/arrayKlass.hpp index 5bfe46573d3..02d72c3cde8 100644 --- a/src/hotspot/share/oops/arrayKlass.hpp +++ b/src/hotspot/share/oops/arrayKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, 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 @@ -49,8 +49,6 @@ class ArrayKlass: public Klass { ArrayKlass(Symbol* name, KlassKind kind); ArrayKlass(); - void* operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, TRAPS) throw(); - public: // Testing operation DEBUG_ONLY(bool is_array_klass_slow() const { return true; }) diff --git a/src/hotspot/share/oops/cpCache.inline.hpp b/src/hotspot/share/oops/cpCache.inline.hpp index 791f0a1f5ce..8dec47a3c73 100644 --- a/src/hotspot/share/oops/cpCache.inline.hpp +++ b/src/hotspot/share/oops/cpCache.inline.hpp @@ -73,6 +73,9 @@ inline ResolvedIndyEntry* ConstantPoolCache::resolved_indy_entry_at(int index) c } inline int ConstantPoolCache::resolved_indy_entries_length() const { + if (_resolved_indy_entries == nullptr) { + return 0; + } return _resolved_indy_entries->length(); } #endif // SHARE_OOPS_CPCACHE_INLINE_HPP diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index 7f617b98c1a..dd15294c3cf 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -312,12 +312,11 @@ InstanceKlass* InstanceKlass::nest_host(TRAPS) { ss.print("Nest host resolution of %s with host %s failed: ", this->external_name(), target_host_class); java_lang_Throwable::print(PENDING_EXCEPTION, &ss); - const char* msg = ss.as_string(true /* on C-heap */); constantPoolHandle cph(THREAD, constants()); - SystemDictionary::add_nest_host_error(cph, _nest_host_index, msg); + SystemDictionary::add_nest_host_error(cph, _nest_host_index, ss); CLEAR_PENDING_EXCEPTION; - log_trace(class, nestmates)("%s", msg); + log_trace(class, nestmates)("%s", ss.base()); } else { // A valid nest-host is an instance class in the current package that lists this // class as a nest member. If any of these conditions are not met the class is @@ -356,10 +355,9 @@ InstanceKlass* InstanceKlass::nest_host(TRAPS) { k->external_name(), k->class_loader_data()->loader_name_and_id(), error); - const char* msg = ss.as_string(true /* on C-heap */); constantPoolHandle cph(THREAD, constants()); - SystemDictionary::add_nest_host_error(cph, _nest_host_index, msg); - log_trace(class, nestmates)("%s", msg); + SystemDictionary::add_nest_host_error(cph, _nest_host_index, ss); + log_trace(class, nestmates)("%s", ss.base()); } } } else { @@ -455,11 +453,6 @@ const char* InstanceKlass::nest_host_error() { } } -void* InstanceKlass::operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, - bool use_class_space, TRAPS) throw() { - return Metaspace::allocate(loader_data, word_size, ClassType, use_class_space, THREAD); -} - InstanceKlass* InstanceKlass::allocate_instance_klass(const ClassFileParser& parser, TRAPS) { const int size = InstanceKlass::size(parser.vtable_size(), parser.itable_size(), @@ -472,27 +465,26 @@ InstanceKlass* InstanceKlass::allocate_instance_klass(const ClassFileParser& par assert(loader_data != nullptr, "invariant"); InstanceKlass* ik; - const bool use_class_space = parser.klass_needs_narrow_id(); // Allocation if (parser.is_instance_ref_klass()) { // java.lang.ref.Reference - ik = new (loader_data, size, use_class_space, THREAD) InstanceRefKlass(parser); + ik = new (loader_data, size, THREAD) InstanceRefKlass(parser); } else if (class_name == vmSymbols::java_lang_Class()) { // mirror - java.lang.Class - ik = new (loader_data, size, use_class_space, THREAD) InstanceMirrorKlass(parser); + ik = new (loader_data, size, THREAD) InstanceMirrorKlass(parser); } else if (is_stack_chunk_class(class_name, loader_data)) { // stack chunk - ik = new (loader_data, size, use_class_space, THREAD) InstanceStackChunkKlass(parser); + ik = new (loader_data, size, THREAD) InstanceStackChunkKlass(parser); } else if (is_class_loader(class_name, parser)) { // class loader - java.lang.ClassLoader - ik = new (loader_data, size, use_class_space, THREAD) InstanceClassLoaderKlass(parser); + ik = new (loader_data, size, THREAD) InstanceClassLoaderKlass(parser); } else { // normal - ik = new (loader_data, size, use_class_space, THREAD) InstanceKlass(parser); + ik = new (loader_data, size, THREAD) InstanceKlass(parser); } - if (ik != nullptr && UseCompressedClassPointers && use_class_space) { + if (ik != nullptr && UseCompressedClassPointers) { assert(CompressedKlassPointers::is_encodable(ik), "Klass " PTR_FORMAT "needs a narrow Klass ID, but is not encodable", p2i(ik)); } @@ -3501,7 +3493,7 @@ void InstanceKlass::add_osr_nmethod(nmethod* n) { for (int l = CompLevel_limited_profile; l < n->comp_level(); l++) { nmethod *inv = lookup_osr_nmethod(n->method(), n->osr_entry_bci(), l, true); if (inv != nullptr && inv->is_in_use()) { - inv->make_not_entrant("OSR invalidation of lower levels"); + inv->make_not_entrant(nmethod::InvalidationReason::OSR_INVALIDATION_OF_LOWER_LEVEL); } } } diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index 55ab0996a4a..e253691b3d4 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -143,8 +143,6 @@ class InstanceKlass: public Klass { protected: InstanceKlass(const ClassFileParser& parser, KlassKind kind = Kind, ReferenceType reference_type = REF_NONE); - void* operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, bool use_class_space, TRAPS) throw(); - public: InstanceKlass(); diff --git a/src/hotspot/share/oops/instanceMirrorKlass.hpp b/src/hotspot/share/oops/instanceMirrorKlass.hpp index 9783d416a1d..e9928647db9 100644 --- a/src/hotspot/share/oops/instanceMirrorKlass.hpp +++ b/src/hotspot/share/oops/instanceMirrorKlass.hpp @@ -52,6 +52,9 @@ class InstanceMirrorKlass: public InstanceKlass { InstanceMirrorKlass(const ClassFileParser& parser) : InstanceKlass(parser, Kind) {} + template + inline void do_metadata(oop obj, OopClosureType* closure); + public: InstanceMirrorKlass(); diff --git a/src/hotspot/share/oops/instanceMirrorKlass.inline.hpp b/src/hotspot/share/oops/instanceMirrorKlass.inline.hpp index 867a0580a12..eed87d2644b 100644 --- a/src/hotspot/share/oops/instanceMirrorKlass.inline.hpp +++ b/src/hotspot/share/oops/instanceMirrorKlass.inline.hpp @@ -46,38 +46,41 @@ void InstanceMirrorKlass::oop_oop_iterate_statics(oop obj, OopClosureType* closu } } +template +void InstanceMirrorKlass::do_metadata(oop obj, OopClosureType* closure) { + Klass* klass = java_lang_Class::as_Klass(obj); + if (klass != nullptr) { + if (klass->class_loader_data() == nullptr) { + // This is a mirror that belongs to a shared class that has not been loaded yet. + assert(klass->is_shared(), "Must be"); + } else if (klass->is_instance_klass() && klass->class_loader_data()->has_class_mirror_holder()) { + // A non-strong hidden class doesn't have its own class loader, + // so when handling the java mirror for the class we need to make sure its class + // loader data is claimed, this is done by calling do_cld explicitly. + // For non-strong hidden classes the call to do_cld is made when the class + // loader itself is handled. + Devirtualizer::do_cld(closure, klass->class_loader_data()); + } else { + Devirtualizer::do_klass(closure, klass); + } + } else { + // Java mirror -> Klass* "nullptr" backlink means either: + // 1. This is a Java mirror for a primitive class. We do not need to follow it, + // these mirrors are always strong roots. + // 2. This is a Java mirror for a newly allocated non-primitive class, and we + // somehow managed to reach the newly allocated Java mirror with not yet + // installed backlink. We cannot do anything here, this case would be handled + // separately by GC, e.g. by keeping the relevant metadata alive during the GC. + // Unfortunately, the existence of corner case (2) prevents us from asserting (1). + } +} + template void InstanceMirrorKlass::oop_oop_iterate(oop obj, OopClosureType* closure) { InstanceKlass::oop_oop_iterate(obj, closure); if (Devirtualizer::do_metadata(closure)) { - Klass* klass = java_lang_Class::as_Klass(obj); - // We'll get null for primitive mirrors. - if (klass != nullptr) { - if (klass->class_loader_data() == nullptr) { - // This is a mirror that belongs to a shared class that has not be loaded yet. - assert(klass->is_shared(), "must be"); - } else if (klass->is_instance_klass() && klass->class_loader_data()->has_class_mirror_holder()) { - // A non-strong hidden class doesn't have its own class loader, - // so when handling the java mirror for the class we need to make sure its class - // loader data is claimed, this is done by calling do_cld explicitly. - // For non-strong hidden classes the call to do_cld is made when the class - // loader itself is handled. - Devirtualizer::do_cld(closure, klass->class_loader_data()); - } else { - Devirtualizer::do_klass(closure, klass); - } - } else { - // We would like to assert here (as below) that if klass has been null, then - // this has been a mirror for a primitive type that we do not need to follow - // as they are always strong roots. - // However, we might get across a klass that just changed during CMS concurrent - // marking if allocation occurred in the old generation. - // This is benign here, as we keep alive all CLDs that were loaded during the - // CMS concurrent phase in the class loading, i.e. they will be iterated over - // and kept alive during remark. - // assert(java_lang_Class::is_primitive(obj), "Sanity check"); - } + do_metadata(obj, closure); } oop_oop_iterate_statics(obj, closure); @@ -121,11 +124,7 @@ void InstanceMirrorKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closu if (Devirtualizer::do_metadata(closure)) { if (mr.contains(obj)) { - Klass* klass = java_lang_Class::as_Klass(obj); - // We'll get null for primitive mirrors. - if (klass != nullptr) { - Devirtualizer::do_klass(closure, klass); - } + do_metadata(obj, closure); } } diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp index aa31f586aab..66e29384d86 100644 --- a/src/hotspot/share/oops/klass.cpp +++ b/src/hotspot/share/oops/klass.cpp @@ -279,18 +279,19 @@ static markWord make_prototype(const Klass* kls) { #ifdef _LP64 if (UseCompactObjectHeaders) { // With compact object headers, the narrow Klass ID is part of the mark word. - // We therfore seed the mark word with the narrow Klass ID. - // Note that only those Klass that can be instantiated have a narrow Klass ID. - // For those who don't, we leave the klass bits empty and assert if someone - // tries to use those. - const narrowKlass nk = CompressedKlassPointers::is_encodable(kls) ? - CompressedKlassPointers::encode(const_cast(kls)) : 0; + // We therefore seed the mark word with the narrow Klass ID. + precond(CompressedKlassPointers::is_encodable(kls)); + const narrowKlass nk = CompressedKlassPointers::encode(const_cast(kls)); prototype = prototype.set_narrow_klass(nk); } #endif return prototype; } +void* Klass::operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, TRAPS) throw() { + return Metaspace::allocate(loader_data, word_size, MetaspaceObj::ClassType, THREAD); +} + Klass::Klass() : _kind(UnknownKlassKind) { assert(CDSConfig::is_dumping_static_archive() || CDSConfig::is_using_archive(), "only for cds"); } @@ -1063,7 +1064,7 @@ void Klass::verify_on(outputStream* st) { // This can be expensive, but it is worth checking that this klass is actually // in the CLD graph but not in production. #ifdef ASSERT - if (UseCompressedClassPointers && needs_narrow_id()) { + if (UseCompressedClassPointers) { // Stricter checks for both correct alignment and placement CompressedKlassPointers::check_encodable(this); } else { diff --git a/src/hotspot/share/oops/klass.hpp b/src/hotspot/share/oops/klass.hpp index b92f7bb8d99..f32f9fe1185 100644 --- a/src/hotspot/share/oops/klass.hpp +++ b/src/hotspot/share/oops/klass.hpp @@ -208,6 +208,8 @@ class Klass : public Metadata { Klass(KlassKind kind); Klass(); + void* operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, TRAPS) throw(); + public: int kind() { return _kind; } @@ -785,10 +787,6 @@ class Klass : public Metadata { static bool is_valid(Klass* k); static void on_secondary_supers_verification_failure(Klass* super, Klass* sub, bool linear_result, bool table_result, const char* msg); - - // Returns true if this Klass needs to be addressable via narrow Klass ID. - inline bool needs_narrow_id() const; - }; #endif // SHARE_OOPS_KLASS_HPP diff --git a/src/hotspot/share/oops/klass.inline.hpp b/src/hotspot/share/oops/klass.inline.hpp index b37c5105f64..4ac50cbc180 100644 --- a/src/hotspot/share/oops/klass.inline.hpp +++ b/src/hotspot/share/oops/klass.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -175,13 +175,4 @@ inline bool Klass::search_secondary_supers(Klass *k) const { return result; } -// Returns true if this Klass needs to be addressable via narrow Klass ID. -inline bool Klass::needs_narrow_id() const { - // Classes that are never instantiated need no narrow Klass Id, since the - // only point of having a narrow id is to put it into an object header. Keeping - // never instantiated classes out of class space lessens the class space pressure. - // For more details, see JDK-8338526. - // Note: don't call this function before access flags are initialized. - return !is_abstract() && !is_interface(); -} #endif // SHARE_OOPS_KLASS_INLINE_HPP diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp index d13458dfa93..bb7a0576eec 100644 --- a/src/hotspot/share/oops/method.cpp +++ b/src/hotspot/share/oops/method.cpp @@ -1028,7 +1028,7 @@ void Method::set_native_function(address function, bool post_event_flag) { // If so, we have to make it not_entrant. nmethod* nm = code(); // Put it into local variable to guard against concurrent updates if (nm != nullptr) { - nm->make_not_entrant("set native function"); + nm->make_not_entrant(nmethod::InvalidationReason::SET_NATIVE_FUNCTION); } } diff --git a/src/hotspot/share/oops/trainingData.cpp b/src/hotspot/share/oops/trainingData.cpp index 2ae1ac18699..44ebf3d1ef3 100644 --- a/src/hotspot/share/oops/trainingData.cpp +++ b/src/hotspot/share/oops/trainingData.cpp @@ -316,7 +316,9 @@ void CompileTrainingData::notice_jit_observation(ciEnv* env, ciBaseObject* what) // This JIT task is (probably) requesting that ik be initialized, // so add him to my _init_deps list. TrainingDataLocker l; - add_init_dep(ktd); + if (l.can_add()) { + add_init_dep(ktd); + } } } } diff --git a/src/hotspot/share/oops/trainingData.hpp b/src/hotspot/share/oops/trainingData.hpp index 6acf19b4d5e..487ceae1f1b 100644 --- a/src/hotspot/share/oops/trainingData.hpp +++ b/src/hotspot/share/oops/trainingData.hpp @@ -96,16 +96,18 @@ class TrainingData : public Metadata { // TrainingDataLocker is used to guard read/write operations on non-MT-safe data structures. // It supports recursive locking and a read-only mode (in which case no locks are taken). - // It is also a part of the TD collection termination protocol (see the "spanshot" field). + // It is also a part of the TD collection termination protocol (see the "snapshot" field). class TrainingDataLocker { +#if INCLUDE_CDS static volatile bool _snapshot; // If true we're not allocating new training data +#endif static int _lock_mode; const bool _recursive; static void lock() { #if INCLUDE_CDS assert(_lock_mode != 0, "Forgot to call TrainingDataLocker::initialize()"); if (_lock_mode > 0) { - TrainingData_lock->lock(); + TrainingData_lock->lock_without_safepoint_check(); } #endif } @@ -150,6 +152,11 @@ class TrainingData : public Metadata { static void initialize() { #if INCLUDE_CDS _lock_mode = need_data() ? +1 : -1; // if -1, we go lock-free +#endif + } + static void assert_locked_or_snapshotted() { +#if INCLUDE_CDS + assert(safely_locked() || _snapshot, "use under TrainingDataLocker or after snapshot"); #endif } static void assert_locked() { @@ -338,20 +345,24 @@ class TrainingData : public Metadata { } int length() const { + TrainingDataLocker::assert_locked_or_snapshotted(); return (_deps_dyn != nullptr ? _deps_dyn->length() : _deps != nullptr ? _deps->length() : 0); } E* adr_at(int i) const { + TrainingDataLocker::assert_locked_or_snapshotted(); return (_deps_dyn != nullptr ? _deps_dyn->adr_at(i) : _deps != nullptr ? _deps->adr_at(i) : nullptr); } E at(int i) const { + TrainingDataLocker::assert_locked_or_snapshotted(); assert(i >= 0 && i < length(), "oob"); return *adr_at(i); } bool append_if_missing(E dep) { + TrainingDataLocker::assert_can_add(); if (_deps_dyn == nullptr) { _deps_dyn = new GrowableArrayCHeap(10); _deps_dyn->append(dep); @@ -361,23 +372,27 @@ class TrainingData : public Metadata { } } bool remove_if_existing(E dep) { + TrainingDataLocker::assert_can_add(); if (_deps_dyn != nullptr) { return _deps_dyn->remove_if_existing(dep); } return false; } void clear() { + TrainingDataLocker::assert_can_add(); if (_deps_dyn != nullptr) { _deps_dyn->clear(); } } void append(E dep) { + TrainingDataLocker::assert_can_add(); if (_deps_dyn == nullptr) { _deps_dyn = new GrowableArrayCHeap(10); } _deps_dyn->append(dep); } bool contains(E dep) { + TrainingDataLocker::assert_locked(); for (int i = 0; i < length(); i++) { if (dep == at(i)) { return true; // found @@ -593,6 +608,7 @@ class CompileTrainingData : public TrainingData { DepList _data; public: OptionalReturnType find(const Args&... args) { + TrainingDataLocker l; ArgumentsType a(args...); for (int i = 0; i < _data.length(); i++) { if (_data.at(i).arguments() == a) { @@ -601,8 +617,11 @@ class CompileTrainingData : public TrainingData { } return OptionalReturnType(false, ReturnType()); } - bool append_if_missing(const ReturnType& result, const Args&... args) { - return _data.append_if_missing(Record(result, ArgumentsType(args...))); + void append_if_missing(const ReturnType& result, const Args&... args) { + TrainingDataLocker l; + if (l.can_add()) { + _data.append_if_missing(Record(result, ArgumentsType(args...))); + } } #if INCLUDE_CDS void remove_unshareable_info() { _data.remove_unshareable_info(); } diff --git a/src/hotspot/share/opto/addnode.cpp b/src/hotspot/share/opto/addnode.cpp index 143398c57d0..4f8590082cd 100644 --- a/src/hotspot/share/opto/addnode.cpp +++ b/src/hotspot/share/opto/addnode.cpp @@ -1425,8 +1425,10 @@ static Node* fold_subI_no_underflow_pattern(Node* n, PhaseGVN* phase) { Node* x = add2->in(1); Node* con2 = add2->in(2); if (is_sub_con(con2)) { + // The graph could be dying (i.e. x is top) in which case type(x) is not a long. + const TypeLong* x_long = phase->type(x)->isa_long(); // Collapsed graph not equivalent if potential over/underflow -> bailing out (*) - if (can_overflow(phase->type(x)->is_long(), con1->get_long() + con2->get_long())) { + if (x_long == nullptr || can_overflow(x_long, con1->get_long() + con2->get_long())) { return nullptr; } Node* new_con = phase->transform(new AddLNode(con1, con2)); diff --git a/src/hotspot/share/opto/bytecodeInfo.cpp b/src/hotspot/share/opto/bytecodeInfo.cpp index e618a708f61..908fff22a77 100644 --- a/src/hotspot/share/opto/bytecodeInfo.cpp +++ b/src/hotspot/share/opto/bytecodeInfo.cpp @@ -60,6 +60,7 @@ InlineTree::InlineTree(Compile* c, // Keep a private copy of the caller_jvms: _caller_jvms = new (C) JVMState(caller_jvms->method(), caller_tree->caller_jvms()); _caller_jvms->set_bci(caller_jvms->bci()); + _caller_jvms->set_receiver_info(caller_jvms->receiver_info()); assert(!caller_jvms->should_reexecute(), "there should be no reexecute bytecode with inlining"); assert(_caller_jvms->same_calls_as(caller_jvms), "consistent JVMS"); } @@ -437,24 +438,26 @@ bool InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_method, // detect direct and indirect recursive inlining { - // count the current method and the callee const bool is_compiled_lambda_form = callee_method->is_compiled_lambda_form(); - int inline_level = 0; - if (!is_compiled_lambda_form) { - if (method() == callee_method) { - inline_level++; - } + const bool is_method_handle_invoker = is_compiled_lambda_form && !jvms->method()->is_compiled_lambda_form(); + + ciInstance* lform_callee_recv = nullptr; + if (is_compiled_lambda_form && !is_method_handle_invoker) { // MH invokers don't have a receiver + lform_callee_recv = jvms->compute_receiver_info(callee_method); } - // count callers of current method and callee - Node* callee_argument0 = is_compiled_lambda_form ? jvms->map()->argument(jvms, 0)->uncast() : nullptr; - for (JVMState* j = jvms->caller(); j != nullptr && j->has_method(); j = j->caller()) { + + int inline_level = 0; + for (JVMState* j = jvms; j != nullptr && j->has_method(); j = j->caller()) { if (j->method() == callee_method) { - if (is_compiled_lambda_form) { - // Since compiled lambda forms are heavily reused we allow recursive inlining. If it is truly - // a recursion (using the same "receiver") we limit inlining otherwise we can easily blow the - // compiler stack. - Node* caller_argument0 = j->map()->argument(j, 0)->uncast(); - if (caller_argument0 == callee_argument0) { + // Since compiled lambda forms are heavily reused we allow recursive inlining. If it is truly + // a recursion (using the same "receiver") we limit inlining otherwise we can easily blow the + // compiler stack. + if (lform_callee_recv != nullptr) { + ciInstance* lform_caller_recv = j->receiver_info(); + assert(lform_caller_recv != nullptr || j->depth() == 1 || + !j->caller()->method()->is_compiled_lambda_form(), // MH invoker + "missing receiver info"); + if (lform_caller_recv == lform_callee_recv || lform_caller_recv == nullptr) { inline_level++; } } else { diff --git a/src/hotspot/share/opto/callnode.cpp b/src/hotspot/share/opto/callnode.cpp index 3527e46c24b..f0fa73f11ce 100644 --- a/src/hotspot/share/opto/callnode.cpp +++ b/src/hotspot/share/opto/callnode.cpp @@ -262,7 +262,8 @@ uint TailJumpNode::match_edge(uint idx) const { //============================================================================= JVMState::JVMState(ciMethod* method, JVMState* caller) : - _method(method) { + _method(method), + _receiver_info(nullptr) { assert(method != nullptr, "must be valid call site"); _bci = InvocationEntryBci; _reexecute = Reexecute_Undefined; @@ -278,7 +279,8 @@ JVMState::JVMState(ciMethod* method, JVMState* caller) : _sp = 0; } JVMState::JVMState(int stack_size) : - _method(nullptr) { + _method(nullptr), + _receiver_info(nullptr) { _bci = InvocationEntryBci; _reexecute = Reexecute_Undefined; DEBUG_ONLY(_map = (SafePointNode*)-1); @@ -613,6 +615,7 @@ JVMState* JVMState::clone_shallow(Compile* C) const { n->set_endoff(_endoff); n->set_sp(_sp); n->set_map(_map); + n->set_receiver_info(_receiver_info); return n; } @@ -687,6 +690,20 @@ int JVMState::interpreter_frame_size() const { return size + Deoptimization::last_frame_adjust(0, callee_locals) * BytesPerWord; } +// Compute receiver info for a compiled lambda form at call site. +ciInstance* JVMState::compute_receiver_info(ciMethod* callee) const { + assert(callee != nullptr && callee->is_compiled_lambda_form(), ""); + if (has_method() && method()->is_compiled_lambda_form()) { // callee is not a MH invoker + Node* recv = map()->argument(this, 0); + assert(recv != nullptr, ""); + const TypeOopPtr* recv_toop = recv->bottom_type()->isa_oopptr(); + if (recv_toop != nullptr && recv_toop->const_oop() != nullptr) { + return recv_toop->const_oop()->as_instance(); + } + } + return nullptr; +} + //============================================================================= bool CallNode::cmp( const Node &n ) const { return _tf == ((CallNode&)n)._tf && _jvms == ((CallNode&)n)._jvms; } @@ -1313,7 +1330,7 @@ void CallLeafNode::dump_spec(outputStream *st) const { //============================================================================= -void SafePointNode::set_local(JVMState* jvms, uint idx, Node *c) { +void SafePointNode::set_local(const JVMState* jvms, uint idx, Node *c) { assert(verify_jvms(jvms), "jvms must match"); int loc = jvms->locoff() + idx; if (in(loc)->is_top() && idx > 0 && !c->is_top() ) { diff --git a/src/hotspot/share/opto/callnode.hpp b/src/hotspot/share/opto/callnode.hpp index db857d4c6d1..2a95cb3b1f2 100644 --- a/src/hotspot/share/opto/callnode.hpp +++ b/src/hotspot/share/opto/callnode.hpp @@ -217,6 +217,7 @@ class JVMState : public ResourceObj { int _bci; // Byte Code Index of this JVM point ReexecuteState _reexecute; // Whether this bytecode need to be re-executed ciMethod* _method; // Method Pointer + ciInstance* _receiver_info; // Constant receiver instance for compiled lambda forms SafePointNode* _map; // Map node associated with this scope public: friend class Compile; @@ -259,6 +260,7 @@ class JVMState : public ResourceObj { bool is_reexecute_undefined() const { return _reexecute==Reexecute_Undefined; } bool has_method() const { return _method != nullptr; } ciMethod* method() const { assert(has_method(), ""); return _method; } + ciInstance* receiver_info() const { assert(has_method(), ""); return _receiver_info; } JVMState* caller() const { return _caller; } SafePointNode* map() const { return _map; } uint depth() const { return _depth; } @@ -304,6 +306,7 @@ class JVMState : public ResourceObj { // _reexecute is initialized to "undefined" for a new bci void set_bci(int bci) {if(_bci != bci)_reexecute=Reexecute_Undefined; _bci = bci; } void set_should_reexecute(bool reexec) {_reexecute = reexec ? Reexecute_True : Reexecute_False;} + void set_receiver_info(ciInstance* recv) { assert(has_method() || recv == nullptr, ""); _receiver_info = recv; } // Miscellaneous utility functions JVMState* clone_deep(Compile* C) const; // recursively clones caller chain @@ -311,6 +314,7 @@ class JVMState : public ResourceObj { void set_map_deep(SafePointNode *map);// reset map for all callers void adapt_position(int delta); // Adapt offsets in in-array after adding an edge. int interpreter_frame_size() const; + ciInstance* compute_receiver_info(ciMethod* callee) const; #ifndef PRODUCT void print_method_with_lineno(outputStream* st, bool show_name) const; @@ -373,7 +377,7 @@ class SafePointNode : public MultiNode { } private: - void verify_input(JVMState* jvms, uint idx) const { + void verify_input(const JVMState* jvms, uint idx) const { assert(verify_jvms(jvms), "jvms must match"); Node* n = in(idx); assert((!n->bottom_type()->isa_long() && !n->bottom_type()->isa_double()) || @@ -382,34 +386,44 @@ class SafePointNode : public MultiNode { public: // Functionality from old debug nodes which has changed - Node *local(JVMState* jvms, uint idx) const { - verify_input(jvms, jvms->locoff() + idx); - return in(jvms->locoff() + idx); + Node* local(const JVMState* jvms, uint idx) const { + uint loc_idx = jvms->locoff() + idx; + assert(jvms->is_loc(loc_idx), "not a local slot"); + verify_input(jvms, loc_idx); + return in(loc_idx); } - Node *stack(JVMState* jvms, uint idx) const { - verify_input(jvms, jvms->stkoff() + idx); - return in(jvms->stkoff() + idx); + Node* stack(const JVMState* jvms, uint idx) const { + uint stk_idx = jvms->stkoff() + idx; + assert(jvms->is_stk(stk_idx), "not a stack slot"); + verify_input(jvms, stk_idx); + return in(stk_idx); } - Node *argument(JVMState* jvms, uint idx) const { - verify_input(jvms, jvms->argoff() + idx); + Node* argument(const JVMState* jvms, uint idx) const { + uint arg_idx = jvms->argoff() + idx; + assert(jvms->is_stk(arg_idx), "not an argument slot"); + verify_input(jvms, arg_idx); return in(jvms->argoff() + idx); } - Node *monitor_box(JVMState* jvms, uint idx) const { + Node* monitor_box(const JVMState* jvms, uint idx) const { assert(verify_jvms(jvms), "jvms must match"); - return in(jvms->monitor_box_offset(idx)); + uint mon_box_idx = jvms->monitor_box_offset(idx); + assert(jvms->is_monitor_box(mon_box_idx), "not a monitor box offset"); + return in(mon_box_idx); } - Node *monitor_obj(JVMState* jvms, uint idx) const { + Node* monitor_obj(const JVMState* jvms, uint idx) const { assert(verify_jvms(jvms), "jvms must match"); - return in(jvms->monitor_obj_offset(idx)); + uint mon_obj_idx = jvms->monitor_obj_offset(idx); + assert(jvms->is_mon(mon_obj_idx) && !jvms->is_monitor_box(mon_obj_idx), "not a monitor obj offset"); + return in(mon_obj_idx); } - void set_local(JVMState* jvms, uint idx, Node *c); + void set_local(const JVMState* jvms, uint idx, Node *c); - void set_stack(JVMState* jvms, uint idx, Node *c) { + void set_stack(const JVMState* jvms, uint idx, Node *c) { assert(verify_jvms(jvms), "jvms must match"); set_req(jvms->stkoff() + idx, c); } - void set_argument(JVMState* jvms, uint idx, Node *c) { + void set_argument(const JVMState* jvms, uint idx, Node *c) { assert(verify_jvms(jvms), "jvms must match"); set_req(jvms->argoff() + idx, c); } diff --git a/src/hotspot/share/opto/chaitin.cpp b/src/hotspot/share/opto/chaitin.cpp index e14d63c7651..30368d80ca9 100644 --- a/src/hotspot/share/opto/chaitin.cpp +++ b/src/hotspot/share/opto/chaitin.cpp @@ -2375,7 +2375,7 @@ void PhaseChaitin::dump_frame() const { tty->print_cr("saved fp register"); else if (return_addr == OptoReg::add(reg, 2*VMRegImpl::slots_per_word) && VerifyStackAtCalls) - tty->print_cr("0xBADB100D +VerifyStackAtCalls"); + tty->print_cr(" +VerifyStackAtCalls"); else tty->print_cr("in_preserve"); } else if ((int)OptoReg::reg2stack(reg) < fixed_slots) { diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index a5023408cdf..8dc493956ae 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -3596,7 +3596,10 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f } else if (t->isa_oopptr()) { new_in2 = ConNode::make(t->make_narrowoop()); } else if (t->isa_klassptr()) { - new_in2 = ConNode::make(t->make_narrowklass()); + ciKlass* klass = t->is_klassptr()->exact_klass(); + if (klass->is_in_encoding_range()) { + new_in2 = ConNode::make(t->make_narrowklass()); + } } } if (new_in2 != nullptr) { @@ -3633,7 +3636,13 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f } else if (t->isa_oopptr()) { n->subsume_by(ConNode::make(t->make_narrowoop()), this); } else if (t->isa_klassptr()) { - n->subsume_by(ConNode::make(t->make_narrowklass()), this); + ciKlass* klass = t->is_klassptr()->exact_klass(); + if (klass->is_in_encoding_range()) { + n->subsume_by(ConNode::make(t->make_narrowklass()), this); + } else { + assert(false, "unencodable klass in ConP -> EncodeP"); + C->record_failure("unencodable klass in ConP -> EncodeP"); + } } } if (in1->outcnt() == 0) { diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 29f737bce08..f74af38387c 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -1575,9 +1575,14 @@ bool LibraryCallKit::inline_string_toBytesU() { Node* src_start = array_element_address(value, offset, T_CHAR); Node* dst_start = basic_plus_adr(newcopy, arrayOopDesc::base_offset_in_bytes(T_BYTE)); - // Check if src array address is aligned to HeapWordSize (dst is always aligned) - const TypeInt* toffset = gvn().type(offset)->is_int(); - bool aligned = toffset->is_con() && ((toffset->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0); + // Check if dst array address is aligned to HeapWordSize + bool aligned = (arrayOopDesc::base_offset_in_bytes(T_BYTE) % HeapWordSize == 0); + // If true, then check if src array address is aligned to HeapWordSize + if (aligned) { + const TypeInt* toffset = gvn().type(offset)->is_int(); + aligned = toffset->is_con() && ((arrayOopDesc::base_offset_in_bytes(T_CHAR) + + toffset->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0); + } // Figure out which arraycopy runtime method to call (disjoint, uninitialized). const char* copyfunc_name = "arraycopy"; @@ -1658,8 +1663,8 @@ bool LibraryCallKit::inline_string_getCharsU() { // Check if array addresses are aligned to HeapWordSize const TypeInt* tsrc = gvn().type(src_begin)->is_int(); const TypeInt* tdst = gvn().type(dst_begin)->is_int(); - bool aligned = tsrc->is_con() && ((tsrc->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0) && - tdst->is_con() && ((tdst->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0); + bool aligned = tsrc->is_con() && ((arrayOopDesc::base_offset_in_bytes(T_BYTE) + tsrc->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0) && + tdst->is_con() && ((arrayOopDesc::base_offset_in_bytes(T_CHAR) + tdst->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0); // Figure out which arraycopy runtime method to call (disjoint, uninitialized). const char* copyfunc_name = "arraycopy"; @@ -3240,7 +3245,7 @@ bool LibraryCallKit::inline_native_jvm_commit() { lease_compare_io->init_req(_true_path, i_o()); lease_compare_io->init_req(_false_path, input_io_state); - lease_result_value->init_req(_true_path, null()); // if the lease was returned, return 0. + lease_result_value->init_req(_true_path, _gvn.longcon(0)); // if the lease was returned, return 0L. lease_result_value->init_req(_false_path, arg); // if not lease, return new updated position. RegionNode* result_rgn = new RegionNode(PATH_LIMIT); diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp index c6ed2411fe3..99fedcdf880 100644 --- a/src/hotspot/share/opto/macro.cpp +++ b/src/hotspot/share/opto/macro.cpp @@ -606,6 +606,11 @@ bool PhaseMacroExpand::can_eliminate_allocation(PhaseIterGVN* igvn, AllocateNode for (DUIterator_Fast kmax, k = use->fast_outs(kmax); k < kmax && can_eliminate; k++) { Node* n = use->fast_out(k); + if (n->is_Mem() && n->as_Mem()->is_mismatched_access()) { + DEBUG_ONLY(disq_node = n); + NOT_PRODUCT(fail_eliminate = "Mismatched access"); + can_eliminate = false; + } if (!n->is_Store() && n->Opcode() != Op_CastP2X && !bs->is_gc_pre_barrier_node(n) && !reduce_merge_precheck) { DEBUG_ONLY(disq_node = n;) if (n->is_Load() || n->is_LoadStore()) { @@ -743,6 +748,41 @@ void PhaseMacroExpand::undo_previous_scalarizations(GrowableArray basic_type(); + BasicType field_bt = field_type->basic_type(); + + // Primitive types must match. + if (is_java_primitive(value_bt) && value_bt == field_bt) { return; } + + // I have been struggling to make a similar assert for non-primitive + // types. I we can add one in the future. For now, I just let them + // pass without checks. + // In particular, I was struggling with a value that came from a call, + // and had only a non-null check CastPP. There was also a checkcast + // in the graph to verify the interface, but the corresponding + // CheckCastPP result was not updated in the stack slot, and so + // we ended up using the CastPP. That means that the field knows + // that it should get an oop from an interface, but the value lost + // that information, and so it is not a subtype. + // There may be other issues, feel free to investigate further! + if (!is_java_primitive(value_bt)) { return; } + + tty->print_cr("value not compatible for field: %s vs %s", + type2name(value_bt), + type2name(field_bt)); + tty->print("value_type: "); + value_type->dump(); + tty->cr(); + tty->print("field_type: "); + field_type->dump(); + tty->cr(); + assert(false, "value_type does not fit field_type"); + } +#endif + SafePointScalarObjectNode* PhaseMacroExpand::create_scalarized_object_description(AllocateNode *alloc, SafePointNode* sfpt) { // Fields of scalar objs are referenced only at the end // of regular debuginfo at the last (youngest) JVMS. @@ -859,6 +899,7 @@ SafePointScalarObjectNode* PhaseMacroExpand::create_scalarized_object_descriptio field_val = transform_later(new DecodeNNode(field_val, field_val->get_ptr_type())); } } + DEBUG_ONLY(verify_type_compatability(field_val->bottom_type(), field_type);) sfpt->add_req(field_val); } diff --git a/src/hotspot/share/opto/parse1.cpp b/src/hotspot/share/opto/parse1.cpp index 6fa0b0f497d..94b8044f814 100644 --- a/src/hotspot/share/opto/parse1.cpp +++ b/src/hotspot/share/opto/parse1.cpp @@ -1149,6 +1149,13 @@ SafePointNode* Parse::create_entry_map() { // Create an initial safepoint to hold JVM state during parsing JVMState* jvms = new (C) JVMState(method(), _caller->has_method() ? _caller : nullptr); set_map(new SafePointNode(len, jvms)); + + // Capture receiver info for compiled lambda forms. + if (method()->is_compiled_lambda_form()) { + ciInstance* recv_info = _caller->compute_receiver_info(method()); + jvms->set_receiver_info(recv_info); + } + jvms->set_map(map()); record_for_igvn(map()); assert(jvms->endoff() == len, "correct jvms sizing"); diff --git a/src/hotspot/share/opto/stringopts.cpp b/src/hotspot/share/opto/stringopts.cpp index 641634b906e..28936a04219 100644 --- a/src/hotspot/share/opto/stringopts.cpp +++ b/src/hotspot/share/opto/stringopts.cpp @@ -1473,9 +1473,14 @@ void PhaseStringOpts::arraycopy(GraphKit& kit, IdealKit& ideal, Node* src_array, Node* src_ptr = __ array_element_address(src_array, __ intcon(0), T_BYTE); Node* dst_ptr = __ array_element_address(dst_array, start, T_BYTE); - // Check if destination address is aligned to HeapWordSize - const TypeInt* tdst = __ gvn().type(start)->is_int(); - bool aligned = tdst->is_con() && ((tdst->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0); + // Check if src array address is aligned to HeapWordSize + bool aligned = (arrayOopDesc::base_offset_in_bytes(T_BYTE) % HeapWordSize == 0); + // If true, then check if dst array address is aligned to HeapWordSize + if (aligned) { + const TypeInt* tdst = __ gvn().type(start)->is_int(); + aligned = tdst->is_con() && ((arrayOopDesc::base_offset_in_bytes(T_BYTE) + + tdst->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0); + } // Figure out which arraycopy runtime method to call (disjoint, uninitialized). const char* copyfunc_name = "arraycopy"; address copyfunc_addr = StubRoutines::select_arraycopy_function(elembt, aligned, true, copyfunc_name, true); diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index 168724ad9b8..9c5c4dac749 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -2593,6 +2593,8 @@ static bool can_subword_truncate(Node* in, const Type* type) { case Op_ReverseI: case Op_CountLeadingZerosI: case Op_CountTrailingZerosI: + case Op_IsFiniteF: + case Op_IsFiniteD: case Op_IsInfiniteF: case Op_IsInfiniteD: case Op_ExtractS: diff --git a/src/hotspot/share/prims/jvmtiAgentList.cpp b/src/hotspot/share/prims/jvmtiAgentList.cpp index a4b7606056d..6a9c62babe5 100644 --- a/src/hotspot/share/prims/jvmtiAgentList.cpp +++ b/src/hotspot/share/prims/jvmtiAgentList.cpp @@ -201,6 +201,11 @@ void JvmtiAgentList::load_xrun_agents() { // Invokes Agent_OnAttach for agents loaded dynamically during runtime. void JvmtiAgentList::load_agent(const char* agent_name, bool is_absolute_path, const char* options, outputStream* st) { + if (JvmtiEnvBase::get_phase() != JVMTI_PHASE_LIVE) { + st->print_cr("Dynamic agent loading is only permitted in the live phase"); + return; + } + JvmtiAgent* const agent = new JvmtiAgent(agent_name, options, is_absolute_path, /* dynamic agent */ true); if (agent->load(st)) { add(agent); diff --git a/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp b/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp index 731db2e82f1..381ad7d12fb 100644 --- a/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp +++ b/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp @@ -996,6 +996,11 @@ void JvmtiClassFileReconstituter::write_u8(u8 x) { void JvmtiClassFileReconstituter::copy_bytecodes(const methodHandle& mh, unsigned char* bytecodes) { + // We must copy bytecodes only from linked classes. + // Being linked guarantees we are not getting bytecodes at + // the same time the linking process is rewriting them. + guarantee(mh->method_holder()->is_linked(), "Bytecodes must be copied from a linked class"); + // use a BytecodeStream to iterate over the bytecodes. JVM/fast bytecodes // and the breakpoint bytecode are converted to their original bytecodes. diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp index 6a1f451bb74..ed575cfb575 100644 --- a/src/hotspot/share/prims/jvmtiEnv.cpp +++ b/src/hotspot/share/prims/jvmtiEnv.cpp @@ -451,6 +451,18 @@ JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) { InstanceKlass* ik = InstanceKlass::cast(klass); if (ik->get_cached_class_file_bytes() == nullptr) { + // Link the class to avoid races with the rewriter. This will call the verifier also + // on the class. Linking is also done in VM_RedefineClasses below, but we need + // to keep that for other VM_RedefineClasses callers. + JavaThread* THREAD = current_thread; + ik->link_class(THREAD); + if (HAS_PENDING_EXCEPTION) { + // Retransform/JVMTI swallows error messages. Using this class will rerun the verifier in a context + // that propagates the VerifyError, if thrown. + CLEAR_PENDING_EXCEPTION; + return JVMTI_ERROR_INVALID_CLASS; + } + // Not cached, we need to reconstitute the class file from the // VM representation. We don't attach the reconstituted class // bytes to the InstanceKlass here because they have not been @@ -3428,7 +3440,8 @@ jvmtiError JvmtiEnv::GetBytecodes(Method* method, jint* bytecode_count_ptr, unsigned char** bytecodes_ptr) { NULL_CHECK(method, JVMTI_ERROR_INVALID_METHODID); - methodHandle mh(Thread::current(), method); + JavaThread* current_thread = JavaThread::current(); + methodHandle mh(current_thread, method); jint size = (jint)mh->code_size(); jvmtiError err = allocate(size, bytecodes_ptr); if (err != JVMTI_ERROR_NONE) { @@ -3437,6 +3450,13 @@ JvmtiEnv::GetBytecodes(Method* method, jint* bytecode_count_ptr, unsigned char** (*bytecode_count_ptr) = size; // get byte codes + // Make sure the class is verified and rewritten first. + JavaThread* THREAD = current_thread; + mh->method_holder()->link_class(THREAD); + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + return JVMTI_ERROR_INVALID_CLASS; + } JvmtiClassFileReconstituter::copy_bytecodes(mh, *bytecodes_ptr); return JVMTI_ERROR_NONE; diff --git a/src/hotspot/share/prims/jvmtiEventController.cpp b/src/hotspot/share/prims/jvmtiEventController.cpp index facbaaf9ad0..bf8df8acf3b 100644 --- a/src/hotspot/share/prims/jvmtiEventController.cpp +++ b/src/hotspot/share/prims/jvmtiEventController.cpp @@ -785,9 +785,6 @@ void JvmtiEventControllerPrivate::set_event_callbacks(JvmtiEnvBase *env, assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check"); EC_TRACE(("[*] # set event callbacks")); - // May be changing the event handler for ObjectFree. - flush_object_free_events(env); - env->set_event_callbacks(callbacks, size_of_callbacks); jlong enabled_bits = env->env_event_enable()->_event_callback_enabled.get_bits(); @@ -1097,6 +1094,8 @@ JvmtiEventController::set_event_callbacks(JvmtiEnvBase *env, // call the functionality without holding the JvmtiThreadState_lock. JvmtiEventControllerPrivate::set_event_callbacks(env, callbacks, size_of_callbacks); } else { + JvmtiEventControllerPrivate::flush_object_free_events(env); + MutexLocker mu(JvmtiThreadState_lock); JvmtiEventControllerPrivate::set_event_callbacks(env, callbacks, size_of_callbacks); } @@ -1184,6 +1183,8 @@ JvmtiEventController::env_dispose(JvmtiEnvBase *env) { // call the functionality without holding the JvmtiThreadState_lock. JvmtiEventControllerPrivate::env_dispose(env); } else { + JvmtiEventControllerPrivate::flush_object_free_events(env); + MutexLocker mu(JvmtiThreadState_lock); JvmtiEventControllerPrivate::env_dispose(env); } diff --git a/src/hotspot/share/prims/jvmtiTagMap.cpp b/src/hotspot/share/prims/jvmtiTagMap.cpp index d3bf8862d37..63d8e31c0c0 100644 --- a/src/hotspot/share/prims/jvmtiTagMap.cpp +++ b/src/hotspot/share/prims/jvmtiTagMap.cpp @@ -944,6 +944,7 @@ class IterateOverHeapObjectClosure: public ObjectClosure { // invoked for each object in the heap void IterateOverHeapObjectClosure::do_object(oop o) { + assert(o != nullptr, "Heap iteration should never produce null!"); // check if iteration has been halted if (is_iteration_aborted()) return; @@ -953,7 +954,7 @@ void IterateOverHeapObjectClosure::do_object(oop o) { } // skip if object is a dormant shared object whose mirror hasn't been loaded - if (o != nullptr && o->klass()->java_mirror() == nullptr) { + if (o->klass()->java_mirror() == nullptr) { log_debug(aot, heap)("skipped dormant archived object " INTPTR_FORMAT " (%s)", p2i(o), o->klass()->external_name()); return; @@ -1032,6 +1033,7 @@ class IterateThroughHeapObjectClosure: public ObjectClosure { // invoked for each object in the heap void IterateThroughHeapObjectClosure::do_object(oop obj) { + assert(obj != nullptr, "Heap iteration should never produce null!"); // check if iteration has been halted if (is_iteration_aborted()) return; @@ -1039,7 +1041,7 @@ void IterateThroughHeapObjectClosure::do_object(oop obj) { if (is_filtered_by_klass_filter(obj, klass())) return; // skip if object is a dormant shared object whose mirror hasn't been loaded - if (obj != nullptr && obj->klass()->java_mirror() == nullptr) { + if (obj->klass()->java_mirror() == nullptr) { log_debug(aot, heap)("skipped dormant archived object " INTPTR_FORMAT " (%s)", p2i(obj), obj->klass()->external_name()); return; diff --git a/src/hotspot/share/prims/vectorSupport.cpp b/src/hotspot/share/prims/vectorSupport.cpp index c907ddb4885..92c1b225a6a 100644 --- a/src/hotspot/share/prims/vectorSupport.cpp +++ b/src/hotspot/share/prims/vectorSupport.cpp @@ -593,6 +593,25 @@ int VectorSupport::vop2ideal(jint id, BasicType bt) { break; } + case VECTOR_OP_TAN: // fall-through + case VECTOR_OP_TANH: // fall-through + case VECTOR_OP_SIN: // fall-through + case VECTOR_OP_SINH: // fall-through + case VECTOR_OP_COS: // fall-through + case VECTOR_OP_COSH: // fall-through + case VECTOR_OP_ASIN: // fall-through + case VECTOR_OP_ACOS: // fall-through + case VECTOR_OP_ATAN: // fall-through + case VECTOR_OP_ATAN2: // fall-through + case VECTOR_OP_CBRT: // fall-through + case VECTOR_OP_LOG: // fall-through + case VECTOR_OP_LOG10: // fall-through + case VECTOR_OP_LOG1P: // fall-through + case VECTOR_OP_POW: // fall-through + case VECTOR_OP_EXP: // fall-through + case VECTOR_OP_EXPM1: // fall-through + case VECTOR_OP_HYPOT: return 0; // not supported; should be handled in Java code + default: fatal("unknown op: %d", vop); } return 0; // Unimplemented diff --git a/src/hotspot/share/prims/vectorSupport.hpp b/src/hotspot/share/prims/vectorSupport.hpp index 5ba18cdfaa8..9ec6500543c 100644 --- a/src/hotspot/share/prims/vectorSupport.hpp +++ b/src/hotspot/share/prims/vectorSupport.hpp @@ -101,6 +101,25 @@ class VectorSupport : AllStatic { VECTOR_OP_COMPRESS_BITS = 33, VECTOR_OP_EXPAND_BITS = 34, + VECTOR_OP_TAN = 101, + VECTOR_OP_TANH = 102, + VECTOR_OP_SIN = 103, + VECTOR_OP_SINH = 104, + VECTOR_OP_COS = 105, + VECTOR_OP_COSH = 106, + VECTOR_OP_ASIN = 107, + VECTOR_OP_ACOS = 108, + VECTOR_OP_ATAN = 109, + VECTOR_OP_ATAN2 = 110, + VECTOR_OP_CBRT = 111, + VECTOR_OP_LOG = 112, + VECTOR_OP_LOG10 = 113, + VECTOR_OP_LOG1P = 114, + VECTOR_OP_POW = 115, + VECTOR_OP_EXP = 116, + VECTOR_OP_EXPM1 = 117, + VECTOR_OP_HYPOT = 118, + VECTOR_OP_SADD = 119, VECTOR_OP_SSUB = 120, VECTOR_OP_SUADD = 121, diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index f14c5efc65d..c84bef57e9b 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -46,6 +46,7 @@ #include "gc/shared/concurrentGCBreakpoints.hpp" #include "gc/shared/gcConfig.hpp" #include "gc/shared/genArguments.hpp" +#include "jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp" #include "jvm.h" #include "jvmtifiles/jvmtiEnv.hpp" #include "logging/log.hpp" @@ -195,6 +196,10 @@ WB_ENTRY(jint, WB_TakeLockAndHangInSafepoint(JNIEnv* env, jobject wb)) return 0; WB_END +WB_ENTRY(jlong, WB_GetMinimumJavaStackSize(JNIEnv* env, jobject o)) + return os::get_minimum_java_stack_size(); +WB_END + class WBIsKlassAliveClosure : public LockedClassesDo { Symbol* _name; int _count; @@ -504,6 +509,14 @@ WB_ENTRY(jboolean, WB_ConcurrentGCRunTo(JNIEnv* env, jobject o, jobject at)) return ConcurrentGCBreakpoints::run_to(c_name); WB_END +WB_ENTRY(jboolean, WB_HasExternalSymbolsStripped(JNIEnv* env, jobject o)) +#if defined(HAS_STRIPPED_DEBUGINFO) + return true; +#else + return false; +#endif +WB_END + #if INCLUDE_G1GC WB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj)) @@ -794,7 +807,7 @@ class VM_WhiteBoxDeoptimizeFrames : public VM_WhiteBoxOperation { if (_make_not_entrant) { nmethod* nm = CodeCache::find_nmethod(f->pc()); assert(nm != nullptr, "did not find nmethod"); - nm->make_not_entrant("Whitebox deoptimization"); + nm->make_not_entrant(nmethod::InvalidationReason::WHITEBOX_DEOPTIMIZATION); } ++_result; } @@ -1097,6 +1110,22 @@ bool WhiteBox::validate_cgroup(bool cgroups_v2_enabled, } #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); @@ -1908,6 +1937,14 @@ WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj)) 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(jlong, WB_getInUseMonitorCount(JNIEnv* env, jobject wb)) return (jlong) WhiteBox::get_in_use_monitor_count(); WB_END @@ -2659,6 +2696,32 @@ WB_ENTRY(void, WB_WaitUnsafe(JNIEnv* env, jobject wb, jint time)) os::naked_short_sleep(time); WB_END +WB_ENTRY(void, WB_BusyWait(JNIEnv* env, jobject wb, jint time)) + ThreadToNativeFromVM ttn(thread); + u8 start = os::current_thread_cpu_time(); + u8 target_duration = time * (u8)1000000; + while (os::current_thread_cpu_time() - start < target_duration) { + for (volatile int i = 0; i < 1000000; i++); + } +WB_END + +WB_ENTRY(jboolean, WB_CPUSamplerSetOutOfStackWalking(JNIEnv* env, jobject wb, jboolean enable)) + #if defined(ASSERT) && INCLUDE_JFR && defined(LINUX) + JfrCPUTimeThreadSampling::set_out_of_stack_walking_enabled(enable == JNI_TRUE); + return JNI_TRUE; + #else + return JNI_FALSE; + #endif +WB_END + +WB_ENTRY(jlong, WB_CPUSamplerOutOfStackWalkingIterations(JNIEnv* env, jobject wb)) + #if defined(ASSERT) && INCLUDE_JFR && defined(LINUX) + return (jlong)JfrCPUTimeThreadSampling::out_of_stack_walking_iterations(); + #else + return 0; + #endif +WB_END + WB_ENTRY(jstring, WB_GetLibcName(JNIEnv* env, jobject o)) ThreadToNativeFromVM ttn(thread); jstring info_string = env->NewStringUTF(XSTR(LIBC)); @@ -2737,6 +2800,7 @@ static JNINativeMethod methods[] = { {CC"getVMLargePageSize", CC"()J", (void*)&WB_GetVMLargePageSize}, {CC"getHeapSpaceAlignment", CC"()J", (void*)&WB_GetHeapSpaceAlignment}, {CC"getHeapAlignment", CC"()J", (void*)&WB_GetHeapAlignment}, + {CC"hasExternalSymbolsStripped", CC"()Z", (void*)&WB_HasExternalSymbolsStripped}, {CC"countAliveClasses0", CC"(Ljava/lang/String;)I", (void*)&WB_CountAliveClasses }, {CC"getSymbolRefcount", CC"(Ljava/lang/String;)I", (void*)&WB_GetSymbolRefcount }, {CC"parseCommandLine0", @@ -2908,6 +2972,8 @@ static JNINativeMethod methods[] = { (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"getInUseMonitorCount", CC"()J", (void*)&WB_getInUseMonitorCount }, {CC"getLockStackCapacity", CC"()I", (void*)&WB_getLockStackCapacity }, {CC"supportsRecursiveLightweightLocking", CC"()Z", (void*)&WB_supportsRecursiveLightweightLocking }, @@ -3006,6 +3072,9 @@ static JNINativeMethod methods[] = { {CC"isJVMTIIncluded", CC"()Z", (void*)&WB_IsJVMTIIncluded}, {CC"waitUnsafe", CC"(I)V", (void*)&WB_WaitUnsafe}, + {CC"busyWait", CC"(I)V", (void*)&WB_BusyWait}, + {CC"cpuSamplerSetOutOfStackWalking", CC"(Z)Z", (void*)&WB_CPUSamplerSetOutOfStackWalking}, + {CC"cpuSamplerOutOfStackWalkingIterations", CC"()J",(void*)&WB_CPUSamplerOutOfStackWalkingIterations}, {CC"getLibcName", CC"()Ljava/lang/String;", (void*)&WB_GetLibcName}, {CC"pinObject", CC"(Ljava/lang/Object;)V", (void*)&WB_PinObject}, @@ -3015,7 +3084,8 @@ static JNINativeMethod methods[] = { {CC"cleanMetaspaces", CC"()V", (void*)&WB_CleanMetaspaces}, {CC"rss", CC"()J", (void*)&WB_Rss}, {CC"printString", CC"(Ljava/lang/String;I)Ljava/lang/String;", (void*)&WB_PrintString}, - {CC"lockAndStuckInSafepoint", CC"()V", (void*)&WB_TakeLockAndHangInSafepoint}, + {CC"lockAndStuckInSafepoint", CC"()V", (void*)&WB_TakeLockAndHangInSafepoint}, + {CC"getMinimumJavaStackSize", CC"()J", (void*)&WB_GetMinimumJavaStackSize}, {CC"wordSize", CC"()J", (void*)&WB_WordSize}, {CC"rootChunkWordSize", CC"()J", (void*)&WB_RootChunkWordSize}, {CC"isStatic", CC"()Z", (void*)&WB_IsStaticallyLinked} diff --git a/src/hotspot/share/prims/whitebox.hpp b/src/hotspot/share/prims/whitebox.hpp index 4ba684fc09a..c20d35abbbb 100644 --- a/src/hotspot/share/prims/whitebox.hpp +++ b/src/hotspot/share/prims/whitebox.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, 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 @@ -72,6 +72,9 @@ class WhiteBox : public AllStatic { #ifdef LINUX static bool validate_cgroup(bool cgroups_v2_enabled, const char* controllers_file, 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 --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp index 5b9d36115f8..6012b87e50b 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.cpp +++ b/src/hotspot/share/runtime/abstract_vm_version.cpp @@ -271,6 +271,20 @@ const char* Abstract_VM_Version::internal_vm_info_string() { #define HOTSPOT_BUILD_COMPILER "MS VC++ 17.7 (VS2022)" #elif _MSC_VER == 1938 #define HOTSPOT_BUILD_COMPILER "MS VC++ 17.8 (VS2022)" + #elif _MSC_VER == 1939 + #define HOTSPOT_BUILD_COMPILER "MS VC++ 17.9 (VS2022)" + #elif _MSC_VER == 1940 + #define HOTSPOT_BUILD_COMPILER "MS VC++ 17.10 (VS2022)" + #elif _MSC_VER == 1941 + #define HOTSPOT_BUILD_COMPILER "MS VC++ 17.11 (VS2022)" + #elif _MSC_VER == 1942 + #define HOTSPOT_BUILD_COMPILER "MS VC++ 17.12 (VS2022)" + #elif _MSC_VER == 1943 + #define HOTSPOT_BUILD_COMPILER "MS VC++ 17.13 (VS2022)" + #elif _MSC_VER == 1944 + #define HOTSPOT_BUILD_COMPILER "MS VC++ 17.14 (VS2022)" + #elif _MSC_VER == 1950 + #define HOTSPOT_BUILD_COMPILER "MS VC++ 18.0 (VS2026)" #else #define HOTSPOT_BUILD_COMPILER "unknown MS VC++:" XSTR(_MSC_VER) #endif diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 7592d233f0c..47398ef4812 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -536,6 +536,7 @@ static SpecialFlag const special_jvm_flags[] = { #ifdef _LP64 { "UseCompressedClassPointers", JDK_Version::jdk(25), JDK_Version::jdk(26), JDK_Version::undefined() }, #endif + { "ShenandoahPacing", JDK_Version::jdk(25), JDK_Version::jdk(26), JDK_Version::jdk(27) }, // --- Deprecated alias flags (see also aliased_jvm_flags) - sorted by obsolete_in then expired_in: { "CreateMinidumpOnCrash", JDK_Version::jdk(9), JDK_Version::undefined(), JDK_Version::undefined() }, diff --git a/src/hotspot/share/runtime/continuationEntry.hpp b/src/hotspot/share/runtime/continuationEntry.hpp index 3c8532b9e87..a9f37bddb43 100644 --- a/src/hotspot/share/runtime/continuationEntry.hpp +++ b/src/hotspot/share/runtime/continuationEntry.hpp @@ -39,6 +39,7 @@ class RegisterMap; // Metadata stored in the continuation entry frame class ContinuationEntry { + friend class VMStructs; friend class JVMCIVMStructs; ContinuationEntryPD _pd; #ifdef ASSERT diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 4042bb01c58..63de5e6d37a 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -1382,6 +1382,9 @@ void Deoptimization::reassign_type_array_elements(frame* fr, RegisterMap* reg_ma case T_INT: case T_FLOAT: { // 4 bytes. assert(value->type() == T_INT, "Agreement."); +#if INCLUDE_JVMCI + // big_value allows encoding double/long value as e.g. [int = 0, long], and storing + // the value in two array elements. bool big_value = false; if (i + 1 < sv->field_size() && type == T_INT) { if (sv->field_at(i)->is_location()) { @@ -1409,6 +1412,9 @@ void Deoptimization::reassign_type_array_elements(frame* fr, RegisterMap* reg_ma } else { obj->int_at_put(index, value->get_jint()); } +#else // not INCLUDE_JVMCI + obj->int_at_put(index, value->get_jint()); +#endif // INCLUDE_JVMCI break; } @@ -1826,7 +1832,7 @@ void Deoptimization::deoptimize(JavaThread* thread, frame fr, DeoptReason reason #if INCLUDE_JVMCI address Deoptimization::deoptimize_for_missing_exception_handler(nmethod* nm) { // there is no exception handler for this pc => deoptimize - nm->make_not_entrant("missing exception handler"); + nm->make_not_entrant(nmethod::InvalidationReason::MISSING_EXCEPTION_HANDLER); // Use Deoptimization::deoptimize for all of its side-effects: // gathering traps statistics, logging... @@ -2455,7 +2461,7 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* current, jint tr // Recompile if (make_not_entrant) { - if (!nm->make_not_entrant("uncommon trap")) { + if (!nm->make_not_entrant(nmethod::InvalidationReason::UNCOMMON_TRAP)) { return; // the call did not change nmethod's state } diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp index efffa8ac753..6c97ae55df5 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp @@ -39,6 +39,14 @@ JVMFlag::Error AOTCacheConstraintFunc(ccstr value, bool verbose) { return JVMFlag::SUCCESS; } +JVMFlag::Error AOTCacheOutputConstraintFunc(ccstr value, bool verbose) { + if (value == nullptr) { + JVMFlag::printError(verbose, "AOTCacheOutput cannot be empty\n"); + return JVMFlag::VIOLATES_CONSTRAINT; + } + return JVMFlag::SUCCESS; +} + JVMFlag::Error AOTConfigurationConstraintFunc(ccstr value, bool verbose) { if (value == nullptr) { JVMFlag::printError(verbose, "AOTConfiguration cannot be empty\n"); @@ -139,3 +147,13 @@ JVMFlag::Error NUMAInterleaveGranularityConstraintFunc(size_t value, bool verbos return JVMFlag::SUCCESS; } + +JVMFlag::Error LargePageSizeInBytesConstraintFunc(size_t value, bool verbose) { + if (!is_power_of_2(value)) { + JVMFlag::printError(verbose, "LargePageSizeInBytes ( %zu ) must be " + "a power of 2\n", + value); + return JVMFlag::VIOLATES_CONSTRAINT; + } + return JVMFlag::SUCCESS; +} diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp index 3040dafabc5..5259f87c19d 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp @@ -35,13 +35,15 @@ #define RUNTIME_CONSTRAINTS(f) \ f(ccstr, AOTCacheConstraintFunc) \ + f(ccstr, AOTCacheOutputConstraintFunc) \ f(ccstr, AOTConfigurationConstraintFunc) \ f(ccstr, AOTModeConstraintFunc) \ f(int, ObjectAlignmentInBytesConstraintFunc) \ f(int, ContendedPaddingWidthConstraintFunc) \ f(int, PerfDataSamplingIntervalFunc) \ f(uintx, VMPageSizeConstraintFunc) \ - f(size_t, NUMAInterleaveGranularityConstraintFunc) + f(size_t, NUMAInterleaveGranularityConstraintFunc) \ + f(size_t, LargePageSizeInBytesConstraintFunc) RUNTIME_CONSTRAINTS(DECLARE_CONSTRAINT) diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 75736d0dc7d..4b32e370dcd 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -242,8 +242,10 @@ const int ObjectAlignmentInBytes = 8; \ product(size_t, LargePageSizeInBytes, 0, \ "Maximum large page size used (0 will use the default large " \ - "page size for the environment as the maximum)") \ + "page size for the environment as the maximum) " \ + "(must be a power of 2)") \ range(0, max_uintx) \ + constraint(LargePageSizeInBytesConstraintFunc, AtParse) \ \ product(size_t, LargePageHeapSizeThreshold, 128*M, \ "Use large pages if maximum heap is at least this big") \ @@ -293,6 +295,9 @@ const int ObjectAlignmentInBytes = 8; product(bool, UseInlineCaches, true, \ "Use Inline Caches for virtual calls ") \ \ + develop(bool, VerifyInlineCaches, true, \ + "Verify Inline Caches") \ + \ product(bool, InlineArrayCopy, true, DIAGNOSTIC, \ "Inline arraycopy native that is known to be part of " \ "base library DLL") \ @@ -485,6 +490,9 @@ const int ObjectAlignmentInBytes = 8; develop(bool, ZapFillerObjects, trueInDebug, \ "Zap filler objects") \ \ + develop(bool, ZapCHeap, trueInDebug, \ + "Zap allocated/freed C heap space") \ + \ develop(bool, ZapTLAB, trueInDebug, \ "Zap allocated TLABs") \ develop(bool, TestingAsyncLoggingDeathTest, false, \ @@ -2009,6 +2017,7 @@ const int ObjectAlignmentInBytes = 8; develop(uint, BinarySearchThreshold, 16, \ "Minimal number of elements in a sorted collection to prefer" \ "binary search over simple linear search." ) \ + \ // end of RUNTIME_FLAGS diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp index aa0b5dca3e4..83280c1f9f1 100644 --- a/src/hotspot/share/runtime/java.cpp +++ b/src/hotspot/share/runtime/java.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp index ddb682cbc75..20de4beebdd 100644 --- a/src/hotspot/share/runtime/javaThread.cpp +++ b/src/hotspot/share/runtime/javaThread.cpp @@ -1339,7 +1339,7 @@ void JavaThread::make_zombies() { // it is a Java nmethod nmethod* nm = CodeCache::find_nmethod(fst.current()->pc()); assert(nm != nullptr, "did not find nmethod"); - nm->make_not_entrant("zombie"); + nm->make_not_entrant(nmethod::InvalidationReason::ZOMBIE); } } } diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp index b917bd78d35..bff6e3d913b 100644 --- a/src/hotspot/share/runtime/mutexLocker.cpp +++ b/src/hotspot/share/runtime/mutexLocker.cpp @@ -259,7 +259,7 @@ void mutex_init() { MUTEX_DEFN(CompiledIC_lock , PaddedMutex , nosafepoint); // locks VtableStubs_lock MUTEX_DEFN(MethodCompileQueue_lock , PaddedMonitor, safepoint); - MUTEX_DEFL(TrainingData_lock , PaddedMutex , MethodCompileQueue_lock); + MUTEX_DEFN(TrainingData_lock , PaddedMutex , nosafepoint); MUTEX_DEFN(TrainingReplayQueue_lock , PaddedMonitor, safepoint); MUTEX_DEFN(CompileStatistics_lock , PaddedMutex , safepoint); MUTEX_DEFN(DirectivesStack_lock , PaddedMutex , nosafepoint); diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index ee1f0a3b081..1e1f8e90be6 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -666,8 +666,8 @@ void* os::malloc(size_t size, MemTag mem_tag, const NativeCallStack& stack) { if (CDSConfig::is_dumping_static_archive()) { // Need to deterministically fill all the alignment gaps in C++ structures. ::memset(inner_ptr, 0, size); - } else { - DEBUG_ONLY(::memset(inner_ptr, uninitBlockPad, size);) + } else if (ZapCHeap) { + ::memset(inner_ptr, uninitBlockPad, size); } DEBUG_ONLY(break_if_ptr_caught(inner_ptr);) return inner_ptr; @@ -740,7 +740,7 @@ void* os::realloc(void *memblock, size_t size, MemTag mem_tag, const NativeCallS #ifdef ASSERT assert(old_size == free_info.size, "Sanity"); - if (old_size < size) { + if (ZapCHeap && old_size < size) { // We also zap the newly extended region. ::memset((char*)new_inner_ptr + old_size, uninitBlockPad, size - old_size); } @@ -2573,6 +2573,10 @@ jint os::set_minimum_stack_sizes() { return JNI_OK; } +jlong os::get_minimum_java_stack_size() { + return static_cast(_java_thread_min_stack_allowed); +} + // Builds a platform dependent Agent_OnLoad_ function name // which is used to find statically linked in agents. // Parameters: diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index b26ec280e72..bb07abad6b1 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -397,6 +397,8 @@ class os: AllStatic { static jint set_minimum_stack_sizes(); public: + // get allowed minimum java stack size + static jlong get_minimum_java_stack_size(); // Find committed memory region within specified range (start, start + size), // return true if found any static bool committed_in_range(address start, size_t size, address& committed_start, size_t& committed_size); diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index 9c710fc98e4..b9610064c13 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -3364,7 +3364,7 @@ JRT_LEAF(intptr_t*, SharedRuntime::OSR_migration_begin( JavaThread *current) ) RegisterMap::WalkContinuation::skip); frame sender = fr.sender(&map); if (sender.is_interpreted_frame()) { - current->push_cont_fastpath(sender.sp()); + current->push_cont_fastpath(sender.unextended_sp()); } return buf; diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 5075efb5c75..879a2324e54 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -624,6 +624,7 @@ nonstatic_field(JavaThread, _active_handles, JNIHandleBlock*) \ nonstatic_field(JavaThread, _monitor_owner_id, int64_t) \ volatile_nonstatic_field(JavaThread, _terminated, JavaThread::TerminatedTypes) \ + nonstatic_field(JavaThread, _cont_entry, ContinuationEntry*) \ nonstatic_field(Thread, _osthread, OSThread*) \ \ /************/ \ @@ -667,6 +668,14 @@ static_field(VMRegImpl, regName[0], const char*) \ static_field(VMRegImpl, stack0, VMReg) \ \ + /******************************************************************************************/ \ + /* CI (NOTE: these CI fields are retained in VMStructs for the benefit of external tools, */ \ + /* to ease their migration to a future alternative.) */ \ + /******************************************************************************************/ \ + \ + nonstatic_field(CompilerThread, _env, ciEnv*) \ + nonstatic_field(ciEnv, _task, CompileTask*) \ + \ /************/ \ /* Monitors */ \ /************/ \ @@ -798,7 +807,8 @@ nonstatic_field(Mutex, _name, const char*) \ static_field(Mutex, _mutex_array, Mutex**) \ static_field(Mutex, _num_mutex, int) \ - volatile_nonstatic_field(Mutex, _owner, Thread*) + volatile_nonstatic_field(Mutex, _owner, Thread*) \ + static_field(ContinuationEntry, _return_pc, address) //-------------------------------------------------------------------------------- // VM_TYPES @@ -1150,6 +1160,12 @@ declare_toplevel_type(BasicLock) \ declare_toplevel_type(BasicObjectLock) \ \ + /*********************/ \ + /* CI */ \ + /*********************/ \ + \ + declare_toplevel_type(ciEnv) \ + \ /********************/ \ /* -XX flags */ \ /********************/ \ @@ -1266,6 +1282,7 @@ declare_toplevel_type(FileMapHeader) \ declare_toplevel_type(CDSFileMapRegion) \ declare_toplevel_type(UpcallStub::FrameData) \ + declare_toplevel_type(ContinuationEntry) \ \ /************/ \ /* GC types */ \ diff --git a/src/hotspot/share/utilities/debug.cpp b/src/hotspot/share/utilities/debug.cpp index abe3d6757b5..bd5adc7acf9 100644 --- a/src/hotspot/share/utilities/debug.cpp +++ b/src/hotspot/share/utilities/debug.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,12 +63,17 @@ #include "utilities/nativeStackPrinter.hpp" #include "utilities/unsigned5.hpp" #include "utilities/vmError.hpp" +#if INCLUDE_JFR +#include "jfr/jfr.hpp" +#endif #include #include -// These functions needs to be exported on Windows only -#define DEBUGEXPORT WINDOWS_ONLY(JNIEXPORT) +// These functions needs to be exported on Windows +// On Linux it is also beneficial to export them to avoid +// losing them e.g. with linktime gc +#define DEBUGEXPORT JNIEXPORT // Support for showing register content on asserts/guarantees. #ifdef CAN_SHOW_REGISTERS_ON_ASSERT @@ -262,6 +267,8 @@ void report_untested(const char* file, int line, const char* message) { void report_java_out_of_memory(const char* message) { static int out_of_memory_reported = 0; + JFR_ONLY(Jfr::on_report_java_out_of_memory();) + // A number of threads may attempt to report OutOfMemoryError at around the // same time. To avoid dumping the heap or executing the data collection // commands multiple times we just do it once when the first threads reports @@ -610,36 +617,60 @@ extern "C" DEBUGEXPORT intptr_t u5p(intptr_t addr, void pp(intptr_t p) { pp((void*)p); } void pp(oop p) { pp((void*)p); } -void help() { +extern "C" DEBUGEXPORT void help() { Command c("help"); tty->print_cr("basic"); - tty->print_cr(" pp(void* p) - try to make sense of p"); - tty->print_cr(" ps() - print current thread stack"); - tty->print_cr(" pss() - print all thread stacks"); - tty->print_cr(" pm(int pc) - print Method* given compiled PC"); - tty->print_cr(" findm(intptr_t pc) - finds Method*"); - tty->print_cr(" find(intptr_t x) - finds & prints nmethod/stub/bytecode/oop based on pointer into it"); - tty->print_cr(" pns(void* sp, void* fp, void* pc) - print native (i.e. mixed) stack trace. E.g."); - tty->print_cr(" pns($sp, $rbp, $pc) on Linux/amd64 or"); - tty->print_cr(" pns($sp, $ebp, $pc) on Linux/x86 or"); - tty->print_cr(" pns($sp, $fp, $pc) on Linux/AArch64 or"); - tty->print_cr(" pns($sp, 0, $pc) on Linux/ppc64 or"); - tty->print_cr(" pns($sp, $s8, $pc) on Linux/mips or"); - tty->print_cr(" pns($sp, $fp, $pc) on Linux/RISC-V"); + tty->print_cr(" pp(void* p) - try to make sense of p"); + tty->print_cr(" ps() - print current thread stack"); + tty->print_cr(" pss() - print all thread stacks"); + tty->print_cr(" findnm(intptr_t pc) - find nmethod*"); + tty->print_cr(" findm(intptr_t pc) - find Method*"); + tty->print_cr(" find(intptr_t x) - find & print nmethod/stub/bytecode/oop based on pointer into it"); + tty->print_cr(" findpc(intptr_t x) - find & print nmethod/stub/bytecode/oop based on pointer into it (verbose)"); + +#ifndef PRODUCT + tty->print_cr(" pns(void* sp, void* fp, void* pc) - print native (i.e. mixed) stack trace, e.g."); +#ifdef LINUX + AMD64_ONLY( tty->print_cr(" pns($sp, $rbp, $pc) on Linux/amd64")); + IA32_ONLY( tty->print_cr(" pns($sp, $ebp, $pc) on Linux/x86")); + AARCH64_ONLY(tty->print_cr(" pns($sp, $fp, $pc) on Linux/AArch64")); + RISCV_ONLY( tty->print_cr(" pns($sp, $fp, $pc) on Linux/RISC-V")); + PPC64_ONLY( tty->print_cr(" pns($sp, 0, $pc) on Linux/ppc64")); +#endif // LINUX tty->print_cr(" - in gdb do 'set overload-resolution off' before calling pns()"); tty->print_cr(" - in dbx do 'frame 1' before calling pns()"); +#endif // !PRODUCT + + tty->print_cr("universe."); + tty->print_cr(" verify(intptr_t p) - run verify on Universe"); + tty->print_cr(" threads() - print all threads"); + tty->print_cr(" psd() - print system dictionary"); + tty->print_cr("class metadata."); tty->print_cr(" findclass(name_pattern, flags)"); tty->print_cr(" findmethod(class_name_pattern, method_pattern, flags)"); - tty->print_cr("misc."); - tty->print_cr(" flush() - flushes the log file"); - tty->print_cr(" events() - dump events from ring buffers"); + tty->print_cr("method metadata."); + tty->print_cr(" blob(CodeBlob* p) - print CodeBlob"); + tty->print_cr(" dump_vtable(address p) - dump vtable of the Klass"); + tty->print_cr(" nm(intptr_t p) - find & print CodeBlob details"); + tty->print_cr(" disnm(intptr_t p) - find & print disassembly of CodeBlob"); + tty->print_cr(" printnm(intptr_t p) - print nmethod details"); + tty->print_cr(" findbcp(method, bcp) - find & prints bcp"); + tty->print_cr("stack frame details."); + tty->print_cr(" pfl() - print frame layout"); + tty->print_cr(" psf() - print stack frames"); + + tty->print_cr("misc."); + tty->print_cr(" flush() - flush the log file"); + tty->print_cr(" events() - dump events from ring buffers"); + tty->print_cr(" u5decode(intptr_t addr) - decode a single u5 value"); + tty->print_cr(" u5p(intptr_t addr, intptr_t limit, int count) - decode u5 values"); tty->print_cr("compiler debugging"); - tty->print_cr(" debug() - to set things up for compiler debugging"); - tty->print_cr(" ndebug() - undo debug"); + tty->print_cr(" debug() - set things up for compiler debugging"); + tty->print_cr(" ndebug() - undo debug"); } #ifndef PRODUCT diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp index 7d1b17d5deb..93ae435ae72 100644 --- a/src/hotspot/share/utilities/vmError.cpp +++ b/src/hotspot/share/utilities/vmError.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2024 SAP SE. All rights reserved. * Copyright (c) 2023, 2025, Red Hat, Inc. and/or its affiliates. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -109,12 +109,13 @@ const intptr_t VMError::segfault_address = pd_segfault_address; static const char* env_list[] = { // All platforms "JAVA_HOME", "JAVA_TOOL_OPTIONS", "_JAVA_OPTIONS", "CLASSPATH", - "PATH", "USERNAME", + "JDK_AOT_VM_OPTIONS", + "JAVA_OPTS", "PATH", "USERNAME", "XDG_CACHE_HOME", "XDG_CONFIG_HOME", "FC_LANG", "FONTCONFIG_USE_MMAP", // Env variables that are defined on Linux/BSD - "LD_LIBRARY_PATH", "LD_PRELOAD", "SHELL", "DISPLAY", + "LD_LIBRARY_PATH", "LD_PRELOAD", "SHELL", "DISPLAY", "WAYLAND_DISPLAY", "HOSTTYPE", "OSTYPE", "ARCH", "MACHTYPE", "LANG", "LC_ALL", "LC_CTYPE", "LC_NUMERIC", "LC_TIME", "TERM", "TMPDIR", "TZ", @@ -1856,7 +1857,7 @@ void VMError::report_and_die(int id, const char* message, const char* detail_fmt log.set_fd(-1); } - JFR_ONLY(Jfr::on_vm_shutdown(true);) + JFR_ONLY(Jfr::on_vm_shutdown(true, false, static_cast(_id) == OOM_JAVA_HEAP_FATAL);) if (PrintNMTStatistics) { fdStream fds(fd_out); diff --git a/src/java.base/share/classes/com/sun/crypto/provider/RSACipherAdaptor.java b/src/java.base/share/classes/com/sun/crypto/provider/RSACipherAdaptor.java new file mode 100644 index 00000000000..c0fd9ffa599 --- /dev/null +++ b/src/java.base/share/classes/com/sun/crypto/provider/RSACipherAdaptor.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.crypto.provider; + +import java.io.ByteArrayOutputStream; +import java.security.MessageDigest; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.SignatureSpi; +import java.security.InvalidKeyException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidParameterException; +import java.security.SignatureException; +import java.security.spec.AlgorithmParameterSpec; +import javax.crypto.Cipher; +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; + +/** + * NONEwithRSA Signature implementation using the RSA/ECB/PKCS1Padding Cipher + * implementation from SunJCE. + */ +public final class RSACipherAdaptor extends SignatureSpi { + + private final RSACipher c; + private ByteArrayOutputStream verifyBuf; + + public RSACipherAdaptor() { + c = new RSACipher(); + } + + @Override + protected void engineInitVerify(PublicKey publicKey) + throws InvalidKeyException { + c.engineInit(Cipher.DECRYPT_MODE, publicKey, null); + if (verifyBuf == null) { + verifyBuf = new ByteArrayOutputStream(128); + } else { + verifyBuf.reset(); + } + } + + @Override + protected void engineInitSign(PrivateKey privateKey) + throws InvalidKeyException { + c.engineInit(Cipher.ENCRYPT_MODE, privateKey, null); + verifyBuf = null; + } + + @Override + protected void engineInitSign(PrivateKey privateKey, SecureRandom random) + throws InvalidKeyException { + c.engineInit(Cipher.ENCRYPT_MODE, privateKey, random); + verifyBuf = null; + } + + @Override + protected void engineUpdate(byte b) throws SignatureException { + engineUpdate(new byte[] {b}, 0, 1); + } + + @Override + protected void engineUpdate(byte[] b, int off, int len) + throws SignatureException { + if (verifyBuf != null) { + verifyBuf.write(b, off, len); + } else { + byte[] out = c.engineUpdate(b, off, len); + if ((out != null) && (out.length != 0)) { + throw new SignatureException + ("Cipher unexpectedly returned data"); + } + } + } + + @Override + protected byte[] engineSign() throws SignatureException { + try { + return c.engineDoFinal(null, 0, 0); + } catch (IllegalBlockSizeException | BadPaddingException e) { + throw new SignatureException("doFinal() failed", e); + } + } + + @Override + protected boolean engineVerify(byte[] sigBytes) throws SignatureException { + try { + byte[] out = c.engineDoFinal(sigBytes, 0, sigBytes.length); + byte[] data = verifyBuf.toByteArray(); + verifyBuf.reset(); + return MessageDigest.isEqual(out, data); + } catch (BadPaddingException e) { + // e.g. wrong public key used + // return false rather than throwing exception + return false; + } catch (IllegalBlockSizeException e) { + throw new SignatureException("doFinal() failed", e); + } + } + + @Override + protected void engineSetParameter(AlgorithmParameterSpec params) + throws InvalidAlgorithmParameterException { + if (params != null) { + throw new InvalidParameterException("Parameters not supported"); + } + } + + @Override + @SuppressWarnings("deprecation") + protected void engineSetParameter(String param, Object value) + throws InvalidParameterException { + throw new InvalidParameterException("Parameters not supported"); + } + + @Override + @SuppressWarnings("deprecation") + protected Object engineGetParameter(String param) + throws InvalidParameterException { + throw new InvalidParameterException("Parameters not supported"); + } +} diff --git a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java index cc99464dff3..22d5f17c6e0 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java @@ -136,6 +136,12 @@ public SunJCE() { void putEntries() { // reuse attribute map and reset before each reuse HashMap attrs = new HashMap<>(3); + attrs.put("SupportedKeyClasses", + "java.security.interfaces.RSAPublicKey" + + "|java.security.interfaces.RSAPrivateKey"); + ps("Signature", "NONEwithRSA", + "com.sun.crypto.provider.RSACipherAdaptor", null, attrs); + // continue adding cipher specific attributes attrs.put("SupportedModes", "ECB"); attrs.put("SupportedPaddings", "NOPADDING|PKCS1PADDING|OAEPPADDING" + "|OAEPWITHMD5ANDMGF1PADDING" @@ -147,9 +153,6 @@ void putEntries() { + "|OAEPWITHSHA-512ANDMGF1PADDING" + "|OAEPWITHSHA-512/224ANDMGF1PADDING" + "|OAEPWITHSHA-512/256ANDMGF1PADDING"); - attrs.put("SupportedKeyClasses", - "java.security.interfaces.RSAPublicKey" + - "|java.security.interfaces.RSAPrivateKey"); ps("Cipher", "RSA", "com.sun.crypto.provider.RSACipher", null, attrs); diff --git a/src/java.base/share/classes/java/io/Console.java b/src/java.base/share/classes/java/io/Console.java index cedb6124a31..c9c47666bf0 100644 --- a/src/java.base/share/classes/java/io/Console.java +++ b/src/java.base/share/classes/java/io/Console.java @@ -25,6 +25,7 @@ package java.io; +import java.lang.annotation.Native; import java.util.*; import java.nio.charset.Charset; import jdk.internal.access.JavaIOAccess; @@ -545,7 +546,7 @@ public Charset charset() { * @since 22 */ public boolean isTerminal() { - return istty; + return isStdinTty() && isStdoutTty(); } private static UnsupportedOperationException newUnsupportedOperationException() { @@ -553,7 +554,12 @@ private static UnsupportedOperationException newUnsupportedOperationException() "Console class itself does not provide implementation"); } - private static final boolean istty = istty(); + @Native static final int TTY_STDIN_MASK = 0x00000001; + @Native static final int TTY_STDOUT_MASK = 0x00000002; + @Native static final int TTY_STDERR_MASK = 0x00000004; + // ttyStatus() returns bit patterns above, a bit is set if the corresponding file + // descriptor is a character device + private static final int ttyStatus = ttyStatus(); private static final Charset STDIN_CHARSET = Charset.forName(System.getProperty("stdin.encoding"), UTF_8.INSTANCE); private static final Charset STDOUT_CHARSET = @@ -565,6 +571,9 @@ private static UnsupportedOperationException newUnsupportedOperationException() public Console console() { return cons; } + public boolean isStdinTty() { + return Console.isStdinTty(); + } }); } @@ -586,7 +595,7 @@ private static Console instantiateConsole() { for (var jcp : ServiceLoader.load(ModuleLayer.boot(), JdkConsoleProvider.class)) { if (consModName.equals(jcp.getClass().getModule().getName())) { - var jc = jcp.console(istty, STDIN_CHARSET, STDOUT_CHARSET); + var jc = jcp.console(isStdinTty() && isStdoutTty(), STDIN_CHARSET, STDOUT_CHARSET); if (jc != null) { c = new ProxyingConsole(jc); } @@ -597,12 +606,21 @@ private static Console instantiateConsole() { } // If not found, default to built-in Console - if (istty && c == null) { + if (isStdinTty() && isStdoutTty() && c == null) { c = new ProxyingConsole(new JdkConsoleImpl(STDIN_CHARSET, STDOUT_CHARSET)); } return c; } - private static native boolean istty(); + private static boolean isStdinTty() { + return (ttyStatus & TTY_STDIN_MASK) != 0; + } + private static boolean isStdoutTty() { + return (ttyStatus & TTY_STDOUT_MASK) != 0; + } + private static boolean isStderrTty() { + return (ttyStatus & TTY_STDERR_MASK) != 0; + } + private static native int ttyStatus(); } diff --git a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java index d317557cbb1..f1da102236a 100644 --- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java +++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java @@ -1448,8 +1448,8 @@ public AbstractStringBuilder insert(int dstOffset, CharSequence s, shift(currValue, coder, count, dstOffset, len); count += len; // Coder of CharSequence may be a mismatch, requiring the value array to be inflated - byte[] newValue = (s instanceof String str) - ? putStringAt(currValue, coder, count, dstOffset, str, start, end) + byte[] newValue = (s instanceof String str && str.length() == len) + ? putStringAt(currValue, coder, count, dstOffset, str) : putCharsAt(currValue, coder, count, dstOffset, s, start, end); if (currValue != newValue) { this.coder = UTF16; @@ -1928,10 +1928,10 @@ private static byte[] inflateIfNeededFor(byte[] value, int count, byte coder, by * @param index the index to insert the string * @param str the string */ - private static byte[] putStringAt(byte[] value, byte coder, int count, int index, String str, int off, int end) { + private static byte[] putStringAt(byte[] value, byte coder, int count, int index, String str) { byte[] newValue = inflateIfNeededFor(value, count, coder, str.coder()); coder = (newValue == value) ? coder : UTF16; - str.getBytes(newValue, off, index, coder, end - off); + str.getBytes(newValue, 0, index, coder, str.length()); return newValue; } diff --git a/src/java.base/share/classes/java/lang/ClassValue.java b/src/java.base/share/classes/java/lang/ClassValue.java index dfbdf3c5bf8..2a133324fb5 100644 --- a/src/java.base/share/classes/java/lang/ClassValue.java +++ b/src/java.base/share/classes/java/lang/ClassValue.java @@ -476,6 +476,9 @@ synchronized Object readAccess(ClassValue classValue) { if (updated != entry) { put(classValue.identity, updated); } + // Add to the cache, to enable the fast path, next time. + checkCacheLoad(); + addToCache(classValue, updated); } return item; } diff --git a/src/java.base/share/classes/java/lang/ScopedValue.java b/src/java.base/share/classes/java/lang/ScopedValue.java index 206c81d5238..c3d4cab162d 100644 --- a/src/java.base/share/classes/java/lang/ScopedValue.java +++ b/src/java.base/share/classes/java/lang/ScopedValue.java @@ -566,7 +566,7 @@ public T get() { @SuppressWarnings("unchecked") private T slowGet() { - var value = findBinding(); + Object value = scopedValueBindings().find(this); if (value == Snapshot.NIL) { throw new NoSuchElementException("ScopedValue not bound"); } @@ -575,32 +575,35 @@ private T slowGet() { } /** - * {@return {@code true} if this scoped value is bound in the current thread} + * Return the value of the scoped value or NIL if not bound. + * Consult the cache, and only if the value is not found there + * search the list of bindings. Update the cache if the binding + * was found. */ - public boolean isBound() { + private Object findBinding() { Object[] objects = scopedValueCache(); if (objects != null) { int n = (hash & Cache.SLOT_MASK) * 2; if (objects[n] == this) { - return true; + return objects[n + 1]; } n = ((hash >>> Cache.INDEX_BITS) & Cache.SLOT_MASK) * 2; if (objects[n] == this) { - return true; + return objects[n + 1]; } } - var value = findBinding(); - boolean result = (value != Snapshot.NIL); - if (result) Cache.put(this, value); - return result; + Object value = scopedValueBindings().find(this); + boolean found = (value != Snapshot.NIL); + if (found) Cache.put(this, value); + return value; } /** - * Return the value of the scoped value or NIL if not bound. + * {@return {@code true} if this scoped value is bound in the current thread} */ - private Object findBinding() { - Object value = scopedValueBindings().find(this); - return value; + public boolean isBound() { + Object obj = findBinding(); + return obj != Snapshot.NIL; } /** diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java index bcdbc39e665..bc42aa8a9fe 100644 --- a/src/java.base/share/classes/java/lang/System.java +++ b/src/java.base/share/classes/java/lang/System.java @@ -238,10 +238,11 @@ public static void setErr(PrintStream err) { private static volatile Console cons; /** - * Returns the unique {@link java.io.Console Console} object associated + * Returns the unique {@link Console Console} object associated * with the current Java virtual machine, if any. * * @return The system console, if any, otherwise {@code null}. + * @see Console * * @since 1.6 */ diff --git a/src/java.base/share/classes/java/lang/VirtualThread.java b/src/java.base/share/classes/java/lang/VirtualThread.java index 19465eb32db..b0b134e69a3 100644 --- a/src/java.base/share/classes/java/lang/VirtualThread.java +++ b/src/java.base/share/classes/java/lang/VirtualThread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -89,15 +89,19 @@ final class VirtualThread extends BaseVirtualThread { * * RUNNING -> PARKING // Thread parking with LockSupport.park * PARKING -> PARKED // cont.yield successful, parked indefinitely - * PARKING -> PINNED // cont.yield failed, parked indefinitely on carrier * PARKED -> UNPARKED // unparked, may be scheduled to continue - * PINNED -> RUNNING // unparked, continue execution on same carrier * UNPARKED -> RUNNING // continue execution after park * + * PARKING -> RUNNING // cont.yield failed, need to park on carrier + * RUNNING -> PINNED // park on carrier + * PINNED -> RUNNING // unparked, continue execution on same carrier + * * RUNNING -> TIMED_PARKING // Thread parking with LockSupport.parkNanos * TIMED_PARKING -> TIMED_PARKED // cont.yield successful, timed-parked - * TIMED_PARKING -> TIMED_PINNED // cont.yield failed, timed-parked on carrier * TIMED_PARKED -> UNPARKED // unparked, may be scheduled to continue + * + * TIMED_PARKING -> RUNNING // cont.yield failed, need to park on carrier + * RUNNING -> TIMED_PINNED // park on carrier * TIMED_PINNED -> RUNNING // unparked, continue execution on same carrier * * RUNNING -> BLOCKING // blocking on monitor enter @@ -108,7 +112,7 @@ final class VirtualThread extends BaseVirtualThread { * RUNNING -> WAITING // transitional state during wait on monitor * WAITING -> WAIT // waiting on monitor * WAIT -> BLOCKED // notified, waiting to be unblocked by monitor owner - * WAIT -> UNBLOCKED // timed-out/interrupted + * WAIT -> UNBLOCKED // interrupted * * RUNNING -> TIMED_WAITING // transition state during timed-waiting on monitor * TIMED_WAITING -> TIMED_WAIT // timed-waiting on monitor @@ -838,16 +842,20 @@ private void parkOnCarrierThread(boolean timed, long nanos) { * Re-enables this virtual thread for scheduling. If this virtual thread is parked * then its task is scheduled to continue, otherwise its next call to {@code park} or * {@linkplain #parkNanos(long) parkNanos} is guaranteed not to block. + * @param lazySubmit to use lazySubmit if possible * @throws RejectedExecutionException if the scheduler cannot accept a task */ - @Override - void unpark() { + private void unpark(boolean lazySubmit) { if (!getAndSetParkPermit(true) && currentThread() != this) { int s = state(); // unparked while parked if ((s == PARKED || s == TIMED_PARKED) && compareAndSetState(s, UNPARKED)) { - submitRunContinuation(); + if (lazySubmit) { + lazySubmitRunContinuation(); + } else { + submitRunContinuation(); + } return; } @@ -870,6 +878,11 @@ void unpark() { } } + @Override + void unpark() { + unpark(false); + } + /** * Invoked by unblocker thread to unblock this virtual thread. */ @@ -886,11 +899,7 @@ private void unblock() { */ private void parkTimeoutExpired() { assert !VirtualThread.currentThread().isVirtual(); - if (!getAndSetParkPermit(true) - && (state() == TIMED_PARKED) - && compareAndSetState(TIMED_PARKED, UNPARKED)) { - lazySubmitRunContinuation(); - } + unpark(true); } /** diff --git a/src/java.base/share/classes/java/net/InMemoryCookieStore.java b/src/java.base/share/classes/java/net/InMemoryCookieStore.java index 0ce3dc5b68c..1c72549e37d 100644 --- a/src/java.base/share/classes/java/net/InMemoryCookieStore.java +++ b/src/java.base/share/classes/java/net/InMemoryCookieStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, 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,10 +25,6 @@ package java.net; -import java.net.URI; -import java.net.CookieStore; -import java.net.HttpCookie; -import java.net.URISyntaxException; import java.util.List; import java.util.Map; import java.util.ArrayList; @@ -72,6 +68,7 @@ public InMemoryCookieStore() { /** * Add one cookie into cookie store. */ + @Override public void add(URI uri, HttpCookie cookie) { // pre-condition : argument can't be null if (cookie == null) { @@ -109,6 +106,7 @@ public void add(URI uri, HttpCookie cookie) { * 3) not expired. * See RFC 2965 sec. 3.3.4 for more detail. */ + @Override public List get(URI uri) { // argument can't be null if (uri == null) { @@ -127,12 +125,13 @@ public List get(URI uri) { lock.unlock(); } - return cookies; + return Collections.unmodifiableList(cookies); } /** * Get all cookies in cookie store, except those have expired */ + @Override public List getCookies() { List rt; @@ -156,6 +155,7 @@ public List getCookies() { * Get all URIs, which are associated with at least one cookie * of this cookie store. */ + @Override public List getURIs() { List uris = new ArrayList<>(); @@ -165,7 +165,7 @@ public List getURIs() { while (it.hasNext()) { URI uri = it.next(); List cookies = uriIndex.get(uri); - if (cookies == null || cookies.size() == 0) { + if (cookies == null || cookies.isEmpty()) { // no cookies list or an empty list associated with // this uri entry, delete it it.remove(); @@ -176,13 +176,14 @@ public List getURIs() { lock.unlock(); } - return uris; + return Collections.unmodifiableList(uris); } /** * Remove a cookie from store */ + @Override public boolean remove(URI uri, HttpCookie ck) { // argument can't be null if (ck == null) { @@ -204,6 +205,7 @@ public boolean remove(URI uri, HttpCookie ck) { /** * Remove all cookies in this cookie store. */ + @Override public boolean removeAll() { lock.lock(); try { diff --git a/src/java.base/share/classes/java/nio/Bits.java b/src/java.base/share/classes/java/nio/Bits.java index b11cb4947db..a9a22d6079e 100644 --- a/src/java.base/share/classes/java/nio/Bits.java +++ b/src/java.base/share/classes/java/nio/Bits.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -234,4 +234,28 @@ public long getMemoryUsed() { // of an element by element copy. These numbers may change over time. static final int JNI_COPY_TO_ARRAY_THRESHOLD = 6; static final int JNI_COPY_FROM_ARRAY_THRESHOLD = 6; + + // Maximum number of bytes to set in one call to {@code Unsafe.setMemory}. + // This threshold allows safepoint polling during large memory operations. + static final long UNSAFE_SET_THRESHOLD = 1024 * 1024; + + /** + * Sets a block of memory starting from a given address to a specified byte value. + * + * @param srcAddr + * the starting memory address + * @param count + * the number of bytes to set + * @param value + * the byte value to set + */ + static void setMemory(long srcAddr, long count, byte value) { + long offset = 0; + while (offset < count) { + long len = Math.min(UNSAFE_SET_THRESHOLD, count - offset); + UNSAFE.setMemory(srcAddr + offset, len, value); + offset += len; + } + } + } diff --git a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template index 0da1dc66a9a..580109a2eb0 100644 --- a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template +++ b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -114,7 +114,7 @@ class Direct$Type$Buffer$RW$$BO$ Bits.unreserveMemory(size, cap); throw x; } - UNSAFE.setMemory(base, size, (byte) 0); + Bits.setMemory(base, size, (byte) 0); if (pa && (base % ps != 0)) { // Round up to page boundary address = base + ps - (base & (ps - 1)); diff --git a/src/java.base/share/classes/java/security/KeyStore.java b/src/java.base/share/classes/java/security/KeyStore.java index 9e50a1588e7..8f3d4ba29fd 100644 --- a/src/java.base/share/classes/java/security/KeyStore.java +++ b/src/java.base/share/classes/java/security/KeyStore.java @@ -37,6 +37,7 @@ import javax.security.auth.callback.*; import sun.security.util.Debug; +import sun.security.util.CryptoAlgorithmConstraints; /** * This class represents a storage facility for cryptographic @@ -841,12 +842,21 @@ private String getProviderName() { * the {@link Security#getProviders() Security.getProviders()} method. * * @implNote - * The JDK Reference Implementation additionally uses the - * {@code jdk.security.provider.preferred} + * The JDK Reference Implementation additionally uses + *

* * @param type the type of keystore. * See the KeyStore section in the Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * + * @implNote + * The JDK Reference Implementation additionally uses + * the {@code jdk.crypto.disabledAlgorithms} + * {@link Security#getProperty(String) Security} property to determine + * if the specified keystore type is allowed. If the + * {@systemProperty jdk.crypto.disabledAlgorithms} is set, it supersedes + * the security property value. + * * @param type the type of keystore. * See the KeyStore section in the @@ -917,8 +940,15 @@ public static KeyStore getInstance(String type, String provider) throws KeyStoreException, NoSuchProviderException { Objects.requireNonNull(type, "null type name"); - if (provider == null || provider.isEmpty()) + + if (provider == null || provider.isEmpty()) { throw new IllegalArgumentException("missing provider"); + } + + if (!CryptoAlgorithmConstraints.permits("KEYSTORE", type)) { + throw new KeyStoreException(type + " is disabled"); + } + try { Object[] objs = Security.getImpl(type, "KeyStore", provider); return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type); @@ -935,6 +965,14 @@ public static KeyStore getInstance(String type, String provider) * object is returned. Note that the specified provider object * does not have to be registered in the provider list. * + * @implNote + * The JDK Reference Implementation additionally uses + * the {@code jdk.crypto.disabledAlgorithms} + * {@link Security#getProperty(String) Security} property to determine + * if the specified keystore type is allowed. If the + * {@systemProperty jdk.crypto.disabledAlgorithms} is set, it supersedes + * the security property value. + * * @param type the type of keystore. * See the KeyStore section in the @@ -963,8 +1001,15 @@ public static KeyStore getInstance(String type, Provider provider) throws KeyStoreException { Objects.requireNonNull(type, "null type name"); - if (provider == null) + + if (provider == null) { throw new IllegalArgumentException("missing provider"); + } + + if (!CryptoAlgorithmConstraints.permits("KEYSTORE", type)) { + throw new KeyStoreException(type + " is disabled"); + } + try { Object[] objs = Security.getImpl(type, "KeyStore", provider); return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type); @@ -1677,6 +1722,14 @@ public final void setEntry(String alias, Entry entry, *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * + * @implNote + * The JDK Reference Implementation additionally uses + * the {@code jdk.crypto.disabledAlgorithms} + * {@link Security#getProperty(String) Security} property to determine + * if the specified keystore type is allowed. If the + * {@systemProperty jdk.crypto.disabledAlgorithms} is set, it supersedes + * the security property value. Disallowed type will be skipped. + * * @param file the keystore file * @param password the keystore password, which may be {@code null} * @@ -1730,6 +1783,14 @@ public static final KeyStore getInstance(File file, char[] password) *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * + * @implNote + * The JDK Reference Implementation additionally uses + * the {@code jdk.crypto.disabledAlgorithms} + * {@link Security#getProperty(String) Security} property to determine + * if the specified keystore type is allowed. If the + * {@systemProperty jdk.crypto.disabledAlgorithms} is set, it supersedes + * the security property value. Disallowed type will be skipped. + * * @param file the keystore file * @param param the {@code LoadStoreParameter} that specifies how to load * the keystore, which may be {@code null} @@ -1798,8 +1859,12 @@ private static final KeyStore getInstance(File file, char[] password, kdebug.println(s.getAlgorithm() + " keystore detected: " + file); } - keystore = new KeyStore(impl, p, s.getAlgorithm()); - break; + String ksAlgo = s.getAlgorithm(); + if (CryptoAlgorithmConstraints.permits( + "KEYSTORE", ksAlgo)) { + keystore = new KeyStore(impl, p, ksAlgo); + break; + } } } catch (NoSuchAlgorithmException e) { // ignore diff --git a/src/java.base/share/classes/java/security/MessageDigest.java b/src/java.base/share/classes/java/security/MessageDigest.java index fa8d3dea8fd..6e8f64f7ebe 100644 --- a/src/java.base/share/classes/java/security/MessageDigest.java +++ b/src/java.base/share/classes/java/security/MessageDigest.java @@ -33,6 +33,7 @@ import sun.security.jca.GetInstance; import sun.security.util.Debug; import sun.security.util.MessageDigestSpi2; +import sun.security.util.CryptoAlgorithmConstraints; import javax.crypto.SecretKey; @@ -155,12 +156,22 @@ private MessageDigest(String algorithm, Provider p) { * the {@link Security#getProviders() Security.getProviders()} method. * * @implNote - * The JDK Reference Implementation additionally uses the - * {@code jdk.security.provider.preferred} + * The JDK Reference Implementation additionally uses the following + * security properties: + *

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

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * + * @implNote + * The JDK Reference Implementation additionally uses + * the {@code jdk.crypto.disabledAlgorithms} + * {@link Security#getProperty(String) Security} property to determine + * if the specified algorithm is allowed. If the + * {@systemProperty jdk.crypto.disabledAlgorithms} is set, it supersedes + * the security property value. + * * @param algorithm the name of the algorithm requested. * See the Signature section in the @@ -398,18 +396,11 @@ private static boolean isSpi(Service s) { public static Signature getInstance(String algorithm, String provider) throws NoSuchAlgorithmException, NoSuchProviderException { Objects.requireNonNull(algorithm, "null algorithm name"); - if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) { - // exception compatibility with existing code - if (provider == null || provider.isEmpty()) { - throw new IllegalArgumentException("missing provider"); - } - Provider p = Security.getProvider(provider); - if (p == null) { - throw new NoSuchProviderException - ("no such provider: " + provider); - } - return getInstanceRSA(p); + + if (!CryptoAlgorithmConstraints.permits("Signature", algorithm)) { + throw new NoSuchAlgorithmException(algorithm + " is disabled"); } + Instance instance = GetInstance.getInstance ("Signature", SignatureSpi.class, algorithm, provider); return getInstance(instance, algorithm); @@ -424,6 +415,14 @@ public static Signature getInstance(String algorithm, String provider) * is returned. Note that the specified provider does not * have to be registered in the provider list. * + * @implNote + * The JDK Reference Implementation additionally uses + * the {@code jdk.crypto.disabledAlgorithms} + * {@link Security#getProperty(String) Security} property to determine + * if the specified algorithm is allowed. If the + * {@systemProperty jdk.crypto.disabledAlgorithms} is set, it supersedes + * the security property value. + * * @param algorithm the name of the algorithm requested. * See the Signature section in the @@ -450,40 +449,16 @@ public static Signature getInstance(String algorithm, String provider) public static Signature getInstance(String algorithm, Provider provider) throws NoSuchAlgorithmException { Objects.requireNonNull(algorithm, "null algorithm name"); - if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) { - // exception compatibility with existing code - if (provider == null) { - throw new IllegalArgumentException("missing provider"); - } - return getInstanceRSA(provider); + + if (!CryptoAlgorithmConstraints.permits("Signature", algorithm)) { + throw new NoSuchAlgorithmException(algorithm + " is disabled"); } + Instance instance = GetInstance.getInstance ("Signature", SignatureSpi.class, algorithm, provider); return getInstance(instance, algorithm); } - // return an implementation for NONEwithRSA, which is a special case - // because of the Cipher.RSA/ECB/PKCS1Padding compatibility wrapper - private static Signature getInstanceRSA(Provider p) - throws NoSuchAlgorithmException { - // try Signature first - Service s = p.getService("Signature", RSA_SIGNATURE); - if (s != null) { - Instance instance = GetInstance.getInstance(s, SignatureSpi.class); - return getInstance(instance, RSA_SIGNATURE); - } - // check Cipher - try { - Cipher c = Cipher.getInstance(RSA_CIPHER, p); - return Delegate.of(new CipherAdapter(c), RSA_SIGNATURE); - } catch (GeneralSecurityException e) { - // throw Signature style exception message to avoid confusion, - // but append Cipher exception as cause - throw new NoSuchAlgorithmException("no such algorithm: " - + RSA_SIGNATURE + " for provider " + p.getName(), e); - } - } - /** * Returns the provider of this {@code Signature} object. * @@ -1179,22 +1154,12 @@ public Object clone() throws CloneNotSupportedException { private static SignatureSpi newInstance(Service s) throws NoSuchAlgorithmException { - if (s.getType().equals("Cipher")) { - // must be NONEwithRSA - try { - Cipher c = Cipher.getInstance(RSA_CIPHER, s.getProvider()); - return new CipherAdapter(c); - } catch (NoSuchPaddingException e) { - throw new NoSuchAlgorithmException(e); - } - } else { - Object o = s.newInstance(null); - if (!(o instanceof SignatureSpi)) { - throw new NoSuchAlgorithmException - ("Not a SignatureSpi: " + o.getClass().getName()); - } - return (SignatureSpi)o; + Object o = s.newInstance(null); + if (!(o instanceof SignatureSpi)) { + throw new NoSuchAlgorithmException + ("Not a SignatureSpi: " + o.getClass().getName()); } + return (SignatureSpi)o; } // max number of debug warnings to print from chooseFirstProvider() @@ -1471,92 +1436,4 @@ protected AlgorithmParameters engineGetParameters() { return sigSpi.engineGetParameters(); } } - - // adapter for RSA/ECB/PKCS1Padding ciphers - @SuppressWarnings("deprecation") - private static class CipherAdapter extends SignatureSpi { - - private final Cipher cipher; - - private ByteArrayOutputStream data; - - CipherAdapter(Cipher cipher) { - this.cipher = cipher; - } - - protected void engineInitVerify(PublicKey publicKey) - throws InvalidKeyException { - cipher.init(Cipher.DECRYPT_MODE, publicKey); - if (data == null) { - data = new ByteArrayOutputStream(128); - } else { - data.reset(); - } - } - - protected void engineInitSign(PrivateKey privateKey) - throws InvalidKeyException { - cipher.init(Cipher.ENCRYPT_MODE, privateKey); - data = null; - } - - protected void engineInitSign(PrivateKey privateKey, - SecureRandom random) throws InvalidKeyException { - cipher.init(Cipher.ENCRYPT_MODE, privateKey, random); - data = null; - } - - protected void engineUpdate(byte b) throws SignatureException { - engineUpdate(new byte[] {b}, 0, 1); - } - - protected void engineUpdate(byte[] b, int off, int len) - throws SignatureException { - if (data != null) { - data.write(b, off, len); - return; - } - byte[] out = cipher.update(b, off, len); - if ((out != null) && (out.length != 0)) { - throw new SignatureException - ("Cipher unexpectedly returned data"); - } - } - - protected byte[] engineSign() throws SignatureException { - try { - return cipher.doFinal(); - } catch (IllegalBlockSizeException | BadPaddingException e) { - throw new SignatureException("doFinal() failed", e); - } - } - - protected boolean engineVerify(byte[] sigBytes) - throws SignatureException { - try { - byte[] out = cipher.doFinal(sigBytes); - byte[] dataBytes = data.toByteArray(); - data.reset(); - return MessageDigest.isEqual(out, dataBytes); - } catch (BadPaddingException e) { - // e.g. wrong public key used - // return false rather than throwing exception - return false; - } catch (IllegalBlockSizeException e) { - throw new SignatureException("doFinal() failed", e); - } - } - - protected void engineSetParameter(String param, Object value) - throws InvalidParameterException { - throw new InvalidParameterException("Parameters not supported"); - } - - protected Object engineGetParameter(String param) - throws InvalidParameterException { - throw new InvalidParameterException("Parameters not supported"); - } - - } - } diff --git a/src/java.base/share/classes/java/text/Collator.java b/src/java.base/share/classes/java/text/Collator.java index 7f6db310366..9b8ab0e5d9a 100644 --- a/src/java.base/share/classes/java/text/Collator.java +++ b/src/java.base/share/classes/java/text/Collator.java @@ -111,8 +111,13 @@ *
* @apiNote {@code CollationKey}s from different * {@code Collator}s can not be compared. See the class description - * for {@link CollationKey} - * for an example using {@code CollationKey}s. + * for {@link CollationKey} for an example using {@code CollationKey}s. + * + * @implNote Significant thread contention may occur during concurrent usage + * of the JDK Reference Implementation's {@link RuleBasedCollator}, which is the + * subtype returned by the default provider of the {@link #getInstance()} factory + * methods. As such, users should consider retrieving a separate instance for + * each thread when used in multithreaded environments. * * @see RuleBasedCollator * @see CollationKey diff --git a/src/java.base/share/classes/java/text/CompactNumberFormat.java b/src/java.base/share/classes/java/text/CompactNumberFormat.java index fae11cbdba1..b14d9645f8a 100644 --- a/src/java.base/share/classes/java/text/CompactNumberFormat.java +++ b/src/java.base/share/classes/java/text/CompactNumberFormat.java @@ -247,38 +247,43 @@ public final class CompactNumberFormat extends NumberFormat { /** * List of positive prefix patterns of this formatter's - * compact number patterns. + * compact number patterns. This field is a read-only + * constant once initialized. */ private transient List positivePrefixPatterns; /** * List of negative prefix patterns of this formatter's - * compact number patterns. + * compact number patterns. This field is a read-only + * constant once initialized. */ private transient List negativePrefixPatterns; /** * List of positive suffix patterns of this formatter's - * compact number patterns. + * compact number patterns. This field is a read-only + * constant once initialized. */ private transient List positiveSuffixPatterns; /** * List of negative suffix patterns of this formatter's - * compact number patterns. + * compact number patterns. This field is a read-only + * constant once initialized. */ private transient List negativeSuffixPatterns; /** * List of divisors of this formatter's compact number patterns. * Divisor can be either Long or BigInteger (if the divisor value goes - * beyond long boundary) + * beyond long boundary). This field is a read-only constant + * once initialized. */ private transient List divisors; /** * List of place holders that represent minimum integer digits at each index - * for each count. + * for each count. This field is a read-only constant once initialized. */ private transient List placeHolderPatterns; @@ -371,7 +376,7 @@ public final class CompactNumberFormat extends NumberFormat { /** * The map for plural rules that maps LDML defined tags (e.g. "one") to - * its rule. + * its rule. This field is a read-only constant once initialized. */ private transient Map rulesMap; @@ -1512,7 +1517,7 @@ private void applyPattern(String count, String pattern, int index) { } } - private final transient DigitList digitList = new DigitList(); + private transient DigitList digitList = new DigitList(); private static final int STATUS_INFINITE = 0; private static final int STATUS_POSITIVE = 1; private static final int STATUS_LENGTH = 2; @@ -2504,8 +2509,14 @@ public String toString() { @Override public CompactNumberFormat clone() { CompactNumberFormat other = (CompactNumberFormat) super.clone(); + + // Cloning reference fields. Other fields (e.g., "positivePrefixPatterns") + // are not cloned since they are read-only constants after initialization. other.compactPatterns = compactPatterns.clone(); other.symbols = (DecimalFormatSymbols) symbols.clone(); + other.decimalFormat = (DecimalFormat) decimalFormat.clone(); + other.defaultDecimalFormat = (DecimalFormat) defaultDecimalFormat.clone(); + other.digitList = (DigitList) digitList.clone(); return other; } diff --git a/src/java.base/share/classes/java/text/DigitList.java b/src/java.base/share/classes/java/text/DigitList.java index d757f03bb84..fb012e86f6e 100644 --- a/src/java.base/share/classes/java/text/DigitList.java +++ b/src/java.base/share/classes/java/text/DigitList.java @@ -361,6 +361,11 @@ private void set(boolean isNegative, String s, decimalAt += exponent - leadingZerosAfterDecimal; } + // Eliminate trailing zeros. + while (count > 1 && digits[count - 1] == '0') { + --count; + } + if (fixedPoint) { // The negative of the exponent represents the number of leading // zeros between the decimal and the first non-zero digit, for @@ -387,11 +392,6 @@ private void set(boolean isNegative, String s, // else fall through } - // Eliminate trailing zeros. - while (count > 1 && digits[count - 1] == '0') { - --count; - } - // Eliminate digits beyond maximum digits to be displayed. // Round up if appropriate. round(fixedPoint ? (maximumDigits + decimalAt) : maximumDigits, diff --git a/src/java.base/share/classes/java/text/RuleBasedCollator.java b/src/java.base/share/classes/java/text/RuleBasedCollator.java index dc45dafb846..af1b6b62bdf 100644 --- a/src/java.base/share/classes/java/text/RuleBasedCollator.java +++ b/src/java.base/share/classes/java/text/RuleBasedCollator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, 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 @@ -38,10 +38,6 @@ package java.text; -import java.text.Normalizer; -import java.util.Vector; -import java.util.Locale; - /** * The {@code RuleBasedCollator} class is a concrete subclass of * {@code Collator} that provides a simple, data-driven, table @@ -239,6 +235,11 @@ * * * + * @implNote For this implementation, concurrent usage of this class may + * lead to significant thread contention since {@code synchronized} is employed + * to ensure thread-safety. As such, users of this class should consider creating + * a separate instance for each thread when used in multithreaded environments. + * * @see Collator * @see CollationElementIterator * @author Helena Shih, Laura Werner, Richard Gillam diff --git a/src/java.base/share/classes/java/time/LocalDate.java b/src/java.base/share/classes/java/time/LocalDate.java index 6724410da2b..016bdab5394 100644 --- a/src/java.base/share/classes/java/time/LocalDate.java +++ b/src/java.base/share/classes/java/time/LocalDate.java @@ -182,11 +182,11 @@ public final class LocalDate /** * @serial The month-of-year. */ - private final byte month; + private final short month; /** * @serial The day-of-month. */ - private final byte day; + private final short day; //----------------------------------------------------------------------- /** @@ -490,8 +490,8 @@ private static LocalDate resolvePreviousValid(int year, int month, int day) { */ private LocalDate(int year, int month, int dayOfMonth) { this.year = year; - this.month = (byte) month; - this.day = (byte) dayOfMonth; + this.month = (short) month; + this.day = (short) dayOfMonth; } //----------------------------------------------------------------------- diff --git a/src/java.base/share/classes/java/time/MonthDay.java b/src/java.base/share/classes/java/time/MonthDay.java index 6244c14e6e1..1de4fa84d3e 100644 --- a/src/java.base/share/classes/java/time/MonthDay.java +++ b/src/java.base/share/classes/java/time/MonthDay.java @@ -146,11 +146,11 @@ public final class MonthDay /** * @serial The month-of-year, not null. */ - private final byte month; + private final int month; /** * @serial The day-of-month. */ - private final byte day; + private final int day; //----------------------------------------------------------------------- /** @@ -319,8 +319,8 @@ public static MonthDay parse(CharSequence text, DateTimeFormatter formatter) { * @param dayOfMonth the day-of-month to represent, validated from 1 to 29-31 */ private MonthDay(int month, int dayOfMonth) { - this.month = (byte) month; - this.day = (byte) dayOfMonth; + this.month = month; + this.day = dayOfMonth; } //----------------------------------------------------------------------- diff --git a/src/java.base/share/classes/java/time/YearMonth.java b/src/java.base/share/classes/java/time/YearMonth.java index b24151de3f0..8ad1172811f 100644 --- a/src/java.base/share/classes/java/time/YearMonth.java +++ b/src/java.base/share/classes/java/time/YearMonth.java @@ -153,7 +153,7 @@ public final class YearMonth /** * @serial The month-of-year, not null. */ - private final byte month; + private final int month; //----------------------------------------------------------------------- /** @@ -306,7 +306,7 @@ public static YearMonth parse(CharSequence text, DateTimeFormatter formatter) { */ private YearMonth(int year, int month) { this.year = year; - this.month = (byte) month; + this.month = month; } /** diff --git a/src/java.base/share/classes/java/time/chrono/HijrahDate.java b/src/java.base/share/classes/java/time/chrono/HijrahDate.java index 2d3e4f93e69..114a47e4797 100644 --- a/src/java.base/share/classes/java/time/chrono/HijrahDate.java +++ b/src/java.base/share/classes/java/time/chrono/HijrahDate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -137,11 +137,11 @@ public final class HijrahDate /** * The month-of-year. */ - private final transient byte monthOfYear; + private final transient int monthOfYear; /** * The day-of-month. */ - private final transient byte dayOfMonth; + private final transient int dayOfMonth; //------------------------------------------------------------------------- /** @@ -273,8 +273,8 @@ private HijrahDate(HijrahChronology chrono, int prolepticYear, int monthOfYear, this.chrono = chrono; this.prolepticYear = prolepticYear; - this.monthOfYear = (byte) monthOfYear; - this.dayOfMonth = (byte) dayOfMonth; + this.monthOfYear = monthOfYear; + this.dayOfMonth = dayOfMonth; } /** @@ -287,8 +287,8 @@ private HijrahDate(HijrahChronology chrono, long epochDay) { this.chrono = chrono; this.prolepticYear = dateInfo[0]; - this.monthOfYear = (byte) dateInfo[1]; - this.dayOfMonth = (byte) dateInfo[2]; + this.monthOfYear = dateInfo[1]; + this.dayOfMonth = dateInfo[2]; } //----------------------------------------------------------------------- diff --git a/src/java.base/share/classes/java/util/GregorianCalendar.java b/src/java.base/share/classes/java/util/GregorianCalendar.java index 9c75cbc5732..26b0c7c1f2f 100644 --- a/src/java.base/share/classes/java/util/GregorianCalendar.java +++ b/src/java.base/share/classes/java/util/GregorianCalendar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, 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 @@ -1214,8 +1214,10 @@ public void roll(int field, int amount) { d.setHours(hourOfDay); time = calsys.getTime(d); - // If we stay on the same wall-clock time, try the next or previous hour. - if (internalGet(HOUR_OF_DAY) == d.getHours()) { + // If the rolled amount is not a full HOUR/HOUR_OF_DAY (12/24-hour) cycle and + // if we stay on the same wall-clock time, try the next or previous hour. + if (((field == HOUR_OF_DAY && amount % 24 != 0) || (field == HOUR && amount % 12 != 0)) + && internalGet(HOUR_OF_DAY) == d.getHours()) { hourOfDay = getRolledValue(rolledValue, amount > 0 ? +1 : -1, min, max); if (field == HOUR && internalGet(AM_PM) == PM) { hourOfDay += 12; diff --git a/src/java.base/share/classes/java/util/SimpleTimeZone.java b/src/java.base/share/classes/java/util/SimpleTimeZone.java index 58d43692ee0..f047ce26e58 100644 --- a/src/java.base/share/classes/java/util/SimpleTimeZone.java +++ b/src/java.base/share/classes/java/util/SimpleTimeZone.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, 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 @@ -112,15 +112,15 @@ *


  *      // Base GMT offset: -8:00
  *      // DST starts:      at 2:00am in standard time
- *      //                  on the first Sunday in April
+ *      //                  on the second Sunday in March
  *      // DST ends:        at 2:00am in daylight time
- *      //                  on the last Sunday in October
+ *      //                  on the first Sunday in November
  *      // Save:            1 hour
  *      SimpleTimeZone(-28800000,
  *                     "America/Los_Angeles",
- *                     Calendar.APRIL, 1, -Calendar.SUNDAY,
+ *                     Calendar.MARCH, 8, -Calendar.SUNDAY,
  *                     7200000,
- *                     Calendar.OCTOBER, -1, Calendar.SUNDAY,
+ *                     Calendar.NOVEMBER, 1, -Calendar.SUNDAY,
  *                     7200000,
  *                     3600000)
  *
@@ -863,13 +863,24 @@ public Object clone()
     }
 
     /**
-     * Generates the hash code for the SimpleDateFormat object.
+     * Generates the hash code for the SimpleTimeZone object.
      * @return the hash code for this object
      */
     public int hashCode()
     {
-        return startMonth ^ startDay ^ startDayOfWeek ^ startTime ^
-            endMonth ^ endDay ^ endDayOfWeek ^ endTime ^ rawOffset;
+        int hash = 31 * getID().hashCode() + rawOffset;
+        hash = 31 * hash + Boolean.hashCode(useDaylight);
+        if (useDaylight) {
+            hash = 31 * hash + startMonth;
+            hash = 31 * hash + startDay;
+            hash = 31 * hash + startDayOfWeek;
+            hash = 31 * hash + startTime;
+            hash = 31 * hash + endMonth;
+            hash = 31 * hash + endDay;
+            hash = 31 * hash + endDayOfWeek;
+            hash = 31 * hash + endTime;
+        }
+        return hash;
     }
 
     /**
diff --git a/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java b/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java
index 7503c154ddb..1338f2fd804 100644
--- a/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java
+++ b/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java
@@ -1904,8 +1904,8 @@ private Object waitingGet(boolean interruptible) {
         while ((r = result) == null) {
             if (q == null) {
                 q = new Signaller(interruptible, 0L, 0L);
-                if (Thread.currentThread() instanceof ForkJoinWorkerThread)
-                    ForkJoinPool.helpAsyncBlocker(defaultExecutor(), q);
+                if (Thread.currentThread() instanceof ForkJoinWorkerThread wt)
+                    ForkJoinPool.helpAsyncBlocker(wt.pool, q);
             }
             else if (!queued)
                 queued = tryPushStack(q);
@@ -1950,8 +1950,8 @@ else if (nanos <= 0L)
                 break;
             else if (q == null) {
                 q = new Signaller(true, nanos, deadline);
-                if (Thread.currentThread() instanceof ForkJoinWorkerThread)
-                    ForkJoinPool.helpAsyncBlocker(defaultExecutor(), q);
+                if (Thread.currentThread() instanceof ForkJoinWorkerThread wt)
+                    ForkJoinPool.helpAsyncBlocker(wt.pool, q);
             }
             else if (!queued)
                 queued = tryPushStack(q);
diff --git a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java
index cef1682b0b1..abc9fdb348c 100644
--- a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java
+++ b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java
@@ -35,6 +35,13 @@
 
 package java.util.concurrent;
 
+import jdk.internal.misc.Unsafe;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamException;
+import java.io.Serial;
+import java.io.StreamCorruptedException;
 import java.util.AbstractSet;
 import java.util.Collection;
 import java.util.Iterator;
@@ -445,4 +452,38 @@ public Spliterator spliterator() {
         return Spliterators.spliterator
             (al.getArray(), Spliterator.IMMUTABLE | Spliterator.DISTINCT);
     }
+
+    /**
+     * De-serialization without data not supported for this class.
+     */
+    @Serial
+    private void readObjectNoData() throws ObjectStreamException {
+        throw new StreamCorruptedException("Deserialized CopyOnWriteArraySet requires data");
+    }
+
+    /**
+     * Reconstitutes the {@code CopyOnWriteArraySet} instance from a stream
+     * (that is, deserializes it).
+     * @throws StreamCorruptedException if the object read from the stream is invalid.
+     */
+    @Serial
+    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+        CopyOnWriteArrayList newAl; // Set during the duplicate check
+
+        @SuppressWarnings("unchecked")
+        CopyOnWriteArrayList inAl = (CopyOnWriteArrayList) in.readFields().get("al", null);
+
+        if (inAl == null
+                || inAl.getClass() != CopyOnWriteArrayList.class
+                || (newAl = new CopyOnWriteArrayList<>()).addAllAbsent(inAl) != inAl.size()) {
+            throw new StreamCorruptedException("Content is invalid");
+        }
+
+        final Unsafe U = Unsafe.getUnsafe();
+        U.putReference(
+                this,
+                U.objectFieldOffset(CopyOnWriteArraySet.class, "al"),
+                newAl
+        );
+    }
 }
diff --git a/src/java.base/share/classes/java/util/concurrent/DelayScheduler.java b/src/java.base/share/classes/java/util/concurrent/DelayScheduler.java
index 358d3b69f1e..339249d8eb7 100644
--- a/src/java.base/share/classes/java/util/concurrent/DelayScheduler.java
+++ b/src/java.base/share/classes/java/util/concurrent/DelayScheduler.java
@@ -360,31 +360,36 @@ private static int replace(ScheduledForkJoinTask[] h, int k, int n) {
                         u.heapIndex = -1;
                     }
                 }
-                if (t != null) {       // sift down
-                    for (int cs; (cs = (k << 2) + 1) < n; ) {
-                        ScheduledForkJoinTask leastChild = null, c;
+                if (t != null) {
+                    while (k > 0) {    // sift up if replaced with smaller value
+                        ScheduledForkJoinTask parent; int pk;
+                        if ((parent = h[pk = (k - 1) >>> 2]) == null ||
+                            parent.when <= d)
+                            break;
+                        parent.heapIndex = k;
+                        h[k] = parent;
+                        k = pk;
+                    }
+                    for (int cs; (cs = (k << 2) + 1) < n; ) { // sift down
+                        ScheduledForkJoinTask leastChild = null;
                         int leastIndex = 0;
-                        long leastValue = Long.MAX_VALUE;
-                        for (int ck = cs, j = 4;;) { // at most 4 children
-                            if ((c = h[ck]) == null)
-                                break;
-                            long cd = c.when;
-                            if (c.status < 0 && alsoReplace < 0) {
-                                alsoReplace = ck;    // at most once per pass
-                                c.heapIndex = -1;
-                            }
-                            else if (leastChild == null || cd < leastValue) {
+                        long leastValue = d;    // at most 4 children
+                        for (int ck, j = 0; j < 4 && (ck = j + cs) < n; ++j) {
+                            ScheduledForkJoinTask c; long cd;
+                            if ((c = h[ck]) != null && (cd = c.when) < leastValue) {
                                 leastValue = cd;
                                 leastIndex = ck;
                                 leastChild = c;
                             }
-                            if (--j == 0 || ++ck >= n)
-                                break;
                         }
-                        if (leastChild == null || d <= leastValue)
+                        if (leastChild == null) // already ordered
                             break;
-                        leastChild.heapIndex = k;
-                        h[k] = leastChild;
+                        if ((h[k] = leastChild).status >= 0 || alsoReplace >= 0)
+                            leastChild.heapIndex = k;
+                        else {
+                            leastChild.heapIndex = -1;
+                            alsoReplace = k;
+                        }
                         k = leastIndex;
                     }
                     t.heapIndex = k;
@@ -393,6 +398,7 @@ else if (leastChild == null || cd < leastValue) {
                 k = alsoReplace;
             }
         }
+        assert checkHeap(h, n);
         return n;
     }
 
@@ -451,6 +457,33 @@ private static void cancelAll(ScheduledForkJoinTask[] h, int n) {
         }
     }
 
+    /**
+     * Invariant checks
+     */
+    private static boolean checkHeap(ScheduledForkJoinTask[] h, int n) {
+        for (int i = 0; i < h.length; ++i) {
+            ScheduledForkJoinTask t = h[i];
+            if (t == null) {         // unused slots all null
+                if (i < n)
+                    return false;
+            }
+            else {
+                long v = t.when;
+                int x = t.heapIndex;
+                if (x != i && x >= 0) // valid index unless removing
+                    return false;
+                if (i > 0 && h[(i - 1) >>> 2].when > v) // ordered wrt parent
+                    return false;
+                int cs = (i << 2) + 1; // ordered wrt children
+                for (int ck, j = 0; j < 4 && (ck = cs + j) < n; ++j) {
+                    if (h[ck].when < v)
+                        return false;
+                }
+            }
+        }
+        return true;
+    }
+
     /**
      * Task class for DelayScheduler operations
      */
diff --git a/src/java.base/share/classes/java/util/concurrent/Executors.java b/src/java.base/share/classes/java/util/concurrent/Executors.java
index ba7c2e1efee..b3ffcdfb4ef 100644
--- a/src/java.base/share/classes/java/util/concurrent/Executors.java
+++ b/src/java.base/share/classes/java/util/concurrent/Executors.java
@@ -755,6 +755,13 @@ public void shutdown() {
             super.shutdown();
             cleanable.clean();  // unregisters the cleanable
         }
+
+        @Override
+        public List shutdownNow() {
+            List unexecuted = super.shutdownNow();
+            cleanable.clean();  // unregisters the cleanable
+            return unexecuted;
+        }
     }
 
     /**
diff --git a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
index a7821921bc9..cdc5e0b9ea6 100644
--- a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
+++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
@@ -1297,7 +1297,7 @@ final void push(ForkJoinTask task, ForkJoinPool pool, boolean internal) {
                     unlockPhase();
                 if (room < 0)
                     throw new RejectedExecutionException("Queue capacity exceeded");
-                if ((room == 0 || a[m & (s - pk)] == null) &&
+                if ((room == 0 || U.getReferenceAcquire(a, slotOffset(m & (s - pk))) == null) &&
                     pool != null)
                     pool.signalWork();   // may have appeared empty
             }
diff --git a/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java b/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java
index 51b2488264e..137cac45ed0 100644
--- a/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java
+++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java
@@ -531,19 +531,22 @@ final void doExec() {
      * still correct, although it may contain a misleading stack
      * trace.
      *
-     * @param asExecutionException true if wrap as ExecutionException
+     * @param asExecutionException true if wrap the result as an
+     * ExecutionException. This applies only to actual exceptions, not
+     * implicit CancellationExceptions issued when not THROWN or
+     * available, which are not wrapped because by default they are
+     * issued separately from ExecutionExceptions by callers. Which
+     * may require further handling when this is not true (currently
+     * only in InvokeAnyTask).
      * @return the exception, or null if none
      */
     private Throwable getException(boolean asExecutionException) {
         int s; Throwable ex; Aux a;
         if ((s = status) >= 0 || (s & ABNORMAL) == 0)
             return null;
-        else if ((s & THROWN) == 0 || (a = aux) == null || (ex = a.ex) == null) {
-            ex = new CancellationException();
-            if (!asExecutionException || !(this instanceof InterruptibleTask))
-                return ex;         // else wrap below
-        }
-        else if (a.thread != Thread.currentThread()) {
+        if ((s & THROWN) == 0 || (a = aux) == null || (ex = a.ex) == null)
+            return new CancellationException();
+        if (a.thread != Thread.currentThread()) {
             try {
                 Constructor noArgCtor = null, oneArgCtor = null;
                 for (Constructor c : ex.getClass().getConstructors()) {
@@ -1814,6 +1817,8 @@ final T invokeAny(Collection> tasks,
                                  (t = new InvokeAnyTask(c, this, t)));
                 }
                 return timed ? get(nanos, TimeUnit.NANOSECONDS) : get();
+            } catch (CancellationException ce) {
+                throw new ExecutionException(ce);
             } finally {
                 for (; t != null; t = t.pred)
                     t.onRootCompletion();
diff --git a/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java b/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java
index b942d3ecd09..566fc417952 100644
--- a/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java
+++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java
@@ -267,10 +267,8 @@ public void setUncaughtExceptionHandler(UncaughtExceptionHandler x) { }
 
         @Override // to record changes
         public void setContextClassLoader(ClassLoader cl) {
-            if (ClassLoader.getSystemClassLoader() != cl) {
-                resetCCL = true;
-                super.setContextClassLoader(cl);
-            }
+            resetCCL = ClassLoader.getSystemClassLoader() != cl;
+            super.setContextClassLoader(cl);
         }
 
         @Override // to re-establish CCL if necessary
diff --git a/src/java.base/share/classes/java/util/zip/GZIPInputStream.java b/src/java.base/share/classes/java/util/zip/GZIPInputStream.java
index ab7ea53793f..ebcb9e3204c 100644
--- a/src/java.base/share/classes/java/util/zip/GZIPInputStream.java
+++ b/src/java.base/share/classes/java/util/zip/GZIPInputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2026, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -79,7 +79,11 @@ public GZIPInputStream(InputStream in, int size) throws IOException {
         super(in, createInflater(in, size), size);
         usesDefaultInflater = true;
         try {
-            readHeader(in);
+            // we don't expect the stream to be at EOF
+            // and if it is, then we want readHeader to
+            // raise an exception, so we pass "true" for
+            // the "failOnEOF" param.
+            readHeader(in, true);
         } catch (IOException ioe) {
             this.inf.end();
             throw ioe;
@@ -190,12 +194,40 @@ public void close() throws IOException {
     /*
      * Reads GZIP member header and returns the total byte number
      * of this member header.
+     * If failOnEOF is false and if the given InputStream has already
+     * reached EOF when this method was invoked, then this method returns
+     * -1 (indicating that there's no GZIP member header).
+     * In all other cases of malformed header or EOF being detected
+     * when reading the header, this method will throw an IOException.
      */
-    private int readHeader(InputStream this_in) throws IOException {
+    private int readHeader(InputStream this_in, boolean failOnEOF) throws IOException {
         CheckedInputStream in = new CheckedInputStream(this_in, crc);
         crc.reset();
+
+        int magic;
+        if (!failOnEOF) {
+            // read an unsigned short value representing the GZIP magic header.
+            // this is the same as calling readUShort(in), except that here,
+            // when reading the first byte, we don't raise an EOFException
+            // if the stream has already reached EOF.
+
+            // read unsigned byte
+            int b = in.read();
+            if (b == -1) { // EOF
+                crc.reset();
+                return -1; // represents no header bytes available
+            }
+            checkUnexpectedByte(b);
+            // read the next unsigned byte to form the unsigned
+            // short. we throw the usual EOFException/ZipException
+            // from this point on if there is no more data or
+            // the data doesn't represent a header.
+            magic = (readUByte(in) << 8) | b;
+        } else {
+            magic = readUShort(in);
+        }
         // Check header magic
-        if (readUShort(in) != GZIP_MAGIC) {
+        if (magic != GZIP_MAGIC) {
             throw new ZipException("Not in GZIP format");
         }
         // Check compression method
@@ -261,7 +293,11 @@ public void close() throws IOException {}
         // try concatenated case
         int m = 8;                  // this.trailer
         try {
-            m += readHeader(in);    // next.header
+            int numNextHeaderBytes = readHeader(in, false); // next.header (if available)
+            if (numNextHeaderBytes == -1) {
+                return true; // end of stream reached
+            }
+            m += numNextHeaderBytes;
         } catch (IOException ze) {
             return true;  // ignore any malformed, do nothing
         }
@@ -295,12 +331,16 @@ private int readUByte(InputStream in) throws IOException {
         if (b == -1) {
             throw new EOFException();
         }
+        checkUnexpectedByte(b);
+        return b;
+    }
+
+    private void checkUnexpectedByte(final int b) throws IOException {
         if (b < -1 || b > 255) {
-            // Report on this.in, not argument in; see read{Header, Trailer}.
+            // report the InputStream type which returned this unexpected byte
             throw new IOException(this.in.getClass().getName()
-                + ".read() returned value out of range -1..255: " + b);
+                    + ".read() returned value out of range -1..255: " + b);
         }
-        return b;
     }
 
     private byte[] tmpbuf = new byte[128];
diff --git a/src/java.base/share/classes/javax/crypto/Cipher.java b/src/java.base/share/classes/javax/crypto/Cipher.java
index 3de732c6687..e00d17e2549 100644
--- a/src/java.base/share/classes/javax/crypto/Cipher.java
+++ b/src/java.base/share/classes/javax/crypto/Cipher.java
@@ -30,7 +30,6 @@
 import java.util.concurrent.ConcurrentMap;
 import java.util.regex.*;
 
-
 import java.security.*;
 import java.security.Provider.Service;
 import java.security.spec.AlgorithmParameterSpec;
@@ -46,6 +45,7 @@
 import sun.security.util.Debug;
 import sun.security.jca.*;
 import sun.security.util.KnownOIDs;
+import sun.security.util.CryptoAlgorithmConstraints;
 
 /**
  * This class provides the functionality of a cryptographic cipher for
@@ -316,19 +316,23 @@ private Cipher(CipherSpi firstSpi, Service firstService,
 
     private static final String SHA512TRUNCATED = "SHA512/2";
 
+    // Parse the specified cipher transformation for algorithm and the
+    // optional mode and padding. If the transformation contains only
+    // algorithm, then only algorithm is returned. Otherwise, the
+    // transformation must contain all 3 and they must be non-empty.
     private static String[] tokenizeTransformation(String transformation)
             throws NoSuchAlgorithmException {
         if (transformation == null) {
             throw new NoSuchAlgorithmException("No transformation given");
         }
+
         /*
-         * array containing the components of a cipher transformation:
+         * Components of a cipher transformation:
          *
-         * index 0: algorithm component (e.g., AES)
-         * index 1: feedback component (e.g., CFB)
-         * index 2: padding component (e.g., PKCS5Padding)
+         * 1) algorithm component (e.g., AES)
+         * 2) feedback component (e.g., CFB) - optional
+         * 3) padding component (e.g., PKCS5Padding) - optional
          */
-        String[] parts = { "", "", "" };
 
         // check if the transformation contains algorithms with "/" in their
         // name which can cause the parsing logic to go wrong
@@ -337,27 +341,35 @@ private static String[] tokenizeTransformation(String transformation)
         int startIdx = (sha512Idx == -1 ? 0 :
                 sha512Idx + SHA512TRUNCATED.length());
         int endIdx = transformation.indexOf('/', startIdx);
-        if (endIdx == -1) {
-            // algorithm
-            parts[0] = transformation.trim();
+
+        boolean algorithmOnly = (endIdx == -1);
+        String algo = (algorithmOnly ? transformation.trim() :
+                transformation.substring(0, endIdx).trim());
+        if (algo.isEmpty()) {
+            throw new NoSuchAlgorithmException("Invalid transformation: " +
+                                   "algorithm not specified-"
+                                   + transformation);
+        }
+        if (algorithmOnly) { // done
+            return new String[] { algo };
         } else {
-            // algorithm/mode/padding
-            parts[0] = transformation.substring(0, endIdx).trim();
+            // continue parsing mode and padding
             startIdx = endIdx+1;
             endIdx = transformation.indexOf('/', startIdx);
             if (endIdx == -1) {
                 throw new NoSuchAlgorithmException("Invalid transformation"
                             + " format:" + transformation);
             }
-            parts[1] = transformation.substring(startIdx, endIdx).trim();
-            parts[2] = transformation.substring(endIdx+1).trim();
-        }
-        if (parts[0].isEmpty()) {
-            throw new NoSuchAlgorithmException("Invalid transformation: " +
-                                   "algorithm not specified-"
+            String mode = transformation.substring(startIdx, endIdx).trim();
+            String padding = transformation.substring(endIdx+1).trim();
+            // ensure mode and padding are specified
+            if (mode.isEmpty() || padding.isEmpty()) {
+                throw new NoSuchAlgorithmException("Invalid transformation: " +
+                                   "missing mode and/or padding-"
                                    + transformation);
+            }
+            return new String[] { algo, mode, padding };
         }
-        return parts;
     }
 
     // Provider attribute name for supported chaining mode
@@ -453,22 +465,17 @@ private static List getTransforms(String transformation)
             throws NoSuchAlgorithmException {
         String[] parts = tokenizeTransformation(transformation);
 
-        String alg = parts[0];
-        String mode = parts[1];
-        String pad = parts[2];
-
-        if ((mode.length() == 0) && (pad.length() == 0)) {
+        if (parts.length == 1) {
             // Algorithm only
-            Transform tr = new Transform(alg, "", null, null);
-            return Collections.singletonList(tr);
+            return List.of(new Transform(parts[0], "", null, null));
         } else {
-            // Algorithm w/ at least mode or padding or both
-            List list = new ArrayList<>(4);
-            list.add(new Transform(alg, "/" + mode + "/" + pad, null, null));
-            list.add(new Transform(alg, "/" + mode, null, pad));
-            list.add(new Transform(alg, "//" + pad, mode, null));
-            list.add(new Transform(alg, "", mode, pad));
-            return list;
+            // Algorithm w/ both mode and padding
+            return List.of(
+                    new Transform(parts[0], "/" + parts[1] + "/" + parts[2],
+                    null, null),
+                    new Transform(parts[0], "/" + parts[1], null, parts[2]),
+                    new Transform(parts[0], "//" + parts[2], parts[1], null),
+                    new Transform(parts[0], "", parts[1], parts[2]));
         }
     }
 
@@ -504,8 +511,10 @@ private static Transform getTransform(Service s,
      * requirements of your application.
      *
      * @implNote
-     * The JDK Reference Implementation additionally uses the
-     * {@code jdk.security.provider.preferred}
+     * The JDK Reference Implementation additionally uses the following
+     * security properties:
+     * 
    + *
  • the {@code jdk.security.provider.preferred} * {@link Security#getProperty(String) Security} property to determine * the preferred provider order for the specified algorithm. This * may be different than the order of providers returned by @@ -513,6 +522,14 @@ private static Transform getTransform(Service s, * See also the Cipher Transformations section of the {@extLink * security_guide_jdk_providers JDK Providers} document for information * on the transformation defaults used by JDK providers. + *
  • + *
  • the {@code jdk.crypto.disabledAlgorithms} + * {@link Security#getProperty(String) Security} property to determine + * if the specified algorithm is allowed. If the + * {@systemProperty jdk.crypto.disabledAlgorithms} is set, it supersedes + * the security property value. + *
  • + *
* * @param transformation the name of the transformation, e.g., * AES/CBC/PKCS5Padding. @@ -541,6 +558,13 @@ public static final Cipher getInstance(String transformation) if ((transformation == null) || transformation.isEmpty()) { throw new NoSuchAlgorithmException("Null or empty transformation"); } + + // throws NoSuchAlgorithmException if java.security disables it + if (!CryptoAlgorithmConstraints.permits("Cipher", transformation)) { + throw new NoSuchAlgorithmException(transformation + + " is disabled"); + } + List transforms = getTransforms(transformation); List cipherServices = new ArrayList<>(transforms.size()); for (Transform transform : transforms) { @@ -604,6 +628,14 @@ public static final Cipher getInstance(String transformation) * security_guide_jdk_providers JDK Providers} document for information * on the transformation defaults used by JDK providers. * + * @implNote + * The JDK Reference Implementation additionally uses + * the {@code jdk.crypto.disabledAlgorithms} + * {@link Security#getProperty(String) Security} property to determine + * if the specified algorithm is allowed. If the + * {@systemProperty jdk.crypto.disabledAlgorithms} is set, it supersedes + * the security property value. + * * @param transformation the name of the transformation, * e.g., AES/CBC/PKCS5Padding. * See the Cipher section in the
AES/CBC/PKCS5Padding. * See the Cipher section in the transforms = getTransforms(transformation); boolean providerChecked = false; diff --git a/src/java.base/share/classes/jdk/internal/access/JavaIOAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaIOAccess.java index 532c1f259d4..bdeb2282a02 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaIOAccess.java +++ b/src/java.base/share/classes/jdk/internal/access/JavaIOAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,4 +29,5 @@ public interface JavaIOAccess { Console console(); + boolean isStdinTty(); } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerifierImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerifierImpl.java index 4c2104c5a78..b94e1ba3921 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerifierImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerifierImpl.java @@ -1515,13 +1515,6 @@ void verify_field_instructions(RawBytecodeHelper bcs, VerificationFrame current_ } } - // Return TRUE if all code paths starting with start_bc_offset end in - // bytecode athrow or loop. - boolean ends_in_athrow(int start_bc_offset) { - log_info("unimplemented VerifierImpl.ends_in_athrow"); - return true; - } - boolean verify_invoke_init(RawBytecodeHelper bcs, int ref_class_index, VerificationType ref_class_type, VerificationFrame current_frame, int code_length, boolean in_try_block, boolean this_uninit, ConstantPoolWrapper cp, VerificationTable stackmap_table) { @@ -1534,16 +1527,6 @@ boolean verify_invoke_init(RawBytecodeHelper bcs, int ref_class_index, Verificat verifyError("Bad method call"); } if (in_try_block) { - for(var exhandler : _method.exceptionTable()) { - int start_pc = exhandler[0]; - int end_pc = exhandler[1]; - - if (bci >= start_pc && bci < end_pc) { - if (!ends_in_athrow(exhandler[2])) { - verifyError("Bad method call from after the start of a try block"); - } - } - } verify_exception_handler_targets(bci, true, current_frame, stackmap_table); } current_frame.initialize_object(type, current_type()); diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java b/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java index a1323e16945..20ccec61fd2 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java @@ -297,7 +297,7 @@ private void specialize() { if (callingSequence.allocationSize() != 0) { cb.loadConstant(callingSequence.allocationSize()) .invokestatic(CD_SharedUtils, "newBoundedArena", MTD_NEW_BOUNDED_ARENA); - } else if (callingSequence.forUpcall() && needsSession()) { + } else if (callingSequence.forUpcall() && anyArgNeedsScope()) { cb.invokestatic(CD_SharedUtils, "newEmptyArena", MTD_NEW_EMPTY_ARENA); } else { cb.getstatic(CD_SharedUtils, "DUMMY_ARENA", CD_Arena); @@ -437,7 +437,7 @@ private void specialize() { cb.exceptionCatchAll(tryStart, tryEnd, catchStart); } - private boolean needsSession() { + private boolean anyArgNeedsScope() { return callingSequence.argumentBindings() .filter(BoxAddress.class::isInstance) .map(BoxAddress.class::cast) @@ -590,7 +590,7 @@ private void emitBoxAddress(BoxAddress boxAddress) { popType(long.class); cb.loadConstant(boxAddress.size()) .loadConstant(boxAddress.align()); - if (needsSession()) { + if (boxAddress.needsScope()) { emitLoadInternalSession(); cb.invokestatic(CD_Utils, "longToAddress", MTD_LONG_TO_ADDRESS_SCOPE); } else { diff --git a/src/java.base/share/classes/jdk/internal/io/JdkConsoleImpl.java b/src/java.base/share/classes/jdk/internal/io/JdkConsoleImpl.java index ec94d4ec4d6..f6ea183e8a7 100644 --- a/src/java.base/share/classes/jdk/internal/io/JdkConsoleImpl.java +++ b/src/java.base/share/classes/jdk/internal/io/JdkConsoleImpl.java @@ -38,10 +38,13 @@ import java.util.Formatter; import java.util.Locale; import java.util.Objects; +import java.util.Optional; import jdk.internal.access.SharedSecrets; +import jdk.internal.util.StaticProperty; import sun.nio.cs.StreamDecoder; import sun.nio.cs.StreamEncoder; +import sun.nio.cs.UTF_8; /** * JdkConsole implementation based on the platform's TTY. @@ -103,6 +106,42 @@ public String readLine() { @Override public char[] readPassword(Locale locale, String format, Object ... args) { + return readPassword0(false, locale, format, args); + } + + // These two methods are intended for sun.security.util.Password, so tools like keytool can + // use JdkConsoleImpl even when standard output is redirected. The Password class should first + // check if `System.console()` returns a Console instance and use it if available. Otherwise, + // it should call this method to obtain a JdkConsoleImpl. This ensures only one Console + // instance exists in the Java runtime. + private static final StableValue> INSTANCE = StableValue.of(); + public static Optional passwordConsole() { + return INSTANCE.orElseSet(() -> { + // If there's already a proper console, throw an exception + if (System.console() != null) { + throw new IllegalStateException("Can’t create a dedicated password " + + "console since a real console already exists"); + } + + // If stdin is NOT redirected, return an Optional containing a JdkConsoleImpl + // instance, otherwise an empty Optional. + return SharedSecrets.getJavaIOAccess().isStdinTty() ? + Optional.of( + new JdkConsoleImpl( + UTF_8.INSTANCE, + UTF_8.INSTANCE)) : + Optional.empty(); + }); + } + + // Dedicated entry for sun.security.util.Password when stdout is redirected. + // This method strictly avoids producing any output by using noNewLine = true + // and an empty format string. + public char[] readPasswordNoNewLine() { + return readPassword0(true, Locale.getDefault(Locale.Category.FORMAT), ""); + } + + private char[] readPassword0(boolean noNewLine, Locale locale, String format, Object ... args) { char[] passwd = null; synchronized (writeLock) { synchronized(readLock) { @@ -135,7 +174,9 @@ public char[] readPassword(Locale locale, String format, Object ... args) { ioe.addSuppressed(x); } if (ioe != null) { - Arrays.fill(passwd, ' '); + if (passwd != null) { + Arrays.fill(passwd, ' '); + } try { if (reader instanceof LineReader lr) { lr.zeroOut(); @@ -146,7 +187,9 @@ public char[] readPassword(Locale locale, String format, Object ... args) { throw ioe; } } - pw.println(); + if (!noNewLine) { + pw.println(); + } } } return passwd; diff --git a/src/java.base/share/classes/jdk/internal/util/Exceptions.java b/src/java.base/share/classes/jdk/internal/util/Exceptions.java index eb4286cd1af..70ee7026a7b 100644 --- a/src/java.base/share/classes/jdk/internal/util/Exceptions.java +++ b/src/java.base/share/classes/jdk/internal/util/Exceptions.java @@ -274,12 +274,9 @@ public static boolean enhancedSocketExceptions() { */ public static IOException ioException(IOException e, SocketAddress addr) { setup(); - if (addr == null) { + if (!enhancedSocketExceptionText || addr == null) { return e; } - if (!enhancedSocketExceptionText) { - return create(e, e.getMessage()); - } if (addr instanceof UnixDomainSocketAddress) { return ofUnixDomain(e, (UnixDomainSocketAddress)addr); } else if (addr instanceof InetSocketAddress) { diff --git a/src/java.base/share/classes/sun/invoke/util/BytecodeDescriptor.java b/src/java.base/share/classes/sun/invoke/util/BytecodeDescriptor.java index 53fd6322758..76bbff2a610 100644 --- a/src/java.base/share/classes/sun/invoke/util/BytecodeDescriptor.java +++ b/src/java.base/share/classes/sun/invoke/util/BytecodeDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, 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 @@ -96,8 +96,15 @@ private static Class parseSig(String str, int[] i, int end, ClassLoader loade } } else if (c == '[') { Class t = parseSig(str, i, end, loader); - if (t != null) - t = t.arrayType(); + if (t != null) { + try { + t = t.arrayType(); + } catch (UnsupportedOperationException ex) { + // Bad arrays, such as [V or more than 255 dims + // We have a more informative IAE + return null; + } + } return t; } else { return Wrapper.forBasicType(c).primitiveType(); diff --git a/src/java.base/share/classes/sun/security/provider/certpath/URICertStore.java b/src/java.base/share/classes/sun/security/provider/certpath/URICertStore.java index 28729a56dbd..3e1fc8db164 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/URICertStore.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/URICertStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2024, 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 @@ -29,6 +29,7 @@ import java.io.IOException; import java.net.HttpURLConnection; import java.net.URI; +import java.net.URISyntaxException; import java.net.URLConnection; import java.security.InvalidAlgorithmParameterException; import java.security.NoSuchAlgorithmException; @@ -48,8 +49,11 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; +import java.util.Optional; +import java.util.Set; import sun.security.x509.AccessDescription; import sun.security.x509.GeneralNameInterface; @@ -58,6 +62,8 @@ import sun.security.util.Debug; import sun.security.util.SecurityProperties; +import javax.security.auth.x500.X500Principal; + /** * A CertStore that retrieves Certificates or * CRLs from a URI, for example, as specified in an X.509 @@ -182,6 +188,166 @@ private static int initializeTimeout(String prop, int def) { return timeoutVal; } + /** + * Enumeration for the allowed schemes we support when following a + * URI from an authorityInfoAccess extension on a certificate. + */ + private enum AllowedScheme { + HTTP(HttpFtpRuleMatcher.HTTP), + HTTPS(HttpFtpRuleMatcher.HTTPS), + LDAP(LdapRuleMatcher.LDAP), + LDAPS(LdapRuleMatcher.LDAPS), + FTP(HttpFtpRuleMatcher.FTP); + + final URIRuleMatcher ruleMatcher; + + AllowedScheme(URIRuleMatcher matcher) { + ruleMatcher = matcher; + } + + /** + * Return an {@code AllowedScheme} based on a case-insensitive match + * @param name the scheme name to be matched + * @return the {@code AllowedScheme} that corresponds to the + * {@code name} provided, or null if there is no match. + */ + static AllowedScheme nameOf(String name) { + if (name == null) { + return null; + } + + try { + return AllowedScheme.valueOf(name.toUpperCase(Locale.ROOT)); + } catch (IllegalArgumentException _) { + return null; + } + } + } + + private static Set CA_ISS_URI_FILTERS = null; + private static final boolean CA_ISS_ALLOW_ANY; + + static { + boolean allowAny = false; + try { + if (Builder.USE_AIA) { + CA_ISS_URI_FILTERS = new LinkedHashSet<>(); + String aiaPropVal = Optional.ofNullable( + SecurityProperties.getOverridableProperty( + "com.sun.security.allowedAIALocations")). + map(String::trim).orElse(""); + if (aiaPropVal.equalsIgnoreCase("any")) { + allowAny = true; + if (debug != null) { + debug.println("allowedAIALocations: Warning: " + + "Allow-All URI filtering enabled!"); + } + } else { + // Load all the valid rules from the Security property + if (!aiaPropVal.isEmpty()) { + String[] aiaUriStrs = aiaPropVal.trim().split("\\s+"); + addCaIssUriFilters(aiaUriStrs); + } + + if (CA_ISS_URI_FILTERS.isEmpty()) { + if (debug != null) { + debug.println("allowedAIALocations: Warning: " + + "No valid filters found. Deny-all URI " + + "filtering is active."); + } + } + } + } + } finally { + CA_ISS_ALLOW_ANY = allowAny; + } + } + + /** + * Populate the filter collection from the list of AIA CA issuer URIs + * found in the {@code com.sun.security.allowedAIALocations} security + * or system property. + * + * @param aiaUriStrs array containing String URI filters + */ + private static void addCaIssUriFilters(String[] aiaUriStrs) { + for (String aiaStr : aiaUriStrs) { + if (aiaStr != null && !aiaStr.isEmpty()) { + try { + AllowedScheme scheme; + URI aiaUri = new URI(aiaStr).normalize(); + // It must be absolute and non-opaque + if (!aiaUri.isAbsolute() || aiaUri.isOpaque()) { + if (debug != null) { + debug.println("allowedAIALocations: Skipping " + + "non-absolute or opaque URI " + aiaUri); + } + } else if (aiaUri.getHost() == null) { + // We do not allow rules with URIs that omit a hostname + // or address. + if (debug != null) { + debug.println("allowedAIALocations: Skipping " + + "URI rule with no hostname or address: " + + aiaUri); + } + } else if ((scheme = AllowedScheme.nameOf( + aiaUri.getScheme())) != null) { + // When it is an LDAP type, we can check the path + // portion (the DN) for proper structure and reject + // the rule early if it isn't correct. + if (scheme == AllowedScheme.LDAP || + scheme == AllowedScheme.LDAPS) { + try { + new X500Principal(aiaUri.getPath(). + replaceFirst("^/+", "")); + } catch (IllegalArgumentException iae) { + if (debug != null) { + debug.println("allowedAIALocations: " + + "Skipping LDAP rule: " + iae); + } + continue; + } + } + + // When a URI has a non-null query or fragment + // warn the user upon adding the rule that those + // components will be ignored + if (aiaUri.getQuery() != null) { + if (debug != null) { + debug.println("allowedAIALocations: " + + "Rule will ignore non-null query"); + } + } + if (aiaUri.getFragment() != null) { + if (debug != null) { + debug.println("allowedAIALocations: " + + "Rule will ignore non-null fragment"); + } + } + + CA_ISS_URI_FILTERS.add(aiaUri); + if (debug != null) { + debug.println("allowedAIALocations: Added " + + aiaUri + " to URI filters"); + } + } else { + if (debug != null) { + debug.println("allowedAIALocations: Disallowed " + + "filter URI scheme: " + + aiaUri.getScheme()); + } + } + } catch (URISyntaxException urise) { + if (debug != null) { + debug.println("allowedAIALocations: Skipping " + + "filter URI entry " + aiaStr + + ": parse failure at index " + urise.getIndex()); + } + } + } + } + } + /** * Creates a URICertStore. * @@ -244,6 +410,39 @@ static CertStore getInstance(AccessDescription ad) { return null; } URI uri = ((URIName) gn).getURI(); + + // Before performing any instantiation make sure that + // the URI passes any filtering rules. This processing should + // only occur if the com.sun.security.enableAIAcaIssuers is true + // and the "any" rule has not been specified. + if (Builder.USE_AIA && !CA_ISS_ALLOW_ANY) { + URI normAIAUri = uri.normalize(); + AllowedScheme scheme = AllowedScheme.nameOf(normAIAUri.getScheme()); + + if (scheme == null) { + if (debug != null) { + debug.println("allowedAIALocations: No matching ruleset " + + "for scheme " + normAIAUri.getScheme()); + } + return null; + } + + // Go through each of the filter rules and see if any will + // make a positive match against the caIssuer URI. If nothing + // matches then we won't instantiate a URICertStore. + if (CA_ISS_URI_FILTERS.stream().noneMatch(rule -> + scheme.ruleMatcher.matchRule(rule, normAIAUri))) { + if (debug != null) { + debug.println("allowedAIALocations: Warning - " + + "The caIssuer URI " + normAIAUri + + " in the AuthorityInfoAccess extension is denied " + + "access. Use the com.sun.security.allowedAIALocations" + + " security/system property to allow access."); + } + return null; + } + } + try { return URICertStore.getInstance(new URICertStoreParameters(uri)); } catch (Exception ex) { @@ -270,7 +469,7 @@ static CertStore getInstance(AccessDescription ad) { @Override @SuppressWarnings("unchecked") public synchronized Collection engineGetCertificates - (CertSelector selector) throws CertStoreException { + (CertSelector selector) throws CertStoreException { if (ldap) { // caching mechanism, see the class description for more info. @@ -462,4 +661,159 @@ protected UCS(CertStoreSpi spi, Provider p, String type, super(spi, p, type, params); } } + + /** + * URIRuleMatcher - abstract base class for the rule sets used for + * various URI schemes. + */ + static abstract class URIRuleMatcher { + protected final int wellKnownPort; + + protected URIRuleMatcher(int port) { + wellKnownPort = port; + } + + /** + * Attempt to match the scheme, host and port between a filter + * rule URI and a URI coming from an AIA extension. + * + * @param filterRule the filter rule to match against + * @param caIssuer the AIA URI being compared + * @return true if the scheme, host and port numbers match, false if + * any of the components do not match. If a port number is omitted in + * either the filter rule or AIA URI, the well-known port for that + * scheme is used in the comparison. + */ + boolean schemeHostPortCheck(URI filterRule, URI caIssuer) { + if (!filterRule.getScheme().equalsIgnoreCase( + caIssuer.getScheme())) { + return false; + } else if (!filterRule.getHost().equalsIgnoreCase( + caIssuer.getHost())) { + return false; + } else { + try { + // Check for port matching, taking into consideration + // default ports + int fPort = (filterRule.getPort() == -1) ? wellKnownPort : + filterRule.getPort(); + int caiPort = (caIssuer.getPort() == -1) ? wellKnownPort : + caIssuer.getPort(); + if (fPort != caiPort) { + return false; + } + } catch (IllegalArgumentException iae) { + return false; + } + } + return true; + } + + /** + * Attempt to match an AIA URI against a specific filter rule. The + * specific rules to apply are implementation dependent. + * + * @param filterRule the filter rule to match against + * @param caIssuer the AIA URI being compared + * @return true if all matching rules pass, false if any fail. + */ + abstract boolean matchRule(URI filterRule, URI caIssuer); + } + + static class HttpFtpRuleMatcher extends URIRuleMatcher { + static final HttpFtpRuleMatcher HTTP = new HttpFtpRuleMatcher(80); + static final HttpFtpRuleMatcher HTTPS = new HttpFtpRuleMatcher(443); + static final HttpFtpRuleMatcher FTP = new HttpFtpRuleMatcher(21); + + private HttpFtpRuleMatcher(int port) { + super(port); + } + + @Override + boolean matchRule(URI filterRule, URI caIssuer) { + // Check for scheme/host/port matching + if (!schemeHostPortCheck(filterRule, caIssuer)) { + return false; + } + + // Check the path component to make sure the filter is at + // least a root of the AIA caIssuer URI's path. It must be + // a case-sensitive match for all platforms. + if (!isRootOf(filterRule, caIssuer)) { + if (debug != null) { + debug.println("allowedAIALocations: Match failed: " + + "AIA URI is not within the rule's path hierarchy."); + } + return false; + } + return true; + } + + /** + * Performs a hierarchical containment check, ensuring that the + * base URI's path is a root component of the candidate path. The + * path comparison is case-sensitive. If the base path ends in a + * slash (/) then all candidate paths that begin with the base + * path are allowed. If it does not end in a slash, then it is + * assumed that the leaf node in the base path is a file component + * and both paths must match exactly. + * + * @param base the URI that contains the root path + * @param candidate the URI that contains the path being evaluated + * @return true if {@code candidate} is a child path of {@code base}, + * false otherwise. + */ + private static boolean isRootOf(URI base, URI candidate) { + // Note: The URIs have already been normalized at this point and + // HTTP URIs cannot have null paths. If it's an empty path + // then consider the path to be "/". + String basePath = Optional.of(base.getPath()). + filter(p -> !p.isEmpty()).orElse("/"); + String candPath = Optional.of(candidate.getPath()). + filter(p -> !p.isEmpty()).orElse("/"); + return (basePath.endsWith("/")) ? candPath.startsWith(basePath) : + candPath.equals(basePath); + } + } + + static class LdapRuleMatcher extends URIRuleMatcher { + static final LdapRuleMatcher LDAP = new LdapRuleMatcher(389); + static final LdapRuleMatcher LDAPS = new LdapRuleMatcher(636); + + private LdapRuleMatcher(int port) { + super(port); + } + + @Override + boolean matchRule(URI filterRule, URI caIssuer) { + // Check for scheme/host/port matching + if (!schemeHostPortCheck(filterRule, caIssuer)) { + return false; + } + + // Obtain the base DN component and compare + try { + X500Principal filterBaseDn = new X500Principal( + filterRule.getPath().replaceFirst("^/+", "")); + X500Principal caIssBaseDn = new X500Principal( + caIssuer.getPath().replaceFirst("^/+", "")); + if (!filterBaseDn.equals(caIssBaseDn)) { + if (debug != null) { + debug.println("allowedAIALocations: Match failed: " + + "Base DN mismatch (" + filterBaseDn + " vs " + + caIssBaseDn + ")"); + } + return false; + } + } catch (IllegalArgumentException iae) { + if (debug != null) { + debug.println("allowedAIALocations: Match failed on DN: " + + iae); + } + return false; + } + + return true; + } + } } diff --git a/src/java.base/share/classes/sun/security/ssl/DTLSInputRecord.java b/src/java.base/share/classes/sun/security/ssl/DTLSInputRecord.java index e0196f3009c..101a42a5407 100644 --- a/src/java.base/share/classes/sun/security/ssl/DTLSInputRecord.java +++ b/src/java.base/share/classes/sun/security/ssl/DTLSInputRecord.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -801,8 +801,11 @@ void queueUpHandshake(HandshakeFragment hsf) throws SSLProtocolException { // buffer this fragment if (hsf.handshakeType == SSLHandshake.FINISHED.id) { - // Need no status update. - bufferedFragments.add(hsf); + // Make sure it's not a retransmitted message + if (hsf.recordEpoch > handshakeEpoch) { + bufferedFragments.add(hsf); + flightIsReady = holes.isEmpty(); + } } else { bufferFragment(hsf); } diff --git a/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java b/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java index 5c2a09b7c03..b3155f5170a 100644 --- a/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java +++ b/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -187,7 +187,7 @@ boolean isCookieValid(ServerHandshakeContext context, byte[] secret; d10ManagerLock.lock(); try { - if (((cookieVersion >> 24) & 0xFF) == cookie[0]) { + if ((byte) ((cookieVersion >> 24) & 0xFF) == cookie[0]) { secret = cookieSecret; } else { secret = legacySecret; // including out of window cookies diff --git a/src/java.base/share/classes/sun/security/util/AbstractAlgorithmConstraints.java b/src/java.base/share/classes/sun/security/util/AbstractAlgorithmConstraints.java index dc5b1aafb20..d05fb262fa8 100644 --- a/src/java.base/share/classes/sun/security/util/AbstractAlgorithmConstraints.java +++ b/src/java.base/share/classes/sun/security/util/AbstractAlgorithmConstraints.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 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 @@ -46,7 +46,16 @@ protected AbstractAlgorithmConstraints(AlgorithmDecomposer decomposer) { // Get algorithm constraints from the specified security property. static Set getAlgorithms(String propertyName) { - String property = Security.getProperty(propertyName); + return getAlgorithms(propertyName, false); + } + + // Get algorithm constraints from the specified security property or + // system property if allowSystemOverride == true. + static Set getAlgorithms(String propertyName, + boolean allowSystemOverride) { + String property = allowSystemOverride ? + SecurityProperties.getOverridableProperty(propertyName) : + Security.getProperty(propertyName); String[] algorithmsInProperty = null; if (property != null && !property.isEmpty()) { @@ -65,7 +74,8 @@ static Set getAlgorithms(String propertyName) { if (algorithmsInProperty == null) { return Collections.emptySet(); } - Set algorithmsInPropertySet = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); + Set algorithmsInPropertySet = + new TreeSet<>(String.CASE_INSENSITIVE_ORDER); algorithmsInPropertySet.addAll(Arrays.asList(algorithmsInProperty)); return algorithmsInPropertySet; } @@ -80,17 +90,17 @@ static boolean checkAlgorithm(Set algorithms, String algorithm, return false; } - // decompose the algorithm into sub-elements - Set elements = decomposer.decompose(algorithm); + if (decomposer != null) { + // decompose the algorithm into sub-elements + Set elements = decomposer.decompose(algorithm); - // check the element of the elements - for (String element : elements) { - if (algorithms.contains(element)) { - return false; + // check the element of the elements + for (String element : elements) { + if (algorithms.contains(element)) { + return false; + } } } - return true; } - } diff --git a/src/java.base/share/classes/sun/security/util/CryptoAlgorithmConstraints.java b/src/java.base/share/classes/sun/security/util/CryptoAlgorithmConstraints.java new file mode 100644 index 00000000000..ad3beab350f --- /dev/null +++ b/src/java.base/share/classes/sun/security/util/CryptoAlgorithmConstraints.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.util; + +import java.lang.ref.SoftReference; +import java.security.AlgorithmParameters; +import java.security.CryptoPrimitive; +import java.security.Key; +import java.util.Arrays; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * This class implements the algorithm constraints for the + * "jdk.crypto.disabledAlgorithms" security property. This security property + * can be overridden by the system property of the same name. See the + * java.security file for the syntax of the property value. + */ +public class CryptoAlgorithmConstraints extends AbstractAlgorithmConstraints { + private static final Debug debug = Debug.getInstance("jca"); + + // for validating the service + private static final Set SUPPORTED_SERVICES = + Set.of("Cipher", "KeyStore", "MessageDigest", "Signature"); + + // Disabled algorithm security property for JCE crypto services + private static final String PROPERTY_CRYPTO_DISABLED_ALGS = + "jdk.crypto.disabledAlgorithms"; + + private static class CryptoHolder { + static final CryptoAlgorithmConstraints CONSTRAINTS = + new CryptoAlgorithmConstraints(PROPERTY_CRYPTO_DISABLED_ALGS); + } + + private static void debug(String msg) { + if (debug != null) { + debug.println("CryptoAlgoConstraints: ", msg); + } + } + + public static boolean permits(String service, String algo) { + return CryptoHolder.CONSTRAINTS.cachedCheckAlgorithm( + service + "." + algo); + } + + private final Set disabledServices; // syntax is . + private volatile SoftReference> cacheRef = + new SoftReference<>(null); + + /** + * Initialize algorithm constraints with the specified security property + * {@code propertyName}. Note that if a system property of the same name + * is set, it overrides the security property. + * + * @param propertyName the security property name that define the disabled + * algorithm constraints + */ + CryptoAlgorithmConstraints(String propertyName) { + super(null); + disabledServices = getAlgorithms(propertyName, true); + String[] entries = disabledServices.toArray(new String[0]); + debug("Before " + Arrays.deepToString(entries)); + + for (String dk : entries) { + int idx = dk.indexOf("."); + if (idx < 1 || idx == dk.length() - 1) { + // wrong syntax: missing "." or empty service or algorithm + throw new IllegalArgumentException("Invalid entry: " + dk); + } + String service = dk.substring(0, idx); + String algo = dk.substring(idx + 1); + if (SUPPORTED_SERVICES.stream().anyMatch(e -> e.equalsIgnoreCase + (service))) { + KnownOIDs oid = KnownOIDs.findMatch(algo); + if (oid != null) { + debug("Add oid: " + oid.value()); + disabledServices.add(service + "." + oid.value()); + debug("Add oid stdName: " + oid.stdName()); + disabledServices.add(service + "." + oid.stdName()); + for (String a : oid.aliases()) { + debug("Add oid alias: " + a); + disabledServices.add(service + "." + a); + } + } + } else { + // unsupported service + throw new IllegalArgumentException("Invalid entry: " + dk); + } + } + debug("After " + Arrays.deepToString(disabledServices.toArray())); + } + + @Override + public final boolean permits(Set notUsed1, + String serviceDesc, AlgorithmParameters notUsed2) { + throw new UnsupportedOperationException("Unsupported permits() method"); + } + + @Override + public final boolean permits(Set primitives, Key key) { + throw new UnsupportedOperationException("Unsupported permits() method"); + } + + @Override + public final boolean permits(Set primitives, + String algorithm, Key key, AlgorithmParameters parameters) { + throw new UnsupportedOperationException("Unsupported permits() method"); + } + + // Return false if algorithm is found in the disabledServices Set. + // Otherwise, return true. + private boolean cachedCheckAlgorithm(String serviceDesc) { + Map cache; + if ((cache = cacheRef.get()) == null) { + synchronized (this) { + if ((cache = cacheRef.get()) == null) { + cache = new ConcurrentHashMap<>(); + cacheRef = new SoftReference<>(cache); + } + } + } + Boolean result = cache.get(serviceDesc); + if (result != null) { + return result; + } + result = checkAlgorithm(disabledServices, serviceDesc, null); + cache.put(serviceDesc, result); + return result; + } +} diff --git a/src/java.base/share/classes/sun/security/util/DerValue.java b/src/java.base/share/classes/sun/security/util/DerValue.java index 19e7083180b..ec8b482b07d 100644 --- a/src/java.base/share/classes/sun/security/util/DerValue.java +++ b/src/java.base/share/classes/sun/security/util/DerValue.java @@ -859,6 +859,22 @@ public String getUniversalString() throws IOException { return readStringInternal(tag_UniversalString, new UTF_32BE()); } + /** + * 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 */ diff --git a/src/java.base/share/classes/sun/security/util/KnownOIDs.java b/src/java.base/share/classes/sun/security/util/KnownOIDs.java index 8e764b75730..cbb0c1e0b57 100644 --- a/src/java.base/share/classes/sun/security/util/KnownOIDs.java +++ b/src/java.base/share/classes/sun/security/util/KnownOIDs.java @@ -184,7 +184,7 @@ public enum KnownOIDs { // RSASecurity // PKCS1 1.2.840.113549.1.1.* PKCS1("1.2.840.113549.1.1", "RSA", false), // RSA KeyPairGenerator and KeyFactory - RSA("1.2.840.113549.1.1.1"), // RSA encryption + RSA("1.2.840.113549.1.1.1", "RSA", "RSA/ECB/PKCS1Padding"), // RSA encryption MD2withRSA("1.2.840.113549.1.1.2"), MD5withRSA("1.2.840.113549.1.1.4"), diff --git a/src/java.base/share/classes/sun/security/util/Password.java b/src/java.base/share/classes/sun/security/util/Password.java index 7acece65a57..02cdcaf53fd 100644 --- a/src/java.base/share/classes/sun/security/util/Password.java +++ b/src/java.base/share/classes/sun/security/util/Password.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,11 +29,13 @@ import java.nio.*; import java.nio.charset.*; import java.util.Arrays; + import jdk.internal.access.SharedSecrets; +import jdk.internal.io.JdkConsoleImpl; +import jdk.internal.misc.VM; /** * A utility class for reading passwords - * */ public class Password { /** Reads user password from given input stream. */ @@ -50,30 +52,39 @@ public static char[] readPassword(InputStream in, boolean isEchoOn) char[] consoleEntered = null; byte[] consoleBytes = null; + char[] buf = null; try { // Only use Console if `in` is the initial System.in - Console con; - if (!isEchoOn && - in == SharedSecrets.getJavaLangAccess().initialSystemIn() && - ((con = System.console()) != null)) { - consoleEntered = con.readPassword(); - // readPassword returns "" if you just press ENTER with the built-in Console, - // to be compatible with old Password class, change to null - if (consoleEntered == null || consoleEntered.length == 0) { - return null; + if (!isEchoOn) { + if (in == SharedSecrets.getJavaLangAccess().initialSystemIn() + && ConsoleHolder.consoleIsAvailable()) { + consoleEntered = ConsoleHolder.readPassword(); + // readPassword might return null. Stop now. + if (consoleEntered == null) { + return null; + } + consoleBytes = ConsoleHolder.convertToBytes(consoleEntered); + in = new ByteArrayInputStream(consoleBytes); + } else if (in == System.in && VM.isBooted() + && System.in.available() == 0) { + // Warn if reading password from System.in but it's empty. + // This may be running in an IDE Run Window or in JShell, + // which acts like an interactive console and echoes the + // entered password. In this case, print a warning that + // the password might be echoed. If available() is not zero, + // it's more likely the input comes from a pipe, such as + // "echo password |" or "cat password_file |" where input + // will be silently consumed without echoing to the screen. + // Warn only if VM is booted and ResourcesMgr is available. + System.err.print(ResourcesMgr.getString + ("warning.input.may.be.visible.on.screen")); } - consoleBytes = convertToBytes(consoleEntered); - in = new ByteArrayInputStream(consoleBytes); } // Rest of the lines still necessary for KeyStoreLoginModule // and when there is no console. - - char[] lineBuffer; - char[] buf; - - buf = lineBuffer = new char[128]; + buf = new char[128]; int room = buf.length; int offset = 0; @@ -101,11 +112,11 @@ public static char[] readPassword(InputStream in, boolean isEchoOn) /* fall through */ default: if (--room < 0) { + char[] oldBuf = buf; buf = new char[offset + 128]; room = buf.length - offset - 1; - System.arraycopy(lineBuffer, 0, buf, 0, offset); - Arrays.fill(lineBuffer, ' '); - lineBuffer = buf; + System.arraycopy(oldBuf, 0, buf, 0, offset); + Arrays.fill(oldBuf, ' '); } buf[offset++] = (char) c; break; @@ -118,8 +129,6 @@ public static char[] readPassword(InputStream in, boolean isEchoOn) char[] ret = new char[offset]; System.arraycopy(buf, 0, ret, 0, offset); - Arrays.fill(buf, ' '); - return ret; } finally { if (consoleEntered != null) { @@ -128,35 +137,72 @@ public static char[] readPassword(InputStream in, boolean isEchoOn) if (consoleBytes != null) { Arrays.fill(consoleBytes, (byte)0); } + if (buf != null) { + Arrays.fill(buf, ' '); + } } } - /** - * Change a password read from Console.readPassword() into - * its original bytes. - * - * @param pass a char[] - * @return its byte[] format, similar to new String(pass).getBytes() - */ - private static byte[] convertToBytes(char[] pass) { - if (enc == null) { - synchronized (Password.class) { - enc = System.console() - .charset() - .newEncoder() - .onMalformedInput(CodingErrorAction.REPLACE) - .onUnmappableCharacter(CodingErrorAction.REPLACE); + // Everything on Console or JdkConsoleImpl is inside this class. + private static class ConsoleHolder { + + // primary console; may be null + private static final Console c1; + // secondary console (when stdout is redirected); may be null + private static final JdkConsoleImpl c2; + // encoder for c1 or c2 + private static final CharsetEncoder enc; + + static { + c1 = System.console(); + Charset charset; + if (c1 != null) { + c2 = null; + charset = c1.charset(); + } else { + c2 = JdkConsoleImpl.passwordConsole().orElse(null); + charset = (c2 != null) ? c2.charset() : null; } + enc = charset == null ? null : charset.newEncoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); } - byte[] ba = new byte[(int)(enc.maxBytesPerChar() * pass.length)]; - ByteBuffer bb = ByteBuffer.wrap(ba); - synchronized (enc) { - enc.reset().encode(CharBuffer.wrap(pass), bb, true); + + public static boolean consoleIsAvailable() { + return c1 != null || c2 != null; + } + + public static char[] readPassword() { + assert consoleIsAvailable(); + if (c1 != null) { + return c1.readPassword(); + } else { + try { + return c2.readPasswordNoNewLine(); + } finally { + System.err.println(); + } + } } - if (bb.position() < ba.length) { - ba[bb.position()] = '\n'; + + /** + * Convert a password read from console into its original bytes. + * + * @param pass a char[] + * @return its byte[] format, equivalent to new String(pass).getBytes() + * but String is immutable and cannot be cleaned up. + */ + public static byte[] convertToBytes(char[] pass) { + assert consoleIsAvailable(); + byte[] ba = new byte[(int) (enc.maxBytesPerChar() * pass.length)]; + ByteBuffer bb = ByteBuffer.wrap(ba); + synchronized (enc) { + enc.reset().encode(CharBuffer.wrap(pass), bb, true); + } + if (bb.remaining() > 0) { + bb.put((byte)'\n'); // will be recognized as a stop sign + } + return ba; } - return ba; } - private static volatile CharsetEncoder enc; } diff --git a/src/java.base/share/classes/sun/security/util/resources/security.properties b/src/java.base/share/classes/sun/security/util/resources/security.properties index 9533b4b8eee..d8a0cbfac29 100644 --- a/src/java.base/share/classes/sun/security/util/resources/security.properties +++ b/src/java.base/share/classes/sun/security/util/resources/security.properties @@ -74,3 +74,6 @@ line.number.expected.expect.found.actual.=line {0}: expected [{1}], found [{2}] # sun.security.pkcs11.SunPKCS11 PKCS11.Token.providerName.Password.=PKCS11 Token [{0}] Password:\u0020 + +# sun.security.util.Password +warning.input.may.be.visible.on.screen=[WARNING: Input may be visible on screen]\u0020 diff --git a/src/java.base/share/classes/sun/security/validator/EntrustTLSPolicy.java b/src/java.base/share/classes/sun/security/validator/EntrustTLSPolicy.java index 4c4906d8eb3..f93e534f46a 100644 --- a/src/java.base/share/classes/sun/security/validator/EntrustTLSPolicy.java +++ b/src/java.base/share/classes/sun/security/validator/EntrustTLSPolicy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,19 +71,7 @@ final class EntrustTLSPolicy { // 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 --git a/src/java.base/share/classes/sun/security/x509/AVA.java b/src/java.base/share/classes/sun/security/x509/AVA.java index 915421c76f2..214ae718288 100644 --- a/src/java.base/share/classes/sun/security/x509/AVA.java +++ b/src/java.base/share/classes/sun/security/x509/AVA.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, 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.util.*; import sun.security.pkcs.PKCS9Attribute; @@ -589,6 +592,10 @@ private static boolean trailingSpace(Reader in) throws IOException { throw new IOException("AVA, extra bytes = " + derval.data.available()); } + + if (value.tag == DerValue.tag_BMPString) { + value.validateBMPString(); + } } AVA(DerInputStream in) throws IOException { @@ -713,7 +720,8 @@ public String toRFC2253String(Map oidMap) { * 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 @@ -832,7 +840,8 @@ public String toRFC2253CanonicalString() { * 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 @@ -927,6 +936,39 @@ private static boolean isDerString(DerValue value, boolean canonical) { } } + /* + * 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 --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security index 61e8aaaf6d1..b94ca730a67 100644 --- a/src/java.base/share/conf/security/java.security +++ b/src/java.base/share/conf/security/java.security @@ -771,6 +771,54 @@ jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, DTLSv1.0, RC4, DES, \ ECDH, TLS_RSA_*, rsa_pkcs1_sha1 usage HandshakeSignature, \ ecdsa_sha1 usage HandshakeSignature, dsa_sha1 usage HandshakeSignature +# +# Algorithm restrictions for Java Crypto API services +# +# In some environments, certain algorithms may be undesirable for certain +# cryptographic services. For example, "MD2" is generally no longer considered +# to be a secure hash algorithm. This section describes the mechanism for +# disabling algorithms at the JCA/JCE level based on service name and algorithm +# name. +# +# If a system property of the same name is also specified, it supersedes the +# security property value defined here. +# +# The syntax of the disabled services string is described as follows: +# "DisabledService {, DisabledService}" +# +# DisabledService: +# Service.AlgorithmName +# +# Service: (one of the following, more services may be added later) +# Cipher | KeyStore | MessageDigest | Signature +# +# AlgorithmName: +# (see below) +# +# The "AlgorithmName" is the standard algorithm name of the disabled +# service. See the Java Security Standard Algorithm Names Specification +# for information about Standard Algorithm Names. Matching is +# performed using a case-insensitive exact matching rule. For Cipher service, +# its algorithm is the transformation string. +# +# Note: If the property value contains entries with invalid syntax or +# unsupported services at the time of checking, an ExceptionInInitializerError +# with a cause of IllegalArgumentException will be thrown. +# +# Note: The restriction is applied in the various getInstance(...) methods +# of the supported Service classes, i.e. Cipher, KeyStore, MessageDigest, +# and Signature. If the algorithm is disabled, a NoSuchAlgorithmException will +# be thrown by the getInstance methods of Cipher, MessageDigest, and Signature +# and a KeyStoreException by the getInstance methods of KeyStore. +# +# Note: This property is currently used by the JDK Reference implementation. +# It is not guaranteed to be examined and used by other implementations. +# +# Example: +# jdk.crypto.disabledAlgorithms=Cipher.RSA/ECB/PKCS1Padding, MessageDigest.MD2 +# +#jdk.crypto.disabledAlgorithms= + # # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS) # processing in JSSE implementation. @@ -1574,3 +1622,48 @@ jdk.tls.alpnCharset=ISO_8859_1 # withEncryption method. # jdk.epkcs8.defaultAlgorithm=PBEWithHmacSHA256AndAES_128 + +# +# X.509 AuthorityInfoAccess caIssuer URI Filtering +# +# This property defines a whitespace-separated list of filters that +# are applied to URIs found in the authorityInfoAccess extension in +# X.509 certificates. Any caIssuers URIs in X.509 certificates are only +# followed when the com.sun.security.enableAIAcaIssuers System property is +# enabled and the filter allows the URI. By default this property imposes a +# deny-all ruleset. This property may be overridden by a System property +# of the same name. +# +# The filters must take the form of absolute, hierarchical URIs as defined by +# the java.net.URI class. Additionally, only the following protocols are +# allowed as filters: http, https, ldap and ftp. +# See RFC 5280, section 4.2.2.1 for details about the types of URIs allowed for +# the extension and their specific requirements. +# The filter matching rules are applied to each CA issuer URI as follows: +# 1. The scheme must match (case-insensitive). +# 2. A hostname or address must be specified in the filter URI. It must match +# the host or address in the caIssuers URI (case-insensitive). No name +# resolution is performed on hostnames to match IP addresses. +# 3. The port number must match. For filter and caIssuer URIs, when a port +# number is omitted, the well-known port for that scheme will be used in the +# comparison. +# 4. For hierarchical filesystem schemes (e.g. http[s], ftp): +# a. The normalized path portion of the filter URI is matched in a +# case-sensitive manner. If the final component of the path does not end +# in a slash (/), it is considered to be a file path component and must +# be an exact match of the caIssuer's URI file path component. If the +# final filter component ends in a slash, then it must either match or be +# a prefix of the caIssuer's URI path component (e.g. a filter path of +# /ab/cd/ will match a caIssuer path of /ab/cd/, /ab/cd/ef and +# /ab/cd/ef/ghi). +# b. Query strings will be ignored in filter rules and caIssuer URIs. +# c. Fragments will be ignored in filter rules and caIssuer URIs. +# 5. For ldap URIs: +# a. The base DN must be an exact match (case-insensitive). +# b. Any query string in the rule, if specified, is ignored. +# 6. A single value "any" (case-insensitive) will create an allow-all rule. +# +# As an example, here is a valid filter policy consisting of two rules: +# com.sun.security.allowedAIALocations=http://some.company.com/cacert \ +# ldap://ldap.company.com/dc=company,dc=com?caCertificate;binary +com.sun.security.allowedAIALocations= diff --git a/src/java.base/share/data/cacerts/affirmtrustcommercialca b/src/java.base/share/data/cacerts/affirmtrustcommercialca deleted file mode 100644 index 5caddfd3a0a..00000000000 --- a/src/java.base/share/data/cacerts/affirmtrustcommercialca +++ /dev/null @@ -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 --git a/src/java.base/share/data/cacerts/affirmtrustnetworkingca b/src/java.base/share/data/cacerts/affirmtrustnetworkingca deleted file mode 100644 index c773326d4b9..00000000000 --- a/src/java.base/share/data/cacerts/affirmtrustnetworkingca +++ /dev/null @@ -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 --git a/src/java.base/share/data/cacerts/affirmtrustpremiumca b/src/java.base/share/data/cacerts/affirmtrustpremiumca deleted file mode 100644 index 275b495a25e..00000000000 --- a/src/java.base/share/data/cacerts/affirmtrustpremiumca +++ /dev/null @@ -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 --git a/src/java.base/share/data/cacerts/affirmtrustpremiumeccca b/src/java.base/share/data/cacerts/affirmtrustpremiumeccca deleted file mode 100644 index d0fcc1e7793..00000000000 --- a/src/java.base/share/data/cacerts/affirmtrustpremiumeccca +++ /dev/null @@ -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 --git a/src/java.base/share/data/currency/CurrencyData.properties b/src/java.base/share/data/currency/CurrencyData.properties index ff2d1f87ed3..9b82318776a 100644 --- a/src/java.base/share/data/currency/CurrencyData.properties +++ b/src/java.base/share/data/currency/CurrencyData.properties @@ -32,7 +32,7 @@ formatVersion=3 # 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 @@ IO=USD # 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 @@ HR=EUR # CUBA CU=CUP # Curaçao -CW=ANG;2025-04-01-04-00-00;XCG +CW=XCG # CYPRUS CY=EUR # CZECHIA @@ -510,7 +510,7 @@ SR=SRD # 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 --git a/src/java.base/share/data/tzdata/VERSION b/src/java.base/share/data/tzdata/VERSION index 4bd54efbcdc..ce25e7653b0 100644 --- a/src/java.base/share/data/tzdata/VERSION +++ b/src/java.base/share/data/tzdata/VERSION @@ -21,4 +21,4 @@ # or visit www.oracle.com if you need additional information or have any # questions. # -tzdata2025b +tzdata2025c diff --git a/src/java.base/share/data/tzdata/africa b/src/java.base/share/data/tzdata/africa index 8098f4bea9d..cf1247ee3ab 100644 --- a/src/java.base/share/data/tzdata/africa +++ b/src/java.base/share/data/tzdata/africa @@ -27,9 +27,9 @@ # 2009-05-17 by Arthur David Olson. # This file is by no means authoritative; if you think you know better, -# go ahead and edit the file (and please send any changes to -# tz@iana.org for general use in the future). For more, please see -# the file CONTRIBUTING in the tz distribution. +# go ahead and edit the file, and please send any changes to +# the public mailing list tz@iana.org for general use in the future. +# For more, please see the file CONTRIBUTING in the tz distribution. # From Paul Eggert (2018-05-27): # @@ -138,8 +138,9 @@ Zone Atlantic/Cape_Verde -1:34:04 - LMT 1912 Jan 01 2:00u # Praia -1:00 - %z # Chad +# Fort-Lamy was renamed to N’Djamena on 1973-04-06. # Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Africa/Ndjamena 1:00:12 - LMT 1912 Jan 1 # N'Djamena +Zone Africa/Ndjamena 1:00:12 - LMT 1912 Jan 1 # Fort-Lamy 1:00 - WAT 1979 Oct 14 1:00 1:00 WAST 1980 Mar 8 1:00 - WAT diff --git a/src/java.base/share/data/tzdata/antarctica b/src/java.base/share/data/tzdata/antarctica index 87787d31cfe..b3c186851f1 100644 --- a/src/java.base/share/data/tzdata/antarctica +++ b/src/java.base/share/data/tzdata/antarctica @@ -26,13 +26,10 @@ # This file is in the public domain, so clarified as of # 2009-05-17 by Arthur David Olson. -# From Paul Eggert (1999-11-15): -# To keep things manageable, we list only locations occupied year-round; see -# COMNAP - Stations and Bases -# http://www.comnap.aq/comnap/comnap.nsf/P/Stations/ -# and -# Summary of the Peri-Antarctic Islands (1998-07-23) -# http://www.spri.cam.ac.uk/bob/periant.htm +# From Paul Eggert (2025-08-16): +# To keep things manageable, list only locations occupied year-round; see +# Antarctic Facilities Information +# https://www.comnap.aq/antarctic-facilities-information # for information. # Unless otherwise specified, we have no time zone information. @@ -167,6 +164,7 @@ Zone Antarctica/Mawson 0 - -00 1954 Feb 13 # China - year-round bases # Great Wall, King George Island, -6213-05858, since 1985-02-20 # Zhongshan, Larsemann Hills, Prydz Bay, -6922+07623, since 1989-02-26 +# Qinling, Inexpressible I, Terra Nova Bay, -7456+16343, since 2024-02-07 # France - year-round bases (also see "France & Italy") # diff --git a/src/java.base/share/data/tzdata/asia b/src/java.base/share/data/tzdata/asia index 55b13134f9c..005abd01793 100644 --- a/src/java.base/share/data/tzdata/asia +++ b/src/java.base/share/data/tzdata/asia @@ -27,9 +27,9 @@ # 2009-05-17 by Arthur David Olson. # This file is by no means authoritative; if you think you know better, -# go ahead and edit the file (and please send any changes to -# tz@iana.org for general use in the future). For more, please see -# the file CONTRIBUTING in the tz distribution. +# go ahead and edit the file, and please send any changes to +# the public mailing list tz@iana.org for general use in the future. +# For more, please see the file CONTRIBUTING in the tz distribution. # From Paul Eggert (2019-07-11): # diff --git a/src/java.base/share/data/tzdata/australasia b/src/java.base/share/data/tzdata/australasia index d659d1fb4b1..638789f42da 100644 --- a/src/java.base/share/data/tzdata/australasia +++ b/src/java.base/share/data/tzdata/australasia @@ -960,9 +960,9 @@ Zone Pacific/Efate 11:13:16 - LMT 1912 Jan 13 # Vila # NOTES # This file is by no means authoritative; if you think you know better, -# go ahead and edit the file (and please send any changes to -# tz@iana.org for general use in the future). For more, please see -# the file CONTRIBUTING in the tz distribution. +# go ahead and edit the file, and please send any changes to +# the public mailing list tz@iana.org for general use in the future. +# For more, please see the file CONTRIBUTING in the tz distribution. # From Paul Eggert (2018-11-18): # @@ -2011,6 +2011,7 @@ Zone Pacific/Efate 11:13:16 - LMT 1912 Jan 13 # Vila # From Paul Eggert (2018-11-19): # The 1921-01-15 introduction of standard time is in Shanks; it is also in # "Standard Time Throughout the World", US National Bureau of Standards (1935), +# https://nvlpubs.nist.gov/nistpubs/Legacy/circ/nbscircular406.pdf # page 3, which does not give the UT offset. In response to a comment by # Phake Nick I set the Nauru time of occupation by Japan to # 1942-08-29/1945-09-08 by using dates from: @@ -2078,9 +2079,10 @@ Zone Pacific/Efate 11:13:16 - LMT 1912 Jan 13 # Vila # https://webspace.science.uu.nl/~gent0113/idl/idl_alaska_samoa.htm # Although Shanks & Pottenger says they both switched to UT -11:30 -# in 1911, and to -11 in 1950. many earlier sources give -11 +# in 1911, and to -11 in 1950, many earlier sources give -11 # for American Samoa, e.g., the US National Bureau of Standards # circular "Standard Time Throughout the World", 1932. +# https://nvlpubs.nist.gov/nistpubs/Legacy/circ/nbscircular399.pdf # Assume American Samoa switched to -11 in 1911, not 1950, # and that after 1950 they agreed until (western) Samoa skipped a # day in 2011. Assume also that the Samoas follow the US and New diff --git a/src/java.base/share/data/tzdata/europe b/src/java.base/share/data/tzdata/europe index 7ba6c679609..b82ca6f67bb 100644 --- a/src/java.base/share/data/tzdata/europe +++ b/src/java.base/share/data/tzdata/europe @@ -27,9 +27,9 @@ # 2009-05-17 by Arthur David Olson. # This file is by no means authoritative; if you think you know better, -# go ahead and edit the file (and please send any changes to -# tz@iana.org for general use in the future). For more, please see -# the file CONTRIBUTING in the tz distribution. +# go ahead and edit the file, and please send any changes to +# the public mailing list tz@iana.org for general use in the future. +# For more, please see the file CONTRIBUTING in the tz distribution. # From Paul Eggert (2017-02-10): # @@ -65,7 +65,7 @@ # . He writes: # "It is requested that corrections and additions to these tables # may be sent to Mr. John Milne, Royal Geographical Society, -# Savile Row, London." Nowadays please email them to tz@iana.org. +# Savile Row, London." Nowadays please see the file CONTRIBUTING. # # Byalokoz EL. New Counting of Time in Russia since July 1, 1919. # This Russian-language source was consulted by Vladimir Karpinsky; see @@ -77,7 +77,7 @@ # Десятая гос. тип., 1919. # http://resolver.gpntb.ru/purl?docushare/dsweb/Get/Resource-2011/Byalokoz__E.L.__Novyy__schet__vremeni__v__techenie__sutok__izd__2(1).pdf # -# Brazil's Divisão Serviço da Hora (DSHO), +# Brazil's Divisão de Serviços da Hora (DISHO) # History of Summer Time # # (1998-09-21, in Portuguese) @@ -937,7 +937,7 @@ Rule Belgium 1922 1927 - Oct Sat>=1 23:00s 0 - Rule Belgium 1923 only - Apr 21 23:00s 1:00 S Rule Belgium 1924 only - Mar 29 23:00s 1:00 S Rule Belgium 1925 only - Apr 4 23:00s 1:00 S -# DSH writes that a royal decree of 1926-02-22 specified the Sun following 3rd +# DISHO writes that a royal decree of 1926-02-22 specified the Sun following 3rd # Sat in Apr (except if it's Easter, in which case it's one Sunday earlier), # to Sun following 1st Sat in Oct, and that a royal decree of 1928-09-15 # changed the transition times to 02:00 GMT. @@ -1333,6 +1333,13 @@ Zone Europe/Helsinki 1:39:49 - LMT 1878 May 31 # France # Monaco +# From Robert H. van Gent (2025-07-21): +# The most recent issue of the Annuaire [par le Bureau des Longitudes] +# on Gallica (2021) ... lists information for France +# https://gallica.bnf.fr/ark:/12148/bpt6k9127672b/f52.item +# From Paul Eggert (2025-07-21): +# Go with the 2020 Annuaire (published 2021) except as noted below. + # From Ciro Discepolo (2000-12-20): # # Henri Le Corre, Régimes horaires pour le monde entier, Éditions @@ -1394,7 +1401,6 @@ Zone Europe/Helsinki 1:39:49 - LMT 1878 May 31 # problems in Algiers, Monaco and Tunis. # -# Shank & Pottenger seem to use '24:00' ambiguously; resolve it with Whitman. # Rule NAME FROM TO - IN ON AT SAVE LETTER/S Rule France 1916 only - Jun 14 23:00s 1:00 S Rule France 1916 1919 - Oct Sun>=1 23:00s 0 - @@ -1406,9 +1412,25 @@ Rule France 1920 only - Oct 23 23:00s 0 - Rule France 1921 only - Mar 14 23:00s 1:00 S Rule France 1921 only - Oct 25 23:00s 0 - Rule France 1922 only - Mar 25 23:00s 1:00 S -# DSH writes that a law of 1923-05-24 specified 3rd Sat in Apr at 23:00 to 1st -# Sat in Oct at 24:00; and that in 1930, because of Easter, the transitions -# were Apr 12 and Oct 5. Go with Shanks & Pottenger. +# From Robert H. van Gent (2025-07-22): +# There is a curious history behind the erroneous date for the start of +# daylight saving in France in 1923 as listed in the current issues of +# the Annuaire du Bureau des Longitudes. [See:] +# https://lists.iana.org/hyperkitty/list/tz@iana.org/message/MYQEJMSXO2AIEZ3UIXZKMTTAIPY7KNT2/ +# From Brian Inglis (2025-07-23): +# Légifrance JORF No. 0073 du 15 mars 1922 +# https://www.legifrance.gouv.fr/jorf/jo/id/JORFCONT000000008324 +# Légifrance JORF No. 0139 du 25 mai 1923 +# https://www.legifrance.gouv.fr/jorf/jo/id/JORFCONT000000008416 +# From Paul Eggert (2025-07-23): +# The latter specifies March's last Saturday at 23:00 to October's first +# Saturday at 24:00, except that if neighboring allies agree the dates +# can be moved to April's third Saturday and September's third Saturday. +# Apparently spring 1923 was tricky. DISHO writes that in 1930, +# because of Easter, the transitions were Apr 12 and Oct 5. +# Use the 2020 Annuaire dates, except for spring 1923 where +# Shanks & Pottenger's May 26 matches the dates given in the 1924 and +# 1961-2001 issues of the Annuaire. Rule France 1922 1938 - Oct Sat>=1 23:00s 0 - Rule France 1923 only - May 26 23:00s 1:00 S Rule France 1924 only - Mar 29 23:00s 1:00 S @@ -2119,12 +2141,10 @@ Zone Europe/Warsaw 1:24:00 - LMT 1880 # all clocks therefore having to be advanced or set back correspondingly ... # Rule NAME FROM TO - IN ON AT SAVE LETTER/S -# From Tim Parenti (2024-07-01), per Paul Eggert (1999-01-30): -# DSH writes in their history that Decreto 1469 of 1915-03-30 established -# summer time and that, "despite" this, the change to the clocks was not done -# every year, depending on what Spain did, because of railroad schedules. -# In fact, that decree had nothing to do with DST; rather, it regulated the -# sending of time signals. But we do see linkage to Spain in the 1920s below. +# From Tim Parenti (2024-07-01): +# Decreto 1469 of 1915-03-30 ... had nothing to do with DST; +# rather it regulated the sending of time signals. +# But we do see linkage to Spain in the 1920s below. # https://dre.pt/dr/detalhe/decreto/1469-1915-285721 # https://dre.pt/application/conteudo/285721 # diff --git a/src/java.base/share/data/tzdata/iso3166.tab b/src/java.base/share/data/tzdata/iso3166.tab index 7fa350ecbe3..ddcc841fe97 100644 --- a/src/java.base/share/data/tzdata/iso3166.tab +++ b/src/java.base/share/data/tzdata/iso3166.tab @@ -26,22 +26,22 @@ # This file is in the public domain, so clarified as of # 2009-05-17 by Arthur David Olson. # -# From Paul Eggert (2023-09-06): +# From Paul Eggert (2025-07-01): # This file contains a table of two-letter country codes. Columns are -# separated by a single tab. Lines beginning with '#' are comments. +# separated by a single tab. Lines beginning with ‘#’ are comments. # All text uses UTF-8 encoding. The columns of the table are as follows: # # 1. ISO 3166-1 alpha-2 country code, current as of -# ISO/TC 46 N1108 (2023-04-05). See: ISO/TC 46 Documents +# ISO/TC 46 N1127 (2024-02-29). See: ISO/TC 46 Documents # https://www.iso.org/committee/48750.html?view=documents # 2. The usual English name for the coded region. This sometimes # departs from ISO-listed names, sometimes so that sorted subsets -# of names are useful (e.g., "Samoa (American)" and "Samoa -# (western)" rather than "American Samoa" and "Samoa"), +# of names are useful (e.g., “Samoa (American)” and “Samoa +# (western)” rather than “American Samoa” and “Samoa”), # sometimes to avoid confusion among non-experts (e.g., -# "Czech Republic" and "Turkey" rather than "Czechia" and "Türkiye"), -# and sometimes to omit needless detail or churn (e.g., "Netherlands" -# rather than "Netherlands (the)" or "Netherlands (Kingdom of the)"). +# “Czech Republic” and “Turkey” rather than “Czechia” and “Türkiye”), +# and sometimes to omit needless detail or churn (e.g., “Netherlands” +# rather than “Netherlands (the)” or “Netherlands (Kingdom of the)”). # # The table is sorted by country code. # @@ -94,7 +94,7 @@ CD Congo (Dem. Rep.) CF Central African Rep. CG Congo (Rep.) CH Switzerland -CI Côte d'Ivoire +CI Côte d’Ivoire CK Cook Islands CL Chile CM Cameroon diff --git a/src/java.base/share/data/tzdata/leapseconds b/src/java.base/share/data/tzdata/leapseconds index 042a32b052c..9426b40f07e 100644 --- a/src/java.base/share/data/tzdata/leapseconds +++ b/src/java.base/share/data/tzdata/leapseconds @@ -28,7 +28,8 @@ # This file is generated automatically from the data in the public-domain # NIST/IERS format leap-seconds.list file, which can be copied from # -# or, in a variant with different comments, from +# or via a less-secure protocol and with different comments and +# less volatile last-modified and expiration timestamps, from # . # For more about leap-seconds.list, please see # The NTP Timescale and Leap Seconds @@ -92,11 +93,17 @@ Leap 2016 Dec 31 23:59:60 + S # Any additional leap seconds will come after this. # This Expires line is commented out for now, # so that pre-2020a zic implementations do not reject this file. -#Expires 2025 Dec 28 00:00:00 +#Expires 2026 Jun 28 00:00:00 -# POSIX timestamps for the data in this file: -#updated 1736208000 (2025-01-07 00:00:00 UTC) -#expires 1766880000 (2025-12-28 00:00:00 UTC) +# Here are POSIX timestamps for the data in this file. +# "#updated" gives the last time the leap seconds data changed +# or, if this file was derived from the IERS leap-seconds.list, +# the last time that file changed in any way. +# "#expires" gives the first time this file might be wrong; +# if this file was derived from the IERS leap-seconds.list, +# this is typically a bit less than one year after "updated". +#updated 1751846400 (2025-07-07 00:00:00 UTC) +#expires 1782604800 (2026-06-28 00:00:00 UTC) # Updated through IERS Bulletin C (https://hpiers.obspm.fr/iers/bul/bulc/bulletinc.dat) -# File expires on 28 December 2025 +# File expires on 28 June 2026 diff --git a/src/java.base/share/data/tzdata/northamerica b/src/java.base/share/data/tzdata/northamerica index 21f178ee8cb..f20879e9063 100644 --- a/src/java.base/share/data/tzdata/northamerica +++ b/src/java.base/share/data/tzdata/northamerica @@ -29,9 +29,9 @@ # also includes Central America and the Caribbean # This file is by no means authoritative; if you think you know better, -# go ahead and edit the file (and please send any changes to -# tz@iana.org for general use in the future). For more, please see -# the file CONTRIBUTING in the tz distribution. +# go ahead and edit the file, and please send any changes to +# the public mailing list tz@iana.org for general use in the future. +# For more, please see the file CONTRIBUTING in the tz distribution. # From Paul Eggert (1999-03-22): # A reliable and entertaining source about time zones is @@ -1241,6 +1241,16 @@ Zone America/Menominee -5:50:27 - LMT 1885 Sep 18 12:00 # _Los Angeles Times_ (1998-11-10), A1, A10; it cites # Jimmy Skaggs, _The Great Guano Rush_ (1994). +# From Rob van Gent (2025-07-23): +# Another useful source for historical time zone information appears to be +# a series of circulars with the title "Standard Time Throughout the World" +# issued between 1925 and 1950 by the U.S. Bureau of Standards. +# I found the following issues online: +# https://nvlpubs.nist.gov/nistpubs/Legacy/circ/nbscircular280.pdf (1925) +# https://nvlpubs.nist.gov/nistpubs/Legacy/circ/nbscircular399.pdf (1932) +# https://nvlpubs.nist.gov/nistpubs/Legacy/circ/nbscircular406.pdf (1935) +# https://nvlpubs.nist.gov/nistpubs/Legacy/circ/nbscircular496.pdf (1950) + ################################################################################ @@ -2457,12 +2467,35 @@ Zone America/Dawson -9:17:40 - LMT 1900 Aug 20 # on the same dates or with a difference of one day. # So it may be easier to implement these changes as DST with rule CA # during this whole period. -# -# From Paul Eggert (2024-08-18): -# For now, maintain the slightly-different history for Baja California, + +# From Alois Treindl (2025-07-29): +# I did a quick newspaper archive research on https://hndm.iib.unam.mx/ +# and found that Periódico Oficial del Estado de Baja California Norte +# (1973-04-20) states clearly that DST was observed from last Sunday +# in April to last Sunday in October.... I have a few more data from the +# official bulletin for DST begin or end in Baja California 1964 1967 1969 +# 1972 1973 (already sent) 1974 1975 1976 I do not know whether it is safe to +# assume that it also applied in the years where I did not yet find proof. +# The 1974 end of DST contains a reference to an Acuerdo of 1973-dec-20 which +# I could not find.... One might assume that Baja California, which followed +# US-CA in all these other yours, did the same. +# +# From Paul Eggert (2025-08-04): +# Assume that Tijuana agreed with San Diego from 1953 through 1996, +# as this agrees with Alois Treindl's data and with Shanks. +# For now, keep the slightly-different 1948/1952 history for Baja California, # as we have no information on whether 1948/1952 clocks in Tijuana followed # the decrees or followed San Diego. +# From Mark Schapiro, writing in The Nation (2002-10-28): +# https://www.thenation.com/article/archive/sowing-disaster/ +# When Mexican clocks were turned back for daylight saving time in the spring, +# the Zapotecs refused to make the adjustment, insisting that they live in +# "God's time," not in what they derisively call "Fox time," referring to +# President Vicente Fox in far-off Mexico City. +# From Paul Eggert (2025-08-04): +# Unfortunately we have no data to track this informal practice. + # From Alan Perry (1996-02-15): # A guy from our Mexico subsidiary finally found the Presidential Decree # outlining the timezone changes in Mexico. @@ -2728,7 +2761,7 @@ Zone America/Mexico_City -6:36:36 - LMT 1922 Jan 1 7:00u # Chihuahua (near US border - western side) # This includes the municipios of Janos, Ascensión, Juárez, Guadalupe, and # Práxedis G Guerrero. -# http://gaceta.diputados.gob.mx/PDF/65/2a022/nov/20221124-VII.pdf +# https://gaceta.diputados.gob.mx/PDF/65/2022/nov/20221124-VII.pdf Zone America/Ciudad_Juarez -7:05:56 - LMT 1922 Jan 1 7:00u -7:00 - MST 1927 Jun 10 -6:00 - CST 1930 Nov 15 @@ -2743,7 +2776,7 @@ Zone America/Ciudad_Juarez -7:05:56 - LMT 1922 Jan 1 7:00u # Chihuahua (near US border - eastern side) # This includes the municipios of Coyame del Sotol, Ojinaga, and Manuel # Benavides. -# http://gaceta.diputados.gob.mx/PDF/65/2a022/nov/20221124-VII.pdf +# https://gaceta.diputados.gob.mx/PDF/65/2022/nov/20221124-VII.pdf Zone America/Ojinaga -6:57:40 - LMT 1922 Jan 1 7:00u -7:00 - MST 1927 Jun 10 -6:00 - CST 1930 Nov 15 @@ -2840,9 +2873,7 @@ Zone America/Tijuana -7:48:04 - LMT 1922 Jan 1 7:00u -8:00 1:00 PDT 1951 Sep 30 2:00 -8:00 - PST 1952 Apr 27 2:00 -8:00 1:00 PDT 1952 Sep 28 2:00 - -8:00 - PST 1954 - -8:00 CA P%sT 1961 - -8:00 - PST 1976 + -8:00 CA P%sT 1967 -8:00 US P%sT 1996 -8:00 Mexico P%sT 2001 -8:00 US P%sT 2002 Feb 20 diff --git a/src/java.base/share/data/tzdata/southamerica b/src/java.base/share/data/tzdata/southamerica index ca3c338591f..f932d5a72a1 100644 --- a/src/java.base/share/data/tzdata/southamerica +++ b/src/java.base/share/data/tzdata/southamerica @@ -27,9 +27,9 @@ # 2009-05-17 by Arthur David Olson. # This file is by no means authoritative; if you think you know better, -# go ahead and edit the file (and please send any changes to -# tz@iana.org for general use in the future). For more, please see -# the file CONTRIBUTING in the tz distribution. +# go ahead and edit the file, and please send any changes to +# the public mailing list tz@iana.org for general use in the future. +# For more, please see the file CONTRIBUTING in the tz distribution. # From Paul Eggert (2016-12-05): # diff --git a/src/java.base/share/native/libverify/check_code.c b/src/java.base/share/native/libverify/check_code.c index 7266ac8f93c..32df102dcb3 100644 --- a/src/java.base/share/native/libverify/check_code.c +++ b/src/java.base/share/native/libverify/check_code.c @@ -395,7 +395,8 @@ static jboolean is_superclass(context_type *, fullinfo_type); 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 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset) 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 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset) 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 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset) } } 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 @@ static int instruction_length(unsigned char *iptr, unsigned char *end) /* 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 --git a/src/java.base/unix/classes/sun/nio/ch/NativeThread.java b/src/java.base/unix/classes/sun/nio/ch/NativeThread.java index 2ec67cc7d5c..8d0bcea48d9 100644 --- a/src/java.base/unix/classes/sun/nio/ch/NativeThread.java +++ b/src/java.base/unix/classes/sun/nio/ch/NativeThread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 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 @@ -78,6 +78,17 @@ static boolean isVirtualThread(long tid) { return (tid == VIRTUAL_THREAD_ID); } + /** + * Return true if the operating system supports pending signals. If a signal is sent + * to a thread but cannot be delivered immediately then it will be delivered when the + * thread is in the appropriate state. + */ + static boolean supportPendingSignals() { + return supportPendingSignals0(); + } + + private static native boolean supportPendingSignals0(); + // Returns an opaque token representing the native thread underlying the // invoking Java thread. On systems that do not require signalling, this // method always returns 0. diff --git a/src/java.base/unix/classes/sun/nio/ch/UnixDispatcher.java b/src/java.base/unix/classes/sun/nio/ch/UnixDispatcher.java index fcd2d88d7a6..4cdd0c400ec 100644 --- a/src/java.base/unix/classes/sun/nio/ch/UnixDispatcher.java +++ b/src/java.base/unix/classes/sun/nio/ch/UnixDispatcher.java @@ -29,21 +29,31 @@ import java.io.IOException; abstract class UnixDispatcher extends NativeDispatcher { + private static final boolean SUPPORTS_PENDING_SIGNALS = NativeThread.supportPendingSignals(); @Override void close(FileDescriptor fd) throws IOException { close0(fd); } - @Override - void implPreClose(FileDescriptor fd, long reader, long writer) throws IOException { - preClose0(fd); + private void signalThreads(long reader, long writer) { if (NativeThread.isNativeThread(reader)) NativeThread.signal(reader); if (NativeThread.isNativeThread(writer)) NativeThread.signal(writer); } + @Override + void implPreClose(FileDescriptor fd, long reader, long writer) throws IOException { + if (SUPPORTS_PENDING_SIGNALS) { + signalThreads(reader, writer); + } + preClose0(fd); + if (!SUPPORTS_PENDING_SIGNALS) { + signalThreads(reader, writer); + } + } + private static native void close0(FileDescriptor fd) throws IOException; private static native void preClose0(FileDescriptor fd) throws IOException; diff --git a/src/java.base/unix/native/libjava/Console_md.c b/src/java.base/unix/native/libjava/Console_md.c index 1e71ab3a6b2..17643779b31 100644 --- a/src/java.base/unix/native/libjava/Console_md.c +++ b/src/java.base/unix/native/libjava/Console_md.c @@ -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 @@ -31,8 +31,19 @@ #include #include -JNIEXPORT jboolean JNICALL -Java_java_io_Console_istty(JNIEnv *env, jclass cls) +JNIEXPORT jint JNICALL +Java_java_io_Console_ttyStatus(JNIEnv *env, jclass cls) { - return isatty(fileno(stdin)) && isatty(fileno(stdout)); + jint ret = 0; + + if (isatty(fileno(stdin))) { + ret |= java_io_Console_TTY_STDIN_MASK; + } + if (isatty(fileno(stdout))) { + ret |= java_io_Console_TTY_STDOUT_MASK; + } + if (isatty(fileno(stderr))) { + ret |= java_io_Console_TTY_STDERR_MASK; + } + return ret; } diff --git a/src/java.base/unix/native/libjava/ProcessImpl_md.c b/src/java.base/unix/native/libjava/ProcessImpl_md.c index 1d0c8d21d37..f7531ad5abe 100644 --- a/src/java.base/unix/native/libjava/ProcessImpl_md.c +++ b/src/java.base/unix/native/libjava/ProcessImpl_md.c @@ -732,7 +732,7 @@ Java_java_lang_ProcessImpl_forkAndExec(JNIEnv *env, (fds[2] == -1 && pipe(err) < 0) || (pipe(childenv) < 0) || (pipe(fail) < 0)) { - throwInternalIOException(env, errno, "Bad file descriptor", c->mode); + throwInternalIOException(env, errno, "Bad file descriptor", mode); goto Catch; } c->fds[0] = fds[0]; diff --git a/src/java.base/unix/native/libjava/childproc.c b/src/java.base/unix/native/libjava/childproc.c index 7a21b86565f..de66fa32571 100644 --- a/src/java.base/unix/native/libjava/childproc.c +++ b/src/java.base/unix/native/libjava/childproc.c @@ -416,6 +416,11 @@ childProcess(void *arg) if (fcntl(FAIL_FILENO, F_SETFD, FD_CLOEXEC) == -1) goto WhyCantJohnnyExec; + // Children should be started with default signal disposition for SIGPIPE + if (signal(SIGPIPE, SIG_DFL) == SIG_ERR) { + goto WhyCantJohnnyExec; + } + JDK_execvpe(p->mode, p->argv[0], p->argv, p->envv); WhyCantJohnnyExec: diff --git a/src/java.base/unix/native/libjava/java_props_md.c b/src/java.base/unix/native/libjava/java_props_md.c index 1d5435d5229..30d0ca67652 100644 --- a/src/java.base/unix/native/libjava/java_props_md.c +++ b/src/java.base/unix/native/libjava/java_props_md.c @@ -239,6 +239,7 @@ static int ParseLocale(JNIEnv* env, int cat, char ** std_language, char ** std_s 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 @@ static int ParseLocale(JNIEnv* env, int cat, char ** std_language, char ** std_s 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; @@ -386,8 +388,12 @@ GetJavaProperties(JNIEnv *env) /* supported instruction sets */ { char list[258]; - sysinfo(SI_ISALIST, list, sizeof(list)); - sprops.cpu_isalist = strdup(list); + int ret = sysinfo(SI_ISALIST, list, sizeof(list)); + if (ret == 0) { + sprops.cpu_isalist = strdup(list); + } else { + sprops.cpu_isalist = NULL; + } } #else sprops.cpu_isalist = NULL; diff --git a/src/java.base/unix/native/libnet/net_util_md.c b/src/java.base/unix/native/libnet/net_util_md.c index 9bb6a026961..fc89b910105 100644 --- a/src/java.base/unix/native/libnet/net_util_md.c +++ b/src/java.base/unix/native/libnet/net_util_md.c @@ -282,7 +282,7 @@ NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, } else { jint address; if (family != java_net_InetAddress_IPv4) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable"); + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "IPv6 protocol family unavailable"); return -1; } address = getInetAddress_addr(env, iaObj); diff --git a/src/java.base/unix/native/libnio/ch/NativeThread.c b/src/java.base/unix/native/libnio/ch/NativeThread.c index f273b951569..d6d31b2b12b 100644 --- a/src/java.base/unix/native/libnio/ch/NativeThread.c +++ b/src/java.base/unix/native/libnio/ch/NativeThread.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,3 +88,12 @@ Java_sun_nio_ch_NativeThread_signal0(JNIEnv *env, jclass cl, jlong thread) #endif JNU_ThrowIOExceptionWithLastError(env, "Thread signal failed"); } + +JNIEXPORT jboolean JNICALL +Java_sun_nio_ch_NativeThread_supportPendingSignals0(JNIEnv *env, jclass cl) { +#if defined(_AIX) + return JNI_TRUE; +#else + return JNI_FALSE; +#endif +} diff --git a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c index fbf996886ae..5f81241b7dd 100644 --- a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c +++ b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c @@ -343,22 +343,21 @@ Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this) /* system calls that might not be available at run time */ -#if defined(_ALLBSD_SOURCE) - my_openat_func = (openat_func*) openat; - my_fstatat_func = (fstatat_func*) fstatat; -#else - // Make sure we link to the 64-bit version of the functions - my_openat_func = (openat_func*) dlsym(RTLD_DEFAULT, "openat64"); - my_fstatat_func = (fstatat_func*) dlsym(RTLD_DEFAULT, "fstatat64"); -#endif my_unlinkat_func = (unlinkat_func*) dlsym(RTLD_DEFAULT, "unlinkat"); my_renameat_func = (renameat_func*) dlsym(RTLD_DEFAULT, "renameat"); #if defined(_AIX) // Make sure we link to the 64-bit version of the function + my_openat_func = (openat_func*) dlsym(RTLD_DEFAULT, "open64at"); + my_fstatat_func = (fstatat_func*) dlsym(RTLD_DEFAULT, "stat64at"); my_fdopendir_func = (fdopendir_func*) dlsym(RTLD_DEFAULT, "fdopendir64"); #elif defined(_ALLBSD_SOURCE) + my_openat_func = (openat_func*) openat; + my_fstatat_func = (fstatat_func*) fstatat; my_fdopendir_func = (fdopendir_func*) fdopendir; #else + // Make sure we link to the 64-bit version of the functions + my_openat_func = (openat_func*) dlsym(RTLD_DEFAULT, "openat64"); + my_fstatat_func = (fstatat_func*) dlsym(RTLD_DEFAULT, "fstatat64"); my_fdopendir_func = (fdopendir_func*) dlsym(RTLD_DEFAULT, "fdopendir"); #endif diff --git a/src/java.base/windows/native/libjava/Console_md.c b/src/java.base/windows/native/libjava/Console_md.c index f73e62f8e26..07749f2775a 100644 --- a/src/java.base/windows/native/libjava/Console_md.c +++ b/src/java.base/windows/native/libjava/Console_md.c @@ -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 @@ -31,21 +31,28 @@ #include #include -JNIEXPORT jboolean JNICALL -Java_java_io_Console_istty(JNIEnv *env, jclass cls) +JNIEXPORT jint JNICALL +Java_java_io_Console_ttyStatus(JNIEnv *env, jclass cls) { + jint ret = 0; HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE); + HANDLE hStdErr = GetStdHandle(STD_ERROR_HANDLE); - if (hStdIn == INVALID_HANDLE_VALUE || - hStdOut == INVALID_HANDLE_VALUE) { - return JNI_FALSE; + if (hStdIn != INVALID_HANDLE_VALUE && + GetFileType(hStdIn) == FILE_TYPE_CHAR) { + ret |= java_io_Console_TTY_STDIN_MASK; } - if (GetFileType(hStdIn) != FILE_TYPE_CHAR || - GetFileType(hStdOut) != FILE_TYPE_CHAR) { - return JNI_FALSE; + if (hStdOut != INVALID_HANDLE_VALUE && + GetFileType(hStdOut) == FILE_TYPE_CHAR) { + ret |= java_io_Console_TTY_STDOUT_MASK; } - return JNI_TRUE; + if (hStdErr != INVALID_HANDLE_VALUE && + GetFileType(hStdErr) == FILE_TYPE_CHAR) { + ret |= java_io_Console_TTY_STDERR_MASK; + } + + return ret; } diff --git a/src/java.base/windows/native/libjava/java_props_md.c b/src/java.base/windows/native/libjava/java_props_md.c index 9495faf81e5..75587a09d0b 100644 --- a/src/java.base/windows/native/libjava/java_props_md.c +++ b/src/java.base/windows/native/libjava/java_props_md.c @@ -419,17 +419,6 @@ GetJavaProperties(JNIEnv* env) * Operating system dwMajorVersion dwMinorVersion * ================== ============== ============== * - * Windows 95 4 0 - * Windows 98 4 10 - * Windows ME 4 90 - * Windows 3.51 3 51 - * Windows NT 4.0 4 0 - * Windows 2000 5 0 - * Windows XP 32 bit 5 1 - * Windows Server 2003 family 5 2 - * Windows XP 64 bit 5 2 - * where ((&ver.wServicePackMinor) + 2) = 1 - * and si.wProcessorArchitecture = 9 * Windows Vista family 6 0 (VER_NT_WORKSTATION) * Windows Server 2008 6 0 (!VER_NT_WORKSTATION) * Windows 7 6 1 (VER_NT_WORKSTATION) @@ -452,61 +441,19 @@ GetJavaProperties(JNIEnv* env) * versions are released. */ switch (platformId) { - case VER_PLATFORM_WIN32_WINDOWS: - if (majorVersion == 4) { - switch (minorVersion) { - case 0: sprops.os_name = "Windows 95"; break; - case 10: sprops.os_name = "Windows 98"; break; - case 90: sprops.os_name = "Windows Me"; break; - default: sprops.os_name = "Windows 9X (unknown)"; break; - } - } else { - sprops.os_name = "Windows 9X (unknown)"; - } - break; case VER_PLATFORM_WIN32_NT: - if (majorVersion <= 4) { - sprops.os_name = "Windows NT"; - } else if (majorVersion == 5) { - switch (minorVersion) { - case 0: sprops.os_name = "Windows 2000"; break; - case 1: sprops.os_name = "Windows XP"; break; - case 2: - /* - * From MSDN OSVERSIONINFOEX and SYSTEM_INFO documentation: - * - * "Because the version numbers for Windows Server 2003 - * and Windows XP 6u4 bit are identical, you must also test - * whether the wProductType member is VER_NT_WORKSTATION. - * and si.wProcessorArchitecture is - * PROCESSOR_ARCHITECTURE_AMD64 (which is 9) - * If it is, the operating system is Windows XP 64 bit; - * otherwise, it is Windows Server 2003." - */ - if (is_workstation && is_64bit) { - sprops.os_name = "Windows XP"; /* 64 bit */ - } else { - sprops.os_name = "Windows 2003"; - } - break; - default: sprops.os_name = "Windows NT (unknown)"; break; - } - } else if (majorVersion == 6) { + if (majorVersion == 6) { /* * See table in MSDN OSVERSIONINFOEX documentation. */ if (is_workstation) { switch (minorVersion) { - case 0: sprops.os_name = "Windows Vista"; break; - case 1: sprops.os_name = "Windows 7"; break; case 2: sprops.os_name = "Windows 8"; break; case 3: sprops.os_name = "Windows 8.1"; break; default: sprops.os_name = "Windows NT (unknown)"; } } else { switch (minorVersion) { - case 0: sprops.os_name = "Windows Server 2008"; break; - case 1: sprops.os_name = "Windows Server 2008 R2"; break; case 2: sprops.os_name = "Windows Server 2012"; break; case 3: sprops.os_name = "Windows Server 2012 R2"; break; default: sprops.os_name = "Windows NT (unknown)"; diff --git a/src/java.base/windows/native/libnet/net_util_md.c b/src/java.base/windows/native/libnet/net_util_md.c index 410d141e790..bac3d1438ab 100644 --- a/src/java.base/windows/native/libnet/net_util_md.c +++ b/src/java.base/windows/native/libnet/net_util_md.c @@ -513,7 +513,7 @@ NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, } else { jint address; if (family != java_net_InetAddress_IPv4) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable"); + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "IPv6 protocol family unavailable"); return -1; } address = getInetAddress_addr(env, iaObj); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaKeyBindings.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaKeyBindings.java index f9779afdf47..a4c1d93883f 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaKeyBindings.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaKeyBindings.java @@ -157,6 +157,9 @@ LateBoundInputMap getPasswordFieldInputMap() { "shift alt KP_LEFT", null, "shift alt RIGHT", null, "shift alt KP_RIGHT", null, + "alt BACK_SPACE", null, + "ctrl W", null, + "alt DELETE", null, })); } diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDesktopPeer.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDesktopPeer.java index a4ec0767298..cc0e253f23b 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDesktopPeer.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDesktopPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, 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 @@ -34,7 +34,10 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.lang.annotation.Native; import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Path; /** @@ -44,6 +47,12 @@ */ public final class CDesktopPeer implements DesktopPeer { + @Native private static final int OPEN = 0; + @Native private static final int BROWSE = 1; + @Native private static final int EDIT = 2; + @Native private static final int PRINT = 3; + @Native private static final int MAIL = 4; + @Override public boolean isSupported(Action action) { return true; @@ -51,27 +60,27 @@ public boolean isSupported(Action action) { @Override public void open(File file) throws IOException { - this.lsOpenFile(file, false); + this.lsOpenFile(file, OPEN); } @Override public void edit(File file) throws IOException { - this.lsOpenFile(file, false); + this.lsOpenFile(file, EDIT); } @Override public void print(File file) throws IOException { - this.lsOpenFile(file, true); + this.lsOpenFile(file, PRINT); } @Override public void mail(URI uri) throws IOException { - this.lsOpen(uri); + this.lsOpen(uri, MAIL); } @Override public void browse(URI uri) throws IOException { - this.lsOpen(uri); + this.lsOpen(uri, BROWSE); } @Override @@ -162,24 +171,44 @@ public boolean moveToTrash(File file) { } } - private void lsOpen(URI uri) throws IOException { - int status = _lsOpenURI(uri.toString()); + private void lsOpen(URI uri, int action) throws IOException { + int status = _lsOpenURI(uri.toString(), action); if (status != 0 /* noErr */) { - throw new IOException("Failed to mail or browse " + uri + ". Error code: " + status); + String actionString = (action == MAIL) ? "mail" : "browse"; + throw new IOException("Failed to " + actionString + " " + uri + + ". Error code: " + status); } } - private void lsOpenFile(File file, boolean print) throws IOException { - int status = _lsOpenFile(file.getCanonicalPath(), print); + private void lsOpenFile(File file, int action) throws IOException { + int status = -1; + Path tmpFile = null; + String tmpTxtPath = null; + try { + if (action == EDIT) { + tmpFile = Files.createTempFile("TmpFile", ".txt"); + tmpTxtPath = tmpFile.toAbsolutePath().toString(); + } + status = _lsOpenFile(file.getCanonicalPath(), action, tmpTxtPath); + } catch (Exception e) { + throw new IOException("Failed to create tmp file: ", e); + } finally { + if (tmpFile != null) { + Files.deleteIfExists(tmpFile); + } + } if (status != 0 /* noErr */) { - throw new IOException("Failed to open, edit or print " + file + ". Error code: " + status); + String actionString = (action == OPEN) ? "open" + : (action == EDIT) ? "edit" : "print"; + throw new IOException("Failed to " + actionString + " " + file + + ". Error code: " + status); } } - private static native int _lsOpenURI(String uri); + private static native int _lsOpenURI(String uri, int action); - private static native int _lsOpenFile(String path, boolean print); + private static native int _lsOpenFile(String path, int action, String tmpTxtPath); } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CDesktopPeer.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CDesktopPeer.m index 7555c7990c4..e1841c9398c 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CDesktopPeer.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CDesktopPeer.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, 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 @@ -27,27 +27,60 @@ #import "JNIUtilities.h" #import #import +#import "sun_lwawt_macosx_CDesktopPeer.h" /* * Class: sun_lwawt_macosx_CDesktopPeer * Method: _lsOpenURI - * Signature: (Ljava/lang/String;)I; + * Signature: (Ljava/lang/String;I)I */ JNIEXPORT jint JNICALL Java_sun_lwawt_macosx_CDesktopPeer__1lsOpenURI -(JNIEnv *env, jclass clz, jstring uri) +(JNIEnv *env, jclass clz, jstring uri, jint action) { - OSStatus status = noErr; + __block OSStatus status = noErr; JNI_COCOA_ENTER(env); - // I would love to use NSWorkspace here, but it's not thread safe. Why? I don't know. - // So we use LaunchServices directly. - - NSURL *url = [NSURL URLWithString:JavaStringToNSString(env, uri)]; - - LSLaunchFlags flags = kLSLaunchDefaults; - - LSApplicationParameters params = {0, flags, NULL, NULL, NULL, NULL, NULL}; - status = LSOpenURLsWithRole((CFArrayRef)[NSArray arrayWithObject:url], kLSRolesAll, NULL, ¶ms, NULL, 0); + NSURL *urlToOpen = [NSURL URLWithString:JavaStringToNSString(env, uri)]; + NSURL *appURI = nil; + + if (action == sun_lwawt_macosx_CDesktopPeer_BROWSE) { + // To get the defaultBrowser + NSURL *httpsURL = [NSURL URLWithString:@"https://"]; + NSWorkspace *workspace = [NSWorkspace sharedWorkspace]; + appURI = [workspace URLForApplicationToOpenURL:httpsURL]; + } else if (action == sun_lwawt_macosx_CDesktopPeer_MAIL) { + // To get the default mailer + NSURL *mailtoURL = [NSURL URLWithString:@"mailto://"]; + NSWorkspace *workspace = [NSWorkspace sharedWorkspace]; + appURI = [workspace URLForApplicationToOpenURL:mailtoURL]; + } + + if (appURI == nil) { + return -1; + } + + // Prepare NSOpenConfig object + NSArray *urls = @[urlToOpen]; + NSWorkspaceOpenConfiguration *configuration = [NSWorkspaceOpenConfiguration configuration]; + configuration.activates = YES; // To bring app to foreground + configuration.promptsUserIfNeeded = YES; // To allow macOS desktop prompts + + // dispatch semaphores used to wait for the completion handler to update and return status + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(NSEC_PER_SEC)); // 1 second timeout + + // Asynchronous call to openURL + [[NSWorkspace sharedWorkspace] openURLs:urls + withApplicationAtURL:appURI + configuration:configuration + completionHandler:^(NSRunningApplication *app, NSError *error) { + if (error) { + status = (OSStatus) error.code; + } + dispatch_semaphore_signal(semaphore); + }]; + + dispatch_semaphore_wait(semaphore, timeout); JNI_COCOA_EXIT(env); return status; @@ -56,32 +89,73 @@ /* * Class: sun_lwawt_macosx_CDesktopPeer * Method: _lsOpenFile - * Signature: (Ljava/lang/String;Z)I; + * Signature: (Ljava/lang/String;I;Ljava/lang/String;)I; */ JNIEXPORT jint JNICALL Java_sun_lwawt_macosx_CDesktopPeer__1lsOpenFile -(JNIEnv *env, jclass clz, jstring jpath, jboolean print) +(JNIEnv *env, jclass clz, jstring jpath, jint action, jstring jtmpTxtPath) { - OSStatus status = noErr; + __block OSStatus status = noErr; JNI_COCOA_ENTER(env); - // I would love to use NSWorkspace here, but it's not thread safe. Why? I don't know. - // So we use LaunchServices directly. - NSString *path = NormalizedPathNSStringFromJavaString(env, jpath); - - NSURL *url = [NSURL fileURLWithPath:(NSString *)path]; + NSURL *urlToOpen = [NSURL fileURLWithPath:(NSString *)path]; // This byzantine workaround is necessary, or else directories won't open in Finder - url = (NSURL *)CFURLCreateWithFileSystemPath(NULL, (CFStringRef)[url path], kCFURLPOSIXPathStyle, false); - - LSLaunchFlags flags = kLSLaunchDefaults; - if (print) flags |= kLSLaunchAndPrint; - - LSApplicationParameters params = {0, flags, NULL, NULL, NULL, NULL, NULL}; - status = LSOpenURLsWithRole((CFArrayRef)[NSArray arrayWithObject:url], kLSRolesAll, NULL, ¶ms, NULL, 0); - [url release]; + urlToOpen = (NSURL *)CFURLCreateWithFileSystemPath(NULL, (CFStringRef)[urlToOpen path], + kCFURLPOSIXPathStyle, false); + + NSWorkspace *workspace = [NSWorkspace sharedWorkspace]; + NSURL *appURI = [workspace URLForApplicationToOpenURL:urlToOpen]; + NSURL *defaultTerminalApp = [workspace URLForApplicationToOpenURL:[NSURL URLWithString:@"file:///bin/sh"]]; + + // Prepare NSOpenConfig object + NSArray *urls = @[urlToOpen]; + NSWorkspaceOpenConfiguration *configuration = [NSWorkspaceOpenConfiguration configuration]; + configuration.activates = YES; // To bring app to foreground + configuration.promptsUserIfNeeded = YES; // To allow macOS desktop prompts + + // pre-checks for open/print/edit before calling openURLs API + if (action == sun_lwawt_macosx_CDesktopPeer_OPEN + || action == sun_lwawt_macosx_CDesktopPeer_PRINT) { + if (appURI == nil + || [[urlToOpen absoluteString] containsString:[appURI absoluteString]] + || [[defaultTerminalApp absoluteString] containsString:[appURI absoluteString]]) { + return -1; + } + // Additionally set forPrinting=TRUE for print + if (action == sun_lwawt_macosx_CDesktopPeer_PRINT) { + configuration.forPrinting = YES; + } + } else if (action == sun_lwawt_macosx_CDesktopPeer_EDIT) { + if (appURI == nil + || [[urlToOpen absoluteString] containsString:[appURI absoluteString]]) { + return -1; + } + // for EDIT: if (defaultApp = TerminalApp) then set appURI = DefaultTextEditor + if ([[defaultTerminalApp absoluteString] containsString:[appURI absoluteString]]) { + NSString *path = NormalizedPathNSStringFromJavaString(env, jtmpTxtPath); + NSURL *tempFilePath = [NSURL fileURLWithPath:(NSString *)path]; + appURI = [workspace URLForApplicationToOpenURL:tempFilePath]; + } + } + + // dispatch semaphores used to wait for the completion handler to update and return status + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(NSEC_PER_SEC)); // 1 second timeout + + // Asynchronous call - openURLs:withApplicationAtURL + [[NSWorkspace sharedWorkspace] openURLs:urls + withApplicationAtURL:appURI + configuration:configuration + completionHandler:^(NSRunningApplication *app, NSError *error) { + if (error) { + status = (OSStatus) error.code; + } + dispatch_semaphore_signal(semaphore); + }]; + + dispatch_semaphore_wait(semaphore, timeout); JNI_COCOA_EXIT(env); return status; } - diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsDevice.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsDevice.m index 32164493f9f..70f0741347a 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsDevice.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsDevice.m @@ -60,16 +60,14 @@ static int getBPPFromModeString(CFStringRef mode) } static BOOL isValidDisplayMode(CGDisplayModeRef mode) { - // Workaround for apple bug FB13261205, since it only affects arm based macs - // and arm support started with macOS 11 ignore the workaround for previous versions - if (@available(macOS 11, *)) { - if (architecture == -1) { - architecture = [[NSRunningApplication currentApplication] executableArchitecture]; - } - if (architecture == NSBundleExecutableArchitectureARM64) { - return (CGDisplayModeGetPixelWidth(mode) >= 800); - } + // Workaround for apple bug FB13261205, only affects arm based macs + if (architecture == -1) { + architecture = [[NSRunningApplication currentApplication] executableArchitecture]; } + if (architecture == NSBundleExecutableArchitectureARM64) { + return (CGDisplayModeGetPixelWidth(mode) >= 800); + } + return (1 < CGDisplayModeGetWidth(mode) && 1 < CGDisplayModeGetHeight(mode)); } diff --git a/src/java.desktop/share/classes/com/sun/beans/WildcardTypeImpl.java b/src/java.desktop/share/classes/com/sun/beans/WildcardTypeImpl.java index 28e316c90ec..ebbc8d2cb26 100644 --- a/src/java.desktop/share/classes/com/sun/beans/WildcardTypeImpl.java +++ b/src/java.desktop/share/classes/com/sun/beans/WildcardTypeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2006, 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 @@ -73,6 +73,7 @@ final class WildcardTypeImpl implements WildcardType { * @return an array of types representing * the upper bound(s) of this type variable */ + @Override public Type[] getUpperBounds() { return this.upperBounds.clone(); } @@ -87,6 +88,7 @@ public Type[] getUpperBounds() { * @return an array of types representing * the lower bound(s) of this type variable */ + @Override public Type[] getLowerBounds() { return this.lowerBounds.clone(); } diff --git a/src/java.desktop/share/classes/com/sun/beans/decoder/NullElementHandler.java b/src/java.desktop/share/classes/com/sun/beans/decoder/NullElementHandler.java index f865535e4fb..d5ac5368f9a 100644 --- a/src/java.desktop/share/classes/com/sun/beans/decoder/NullElementHandler.java +++ b/src/java.desktop/share/classes/com/sun/beans/decoder/NullElementHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, 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 @@ -61,6 +61,7 @@ protected final ValueObject getValueObject() { * * @return {@code null} by default */ + @Override public Object getValue() { return null; } @@ -70,6 +71,7 @@ public Object getValue() { * * @return {@code false} always */ + @Override public final boolean isVoid() { return false; } diff --git a/src/java.desktop/share/classes/com/sun/beans/decoder/ValueObjectImpl.java b/src/java.desktop/share/classes/com/sun/beans/decoder/ValueObjectImpl.java index 6fa46c93fa8..54c73381191 100644 --- a/src/java.desktop/share/classes/com/sun/beans/decoder/ValueObjectImpl.java +++ b/src/java.desktop/share/classes/com/sun/beans/decoder/ValueObjectImpl.java @@ -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 @@ -72,6 +72,7 @@ private ValueObjectImpl(Object value) { * * @return the result of method execution */ + @Override public Object getValue() { return this.value; } @@ -82,6 +83,7 @@ public Object getValue() { * @return {@code true} if value should be ignored, * {@code false} otherwise */ + @Override public boolean isVoid() { return this.isVoid; } diff --git a/src/java.desktop/share/classes/com/sun/beans/editors/BooleanEditor.java b/src/java.desktop/share/classes/com/sun/beans/editors/BooleanEditor.java index 69aca3238c9..79900b5deb1 100644 --- a/src/java.desktop/share/classes/com/sun/beans/editors/BooleanEditor.java +++ b/src/java.desktop/share/classes/com/sun/beans/editors/BooleanEditor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2012, 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 @@ -34,6 +34,7 @@ public class BooleanEditor extends PropertyEditorSupport { + @Override public String getJavaInitializationString() { Object value = getValue(); return (value != null) @@ -41,6 +42,7 @@ public String getJavaInitializationString() { : "null"; } + @Override public String getAsText() { Object value = getValue(); return (value instanceof Boolean) @@ -48,6 +50,7 @@ public String getAsText() { : null; } + @Override public void setAsText(String text) throws java.lang.IllegalArgumentException { if (text == null) { setValue(null); @@ -60,6 +63,7 @@ public void setAsText(String text) throws java.lang.IllegalArgumentException { } } + @Override public String[] getTags() { return new String[] {getValidName(true), getValidName(false)}; } diff --git a/src/java.desktop/share/classes/com/sun/beans/editors/ByteEditor.java b/src/java.desktop/share/classes/com/sun/beans/editors/ByteEditor.java index 2f4f342774f..fe927fda74d 100644 --- a/src/java.desktop/share/classes/com/sun/beans/editors/ByteEditor.java +++ b/src/java.desktop/share/classes/com/sun/beans/editors/ByteEditor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, 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 @@ -34,6 +34,7 @@ public class ByteEditor extends NumberEditor { + @Override public String getJavaInitializationString() { Object value = getValue(); return (value != null) @@ -41,6 +42,7 @@ public String getJavaInitializationString() { : "null"; } + @Override public void setAsText(String text) throws IllegalArgumentException { setValue((text == null) ? null : Byte.decode(text)); } diff --git a/src/java.desktop/share/classes/com/sun/beans/editors/ColorEditor.java b/src/java.desktop/share/classes/com/sun/beans/editors/ColorEditor.java index 3c3207ccd15..a5cf00923dd 100644 --- a/src/java.desktop/share/classes/com/sun/beans/editors/ColorEditor.java +++ b/src/java.desktop/share/classes/com/sun/beans/editors/ColorEditor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, 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 @@ -79,16 +79,19 @@ public ColorEditor() { resize(ourWidth,40); } + @Override public void setValue(Object o) { Color c = (Color)o; changeColor(c); } + @Override @SuppressWarnings("deprecation") public Dimension preferredSize() { return new Dimension(ourWidth, 40); } + @Override @SuppressWarnings("deprecation") public boolean keyUp(Event e, int key) { if (e.target == text) { @@ -101,6 +104,7 @@ public boolean keyUp(Event e, int key) { return (false); } + @Override public void setAsText(String s) throws java.lang.IllegalArgumentException { if (s == null) { changeColor(null); @@ -124,6 +128,7 @@ public void setAsText(String s) throws java.lang.IllegalArgumentException { } + @Override @SuppressWarnings("deprecation") public boolean action(Event e, Object arg) { if (e.target == chooser) { @@ -132,6 +137,7 @@ public boolean action(Event e, Object arg) { return false; } + @Override public String getJavaInitializationString() { return (this.color != null) ? "new java.awt.Color(" + this.color.getRGB() + ",true)" @@ -165,14 +171,17 @@ private void changeColor(Color c) { support.firePropertyChange("", null, null); } + @Override public Object getValue() { return color; } + @Override public boolean isPaintable() { return true; } + @Override public void paintValue(java.awt.Graphics gfx, java.awt.Rectangle box) { Color oldColor = gfx.getColor(); gfx.setColor(Color.black); @@ -182,28 +191,34 @@ public void paintValue(java.awt.Graphics gfx, java.awt.Rectangle box) { gfx.setColor(oldColor); } + @Override public String getAsText() { return (this.color != null) ? this.color.getRed() + "," + this.color.getGreen() + "," + this.color.getBlue() : null; } + @Override public String[] getTags() { return null; } + @Override public java.awt.Component getCustomEditor() { return this; } + @Override public boolean supportsCustomEditor() { return true; } + @Override public void addPropertyChangeListener(PropertyChangeListener l) { support.addPropertyChangeListener(l); } + @Override public void removePropertyChangeListener(PropertyChangeListener l) { support.removePropertyChangeListener(l); } diff --git a/src/java.desktop/share/classes/com/sun/beans/editors/DoubleEditor.java b/src/java.desktop/share/classes/com/sun/beans/editors/DoubleEditor.java index 55d5a0528a4..3803cca7d7c 100644 --- a/src/java.desktop/share/classes/com/sun/beans/editors/DoubleEditor.java +++ b/src/java.desktop/share/classes/com/sun/beans/editors/DoubleEditor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, 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 @@ -34,6 +34,7 @@ public class DoubleEditor extends NumberEditor { + @Override public void setAsText(String text) throws IllegalArgumentException { setValue((text == null) ? null : Double.valueOf(text)); } diff --git a/src/java.desktop/share/classes/com/sun/beans/editors/EnumEditor.java b/src/java.desktop/share/classes/com/sun/beans/editors/EnumEditor.java index b7f5ada0d1f..b5316a04d65 100644 --- a/src/java.desktop/share/classes/com/sun/beans/editors/EnumEditor.java +++ b/src/java.desktop/share/classes/com/sun/beans/editors/EnumEditor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2014, 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 @@ -63,10 +63,12 @@ public EnumEditor(Class type) { } } + @Override public Object getValue() { return this.value; } + @Override public void setValue( Object value ) { if ( ( value != null ) && !this.type.isInstance( value ) ) { throw new IllegalArgumentException( "Unsupported value: " + value ); @@ -92,12 +94,14 @@ public void setValue( Object value ) { } } + @Override public String getAsText() { return ( this.value != null ) ? ( ( Enum )this.value ).name() : null; } + @Override public void setAsText( String text ) { @SuppressWarnings("unchecked") Object tmp = ( text != null ) @@ -106,10 +110,12 @@ public void setAsText( String text ) { setValue(tmp); } + @Override public String[] getTags() { return this.tags.clone(); } + @Override public String getJavaInitializationString() { String name = getAsText(); return ( name != null ) @@ -117,27 +123,33 @@ public String getJavaInitializationString() { : "null"; } + @Override public boolean isPaintable() { return false; } + @Override public void paintValue( Graphics gfx, Rectangle box ) { } + @Override public boolean supportsCustomEditor() { return false; } + @Override public Component getCustomEditor() { return null; } + @Override public void addPropertyChangeListener( PropertyChangeListener listener ) { synchronized ( this.listeners ) { this.listeners.add( listener ); } } + @Override public void removePropertyChangeListener( PropertyChangeListener listener ) { synchronized ( this.listeners ) { this.listeners.remove( listener ); diff --git a/src/java.desktop/share/classes/com/sun/beans/editors/FloatEditor.java b/src/java.desktop/share/classes/com/sun/beans/editors/FloatEditor.java index 4723c489cc0..5820c00d82e 100644 --- a/src/java.desktop/share/classes/com/sun/beans/editors/FloatEditor.java +++ b/src/java.desktop/share/classes/com/sun/beans/editors/FloatEditor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, 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 @@ -34,6 +34,7 @@ public class FloatEditor extends NumberEditor { + @Override public String getJavaInitializationString() { Object value = getValue(); return (value != null) @@ -41,6 +42,7 @@ public String getJavaInitializationString() { : "null"; } + @Override public void setAsText(String text) throws IllegalArgumentException { setValue((text == null) ? null : Float.valueOf(text)); } diff --git a/src/java.desktop/share/classes/com/sun/beans/editors/FontEditor.java b/src/java.desktop/share/classes/com/sun/beans/editors/FontEditor.java index cf2fdd26307..26d4ab2b182 100644 --- a/src/java.desktop/share/classes/com/sun/beans/editors/FontEditor.java +++ b/src/java.desktop/share/classes/com/sun/beans/editors/FontEditor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, 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 @@ -78,11 +78,13 @@ public FontEditor() { } + @Override @SuppressWarnings("deprecation") public Dimension preferredSize() { return new Dimension(300, 40); } + @Override public void setValue(Object o) { font = (Font) o; if (this.font == null) @@ -130,10 +132,12 @@ private void changeFont(Font f) { support.firePropertyChange("", null, null); } + @Override public Object getValue() { return (font); } + @Override public String getJavaInitializationString() { if (this.font == null) return "null"; @@ -142,6 +146,7 @@ public String getJavaInitializationString() { font.getStyle() + ", " + font.getSize() + ")"; } + @Override @SuppressWarnings("deprecation") public boolean action(Event e, Object arg) { String family = familyChoser.getSelectedItem(); @@ -158,10 +163,12 @@ public boolean action(Event e, Object arg) { } + @Override public boolean isPaintable() { return true; } + @Override public void paintValue(java.awt.Graphics gfx, java.awt.Rectangle box) { // Silent noop. Font oldFont = gfx.getFont(); @@ -172,6 +179,7 @@ public void paintValue(java.awt.Graphics gfx, java.awt.Rectangle box) { gfx.setFont(oldFont); } + @Override public String getAsText() { if (this.font == null) { return null; @@ -195,26 +203,32 @@ public String getAsText() { return sb.toString(); } + @Override public void setAsText(String text) throws IllegalArgumentException { setValue((text == null) ? null : Font.decode(text)); } + @Override public String[] getTags() { return null; } + @Override public java.awt.Component getCustomEditor() { return this; } + @Override public boolean supportsCustomEditor() { return true; } + @Override public void addPropertyChangeListener(PropertyChangeListener l) { support.addPropertyChangeListener(l); } + @Override public void removePropertyChangeListener(PropertyChangeListener l) { support.removePropertyChangeListener(l); } diff --git a/src/java.desktop/share/classes/com/sun/beans/editors/IntegerEditor.java b/src/java.desktop/share/classes/com/sun/beans/editors/IntegerEditor.java index 066b7143ac6..65b4d1dcf19 100644 --- a/src/java.desktop/share/classes/com/sun/beans/editors/IntegerEditor.java +++ b/src/java.desktop/share/classes/com/sun/beans/editors/IntegerEditor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2012, 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 @@ -35,6 +35,7 @@ public class IntegerEditor extends NumberEditor { + @Override public void setAsText(String text) throws IllegalArgumentException { setValue((text == null) ? null : Integer.decode(text)); } diff --git a/src/java.desktop/share/classes/com/sun/beans/editors/LongEditor.java b/src/java.desktop/share/classes/com/sun/beans/editors/LongEditor.java index 3a8efbba53c..ed4d12ac505 100644 --- a/src/java.desktop/share/classes/com/sun/beans/editors/LongEditor.java +++ b/src/java.desktop/share/classes/com/sun/beans/editors/LongEditor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, 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 @@ -34,6 +34,7 @@ public class LongEditor extends NumberEditor { + @Override public String getJavaInitializationString() { Object value = getValue(); return (value != null) @@ -41,6 +42,7 @@ public String getJavaInitializationString() { : "null"; } + @Override public void setAsText(String text) throws IllegalArgumentException { setValue((text == null) ? null : Long.decode(text)); } diff --git a/src/java.desktop/share/classes/com/sun/beans/editors/NumberEditor.java b/src/java.desktop/share/classes/com/sun/beans/editors/NumberEditor.java index 9097546d2e0..3c0c5bb6c9f 100644 --- a/src/java.desktop/share/classes/com/sun/beans/editors/NumberEditor.java +++ b/src/java.desktop/share/classes/com/sun/beans/editors/NumberEditor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, 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 @@ -34,6 +34,7 @@ public abstract class NumberEditor extends PropertyEditorSupport { + @Override public String getJavaInitializationString() { Object value = getValue(); return (value != null) diff --git a/src/java.desktop/share/classes/com/sun/beans/editors/ShortEditor.java b/src/java.desktop/share/classes/com/sun/beans/editors/ShortEditor.java index cf82eef215d..6be5b14b90f 100644 --- a/src/java.desktop/share/classes/com/sun/beans/editors/ShortEditor.java +++ b/src/java.desktop/share/classes/com/sun/beans/editors/ShortEditor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, 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 @@ -35,6 +35,7 @@ public class ShortEditor extends NumberEditor { + @Override public String getJavaInitializationString() { Object value = getValue(); return (value != null) @@ -42,6 +43,7 @@ public String getJavaInitializationString() { : "null"; } + @Override public void setAsText(String text) throws IllegalArgumentException { setValue((text == null) ? null : Short.decode(text)); } diff --git a/src/java.desktop/share/classes/com/sun/beans/editors/StringEditor.java b/src/java.desktop/share/classes/com/sun/beans/editors/StringEditor.java index 2f1cde46ea0..b064ccbddbb 100644 --- a/src/java.desktop/share/classes/com/sun/beans/editors/StringEditor.java +++ b/src/java.desktop/share/classes/com/sun/beans/editors/StringEditor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, 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 @@ public class StringEditor extends PropertyEditorSupport { + @Override public String getJavaInitializationString() { Object value = getValue(); if (value == null) @@ -67,6 +68,7 @@ public String getJavaInitializationString() { return sb.toString(); } + @Override public void setAsText(String text) { setValue(text); } diff --git a/src/java.desktop/share/classes/com/sun/beans/infos/ComponentBeanInfo.java b/src/java.desktop/share/classes/com/sun/beans/infos/ComponentBeanInfo.java index 1514b005074..39d7cbb2146 100644 --- a/src/java.desktop/share/classes/com/sun/beans/infos/ComponentBeanInfo.java +++ b/src/java.desktop/share/classes/com/sun/beans/infos/ComponentBeanInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, 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 @@ -34,6 +34,7 @@ public class ComponentBeanInfo extends SimpleBeanInfo { private static final Class beanClass = java.awt.Component.class; + @Override public PropertyDescriptor[] getPropertyDescriptors() { try { PropertyDescriptor diff --git a/src/java.desktop/share/classes/com/sun/beans/util/Cache.java b/src/java.desktop/share/classes/com/sun/beans/util/Cache.java index 2cb21791416..58151e3a56f 100644 --- a/src/java.desktop/share/classes/com/sun/beans/util/Cache.java +++ b/src/java.desktop/share/classes/com/sun/beans/util/Cache.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -405,11 +405,13 @@ private static interface Ref { */ public static enum Kind { STRONG { + @Override Ref create(Object owner, T value, ReferenceQueue queue) { return new Strong<>(owner, value); } }, SOFT { + @Override Ref create(Object owner, T referent, ReferenceQueue queue) { return (referent == null) ? new Strong<>(owner, referent) @@ -417,6 +419,7 @@ Ref create(Object owner, T referent, ReferenceQueue queue) { } }, WEAK { + @Override Ref create(Object owner, T referent, ReferenceQueue queue) { return (referent == null) ? new Strong<>(owner, referent) @@ -463,6 +466,7 @@ private Strong(Object owner, T referent) { * * @return the owner of the reference or {@code null} if the owner is unknown */ + @Override public Object getOwner() { return this.owner; } @@ -472,6 +476,7 @@ public Object getOwner() { * * @return the referred object */ + @Override public T getReferent() { return this.referent; } @@ -481,6 +486,7 @@ public T getReferent() { * * @return {@code true} if the referred object was collected */ + @Override public boolean isStale() { return false; } @@ -488,6 +494,7 @@ public boolean isStale() { /** * Marks this reference as removed from the cache. */ + @Override public void removeOwner() { this.owner = null; } @@ -522,6 +529,7 @@ private Soft(Object owner, T referent, ReferenceQueue queue) { * * @return the owner of the reference or {@code null} if the owner is unknown */ + @Override public Object getOwner() { return this.owner; } @@ -531,6 +539,7 @@ public Object getOwner() { * * @return the referred object or {@code null} if it was collected */ + @Override public T getReferent() { return get(); } @@ -540,6 +549,7 @@ public T getReferent() { * * @return {@code true} if the referred object was collected */ + @Override public boolean isStale() { return null == get(); } @@ -547,6 +557,7 @@ public boolean isStale() { /** * Marks this reference as removed from the cache. */ + @Override public void removeOwner() { this.owner = null; } @@ -581,6 +592,7 @@ private Weak(Object owner, T referent, ReferenceQueue queue) { * * @return the owner of the reference or {@code null} if the owner is unknown */ + @Override public Object getOwner() { return this.owner; } @@ -590,6 +602,7 @@ public Object getOwner() { * * @return the referred object or {@code null} if it was collected */ + @Override public T getReferent() { return get(); } @@ -599,6 +612,7 @@ public T getReferent() { * * @return {@code true} if the referred object was collected */ + @Override public boolean isStale() { return null == get(); } @@ -606,6 +620,7 @@ public boolean isStale() { /** * Marks this reference as removed from the cache. */ + @Override public void removeOwner() { this.owner = null; } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReaderSpi.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReaderSpi.java index a3098bd9684..63cc1464460 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReaderSpi.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReaderSpi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, 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 @@ -61,6 +61,7 @@ public BMPImageReaderSpi() { null, null); } + @Override public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { @@ -69,10 +70,12 @@ public void onRegistration(ServiceRegistry registry, registered = true; } + @Override public String getDescription(Locale locale) { return "Standard BMP Image Reader"; } + @Override public boolean canDecodeInput(Object source) throws IOException { if (!(source instanceof ImageInputStream)) { return false; @@ -87,6 +90,7 @@ public boolean canDecodeInput(Object source) throws IOException { return full && (b[0] == 0x42) && (b[1] == 0x4d); } + @Override public ImageReader createReaderInstance(Object extension) throws IIOException { return new BMPImageReader(this); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriterSpi.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriterSpi.java index ae6a7f65a3b..736a1c2194e 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriterSpi.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriterSpi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, 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 @@ -66,10 +66,12 @@ public BMPImageWriterSpi() { null, null); } + @Override public String getDescription(Locale locale) { return "Standard BMP Image Writer"; } + @Override public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { @@ -79,6 +81,7 @@ public void onRegistration(ServiceRegistry registry, registered = true; } + @Override public boolean canEncodeImage(ImageTypeSpecifier type) { int dataType= type.getSampleModel().getDataType(); if (dataType < DataBuffer.TYPE_BYTE || dataType > DataBuffer.TYPE_INT) @@ -99,6 +102,7 @@ public boolean canEncodeImage(ImageTypeSpecifier type) { return true; } + @Override public ImageWriter createWriterInstance(Object extension) throws IIOException { return new BMPImageWriter(this); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadata.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadata.java index 5e5a4a52d35..48d3bb12f1c 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadata.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadata.java @@ -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 @@ -94,10 +94,12 @@ public BMPMetadata() { null, null); } + @Override public boolean isReadOnly() { return true; } + @Override public Node getAsTree(String formatName) { if (formatName.equals(nativeMetadataFormatName)) { return getNativeTree(); @@ -177,6 +179,7 @@ private Node getNativeTree() { } // Standard tree node methods + @Override protected IIOMetadataNode getStandardChromaNode() { if ((palette != null) && (paletteSize > 0)) { @@ -202,6 +205,7 @@ protected IIOMetadataNode getStandardChromaNode() { return null; } + @Override protected IIOMetadataNode getStandardCompressionNode() { IIOMetadataNode node = new IIOMetadataNode("Compression"); @@ -212,6 +216,7 @@ protected IIOMetadataNode getStandardCompressionNode() { return node; } + @Override protected IIOMetadataNode getStandardDataNode() { IIOMetadataNode node = new IIOMetadataNode("Data"); @@ -230,6 +235,7 @@ else if (bitsPerPixel == 16 || bitsPerPixel == 32) { return node; } + @Override protected IIOMetadataNode getStandardDimensionNode() { if (yPixelsPerMeter > 0.0F && xPixelsPerMeter > 0.0F) { IIOMetadataNode node = new IIOMetadataNode("Dimension"); @@ -251,14 +257,17 @@ protected IIOMetadataNode getStandardDimensionNode() { return null; } + @Override public void setFromTree(String formatName, Node root) { throw new IllegalStateException(I18N.getString("BMPMetadata1")); } + @Override public void mergeTree(String formatName, Node root) { throw new IllegalStateException(I18N.getString("BMPMetadata1")); } + @Override public void reset() { throw new IllegalStateException(I18N.getString("BMPMetadata1")); } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadataFormat.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadataFormat.java index b9ea0ee0fe3..277169a34e0 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadataFormat.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadataFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2004, 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 @@ -194,6 +194,7 @@ private BMPMetadataFormat() { DATATYPE_STRING, true, null); } + @Override public boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType) { return true; diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadataFormatResources.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadataFormatResources.java index 1f2f444acd7..4d6c4fe49ec 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadataFormatResources.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadataFormatResources.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, 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 @@ -33,6 +33,7 @@ public class BMPMetadataFormatResources extends ListResourceBundle { public BMPMetadataFormatResources() {} + @Override protected Object[][] getContents() { return new Object[][] { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/BogusColorSpace.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/BogusColorSpace.java index 5a064f4f4c5..107ee313b70 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/BogusColorSpace.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/BogusColorSpace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -79,6 +79,7 @@ public BogusColorSpace(int numComponents) { // specified behavior of the methods vis-a-vis exceptions. // + @Override public float[] toRGB(float[] colorvalue) { if(colorvalue.length < getNumComponents()) { throw new ArrayIndexOutOfBoundsException @@ -93,6 +94,7 @@ public float[] toRGB(float[] colorvalue) { return rgbvalue; } + @Override public float[] fromRGB(float[] rgbvalue) { if(rgbvalue.length < 3) { throw new ArrayIndexOutOfBoundsException @@ -107,6 +109,7 @@ public float[] fromRGB(float[] rgbvalue) { return colorvalue; } + @Override public float[] toCIEXYZ(float[] colorvalue) { if(colorvalue.length < getNumComponents()) { throw new ArrayIndexOutOfBoundsException @@ -121,6 +124,7 @@ public float[] toCIEXYZ(float[] colorvalue) { return xyzvalue; } + @Override public float[] fromCIEXYZ(float[] xyzvalue) { if(xyzvalue.length < 3) { throw new ArrayIndexOutOfBoundsException diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/InputStreamAdapter.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/InputStreamAdapter.java index 1b63a54d8ff..b11ffeb6287 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/InputStreamAdapter.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/InputStreamAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,10 +39,12 @@ public InputStreamAdapter(ImageInputStream stream) { this.stream = stream; } + @Override public int read() throws IOException { return stream.read(); } + @Override public int read(byte[] b, int off, int len) throws IOException { return stream.read(b, off, len); } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SimpleCMYKColorSpace.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SimpleCMYKColorSpace.java index a5c283e6c9c..1662d09984d 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SimpleCMYKColorSpace.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SimpleCMYKColorSpace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -58,14 +58,17 @@ private SimpleCMYKColorSpace() { csRGB = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB); } + @Override public boolean equals(Object o) { return o instanceof SimpleCMYKColorSpace; } + @Override public int hashCode() { return System.identityHashCode(theInstance); } + @Override public float[] toRGB(float[] colorvalue) { float C = colorvalue[0]; float M = colorvalue[1]; @@ -97,6 +100,7 @@ public float[] toRGB(float[] colorvalue) { return rgbvalue; } + @Override public float[] fromRGB(float[] rgbvalue) { // Convert from sRGB to linear RGB. for (int i = 0; i < 3; i++) { @@ -128,10 +132,12 @@ public float[] fromRGB(float[] rgbvalue) { return new float[] {C, M, Y, K}; } + @Override public float[] toCIEXYZ(float[] colorvalue) { return csRGB.toCIEXYZ(toRGB(colorvalue)); } + @Override public float[] fromCIEXYZ(float[] xyzvalue) { return fromRGB(csRGB.fromCIEXYZ(xyzvalue)); } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SimpleRenderedImage.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SimpleRenderedImage.java index 1d8c850b4a9..f598aeb06a1 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SimpleRenderedImage.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SimpleRenderedImage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,6 +74,7 @@ public abstract class SimpleRenderedImage implements RenderedImage { protected Hashtable properties = new Hashtable(); /** Returns the X coordinate of the leftmost column of the image. */ + @Override public int getMinX() { return minX; } @@ -89,6 +90,7 @@ public final int getMaxX() { } /** Returns the X coordinate of the uppermost row of the image. */ + @Override public int getMinY() { return minY; } @@ -104,11 +106,13 @@ public final int getMaxY() { } /** Returns the width of the image. */ + @Override public int getWidth() { return width; } /** Returns the height of the image. */ + @Override public int getHeight() { return height; } @@ -119,11 +123,13 @@ public Rectangle getBounds() { } /** Returns the width of a tile. */ + @Override public int getTileWidth() { return tileWidth; } /** Returns the height of a tile. */ + @Override public int getTileHeight() { return tileHeight; } @@ -131,6 +137,7 @@ public int getTileHeight() { /** * Returns the X coordinate of the upper-left pixel of tile (0, 0). */ + @Override public int getTileGridXOffset() { return tileGridXOffset; } @@ -138,6 +145,7 @@ public int getTileGridXOffset() { /** * Returns the Y coordinate of the upper-left pixel of tile (0, 0). */ + @Override public int getTileGridYOffset() { return tileGridYOffset; } @@ -147,6 +155,7 @@ public int getTileGridYOffset() { * getMinTileX() is implemented in terms of getMinX() * and so does not need to be implemented by subclasses. */ + @Override public int getMinTileX() { return XToTileX(getMinX()); } @@ -166,6 +175,7 @@ public int getMaxTileX() { * of getMinTileX() and getMaxTileX() and so does not need to be * implemented by subclasses. */ + @Override public int getNumXTiles() { return getMaxTileX() - getMinTileX() + 1; } @@ -175,6 +185,7 @@ public int getNumXTiles() { * is implemented in terms of getMinY() and so does not need to be * implemented by subclasses. */ + @Override public int getMinTileY() { return YToTileY(getMinY()); } @@ -194,16 +205,19 @@ public int getMaxTileY() { * of getMinTileY() and getMaxTileY() and so does not need to be * implemented by subclasses. */ + @Override public int getNumYTiles() { return getMaxTileY() - getMinTileY() + 1; } /** Returns the SampleModel of the image. */ + @Override public SampleModel getSampleModel() { return sampleModel; } /** Returns the ColorModel of the image. */ + @Override public ColorModel getColorModel() { return colorModel; } @@ -218,6 +232,7 @@ public ColorModel getColorModel() { * Object, or the value * java.awt.Image.UndefinedProperty. */ + @Override public Object getProperty(String name) { name = name.toLowerCase(); Object value = properties.get(name); @@ -232,6 +247,7 @@ public Object getProperty(String name) { * @return an array of Strings representing valid * property names. */ + @Override public String[] getPropertyNames() { String[] names = null; @@ -379,6 +395,7 @@ public int tileYToY(int ty) { return ty*tileHeight + tileGridYOffset; } + @Override public Vector getSources() { return null; } @@ -399,6 +416,7 @@ public Vector getSources() { * * @return a Raster containing a copy of this image's data. */ + @Override public Raster getData() { Rectangle rect = new Rectangle(getMinX(), getMinY(), getWidth(), getHeight()); @@ -422,6 +440,7 @@ public Raster getData() { * * @param bounds the region of the RenderedImage to be returned. */ + @Override public Raster getData(Rectangle bounds) { // Get the image bounds. Rectangle imageBounds = getBounds(); @@ -511,6 +530,7 @@ public Raster getData(Rectangle bounds) { * @return a reference to the supplied WritableRaster, or to a * new WritableRaster if the supplied one was null. */ + @Override public WritableRaster copyData(WritableRaster dest) { // Get the image bounds. Rectangle imageBounds = getBounds(); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SingleTileRenderedImage.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SingleTileRenderedImage.java index 0cbdefa9127..315270e5916 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SingleTileRenderedImage.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SingleTileRenderedImage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2017, 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 @@ -58,6 +58,7 @@ public SingleTileRenderedImage(Raster ras, ColorModel colorModel) { /** * Returns the image's Raster as tile (0, 0). */ + @Override public Raster getTile(int tileX, int tileY) { if (tileX != 0 || tileY != 0) { throw new IllegalArgumentException("tileX != 0 || tileY != 0"); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/StandardMetadataFormat.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/StandardMetadataFormat.java index d880c507cba..05fa72f24ae 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/StandardMetadataFormat.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/StandardMetadataFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, 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 @@ -492,6 +492,7 @@ public StandardMetadataFormat() { null); } + @Override public boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType) { return true; diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/StandardMetadataFormatResources.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/StandardMetadataFormatResources.java index 4a94450d003..20e81dd76fa 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/StandardMetadataFormatResources.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/StandardMetadataFormatResources.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, 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 @@ -31,6 +31,7 @@ public class StandardMetadataFormatResources extends ListResourceBundle { public StandardMetadataFormatResources() {} + @Override protected Object[][] getContents() { return new Object[][] { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SubImageInputStream.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SubImageInputStream.java index 10211c6636c..8996cf09428 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SubImageInputStream.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SubImageInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,6 +43,7 @@ public SubImageInputStream(ImageInputStream stream, int length) this.startingLength = this.length = length; } + @Override public int read() throws IOException { if (length == 0) { // Local EOF return -1; @@ -52,6 +53,7 @@ public int read() throws IOException { } } + @Override public int read(byte[] b, int off, int len) throws IOException { if (length == 0) { // Local EOF return -1; @@ -63,10 +65,12 @@ public int read(byte[] b, int off, int len) throws IOException { return bytes; } + @Override public long length() { return startingLength; } + @Override public void seek(long pos) throws IOException { stream.seek(pos - startingPos); streamPos = pos; diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadata.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadata.java index 061f3b1eaf0..bf2768af4e1 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadata.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -115,10 +115,12 @@ public GIFImageMetadata() { null, null); } + @Override public boolean isReadOnly() { return true; } + @Override public Node getAsTree(String formatName) { if (formatName.equals(nativeMetadataFormatName)) { return getNativeTree(); @@ -252,6 +254,7 @@ private Node getNativeTree() { return root; } + @Override public IIOMetadataNode getStandardChromaNode() { IIOMetadataNode chroma_node = new IIOMetadataNode("Chroma"); IIOMetadataNode node = null; // scratch node @@ -294,6 +297,7 @@ public IIOMetadataNode getStandardChromaNode() { return chroma_node; } + @Override public IIOMetadataNode getStandardCompressionNode() { IIOMetadataNode compression_node = new IIOMetadataNode("Compression"); IIOMetadataNode node = null; // scratch node @@ -315,6 +319,7 @@ public IIOMetadataNode getStandardCompressionNode() { return compression_node; } + @Override public IIOMetadataNode getStandardDataNode() { IIOMetadataNode data_node = new IIOMetadataNode("Data"); IIOMetadataNode node = null; // scratch node @@ -332,6 +337,7 @@ public IIOMetadataNode getStandardDataNode() { return data_node; } + @Override public IIOMetadataNode getStandardDimensionNode() { IIOMetadataNode dimension_node = new IIOMetadataNode("Dimension"); IIOMetadataNode node = null; // scratch node @@ -365,6 +371,7 @@ public IIOMetadataNode getStandardDimensionNode() { // Document not in image + @Override public IIOMetadataNode getStandardTextNode() { if (comments == null) { return null; @@ -391,6 +398,7 @@ public IIOMetadataNode getStandardTextNode() { return text_node; } + @Override public IIOMetadataNode getStandardTransparencyNode() { if (!transparentColorFlag) { return null; @@ -414,22 +422,26 @@ public IIOMetadataNode getStandardTransparencyNode() { return transparency_node; } + @Override public void setFromTree(String formatName, Node root) throws IIOInvalidTreeException { throw new IllegalStateException("Metadata is read-only!"); } + @Override protected void mergeNativeTree(Node root) throws IIOInvalidTreeException { throw new IllegalStateException("Metadata is read-only!"); } + @Override protected void mergeStandardTree(Node root) throws IIOInvalidTreeException { throw new IllegalStateException("Metadata is read-only!"); } + @Override public void reset() { throw new IllegalStateException("Metadata is read-only!"); } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadataFormat.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadataFormat.java index fa55d72bbda..5a6a85a2b57 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadataFormat.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadataFormat.java @@ -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 @@ -157,6 +157,7 @@ private GIFImageMetadataFormat() { DATATYPE_STRING, true, null); } + @Override public boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType) { return true; diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadataFormatResources.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadataFormatResources.java index aa9697a8ee9..f9a29cdebba 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadataFormatResources.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadataFormatResources.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2005, 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 @@ -31,6 +31,7 @@ public class GIFImageMetadataFormatResources extends ListResourceBundle { public GIFImageMetadataFormatResources() {} + @Override protected Object[][] getContents() { return new Object[][] { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageReaderSpi.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageReaderSpi.java index 96a5ba436aa..9484484abf8 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageReaderSpi.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageReaderSpi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,10 +71,12 @@ public GIFImageReaderSpi() { ); } + @Override public String getDescription(Locale locale) { return "Standard GIF image reader"; } + @Override public boolean canDecodeInput(Object input) throws IOException { if (!(input instanceof ImageInputStream)) { return false; @@ -91,6 +93,7 @@ public boolean canDecodeInput(Object input) throws IOException { (b[4] == '7' || b[4] == '9') && b[5] == 'a'; } + @Override public ImageReader createReaderInstance(Object extension) { return new GIFImageReader(this); } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageWriterSpi.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageWriterSpi.java index 0f1b8aec102..6da6332eb50 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageWriterSpi.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageWriterSpi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, 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 @@ -73,6 +73,7 @@ public GIFImageWriterSpi() { ); } + @Override public boolean canEncodeImage(ImageTypeSpecifier type) { if (type == null) { throw new IllegalArgumentException("type == null!"); @@ -94,10 +95,12 @@ public boolean canEncodeImage(ImageTypeSpecifier type) { } } + @Override public String getDescription(Locale locale) { return "Standard GIF image writer"; } + @Override public ImageWriter createWriterInstance(Object extension) { return new GIFImageWriter(this); } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFMetadata.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFMetadata.java index 5fb4dc007b7..dca232352d9 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFMetadata.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, 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 @@ -242,6 +242,7 @@ protected GIFMetadata(boolean standardMetadataFormatSupported, extraMetadataFormatClassNames); } + @Override public void mergeTree(String formatName, Node root) throws IIOInvalidTreeException { if (formatName.equals(nativeMetadataFormatName)) { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFStreamMetadata.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFStreamMetadata.java index 31c1305b58a..b34e96907ee 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFStreamMetadata.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFStreamMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -77,10 +77,12 @@ public GIFStreamMetadata() { } + @Override public boolean isReadOnly() { return true; } + @Override public Node getAsTree(String formatName) { if (formatName.equals(nativeMetadataFormatName)) { return getNativeTree(); @@ -149,6 +151,7 @@ private Node getNativeTree() { return root; } + @Override public IIOMetadataNode getStandardChromaNode() { IIOMetadataNode chroma_node = new IIOMetadataNode("Chroma"); IIOMetadataNode node = null; // scratch node @@ -190,6 +193,7 @@ public IIOMetadataNode getStandardChromaNode() { return chroma_node; } + @Override public IIOMetadataNode getStandardCompressionNode() { IIOMetadataNode compression_node = new IIOMetadataNode("Compression"); IIOMetadataNode node = null; // scratch node @@ -208,6 +212,7 @@ public IIOMetadataNode getStandardCompressionNode() { return compression_node; } + @Override public IIOMetadataNode getStandardDataNode() { IIOMetadataNode data_node = new IIOMetadataNode("Data"); IIOMetadataNode node = null; // scratch node @@ -230,6 +235,7 @@ public IIOMetadataNode getStandardDataNode() { return data_node; } + @Override public IIOMetadataNode getStandardDimensionNode() { IIOMetadataNode dimension_node = new IIOMetadataNode("Dimension"); IIOMetadataNode node = null; // scratch node @@ -270,6 +276,7 @@ public IIOMetadataNode getStandardDimensionNode() { return dimension_node; } + @Override public IIOMetadataNode getStandardDocumentNode() { IIOMetadataNode document_node = new IIOMetadataNode("Document"); IIOMetadataNode node = null; // scratch node @@ -285,32 +292,38 @@ public IIOMetadataNode getStandardDocumentNode() { return document_node; } + @Override public IIOMetadataNode getStandardTextNode() { // Not in stream return null; } + @Override public IIOMetadataNode getStandardTransparencyNode() { // Not in stream return null; } + @Override public void setFromTree(String formatName, Node root) throws IIOInvalidTreeException { throw new IllegalStateException("Metadata is read-only!"); } + @Override protected void mergeNativeTree(Node root) throws IIOInvalidTreeException { throw new IllegalStateException("Metadata is read-only!"); } + @Override protected void mergeStandardTree(Node root) throws IIOInvalidTreeException { throw new IllegalStateException("Metadata is read-only!"); } + @Override public void reset() { throw new IllegalStateException("Metadata is read-only!"); } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFStreamMetadataFormat.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFStreamMetadataFormat.java index b598674ccb3..fcdb8b0d13e 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFStreamMetadataFormat.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFStreamMetadataFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2004, 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 @@ -92,6 +92,7 @@ private GIFStreamMetadataFormat() { "0", "255", true, true); } + @Override public boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType) { return true; diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFStreamMetadataFormatResources.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFStreamMetadataFormatResources.java index 0404b2c88da..65e9f89c557 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFStreamMetadataFormatResources.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFStreamMetadataFormatResources.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2005, 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 @@ -31,6 +31,7 @@ public class GIFStreamMetadataFormatResources extends ListResourceBundle { public GIFStreamMetadataFormatResources() {} + @Override protected Object[][] getContents() { return new Object[][] { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFWritableImageMetadata.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFWritableImageMetadata.java index a3e8a769490..cec4f354ee0 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFWritableImageMetadata.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFWritableImageMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -49,10 +49,12 @@ class GIFWritableImageMetadata extends GIFImageMetadata { null, null); } + @Override public boolean isReadOnly() { return false; } + @Override public void reset() { // Fields from Image Descriptor imageLeftPosition = 0; @@ -96,6 +98,7 @@ private byte[] fromISO8859(String data) { return data.getBytes(ISO_8859_1); } + @Override protected void mergeNativeTree(Node root) throws IIOInvalidTreeException { Node node = root; if (!node.getNodeName().equals(nativeMetadataFormatName)) { @@ -292,6 +295,7 @@ protected void mergeNativeTree(Node root) throws IIOInvalidTreeException { } } + @Override protected void mergeStandardTree(Node root) throws IIOInvalidTreeException { Node node = root; @@ -389,6 +393,7 @@ protected void mergeStandardTree(Node root) } } + @Override public void setFromTree(String formatName, Node root) throws IIOInvalidTreeException { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFWritableStreamMetadata.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFWritableStreamMetadata.java index 8a9a6d865a8..d8863cb4a2d 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFWritableStreamMetadata.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFWritableStreamMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,10 +55,12 @@ public GIFWritableStreamMetadata() { reset(); } + @Override public boolean isReadOnly() { return false; } + @Override public void mergeTree(String formatName, Node root) throws IIOInvalidTreeException { if (formatName.equals(nativeMetadataFormatName)) { @@ -77,6 +79,7 @@ public void mergeTree(String formatName, Node root) } } + @Override public void reset() { version = null; @@ -90,6 +93,7 @@ public void reset() { globalColorTable = null; } + @Override protected void mergeNativeTree(Node root) throws IIOInvalidTreeException { Node node = root; if (!node.getNodeName().equals(nativeMetadataFormatName)) { @@ -164,6 +168,7 @@ protected void mergeNativeTree(Node root) throws IIOInvalidTreeException { } } + @Override protected void mergeStandardTree(Node root) throws IIOInvalidTreeException { Node node = root; @@ -258,6 +263,7 @@ protected void mergeStandardTree(Node root) } } + @Override public void setFromTree(String formatName, Node root) throws IIOInvalidTreeException { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/AdobeMarkerSegment.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/AdobeMarkerSegment.java index 551f4dc4d72..9b1fbd27fc4 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/AdobeMarkerSegment.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/AdobeMarkerSegment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 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 @@ -73,6 +73,7 @@ class AdobeMarkerSegment extends MarkerSegment { updateFromNativeNode(node, true); } + @Override IIOMetadataNode getNativeNode() { IIOMetadataNode node = new IIOMetadataNode("app14Adobe"); node.setAttribute("version", Integer.toString(version)); @@ -108,6 +109,7 @@ void updateFromNativeNode(Node node, boolean fromScratch) * Writes the data for this segment to the stream in * valid JPEG format. */ + @Override void write(ImageOutputStream ios) throws IOException { length = 14; writeTag(ios); @@ -124,6 +126,7 @@ static void writeAdobeSegment(ImageOutputStream ios, int transform) (new AdobeMarkerSegment(transform)).write(ios); } + @Override void print () { printTag("Adobe APP14"); System.out.print("Version: "); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/COMMarkerSegment.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/COMMarkerSegment.java index f28e7b35658..f45bded991a 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/COMMarkerSegment.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/COMMarkerSegment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, 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 @@ -104,6 +104,7 @@ String getComment() { * as a user object and a string encoded using ISO-8895-1, as an * attribute. */ + @Override IIOMetadataNode getNativeNode() { IIOMetadataNode node = new IIOMetadataNode("com"); node.setAttribute("comment", getComment()); @@ -117,12 +118,14 @@ IIOMetadataNode getNativeNode() { * Writes the data for this segment to the stream in * valid JPEG format, directly from the data array. */ + @Override void write(ImageOutputStream ios) throws IOException { length = 2 + data.length; writeTag(ios); ios.write(data); } + @Override void print() { printTag("COM"); System.out.println("<" + getComment() + ">"); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/DHTMarkerSegment.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/DHTMarkerSegment.java index c14402522db..634a266354d 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/DHTMarkerSegment.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/DHTMarkerSegment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, 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 @@ -90,6 +90,7 @@ class DHTMarkerSegment extends MarkerSegment { } } + @Override protected Object clone() { DHTMarkerSegment newGuy = (DHTMarkerSegment) super.clone(); newGuy.tables = new ArrayList<>(tables.size()); @@ -99,6 +100,7 @@ protected Object clone() { return newGuy; } + @Override IIOMetadataNode getNativeNode() { IIOMetadataNode node = new IIOMetadataNode("dht"); for (int i= 0; i(tables.size()); @@ -92,6 +93,7 @@ protected Object clone() { return newGuy; } + @Override IIOMetadataNode getNativeNode() { IIOMetadataNode node = new IIOMetadataNode("dqt"); for (int i= 0; i MAX_THUMB_WIDTH) @@ -949,6 +960,7 @@ void writePixels(ImageOutputStream ios, writeThumbnailData(ios, data, writer); } + @Override void print() { System.out.print(name + " width: "); System.out.println(thumbWidth); @@ -978,10 +990,12 @@ class JFIFThumbRGB extends JFIFThumbUncompressed { super(thumb); } + @Override int getLength() { return (thumbWidth*thumbHeight*3); } + @Override BufferedImage getThumbnail(ImageInputStream iis, JPEGImageReader reader) throws IOException { @@ -1014,6 +1028,7 @@ BufferedImage getThumbnail(ImageInputStream iis, null); } + @Override void write(ImageOutputStream ios, JPEGImageWriter writer) throws IOException { super.write(ios, writer); // width and height @@ -1050,10 +1065,12 @@ class JFIFThumbPalette extends JFIFThumbUncompressed { } } + @Override int getLength() { return (thumbWidth*thumbHeight + PALETTE_SIZE); } + @Override BufferedImage getThumbnail(ImageInputStream iis, JPEGImageReader reader) throws IOException { @@ -1091,6 +1108,7 @@ BufferedImage getThumbnail(ImageInputStream iis, null); } + @Override void write(ImageOutputStream ios, JPEGImageWriter writer) throws IOException { super.write(ios, writer); // width and height @@ -1221,6 +1239,7 @@ static class JFIFThumbJPEG extends JFIFThumb { } } + @Override int getWidth() { int retval = 0; SOFMarkerSegment sof = @@ -1232,6 +1251,7 @@ int getWidth() { return retval; } + @Override int getHeight() { int retval = 0; SOFMarkerSegment sof = @@ -1249,21 +1269,31 @@ static class ThumbnailReadListener ThumbnailReadListener (JPEGImageReader reader) { this.reader = reader; } + @Override public void sequenceStarted(ImageReader source, int minIndex) {} + @Override public void sequenceComplete(ImageReader source) {} + @Override public void imageStarted(ImageReader source, int imageIndex) {} + @Override public void imageProgress(ImageReader source, float percentageDone) { reader.thumbnailProgress(percentageDone); } + @Override public void imageComplete(ImageReader source) {} + @Override public void thumbnailStarted(ImageReader source, int imageIndex, int thumbnailIndex) {} + @Override public void thumbnailProgress(ImageReader source, float percentageDone) {} + @Override public void thumbnailComplete(ImageReader source) {} + @Override public void readAborted(ImageReader source) {} } + @Override BufferedImage getThumbnail(ImageInputStream iis, JPEGImageReader reader) throws IOException { @@ -1279,6 +1309,7 @@ BufferedImage getThumbnail(ImageInputStream iis, return ret; } + @Override protected Object clone() { JFIFThumbJPEG newGuy = (JFIFThumbJPEG) super.clone(); if (thumbMetadata != null) { @@ -1287,6 +1318,7 @@ protected Object clone() { return newGuy; } + @Override IIOMetadataNode getNativeNode() { IIOMetadataNode node = new IIOMetadataNode("JFIFthumbJPEG"); if (thumbMetadata != null) { @@ -1295,6 +1327,7 @@ IIOMetadataNode getNativeNode() { return node; } + @Override int getLength() { if (data == null) { return 0; @@ -1303,6 +1336,7 @@ int getLength() { } } + @Override void write(ImageOutputStream ios, JPEGImageWriter writer) throws IOException { int progInterval = data.length / 20; // approx. every 5% @@ -1322,6 +1356,7 @@ void write(ImageOutputStream ios, } } + @Override void print () { System.out.println("JFIF thumbnail stored as JPEG"); } @@ -1445,6 +1480,7 @@ class ICCMarkerSegment extends MarkerSegment { } } + @Override protected Object clone () { ICCMarkerSegment newGuy = (ICCMarkerSegment) super.clone(); if (profile != null) { @@ -1541,6 +1577,7 @@ boolean addData(JPEGBuffer buffer) throws IOException { return retval; } + @Override IIOMetadataNode getNativeNode() { IIOMetadataNode node = new IIOMetadataNode("app2ICC"); if (profile != null) { @@ -1553,10 +1590,12 @@ IIOMetadataNode getNativeNode() { * No-op. Profiles are never written from metadata. * They are written from the ColorSpace of the image. */ + @Override void write(ImageOutputStream ios) throws IOException { // No-op } + @Override void print () { printTag("ICC Profile APP2"); } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageMetadataFormat.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageMetadataFormat.java index 4c858a47ab1..20b94fb339b 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageMetadataFormat.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageMetadataFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 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 @@ -337,6 +337,7 @@ private JPEGImageMetadataFormat() { tabids); } + @Override public boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType) { // All images can have these diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageMetadataFormatResources.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageMetadataFormatResources.java index e242a355a17..3cbc0054c85 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageMetadataFormatResources.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageMetadataFormatResources.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2005, 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 @@ -122,6 +122,7 @@ public class JPEGImageMetadataFormatResources public JPEGImageMetadataFormatResources() {} + @Override protected Object[][] getContents() { // return a copy of the combined commonContents and imageContents; // in theory we want a deep clone of the combined arrays, diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReaderResources.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReaderResources.java index e4b09197aa7..be6fc32a761 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReaderResources.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReaderResources.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2005, 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 @@ -31,6 +31,7 @@ public class JPEGImageReaderResources extends ListResourceBundle { public JPEGImageReaderResources() {} + @Override protected Object[][] getContents() { return new Object[][] { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReaderSpi.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReaderSpi.java index 450dd89b6f4..ab942ea8de2 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReaderSpi.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReaderSpi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,10 +59,12 @@ public JPEGImageReaderSpi() { ); } + @Override public String getDescription(Locale locale) { return "Standard JPEG Image Reader"; } + @Override public boolean canDecodeInput(Object source) throws IOException { if (!(source instanceof ImageInputStream)) { return false; @@ -80,6 +82,7 @@ public boolean canDecodeInput(Object source) throws IOException { return false; } + @Override public ImageReader createReaderInstance(Object extension) throws IIOException { return new JPEGImageReader(this); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriterResources.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriterResources.java index 3db20b3d39d..3b2a149f6b4 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriterResources.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriterResources.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2005, 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 @@ -31,6 +31,7 @@ public class JPEGImageWriterResources extends ListResourceBundle { public JPEGImageWriterResources() {} + @Override protected Object[][] getContents() { return new Object[][] { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriterSpi.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriterSpi.java index bd6bcc8d784..d6f5abbbccb 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriterSpi.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriterSpi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,14 +63,17 @@ public JPEGImageWriterSpi() { ); } + @Override public String getDescription(Locale locale) { return "Standard JPEG Image Writer"; } + @Override public boolean isFormatLossless() { return false; } + @Override public boolean canEncodeImage(ImageTypeSpecifier type) { SampleModel sampleModel = type.getSampleModel(); ColorModel cm = type.getColorModel(); @@ -95,6 +98,7 @@ public boolean canEncodeImage(ImageTypeSpecifier type) { return true; } + @Override public ImageWriter createWriterInstance(Object extension) throws IIOException { return new JPEGImageWriter(this); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java index c7ad982b35a..3081fd43404 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java @@ -725,6 +725,7 @@ private int findLastUnknownMarkerSegmentPosition() { // Implement Cloneable, but restrict access + @Override protected Object clone() { JPEGMetadata newGuy = null; try { @@ -755,6 +756,7 @@ private List cloneSequence() { // Tree methods + @Override public Node getAsTree(String formatName) { if (formatName == null) { throw new IllegalArgumentException("null formatName!"); @@ -810,6 +812,7 @@ IIOMetadataNode getNativeTree() { // Standard tree node methods + @Override protected IIOMetadataNode getStandardChromaNode() { hasAlpha = false; // Unless we find otherwise @@ -950,6 +953,7 @@ protected IIOMetadataNode getStandardChromaNode() { return chroma; } + @Override protected IIOMetadataNode getStandardCompressionNode() { IIOMetadataNode compression = new IIOMetadataNode("Compression"); @@ -980,6 +984,7 @@ protected IIOMetadataNode getStandardCompressionNode() { return compression; } + @Override protected IIOMetadataNode getStandardDimensionNode() { // If we have a JFIF marker segment, we know a little // otherwise all we know is the orientation, which is always normal @@ -1055,6 +1060,7 @@ protected IIOMetadataNode getStandardDocumentNode() { return doc; } + @Override protected IIOMetadataNode getStandardTextNode() { IIOMetadataNode text = null; // Add a text entry for each COM Marker Segment @@ -1073,6 +1079,7 @@ protected IIOMetadataNode getStandardTextNode() { return text; } + @Override protected IIOMetadataNode getStandardTransparencyNode() { IIOMetadataNode trans = null; if (hasAlpha == true) { @@ -1086,10 +1093,12 @@ protected IIOMetadataNode getStandardTransparencyNode() { // Editing + @Override public boolean isReadOnly() { return false; } + @Override public void mergeTree(String formatName, Node root) throws IIOInvalidTreeException { if (formatName == null) { @@ -2160,6 +2169,7 @@ private void mergeStandardTransparencyNode(Node node) } + @Override public void setFromTree(String formatName, Node root) throws IIOInvalidTreeException { if (formatName == null) { @@ -2404,6 +2414,7 @@ void writeToStream(ImageOutputStream ios, //// End of writer support + @Override public void reset() { if (resetSequence != null) { // Otherwise no need to reset markerSequence = resetSequence; diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadataFormat.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadataFormat.java index 475cc36359e..53b30f333f0 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadataFormat.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadataFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 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 @@ -123,6 +123,7 @@ void addStreamElements(String parentName) { addObjectValue("unknown", byte[].class, 1, MAX_JPEG_DATA_SIZE); } + @Override public boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType) { // Just check if it appears in the format diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGStreamMetadataFormatResources.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGStreamMetadataFormatResources.java index ea6d2b70138..5e29101e83b 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGStreamMetadataFormatResources.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGStreamMetadataFormatResources.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2005, 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 @@ -32,6 +32,7 @@ public class JPEGStreamMetadataFormatResources public JPEGStreamMetadataFormatResources() {} + @Override protected Object[][] getContents() { // return a copy of commonContents; in theory we want a deep clone // of commonContents, but since it only contains (immutable) Strings, diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/MarkerSegment.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/MarkerSegment.java index f4ba27b0fcd..74bf598c4d5 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/MarkerSegment.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/MarkerSegment.java @@ -110,6 +110,7 @@ class MarkerSegment implements Cloneable { /** * Deep copy of data array. */ + @Override protected Object clone() { MarkerSegment newGuy = null; try { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/SOFMarkerSegment.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/SOFMarkerSegment.java index e5b7e861924..fa7acba3325 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/SOFMarkerSegment.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/SOFMarkerSegment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, 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 @@ -95,6 +95,7 @@ class SOFMarkerSegment extends MarkerSegment { updateFromNativeNode(node, true); } + @Override protected Object clone() { SOFMarkerSegment newGuy = (SOFMarkerSegment) super.clone(); if (componentSpecs != null) { @@ -107,6 +108,7 @@ protected Object clone() { return newGuy; } + @Override IIOMetadataNode getNativeNode() { IIOMetadataNode node = new IIOMetadataNode("sof"); node.setAttribute("process", Integer.toString(tag-JPEG.SOF0)); @@ -154,10 +156,12 @@ void updateFromNativeNode(Node node, boolean fromScratch) * Writes the data for this segment to the stream in * valid JPEG format. */ + @Override void write(ImageOutputStream ios) throws IOException { // We don't write SOF segments; the IJG library does. } + @Override void print () { printTag("SOF"); System.out.print("Sample precision: "); @@ -231,6 +235,7 @@ static class ComponentSpec implements Cloneable { 0, 3, true); } + @Override protected Object clone() { try { return super.clone(); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/SOSMarkerSegment.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/SOSMarkerSegment.java index f40acdd0375..a34fc43486a 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/SOSMarkerSegment.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/SOSMarkerSegment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, 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 @@ -89,6 +89,7 @@ class SOSMarkerSegment extends MarkerSegment { updateFromNativeNode(node, true); } + @Override protected Object clone () { SOSMarkerSegment newGuy = (SOSMarkerSegment) super.clone(); if (componentSpecs != null) { @@ -101,6 +102,7 @@ protected Object clone () { return newGuy; } + @Override IIOMetadataNode getNativeNode() { IIOMetadataNode node = new IIOMetadataNode("sos"); node.setAttribute("numScanComponents", @@ -152,10 +154,12 @@ void updateFromNativeNode(Node node, boolean fromScratch) * Writes the data for this segment to the stream in * valid JPEG format. */ + @Override void write(ImageOutputStream ios) throws IOException { // We don't write SOS segments; the IJG library does. } + @Override void print () { printTag("SOS"); System.out.print("Start spectral selection: "); @@ -208,6 +212,7 @@ static class ScanComponentSpec implements Cloneable { 0, 3, true); } + @Override protected Object clone() { try { return super.clone(); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReaderSpi.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReaderSpi.java index 60105e30f8a..bf0576ecb74 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReaderSpi.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReaderSpi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,10 +70,12 @@ public PNGImageReaderSpi() { ); } + @Override public String getDescription(Locale locale) { return "Standard PNG image reader"; } + @Override public boolean canDecodeInput(Object input) throws IOException { if (!(input instanceof ImageInputStream)) { return false; @@ -96,6 +98,7 @@ public boolean canDecodeInput(Object input) throws IOException { b[7] == (byte)10); } + @Override public ImageReader createReaderInstance(Object extension) { return new PNGImageReader(this); } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriterSpi.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriterSpi.java index 44080a05a16..3ce07aa4ba5 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriterSpi.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriterSpi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,6 +74,7 @@ public PNGImageWriterSpi() { ); } + @Override public boolean canEncodeImage(ImageTypeSpecifier type) { SampleModel sampleModel = type.getSampleModel(); ColorModel colorModel = type.getColorModel(); @@ -116,10 +117,12 @@ public boolean canEncodeImage(ImageTypeSpecifier type) { return true; } + @Override public String getDescription(Locale locale) { return "Standard PNG image writer"; } + @Override public ImageWriter createWriterInstance(Object extension) { return new PNGImageWriter(this); } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGMetadata.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGMetadata.java index 03d00f7ae8e..730294c9f01 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGMetadata.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -463,6 +463,7 @@ public void initialize(ImageTypeSpecifier imageType, int numBands) { IHDR_present = true; } + @Override public boolean isReadOnly() { return false; } @@ -480,6 +481,7 @@ private ArrayList cloneBytesArrayList(ArrayList in) { } // Deep clone + @Override public Object clone() { PNGMetadata metadata; try { @@ -495,6 +497,7 @@ public Object clone() { return metadata; } + @Override public Node getAsTree(String formatName) { if (formatName.equals(nativeMetadataFormatName)) { return getNativeTree(); @@ -847,6 +850,7 @@ private int getNumChannels() { return numChannels; } + @Override public IIOMetadataNode getStandardChromaNode() { IIOMetadataNode chroma_node = new IIOMetadataNode("Chroma"); IIOMetadataNode node = null; // scratch node @@ -919,6 +923,7 @@ public IIOMetadataNode getStandardChromaNode() { return chroma_node; } + @Override public IIOMetadataNode getStandardCompressionNode() { IIOMetadataNode compression_node = new IIOMetadataNode("Compression"); IIOMetadataNode node = null; // scratch node @@ -952,6 +957,7 @@ private String repeat(String s, int times) { return sb.toString(); } + @Override public IIOMetadataNode getStandardDataNode() { IIOMetadataNode data_node = new IIOMetadataNode("Data"); IIOMetadataNode node = null; // scratch node @@ -998,6 +1004,7 @@ public IIOMetadataNode getStandardDataNode() { return data_node; } + @Override public IIOMetadataNode getStandardDimensionNode() { IIOMetadataNode dimension_node = new IIOMetadataNode("Dimension"); IIOMetadataNode node = null; // scratch node @@ -1027,6 +1034,7 @@ public IIOMetadataNode getStandardDimensionNode() { return dimension_node; } + @Override public IIOMetadataNode getStandardDocumentNode() { IIOMetadataNode document_node = null; @@ -1067,6 +1075,7 @@ public IIOMetadataNode getStandardDocumentNode() { return document_node; } + @Override public IIOMetadataNode getStandardTextNode() { int numEntries = tEXt_keyword.size() + iTXt_keyword.size() + zTXt_keyword.size(); @@ -1114,6 +1123,7 @@ public IIOMetadataNode getStandardTextNode() { return text_node; } + @Override public IIOMetadataNode getStandardTransparencyNode() { IIOMetadataNode transparency_node = new IIOMetadataNode("Transparency"); @@ -1285,6 +1295,7 @@ private String getAttribute(Node node, String name) return getAttribute(node, name, null, true); } + @Override public void mergeTree(String formatName, Node root) throws IIOInvalidTreeException { if (formatName.equals(nativeMetadataFormatName)) { @@ -2267,6 +2278,7 @@ boolean hasTransparentColor() { } // Reset all instance variables to their initial state + @Override public void reset() { IHDR_present = false; PLTE_present = false; diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGMetadataFormat.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGMetadataFormat.java index b7d96dc3f2b..1518d097903 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGMetadataFormat.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGMetadataFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2004, 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 @@ -486,6 +486,7 @@ private PNGMetadataFormat() { addObjectValue("UnknownChunk", byte.class, 0, Integer.MAX_VALUE); } + @Override public boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType) { return true; diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGMetadataFormatResources.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGMetadataFormatResources.java index d99946bd890..818a2364e23 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGMetadataFormatResources.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGMetadataFormatResources.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2005, 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 @@ -31,6 +31,7 @@ public class PNGMetadataFormatResources extends ListResourceBundle { public PNGMetadataFormatResources() {} + @Override protected Object[][] getContents() { return new Object[][] { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFBaseJPEGCompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFBaseJPEGCompressor.java index dba8d878169..8713eebb47c 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFBaseJPEGCompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFBaseJPEGCompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -325,6 +325,7 @@ private IIOMetadata getImageMetadata(boolean pruneTables) return JPEGImageMetadata; } + @Override public final int encode(byte[] b, int off, int width, int height, int[] bitsPerSample, diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFCIELabColorConverter.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFCIELabColorConverter.java index bc20c57da69..dbddc94516e 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFCIELabColorConverter.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFCIELabColorConverter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, 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 @@ -56,6 +56,7 @@ private float clamp2(float x) { } } + @Override public void fromRGB(float r, float g, float b, float[] result) { float X = 0.412453f*r + 0.357580f*g + 0.180423f*b; float Y = 0.212671f*r + 0.715160f*g + 0.072169f*b; @@ -100,6 +101,7 @@ public void fromRGB(float r, float g, float b, float[] result) { result[2] = clamp2(bStar); } + @Override public void toRGB(float x0, float x1, float x2, float[] rgb) { float LStar = x0*100.0f/255.0f; float aStar = (x1 > 128.0f) ? (x1 - 256.0f) : x1; diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDeflateDecompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDeflateDecompressor.java index 1ce7d56c1c7..5ade4bacfb4 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDeflateDecompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDeflateDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, 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 @@ -48,6 +48,7 @@ public TIFFDeflateDecompressor(int predictor) throws IIOException { this.predictor = predictor; } + @Override public synchronized void decodeRaw(byte[] b, int dstOffset, int bitsPerPixel, diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDeflater.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDeflater.java index 0fde32a229f..3a5a10245df 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDeflater.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDeflater.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, 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 @@ -58,6 +58,7 @@ public TIFFDeflater(String compressionType, this.deflater = new Deflater(deflateLevel); } + @Override public int encode(byte[] b, int off, int width, int height, int[] bitsPerSample, diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFExifJPEGCompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFExifJPEGCompressor.java index 3541ce110db..992cba6cbe5 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFExifJPEGCompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFExifJPEGCompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, 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 @@ -39,6 +39,7 @@ public TIFFExifJPEGCompressor(ImageWriteParam param) { param); } + @Override public void setMetadata(IIOMetadata metadata) { // Set the metadata. super.setMetadata(metadata); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxCompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxCompressor.java index 5c126acab53..2af59c682c4 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxCompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxCompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, 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 @@ -242,6 +242,7 @@ protected TIFFFaxCompressor(String compressionType, * * @see #getMetadata() */ + @Override public void setMetadata(IIOMetadata metadata) { super.setMetadata(metadata); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxDecompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxDecompressor.java index a1947dc6b72..64839c033da 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxDecompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -591,6 +591,7 @@ public TIFFFaxDecompressor() {} * Invokes the superclass method and then sets instance variables on * the basis of the metadata set on this decompressor. */ + @Override public void beginDecoding() { super.beginDecoding(); @@ -627,6 +628,7 @@ public void beginDecoding() { } } + @Override public void decodeRaw(byte[] b, int dstOffset, int pixelBitStride, // will always be 1 int scanlineStride) throws IOException { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFieldNode.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFieldNode.java index 6f23fbad4f2..e8878d93315 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFieldNode.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFieldNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -162,6 +162,7 @@ private synchronized void initialize() { // Need to override this method to avoid a stack overflow exception // which will occur if super.appendChild is called from initialize(). + @Override public Node appendChild(Node newChild) { if (newChild == null) { throw new NullPointerException("newChild == null!"); @@ -172,53 +173,63 @@ public Node appendChild(Node newChild) { // Override all methods which refer to child nodes. + @Override public boolean hasChildNodes() { initialize(); return super.hasChildNodes(); } + @Override public int getLength() { initialize(); return super.getLength(); } + @Override public Node getFirstChild() { initialize(); return super.getFirstChild(); } + @Override public Node getLastChild() { initialize(); return super.getLastChild(); } + @Override public Node getPreviousSibling() { initialize(); return super.getPreviousSibling(); } + @Override public Node getNextSibling() { initialize(); return super.getNextSibling(); } + @Override public Node insertBefore(Node newChild, Node refChild) { initialize(); return super.insertBefore(newChild, refChild); } + @Override public Node replaceChild(Node newChild, Node oldChild) { initialize(); return super.replaceChild(newChild, oldChild); } + @Override public Node removeChild(Node oldChild) { initialize(); return super.removeChild(oldChild); } + @Override public Node cloneNode(boolean deep) { initialize(); return super.cloneNode(deep); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageMetadata.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageMetadata.java index 82ae068d7e4..a3cf39505e6 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageMetadata.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,6 +93,7 @@ public void addShortOrLongField(int tagNumber, long value) { rootIFD.addTIFFField(field); } + @Override public boolean isReadOnly() { return false; } @@ -149,6 +150,7 @@ private Node getIFDAsTree(TIFFIFD ifd, return IFDRoot; } + @Override public Node getAsTree(String formatName) { if (formatName.equals(nativeMetadataFormatName)) { return getNativeTree(); @@ -181,6 +183,7 @@ private Node getNativeTree() { "Lab", // ICCLab }; + @Override public IIOMetadataNode getStandardChromaNode() { IIOMetadataNode chroma_node = new IIOMetadataNode("Chroma"); IIOMetadataNode node = null; // scratch node @@ -278,6 +281,7 @@ public IIOMetadataNode getStandardChromaNode() { return chroma_node; } + @Override public IIOMetadataNode getStandardCompressionNode() { IIOMetadataNode compression_node = new IIOMetadataNode("Compression"); IIOMetadataNode node = null; // scratch node @@ -336,6 +340,7 @@ private String repeat(String s, int times) { return sb.toString(); } + @Override public IIOMetadataNode getStandardDataNode() { IIOMetadataNode data_node = new IIOMetadataNode("Data"); IIOMetadataNode node = null; // scratch node @@ -476,6 +481,7 @@ public IIOMetadataNode getStandardDataNode() { "Rotate90", }; + @Override public IIOMetadataNode getStandardDimensionNode() { IIOMetadataNode dimension_node = new IIOMetadataNode("Dimension"); IIOMetadataNode node = null; // scratch node @@ -604,6 +610,7 @@ public IIOMetadataNode getStandardDimensionNode() { return dimension_node; } + @Override public IIOMetadataNode getStandardDocumentNode() { IIOMetadataNode document_node = new IIOMetadataNode("Document"); IIOMetadataNode node = null; // scratch node @@ -669,6 +676,7 @@ public IIOMetadataNode getStandardDocumentNode() { return document_node; } + @Override public IIOMetadataNode getStandardTextNode() { IIOMetadataNode text_node = null; IIOMetadataNode node = null; // scratch node @@ -705,6 +713,7 @@ public IIOMetadataNode getStandardTextNode() { return text_node; } + @Override public IIOMetadataNode getStandardTransparencyNode() { IIOMetadataNode transparency_node = new IIOMetadataNode("Transparency"); @@ -1579,6 +1588,7 @@ private void mergeNativeTree(Node root) throws IIOInvalidTreeException { } } + @Override public void mergeTree(String formatName, Node root) throws IIOInvalidTreeException{ if (formatName.equals(nativeMetadataFormatName)) { @@ -1597,6 +1607,7 @@ public void mergeTree(String formatName, Node root) } } + @Override public void reset() { rootIFD = new TIFFIFD(tagSets); } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageMetadataFormat.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageMetadataFormat.java index 59c425ec517..edfa3a5be9c 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageMetadataFormat.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageMetadataFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, 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 @@ -34,6 +34,7 @@ public class TIFFImageMetadataFormat extends TIFFMetadataFormat { static { } + @Override public boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType) { return false; diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageMetadataFormatResources.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageMetadataFormatResources.java index 070836e8854..59e68d0dfe2 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageMetadataFormatResources.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageMetadataFormatResources.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, 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 @@ -96,6 +96,7 @@ public class TIFFImageMetadataFormatResources extends ListResourceBundle { public TIFFImageMetadataFormatResources() { } + @Override public Object[][] getContents() { return contents.clone(); } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReaderSpi.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReaderSpi.java index 2332e4be2d1..ef21e0b2042 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReaderSpi.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReaderSpi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, 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 @@ -56,10 +56,12 @@ public TIFFImageReaderSpi() { ); } + @Override public String getDescription(Locale locale) { return "Standard TIFF image reader"; } + @Override public boolean canDecodeInput(Object input) throws IOException { if (!(input instanceof ImageInputStream)) { return false; @@ -78,10 +80,12 @@ public boolean canDecodeInput(Object input) throws IOException { b[2] == (byte)0x00 && b[3] == (byte)0x2a)); } + @Override public ImageReader createReaderInstance(Object extension) { return new TIFFImageReader(this); } + @Override public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriterSpi.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriterSpi.java index 0b93cbedc0b..a742db6f6bb 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriterSpi.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriterSpi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,18 +55,22 @@ public TIFFImageWriterSpi() { ); } + @Override public boolean canEncodeImage(ImageTypeSpecifier type) { return true; } + @Override public String getDescription(Locale locale) { return "Standard TIFF image writer"; } + @Override public ImageWriter createWriterInstance(Object extension) { return new TIFFImageWriter(this); } + @Override public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGCompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGCompressor.java index f524f34e32e..e73ccb2b282 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGCompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGCompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, 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 @@ -54,6 +54,7 @@ public class TIFFJPEGCompressor extends TIFFBaseJPEGCompressor { private static class JPEGSPIFilter implements ServiceRegistry.Filter { JPEGSPIFilter() {} + @Override public boolean filter(Object provider) { ImageReaderSpi readerSPI = (ImageReaderSpi)provider; @@ -112,6 +113,7 @@ public TIFFJPEGCompressor(ImageWriteParam param) { * * @see #getMetadata() */ + @Override public void setMetadata(IIOMetadata metadata) { super.setMetadata(metadata); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGDecompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGDecompressor.java index 0b21835901b..338225e4933 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGDecompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2017, 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 @@ -52,6 +52,7 @@ public class TIFFJPEGDecompressor extends TIFFDecompressor { public TIFFJPEGDecompressor() {} + @Override public void beginDecoding() { // Initialize the JPEG reader if needed. if(this.JPEGReader == null) { @@ -81,6 +82,7 @@ public void beginDecoding() { } } + @Override public void decodeRaw(byte[] b, int dstOffset, int bitsPerPixel, diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLSBCompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLSBCompressor.java index b7bceb89ae4..5052ffedbff 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLSBCompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLSBCompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, 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 @@ -36,6 +36,7 @@ public TIFFLSBCompressor() { super("", BaselineTIFFTagSet.COMPRESSION_NONE, true); } + @Override public int encode(byte[] b, int off, int width, int height, int[] bitsPerSample, diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLSBDecompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLSBDecompressor.java index d871b6a3e86..6724b779334 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLSBDecompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLSBDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, 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 @@ -35,6 +35,7 @@ public class TIFFLSBDecompressor extends TIFFDecompressor { public TIFFLSBDecompressor() {} + @Override public void decodeRaw(byte[] b, int dstOffset, int bitsPerPixel, diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWCompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWCompressor.java index 4b2b945acb7..6780d65053f 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWCompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWCompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, 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 @@ -41,10 +41,12 @@ public TIFFLZWCompressor(int predictorValue) { this.predictor = predictorValue; } + @Override public void setStream(ImageOutputStream stream) { super.setStream(stream); } + @Override public int encode(byte[] b, int off, int width, int height, int[] bitsPerSample, diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java index fc682589ce2..dcf5b2a7f71 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -76,6 +76,7 @@ public TIFFLZWDecompressor(int predictor, int fillOrder) flipBits = fillOrder == BaselineTIFFTagSet.FILL_ORDER_RIGHT_TO_LEFT; } + @Override public void decodeRaw(byte[] b, int dstOffset, int bitsPerPixel, diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFMetadataFormat.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFMetadataFormat.java index 1091cab9bb2..92d15bfdcb4 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFMetadataFormat.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFMetadataFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, 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 @@ -39,6 +39,7 @@ public abstract class TIFFMetadataFormat implements IIOMetadataFormat { protected String resourceBaseName; protected String rootName; + @Override public String getRootName() { return rootName; } @@ -85,16 +86,19 @@ private TIFFAttrInfo getAttrInfo(String elementName, String attrName) { return info; } + @Override public int getElementMinChildren(String elementName) { TIFFElementInfo info = getElementInfo(elementName); return info.minChildren; } + @Override public int getElementMaxChildren(String elementName) { TIFFElementInfo info = getElementInfo(elementName); return info.maxChildren; } + @Override public String getElementDescription(String elementName, Locale locale) { if (!elementInfoMap.containsKey(elementName)) { throw new IllegalArgumentException("No such element: " + @@ -103,64 +107,77 @@ public String getElementDescription(String elementName, Locale locale) { return getResource(elementName, locale); } + @Override public int getChildPolicy(String elementName) { TIFFElementInfo info = getElementInfo(elementName); return info.childPolicy; } + @Override public String[] getChildNames(String elementName) { TIFFElementInfo info = getElementInfo(elementName); return info.childNames; } + @Override public String[] getAttributeNames(String elementName) { TIFFElementInfo info = getElementInfo(elementName); return info.attributeNames; } + @Override public int getAttributeValueType(String elementName, String attrName) { TIFFAttrInfo info = getAttrInfo(elementName, attrName); return info.valueType; } + @Override public int getAttributeDataType(String elementName, String attrName) { TIFFAttrInfo info = getAttrInfo(elementName, attrName); return info.dataType; } + @Override public boolean isAttributeRequired(String elementName, String attrName) { TIFFAttrInfo info = getAttrInfo(elementName, attrName); return info.isRequired; } + @Override public String getAttributeDefaultValue(String elementName, String attrName) { return null; } + @Override public String[] getAttributeEnumerations(String elementName, String attrName) { throw new IllegalArgumentException("The attribute is not an enumeration."); } + @Override public String getAttributeMinValue(String elementName, String attrName) { throw new IllegalArgumentException("The attribute is not a range."); } + @Override public String getAttributeMaxValue(String elementName, String attrName) { throw new IllegalArgumentException("The attribute is not a range."); } + @Override public int getAttributeListMinLength(String elementName, String attrName) { TIFFAttrInfo info = getAttrInfo(elementName, attrName); return info.listMinLength; } + @Override public int getAttributeListMaxLength(String elementName, String attrName) { TIFFAttrInfo info = getAttrInfo(elementName, attrName); return info.listMaxLength; } + @Override public String getAttributeDescription(String elementName, String attrName, Locale locale) { String key = elementName + "/" + attrName; @@ -170,11 +187,13 @@ public String getAttributeDescription(String elementName, String attrName, return getResource(key, locale); } + @Override public int getObjectValueType(String elementName) { TIFFElementInfo info = getElementInfo(elementName); return info.objectValueType; } + @Override public Class getObjectClass(String elementName) { TIFFElementInfo info = getElementInfo(elementName); if (info.objectValueType == VALUE_NONE) { @@ -184,6 +203,7 @@ public Class getObjectClass(String elementName) { return info.objectClass; } + @Override public Object getObjectDefaultValue(String elementName) { TIFFElementInfo info = getElementInfo(elementName); if (info.objectValueType == VALUE_NONE) { @@ -193,6 +213,7 @@ public Object getObjectDefaultValue(String elementName) { return info.objectDefaultValue; } + @Override public Object[] getObjectEnumerations(String elementName) { TIFFElementInfo info = getElementInfo(elementName); if (info.objectValueType == VALUE_NONE) { @@ -202,6 +223,7 @@ public Object[] getObjectEnumerations(String elementName) { return info.objectEnumerations; } + @Override public Comparable getObjectMinValue(String elementName) { TIFFElementInfo info = getElementInfo(elementName); if (info.objectValueType == VALUE_NONE) { @@ -211,6 +233,7 @@ public Comparable getObjectMinValue(String elementName) { return info.objectMinValue; } + @Override public Comparable getObjectMaxValue(String elementName) { TIFFElementInfo info = getElementInfo(elementName); if (info.objectValueType == VALUE_NONE) { @@ -220,6 +243,7 @@ public Comparable getObjectMaxValue(String elementName) { return info.objectMaxValue; } + @Override public int getObjectArrayMinLength(String elementName) { TIFFElementInfo info = getElementInfo(elementName); if (info.objectValueType == VALUE_NONE) { @@ -229,6 +253,7 @@ public int getObjectArrayMinLength(String elementName) { return info.objectArrayMinLength; } + @Override public int getObjectArrayMaxLength(String elementName) { TIFFElementInfo info = getElementInfo(elementName); if (info.objectValueType == VALUE_NONE) { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFNullCompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFNullCompressor.java index fc366f791f7..8f6428035d9 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFNullCompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFNullCompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, 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 @@ -33,6 +33,7 @@ public TIFFNullCompressor() { super("", BaselineTIFFTagSet.COMPRESSION_NONE, true); } + @Override public int encode(byte[] b, int off, int width, int height, int[] bitsPerSample, diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFNullDecompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFNullDecompressor.java index 9b5a746eec1..b73580ef823 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFNullDecompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFNullDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, 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 @@ -56,6 +56,7 @@ public TIFFNullDecompressor() {} // change beginDecoding() and decode() to use the active region values // when random access is easy and the entire region values otherwise. // + @Override public void beginDecoding() { // Determine number of bits per pixel. int bitsPerPixel = 0; @@ -89,6 +90,7 @@ public void beginDecoding() { super.beginDecoding(); } + @Override public void decode() throws IOException { super.decode(); @@ -105,6 +107,7 @@ public void decode() throws IOException { } } + @Override public void decodeRaw(byte[] b, int dstOffset, int bitsPerPixel, diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java index bc787f9127c..d30d1443da0 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java @@ -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 @@ -545,6 +545,7 @@ private synchronized void initialize() throws IOException { // The strategy for cases 4-5 is to concatenate a tables stream created // in initialize() with the entropy coded data in each strip or tile. // + @Override public void decodeRaw(byte[] b, int dstOffset, int bitsPerPixel, diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFPackBitsCompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFPackBitsCompressor.java index 119e4ad4906..b2341f12ed7 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFPackBitsCompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFPackBitsCompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, 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 @@ -86,6 +86,7 @@ private static int packBits(byte[] input, int inOffset, int inCount, return outOffset; } + @Override public int encode(byte[] b, int off, int width, int height, int[] bitsPerSample, diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFPackBitsDecompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFPackBitsDecompressor.java index 0a5dfe8308e..61026f57fed 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFPackBitsDecompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFPackBitsDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -72,6 +72,7 @@ public int decode(byte[] srcData, int srcOffset, return dstIndex - dstOffset; } + @Override public void decodeRaw(byte[] b, int dstOffset, int bitsPerPixel, diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRLECompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRLECompressor.java index 0bf59da81da..1e0270c6ecc 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRLECompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRLECompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, 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 @@ -87,6 +87,7 @@ public int encodeRLE(byte[] data, return outIndex; } + @Override public int encode(byte[] b, int off, int width, int height, int[] bitsPerSample, diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRenderedImage.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRenderedImage.java index 77e0c9a109c..dadabac3d68 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRenderedImage.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRenderedImage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, 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 @@ -130,74 +130,92 @@ private ImageReadParam cloneImageReadParam(ImageReadParam param, return newParam; } + @Override public Vector getSources() { return null; } + @Override public Object getProperty(String name) { return java.awt.Image.UndefinedProperty; } + @Override public String[] getPropertyNames() { return null; } + @Override public ColorModel getColorModel() { return its.getColorModel(); } + @Override public SampleModel getSampleModel() { return its.getSampleModel(); } + @Override public int getWidth() { return width; } + @Override public int getHeight() { return height; } + @Override public int getMinX() { return 0; } + @Override public int getMinY() { return 0; } + @Override public int getNumXTiles() { return (width + tileWidth - 1)/tileWidth; } + @Override public int getNumYTiles() { return (height + tileHeight - 1)/tileHeight; } + @Override public int getMinTileX() { return 0; } + @Override public int getMinTileY() { return 0; } + @Override public int getTileWidth() { return tileWidth; } + @Override public int getTileHeight() { return tileHeight; } + @Override public int getTileGridXOffset() { return 0; } + @Override public int getTileGridYOffset() { return 0; } + @Override public Raster getTile(int tileX, int tileY) { Rectangle tileRect = new Rectangle(tileX*tileWidth, tileY*tileHeight, @@ -206,10 +224,12 @@ public Raster getTile(int tileX, int tileY) { return getData(tileRect); } + @Override public Raster getData() { return read(new Rectangle(0, 0, getWidth(), getHeight())); } + @Override public Raster getData(Rectangle rect) { return read(rect); } @@ -236,6 +256,7 @@ public synchronized WritableRaster read(Rectangle rect) { } } + @Override public WritableRaster copyData(WritableRaster raster) { if (raster == null) { return read(new Rectangle(0, 0, getWidth(), getHeight())); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFStreamMetadata.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFStreamMetadata.java index 96592cc62fb..ac9398fd6e9 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFStreamMetadata.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFStreamMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, 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 @@ -54,6 +54,7 @@ public TIFFStreamMetadata() { null, null); } + @Override public boolean isReadOnly() { return false; } @@ -64,6 +65,7 @@ private static void fatal(Node node, String reason) throw new IIOInvalidTreeException(reason, node); } + @Override public Node getAsTree(String formatName) { IIOMetadataNode root = new IIOMetadataNode(nativeMetadataFormatName); @@ -103,6 +105,7 @@ private void mergeNativeTree(Node root) throws IIOInvalidTreeException { } } + @Override public void mergeTree(String formatName, Node root) throws IIOInvalidTreeException { if (formatName.equals(nativeMetadataFormatName)) { @@ -115,6 +118,7 @@ public void mergeTree(String formatName, Node root) } } + @Override public void reset() { this.byteOrder = ByteOrder.BIG_ENDIAN; } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFStreamMetadataFormat.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFStreamMetadataFormat.java index bf35133811e..50a3d32e239 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFStreamMetadataFormat.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFStreamMetadataFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, 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 @@ -31,6 +31,7 @@ public class TIFFStreamMetadataFormat extends TIFFMetadataFormat { private static TIFFStreamMetadataFormat theInstance = null; + @Override public boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType) { return false; diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFStreamMetadataFormatResources.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFStreamMetadataFormatResources.java index 1e0ea272200..75977c15a41 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFStreamMetadataFormatResources.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFStreamMetadataFormatResources.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, 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 @@ -36,6 +36,7 @@ public class TIFFStreamMetadataFormatResources extends ListResourceBundle { public TIFFStreamMetadataFormatResources() { } + @Override public Object[][] getContents() { return contents.clone(); } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT4Compressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT4Compressor.java index 55088e34dfe..99d45ce4866 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT4Compressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT4Compressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, 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 @@ -52,6 +52,7 @@ public TIFFT4Compressor() { * * @see #getMetadata() */ + @Override public void setMetadata(IIOMetadata metadata) { super.setMetadata(metadata); @@ -214,6 +215,7 @@ public int encodeT4(boolean is1DMode, return outIndex; } + @Override public int encode(byte[] b, int off, int width, int height, int[] bitsPerSample, diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT6Compressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT6Compressor.java index 517c23bde54..7e2625d87e2 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT6Compressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT6Compressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, 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 @@ -146,6 +146,7 @@ public synchronized int encodeT6(byte[] data, return outIndex; } + @Override public int encode(byte[] b, int off, int width, int height, int[] bitsPerSample, diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFYCbCrColorConverter.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFYCbCrColorConverter.java index a006a3a1e38..b5dae8a9298 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFYCbCrColorConverter.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFYCbCrColorConverter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, 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 @@ -80,6 +80,7 @@ public TIFFYCbCrColorConverter(TIFFImageMetadata metadata) { / CodingRange) + ReferenceBlack; */ + @Override public void fromRGB(float r, float g, float b, float[] result) { // Convert RGB to full-range YCbCr. float Y = (lumaRed*r + lumaGreen*g + lumaBlue*b); @@ -95,6 +96,7 @@ public void fromRGB(float r, float g, float b, float[] result) { referenceBlackCr; } + @Override public void toRGB(float x0, float x1, float x2, float[] rgb) { // Convert YCbCr code to full-range YCbCr. float Y = (x0 - referenceBlackY)*CODING_RANGE_Y/ diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFYCbCrDecompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFYCbCrDecompressor.java index 0f10904cab4..c0623885d34 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFYCbCrDecompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFYCbCrDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -95,6 +95,7 @@ private void warning(String message) { // "Chained" decompressor methods. // + @Override public void setReader(ImageReader reader) { if(decompressor != null) { decompressor.setReader(reader); @@ -102,6 +103,7 @@ public void setReader(ImageReader reader) { super.setReader(reader); } + @Override public void setMetadata(IIOMetadata metadata) { if(decompressor != null) { decompressor.setMetadata(metadata); @@ -109,6 +111,7 @@ public void setMetadata(IIOMetadata metadata) { super.setMetadata(metadata); } + @Override public void setPhotometricInterpretation(int photometricInterpretation) { if(decompressor != null) { decompressor.setPhotometricInterpretation(photometricInterpretation); @@ -116,6 +119,7 @@ public void setPhotometricInterpretation(int photometricInterpretation) { super.setPhotometricInterpretation(photometricInterpretation); } + @Override public void setCompression(int compression) { if(decompressor != null) { decompressor.setCompression(compression); @@ -123,6 +127,7 @@ public void setCompression(int compression) { super.setCompression(compression); } + @Override public void setPlanar(boolean planar) { if(decompressor != null) { decompressor.setPlanar(planar); @@ -130,6 +135,7 @@ public void setPlanar(boolean planar) { super.setPlanar(planar); } + @Override public void setSamplesPerPixel(int samplesPerPixel) { if(decompressor != null) { decompressor.setSamplesPerPixel(samplesPerPixel); @@ -137,6 +143,7 @@ public void setSamplesPerPixel(int samplesPerPixel) { super.setSamplesPerPixel(samplesPerPixel); } + @Override public void setBitsPerSample(int[] bitsPerSample) { if(decompressor != null) { decompressor.setBitsPerSample(bitsPerSample); @@ -144,6 +151,7 @@ public void setBitsPerSample(int[] bitsPerSample) { super.setBitsPerSample(bitsPerSample); } + @Override public void setSampleFormat(int[] sampleFormat) { if(decompressor != null) { decompressor.setSampleFormat(sampleFormat); @@ -151,6 +159,7 @@ public void setSampleFormat(int[] sampleFormat) { super.setSampleFormat(sampleFormat); } + @Override public void setExtraSamples(int[] extraSamples) { if(decompressor != null) { decompressor.setExtraSamples(extraSamples); @@ -158,6 +167,7 @@ public void setExtraSamples(int[] extraSamples) { super.setExtraSamples(extraSamples); } + @Override public void setColorMap(char[] colorMap) { if(decompressor != null) { decompressor.setColorMap(colorMap); @@ -165,6 +175,7 @@ public void setColorMap(char[] colorMap) { super.setColorMap(colorMap); } + @Override public void setStream(ImageInputStream stream) { if(decompressor != null) { decompressor.setStream(stream); @@ -173,6 +184,7 @@ public void setStream(ImageInputStream stream) { } } + @Override public void setOffset(long offset) { if(decompressor != null) { decompressor.setOffset(offset); @@ -180,6 +192,7 @@ public void setOffset(long offset) { super.setOffset(offset); } + @Override public void setByteCount(int byteCount) throws IOException { if(decompressor != null) { decompressor.setByteCount(byteCount); @@ -187,6 +200,7 @@ public void setByteCount(int byteCount) throws IOException { super.setByteCount(byteCount); } + @Override public void setSrcMinX(int srcMinX) { if(decompressor != null) { decompressor.setSrcMinX(srcMinX); @@ -194,6 +208,7 @@ public void setSrcMinX(int srcMinX) { super.setSrcMinX(srcMinX); } + @Override public void setSrcMinY(int srcMinY) { if(decompressor != null) { decompressor.setSrcMinY(srcMinY); @@ -201,6 +216,7 @@ public void setSrcMinY(int srcMinY) { super.setSrcMinY(srcMinY); } + @Override public void setSrcWidth(int srcWidth) { if(decompressor != null) { decompressor.setSrcWidth(srcWidth); @@ -208,6 +224,7 @@ public void setSrcWidth(int srcWidth) { super.setSrcWidth(srcWidth); } + @Override public void setSrcHeight(int srcHeight) { if(decompressor != null) { decompressor.setSrcHeight(srcHeight); @@ -215,6 +232,7 @@ public void setSrcHeight(int srcHeight) { super.setSrcHeight(srcHeight); } + @Override public void setSourceXOffset(int sourceXOffset) { if(decompressor != null) { decompressor.setSourceXOffset(sourceXOffset); @@ -222,6 +240,7 @@ public void setSourceXOffset(int sourceXOffset) { super.setSourceXOffset(sourceXOffset); } + @Override public void setDstXOffset(int dstXOffset) { if(decompressor != null) { decompressor.setDstXOffset(dstXOffset); @@ -229,6 +248,7 @@ public void setDstXOffset(int dstXOffset) { super.setDstXOffset(dstXOffset); } + @Override public void setSourceYOffset(int sourceYOffset) { if(decompressor != null) { decompressor.setSourceYOffset(sourceYOffset); @@ -236,6 +256,7 @@ public void setSourceYOffset(int sourceYOffset) { super.setSourceYOffset(sourceYOffset); } + @Override public void setDstYOffset(int dstYOffset) { if(decompressor != null) { decompressor.setDstYOffset(dstYOffset); @@ -260,6 +281,7 @@ public void setSubsampleY(int subsampleY) { } */ + @Override public void setSourceBands(int[] sourceBands) { if(decompressor != null) { decompressor.setSourceBands(sourceBands); @@ -267,6 +289,7 @@ public void setSourceBands(int[] sourceBands) { super.setSourceBands(sourceBands); } + @Override public void setDestinationBands(int[] destinationBands) { if(decompressor != null) { decompressor.setDestinationBands(destinationBands); @@ -274,6 +297,7 @@ public void setDestinationBands(int[] destinationBands) { super.setDestinationBands(destinationBands); } + @Override public void setImage(BufferedImage image) { if(decompressor != null) { ColorModel cm = image.getColorModel(); @@ -287,6 +311,7 @@ public void setImage(BufferedImage image) { super.setImage(image); } + @Override public void setDstMinX(int dstMinX) { if(decompressor != null) { decompressor.setDstMinX(dstMinX); @@ -294,6 +319,7 @@ public void setDstMinX(int dstMinX) { super.setDstMinX(dstMinX); } + @Override public void setDstMinY(int dstMinY) { if(decompressor != null) { decompressor.setDstMinY(dstMinY); @@ -301,6 +327,7 @@ public void setDstMinY(int dstMinY) { super.setDstMinY(dstMinY); } + @Override public void setDstWidth(int dstWidth) { if(decompressor != null) { decompressor.setDstWidth(dstWidth); @@ -308,6 +335,7 @@ public void setDstWidth(int dstWidth) { super.setDstWidth(dstWidth); } + @Override public void setDstHeight(int dstHeight) { if(decompressor != null) { decompressor.setDstHeight(dstHeight); @@ -315,6 +343,7 @@ public void setDstHeight(int dstHeight) { super.setDstHeight(dstHeight); } + @Override public void setActiveSrcMinX(int activeSrcMinX) { if(decompressor != null) { decompressor.setActiveSrcMinX(activeSrcMinX); @@ -322,6 +351,7 @@ public void setActiveSrcMinX(int activeSrcMinX) { super.setActiveSrcMinX(activeSrcMinX); } + @Override public void setActiveSrcMinY(int activeSrcMinY) { if(decompressor != null) { decompressor.setActiveSrcMinY(activeSrcMinY); @@ -329,6 +359,7 @@ public void setActiveSrcMinY(int activeSrcMinY) { super.setActiveSrcMinY(activeSrcMinY); } + @Override public void setActiveSrcWidth(int activeSrcWidth) { if(decompressor != null) { decompressor.setActiveSrcWidth(activeSrcWidth); @@ -336,6 +367,7 @@ public void setActiveSrcWidth(int activeSrcWidth) { super.setActiveSrcWidth(activeSrcWidth); } + @Override public void setActiveSrcHeight(int activeSrcHeight) { if(decompressor != null) { decompressor.setActiveSrcHeight(activeSrcHeight); @@ -353,6 +385,7 @@ private byte clamp(int f) { } } + @Override public void beginDecoding() { if(decompressor != null) { decompressor.beginDecoding(); @@ -445,6 +478,7 @@ public void beginDecoding() { } } + @Override public void decodeRaw(byte[] buf, int dstOffset, int bitsPerPixel, diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java index acff45d5b72..9cd967140c9 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, 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 @@ -63,6 +63,7 @@ public WBMPImageReaderSpi() { null, null); } + @Override public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { @@ -71,10 +72,12 @@ public void onRegistration(ServiceRegistry registry, registered = true; } + @Override public String getDescription(Locale locale) { return "Standard WBMP Image Reader"; } + @Override public boolean canDecodeInput(Object source) throws IOException { if (!(source instanceof ImageInputStream)) { return false; @@ -149,6 +152,7 @@ private static int tryReadMultiByteInteger(ImageInputStream stream) return result; } + @Override public ImageReader createReaderInstance(Object extension) throws IIOException { return new WBMPImageReader(this); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageWriterSpi.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageWriterSpi.java index be2f2d96a38..d6d723c0110 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageWriterSpi.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageWriterSpi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, 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 @@ -63,10 +63,12 @@ public WBMPImageWriterSpi() { null, null, null, null); } + @Override public String getDescription(Locale locale) { return "Standard WBMP Image Writer"; } + @Override public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { @@ -76,6 +78,7 @@ public void onRegistration(ServiceRegistry registry, registered = true; } + @Override public boolean canEncodeImage(ImageTypeSpecifier type) { SampleModel sm = type.getSampleModel(); if (!(sm instanceof MultiPixelPackedSampleModel)) @@ -86,6 +89,7 @@ public boolean canEncodeImage(ImageTypeSpecifier type) { return true; } + @Override public ImageWriter createWriterInstance(Object extension) throws IIOException { return new WBMPImageWriter(this); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPMetadata.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPMetadata.java index 3a13bcca94f..f3a63ff7b13 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPMetadata.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2004, 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 @@ -50,10 +50,12 @@ public WBMPMetadata() { null, null); } + @Override public boolean isReadOnly() { return true; } + @Override public Node getAsTree(String formatName) { if (formatName.equals(nativeMetadataFormatName)) { return getNativeTree(); @@ -76,14 +78,17 @@ private Node getNativeTree() { return root; } + @Override public void setFromTree(String formatName, Node root) { throw new IllegalStateException(I18N.getString("WBMPMetadata1")); } + @Override public void mergeTree(String formatName, Node root) { throw new IllegalStateException(I18N.getString("WBMPMetadata1")); } + @Override public void reset() { throw new IllegalStateException(I18N.getString("WBMPMetadata1")); } @@ -101,6 +106,7 @@ private IIOMetadataNode addChildNode(IIOMetadataNode root, } + @Override protected IIOMetadataNode getStandardChromaNode() { IIOMetadataNode node = new IIOMetadataNode("Chroma"); @@ -112,6 +118,7 @@ protected IIOMetadataNode getStandardChromaNode() { } + @Override protected IIOMetadataNode getStandardDimensionNode() { IIOMetadataNode dimension_node = new IIOMetadataNode("Dimension"); IIOMetadataNode node = null; // scratch node diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPMetadataFormat.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPMetadataFormat.java index 49bce89164a..0aabaa132a3 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPMetadataFormat.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPMetadataFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2004, 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 @@ -56,6 +56,7 @@ private WBMPMetadataFormat() { + @Override public boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType) { return true; diff --git a/src/java.desktop/share/classes/com/sun/imageio/spi/FileImageInputStreamSpi.java b/src/java.desktop/share/classes/com/sun/imageio/spi/FileImageInputStreamSpi.java index 81070ff1cb6..3b52fb2b0f0 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/spi/FileImageInputStreamSpi.java +++ b/src/java.desktop/share/classes/com/sun/imageio/spi/FileImageInputStreamSpi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,10 +43,12 @@ public FileImageInputStreamSpi() { super(vendorName, version, inputClass); } + @Override public String getDescription(Locale locale) { return "Service provider that instantiates a FileImageInputStream from a File"; } + @Override public ImageInputStream createInputStreamInstance(Object input, boolean useCache, File cacheDir) { diff --git a/src/java.desktop/share/classes/com/sun/imageio/spi/FileImageOutputStreamSpi.java b/src/java.desktop/share/classes/com/sun/imageio/spi/FileImageOutputStreamSpi.java index 1ca08005fa1..aa906197d37 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/spi/FileImageOutputStreamSpi.java +++ b/src/java.desktop/share/classes/com/sun/imageio/spi/FileImageOutputStreamSpi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,10 +43,12 @@ public FileImageOutputStreamSpi() { super(vendorName, version, outputClass); } + @Override public String getDescription(Locale locale) { return "Service provider that instantiates a FileImageOutputStream from a File"; } + @Override public ImageOutputStream createOutputStreamInstance(Object output, boolean useCache, File cacheDir) { diff --git a/src/java.desktop/share/classes/com/sun/imageio/spi/InputStreamImageInputStreamSpi.java b/src/java.desktop/share/classes/com/sun/imageio/spi/InputStreamImageInputStreamSpi.java index 2591f77a697..266b09c6d9d 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/spi/InputStreamImageInputStreamSpi.java +++ b/src/java.desktop/share/classes/com/sun/imageio/spi/InputStreamImageInputStreamSpi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,18 +46,22 @@ public InputStreamImageInputStreamSpi() { super(vendorName, version, inputClass); } + @Override public String getDescription(Locale locale) { return "Service provider that instantiates a FileCacheImageInputStream or MemoryCacheImageInputStream from an InputStream"; } + @Override public boolean canUseCacheFile() { return true; } + @Override public boolean needsCacheFile() { return false; } + @Override public ImageInputStream createInputStreamInstance(Object input, boolean useCache, File cacheDir) diff --git a/src/java.desktop/share/classes/com/sun/imageio/spi/OutputStreamImageOutputStreamSpi.java b/src/java.desktop/share/classes/com/sun/imageio/spi/OutputStreamImageOutputStreamSpi.java index 391e00feb46..01c7df2145d 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/spi/OutputStreamImageOutputStreamSpi.java +++ b/src/java.desktop/share/classes/com/sun/imageio/spi/OutputStreamImageOutputStreamSpi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,18 +46,22 @@ public OutputStreamImageOutputStreamSpi() { super(vendorName, version, outputClass); } + @Override public String getDescription(Locale locale) { return "Service provider that instantiates an OutputStreamImageOutputStream from an OutputStream"; } + @Override public boolean canUseCacheFile() { return true; } + @Override public boolean needsCacheFile() { return false; } + @Override public ImageOutputStream createOutputStreamInstance(Object output, boolean useCache, File cacheDir) diff --git a/src/java.desktop/share/classes/com/sun/imageio/spi/RAFImageInputStreamSpi.java b/src/java.desktop/share/classes/com/sun/imageio/spi/RAFImageInputStreamSpi.java index b5c5112c14e..43498b30dbf 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/spi/RAFImageInputStreamSpi.java +++ b/src/java.desktop/share/classes/com/sun/imageio/spi/RAFImageInputStreamSpi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,10 +44,12 @@ public RAFImageInputStreamSpi() { super(vendorName, version, inputClass); } + @Override public String getDescription(Locale locale) { return "Service provider that instantiates a FileImageInputStream from a RandomAccessFile"; } + @Override public ImageInputStream createInputStreamInstance(Object input, boolean useCache, File cacheDir) { diff --git a/src/java.desktop/share/classes/com/sun/imageio/spi/RAFImageOutputStreamSpi.java b/src/java.desktop/share/classes/com/sun/imageio/spi/RAFImageOutputStreamSpi.java index 373f8754f08..1fe6438b27d 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/spi/RAFImageOutputStreamSpi.java +++ b/src/java.desktop/share/classes/com/sun/imageio/spi/RAFImageOutputStreamSpi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,10 +44,12 @@ public RAFImageOutputStreamSpi() { super(vendorName, version, outputClass); } + @Override public String getDescription(Locale locale) { return "Service provider that instantiates a FileImageOutputStream from a RandomAccessFile"; } + @Override public ImageOutputStream createOutputStreamInstance(Object output, boolean useCache, File cacheDir) { diff --git a/src/java.desktop/share/classes/com/sun/imageio/stream/CloseableDisposerRecord.java b/src/java.desktop/share/classes/com/sun/imageio/stream/CloseableDisposerRecord.java index 5ea52def657..370606ea08f 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/stream/CloseableDisposerRecord.java +++ b/src/java.desktop/share/classes/com/sun/imageio/stream/CloseableDisposerRecord.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 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 @@ -41,6 +41,7 @@ public CloseableDisposerRecord(Closeable closeable) { this.closeable = closeable; } + @Override public synchronized void dispose() { if (closeable != null) { try { diff --git a/src/java.desktop/share/classes/com/sun/imageio/stream/StreamCloser.java b/src/java.desktop/share/classes/com/sun/imageio/stream/StreamCloser.java index 229c470335b..7de400ad199 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/stream/StreamCloser.java +++ b/src/java.desktop/share/classes/com/sun/imageio/stream/StreamCloser.java @@ -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 @@ -60,6 +60,7 @@ public static void addToQueue(CloseAction ca) { if (streamCloser == null) { final Runnable streamCloserRunnable = new Runnable() { + @Override public void run() { if (toCloseQueue != null) { synchronized (StreamCloser.class) { diff --git a/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java b/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java index 567d6bfa803..dffc0c8f2cd 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java @@ -72,10 +72,6 @@ public class SwingUtilities3 { private static final Object DELEGATE_REPAINT_MANAGER_KEY = new StringBuilder("DelegateRepaintManagerKey"); - private static Color disabledForeground; - private static Color acceleratorSelectionForeground; - private static Color acceleratorForeground; - /** * Registers delegate RepaintManager for {@code JComponent}. */ @@ -210,7 +206,10 @@ public static void paintIcon(Graphics g, MenuItemLayoutHelper lh, public static void paintAccText(Graphics g, MenuItemLayoutHelper lh, - MenuItemLayoutHelper.LayoutResult lr) { + MenuItemLayoutHelper.LayoutResult lr, + Color disabledForeground, + Color acceleratorSelectionForeground, + Color acceleratorForeground) { if (!lh.getAccText().isEmpty()) { ButtonModel model = lh.getMenuItem().getModel(); g.setFont(lh.getAccFontMetrics().getFont()); @@ -249,18 +248,6 @@ public static void paintAccText(Graphics g, MenuItemLayoutHelper lh, } } - public static void setDisabledForeground(Color disabledFg) { - disabledForeground = disabledFg; - } - - public static void setAcceleratorSelectionForeground(Color acceleratorSelectionFg) { - acceleratorSelectionForeground = acceleratorSelectionFg; - } - - public static void setAcceleratorForeground(Color acceleratorFg) { - acceleratorForeground = acceleratorFg; - } - public static void paintArrowIcon(Graphics g, MenuItemLayoutHelper lh, MenuItemLayoutHelper.LayoutResult lr, Color foreground) { diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java index 19d77115025..4f18dc84f4a 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java @@ -1120,6 +1120,9 @@ public Component getListCellRendererComponent(JList list, Object value, int i if (showFileIcons) { setIcon(getFileChooser().getIcon((File)value)); } + + putClientProperty("html.disable", getFileChooser().getClientProperty("html.disable")); + return this; } } @@ -1137,6 +1140,9 @@ public Component getListCellRendererComponent(JList list, Object value, int i } else { setText(getFileChooser().getName((File)value) + "/"); } + + putClientProperty("html.disable", getFileChooser().getClientProperty("html.disable")); + return this; } } diff --git a/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java b/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java index c641e469972..29f6b1e91f0 100644 --- a/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java +++ b/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java @@ -41,6 +41,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamException; @@ -1567,33 +1568,19 @@ private void writeObject(ObjectOutputStream s) throws IOException { private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); - - String csName = (String) s.readObject(); - byte[] data = (byte[]) s.readObject(); - - int cspace = 0; // ColorSpace.CS_* constant if known - boolean isKnownPredefinedCS = false; - if (csName != null) { - isKnownPredefinedCS = true; - if (csName.equals("CS_sRGB")) { - cspace = ColorSpace.CS_sRGB; - } else if (csName.equals("CS_CIEXYZ")) { - cspace = ColorSpace.CS_CIEXYZ; - } else if (csName.equals("CS_PYCC")) { - cspace = ColorSpace.CS_PYCC; - } else if (csName.equals("CS_GRAY")) { - cspace = ColorSpace.CS_GRAY; - } else if (csName.equals("CS_LINEAR_RGB")) { - cspace = ColorSpace.CS_LINEAR_RGB; - } else { - isKnownPredefinedCS = false; - } - } - - if (isKnownPredefinedCS) { - resolvedDeserializedProfile = getInstance(cspace); - } else { - resolvedDeserializedProfile = getInstance(data); + try { + String csName = (String) s.readObject(); + byte[] data = (byte[]) s.readObject(); + resolvedDeserializedProfile = switch (csName) { + case "CS_sRGB" -> getInstance(ColorSpace.CS_sRGB); + case "CS_CIEXYZ" -> getInstance(ColorSpace.CS_CIEXYZ); + case "CS_PYCC" -> getInstance(ColorSpace.CS_PYCC); + case "CS_GRAY" -> getInstance(ColorSpace.CS_GRAY); + case "CS_LINEAR_RGB" -> getInstance(ColorSpace.CS_LINEAR_RGB); + case null, default -> getInstance(data); + }; + } catch (ClassCastException | IllegalArgumentException e) { + throw new InvalidObjectException("Invalid ICC Profile Data", e); } } diff --git a/src/java.desktop/share/classes/javax/swing/border/LineBorder.java b/src/java.desktop/share/classes/javax/swing/border/LineBorder.java index 9116731eaf0..7fcb644a261 100644 --- a/src/java.desktop/share/classes/javax/swing/border/LineBorder.java +++ b/src/java.desktop/share/classes/javax/swing/border/LineBorder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, 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 @@ -37,6 +37,8 @@ import com.sun.java.swing.SwingUtilities3; +import static sun.java2d.pipe.Region.clipRound; + /** * A class which implements a line border of arbitrary thickness * and of a single color. @@ -161,7 +163,7 @@ private void paintUnscaledBorder(Component c, Graphics g, Shape outer; Shape inner; - int offs = this.thickness * (int) scaleFactor; + int offs = clipRound(this.thickness * scaleFactor); int size = offs + offs; if (this.roundedCorners) { float arc = .2f * offs; diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java index 524f0337a8f..d361906b291 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java @@ -716,11 +716,10 @@ private void paintCheckIcon(Graphics g, MenuItemLayoutHelper lh, private void paintAccText(Graphics g, MenuItemLayoutHelper lh, MenuItemLayoutHelper.LayoutResult lr) { - SwingUtilities3.setDisabledForeground(disabledForeground); - SwingUtilities3.setAcceleratorSelectionForeground( - acceleratorSelectionForeground); - SwingUtilities3.setAcceleratorForeground(acceleratorForeground); - SwingUtilities3.paintAccText(g, lh, lr); + SwingUtilities3.paintAccText(g, lh, lr, + disabledForeground, + acceleratorSelectionForeground, + acceleratorForeground); } private void paintText(Graphics g, MenuItemLayoutHelper lh, diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java index a6d2a448186..8c7ac94b04e 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java @@ -452,78 +452,54 @@ protected void addMessageComponents(Container container, } else if ((nl = s.indexOf('\n')) >= 0) { nll = 1; } - if (s.contains("")) { - /* line break in html text is done by
tag - * and not by /n so it's incorrect to address newline - * same as non-html text. - * Text between tags are extracted - * and rendered as JLabel text - */ - int index1 = s.indexOf(""); - int index2 = s.indexOf(""); - String str = ""; - if (index2 >= 0) { - str = s.substring(index2 + "".length()); - s = s.substring(index1, index2 + + "".length()); + if (nl >= 0) { + // break up newlines + if (nl == 0) { + JPanel breakPanel = new JPanel() { + public Dimension getPreferredSize() { + Font f = getFont(); + + if (f != null) { + return new Dimension(1, f.getSize() + 2); + } + return new Dimension(0, 0); + } + }; + breakPanel.setName("OptionPane.break"); + addMessageComponents(container, cons, breakPanel, maxll, + true); + } else { + addMessageComponents(container, cons, s.substring(0, nl), + maxll, false); + } + // Prevent recursion of more than + // 200 successive newlines in a message + // and indicate message is truncated via ellipsis + if (recursionCount++ > 200) { + recursionCount = 0; + addMessageComponents(container, cons, new String("..."), + maxll, false); + return; } - JLabel label; - label = new JLabel(s, JLabel.LEADING); + addMessageComponents(container, cons, s.substring(nl + nll), maxll, + false); + + } else if (len > maxll) { + Container c = Box.createVerticalBox(); + c.setName("OptionPane.verticalBox"); + burstStringInto(c, s, maxll); + addMessageComponents(container, cons, c, maxll, true); + + } else { + JLabel label = new JLabel(); if (Boolean.TRUE.equals( - this.optionPane.getClientProperty("html.disable"))) { + optionPane.getClientProperty("html.disable"))) { label.putClientProperty("html.disable", true); } + label.setText(s); label.setName("OptionPane.label"); configureMessageLabel(label); addMessageComponents(container, cons, label, maxll, true); - if (!str.isEmpty()) { - addMessageComponents(container, cons, str, maxll, false); - } - } else { - if (nl >= 0) { - // break up newlines - if (nl == 0) { - JPanel breakPanel = new JPanel() { - public Dimension getPreferredSize() { - Font f = getFont(); - - if (f != null) { - return new Dimension(1, f.getSize() + 2); - } - return new Dimension(0, 0); - } - }; - breakPanel.setName("OptionPane.break"); - addMessageComponents(container, cons, breakPanel, maxll, - true); - } else { - addMessageComponents(container, cons, s.substring(0, nl), - maxll, false); - } - // Prevent recursion of more than - // 200 successive newlines in a message - // and indicate message is truncated via ellipsis - if (recursionCount++ > 200) { - recursionCount = 0; - addMessageComponents(container, cons, new String("..."), - maxll, false); - return; - } - addMessageComponents(container, cons, s.substring(nl + nll), maxll, - false); - - } else if (len > maxll) { - Container c = Box.createVerticalBox(); - c.setName("OptionPane.verticalBox"); - burstStringInto(c, s, maxll); - addMessageComponents(container, cons, c, maxll, true); - - } else { - JLabel label; - label = new JLabel(s, JLabel.LEADING); - label.setName("OptionPane.label"); - configureMessageLabel(label); - addMessageComponents(container, cons, label, maxll, true); - } } } } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPasswordFieldUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPasswordFieldUI.java index 6a78e2d6871..ce3b699b886 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPasswordFieldUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPasswordFieldUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, 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 @@ -91,23 +91,4 @@ protected void installDefaults() { public View create(Element elem) { return new PasswordView(elem); } - - /** - * Create the action map for Password Field. This map provides - * same actions for double mouse click and - * and for triple mouse click (see bug 4231444). - */ - - ActionMap createActionMap() { - ActionMap map = super.createActionMap(); - if (map.get(DefaultEditorKit.selectWordAction) != null) { - Action a = map.get(DefaultEditorKit.selectLineAction); - if (a != null) { - map.remove(DefaultEditorKit.selectWordAction); - map.put(DefaultEditorKit.selectWordAction, a); - } - } - return map; - } - } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java index ec0fbaf9928..094f5be68c5 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, 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 @@ -647,6 +647,22 @@ ActionMap createActionMap() { TransferHandler.getCopyAction()); map.put(TransferHandler.getPasteAction().getValue(Action.NAME), TransferHandler.getPasteAction()); + + if (getComponent() instanceof JPasswordField) { + // Edit the action map for Password Field. This map provides + // same actions for double mouse click and + // and for triple mouse click (see bugs 4231444, 8354646). + + if (map.get(DefaultEditorKit.selectWordAction) != null) { + map.remove(DefaultEditorKit.selectWordAction); + + Action a = map.get(DefaultEditorKit.selectLineAction); + if (a != null) { + map.put(DefaultEditorKit.selectWordAction, a); + } + } + } + return map; } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPasswordFieldUI.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPasswordFieldUI.java index 083a118c209..dbdeac3da1f 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPasswordFieldUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPasswordFieldUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, 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 @@ -108,19 +108,4 @@ public void paintBorder(SynthContext context, Graphics g, int x, int y, int w, int h) { context.getPainter().paintPasswordFieldBorder(context, g, x, y, w, h); } - - /** - * {@inheritDoc} - */ - @Override - protected void installKeyboardActions() { - super.installKeyboardActions(); - ActionMap map = SwingUtilities.getUIActionMap(getComponent()); - if (map != null && map.get(DefaultEditorKit.selectWordAction) != null) { - Action a = map.get(DefaultEditorKit.selectLineAction); - if (a != null) { - map.put(DefaultEditorKit.selectWordAction, a); - } - } - } } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthProgressBarUI.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthProgressBarUI.java index ee50976bbf4..a300110cced 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthProgressBarUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthProgressBarUI.java @@ -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 @@ -216,11 +216,9 @@ public void update(Graphics g, JComponent c) { SynthLookAndFeel.update(context, g); - if (((JProgressBar) c).isBorderPainted()) { - context.getPainter().paintProgressBarBackground(context, - g, 0, 0, c.getWidth(), c.getHeight(), - progressBar.getOrientation()); - } + context.getPainter().paintProgressBarBackground(context, + g, 0, 0, c.getWidth(), c.getHeight(), + progressBar.getOrientation()); paint(context, g); } diff --git a/src/java.desktop/share/classes/sun/awt/image/XbmImageDecoder.java b/src/java.desktop/share/classes/sun/awt/image/XbmImageDecoder.java index 03b36b3b819..bc025b87f3c 100644 --- a/src/java.desktop/share/classes/sun/awt/image/XbmImageDecoder.java +++ b/src/java.desktop/share/classes/sun/awt/image/XbmImageDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,13 +23,22 @@ * questions. */ -/*- +/* * Reads xbitmap format images into a DIBitmap structure. */ package sun.awt.image; -import java.io.*; -import java.awt.image.*; +import java.awt.image.ImageConsumer; +import java.awt.image.IndexColorModel; +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static java.lang.Math.multiplyExact; /** * Parse files of the form: @@ -50,6 +59,8 @@ public class XbmImageDecoder extends ImageDecoder { ImageConsumer.COMPLETESCANLINES | ImageConsumer.SINGLEPASS | ImageConsumer.SINGLEFRAME); + private static final int MAX_XBM_SIZE = 16384; + private static final int HEADER_SCAN_LIMIT = 100; public XbmImageDecoder(InputStreamImageSource src, InputStream is) { super(src, is); @@ -72,107 +83,155 @@ private static void error(String s1) throws ImageFormatException { * produce an image from the stream. */ public void produceImage() throws IOException, ImageFormatException { - char[] nm = new char[80]; - int c; - int i = 0; - int state = 0; int H = 0; int W = 0; int x = 0; int y = 0; - boolean start = true; + int n = 0; + int state = 0; byte[] raster = null; IndexColorModel model = null; - while (!aborted && (c = input.read()) != -1) { - if ('a' <= c && c <= 'z' || - 'A' <= c && c <= 'Z' || - '0' <= c && c <= '9' || c == '#' || c == '_') { - if (i < 78) - nm[i++] = (char) c; - } else if (i > 0) { - int nc = i; - i = 0; - if (start) { - if (nc != 7 || - nm[0] != '#' || - nm[1] != 'd' || - nm[2] != 'e' || - nm[3] != 'f' || - nm[4] != 'i' || - nm[5] != 'n' || - nm[6] != 'e') - { - error("Not an XBM file"); + + String matchRegex = "\\s*(0[xX])?((?:(?!,|\\};).)+)(,|\\};)"; + String replaceRegex = "0[xX]|,|\\s+|\\};"; + + String line; + int lineNum = 0; + + try (BufferedReader br = new BufferedReader(new InputStreamReader(input))) { + // loop to process XBM header - width, height and create raster + while (!aborted && (line = br.readLine()) != null + && lineNum <= HEADER_SCAN_LIMIT) { + lineNum++; + // process #define stmts + if (line.trim().startsWith("#define")) { + String[] token = line.split("\\s+"); + if (token.length != 3) { + error("Error while parsing define statement"); + } + try { + if (!token[2].isBlank() && state == 0) { + if (token[1].endsWith("th")) { + W = Integer.parseInt(token[2]); + } else if (token[1].endsWith("t")) { + H = Integer.parseInt(token[2]); + } + state = 1; // after first dimension is set + } else if (!token[2].isBlank() && state == 1) { + if (token[1].endsWith("th")) { + W = Integer.parseInt(token[2]); + } else if (token[1].endsWith("t")) { + H = Integer.parseInt(token[2]); + } + state = 2; // after second dimension is set + } + } catch (NumberFormatException nfe) { + // parseInt() can throw NFE + error("Error while parsing width or height."); } - start = false; } - if (nm[nc - 1] == 'h') - state = 1; /* expecting width */ - else if (nm[nc - 1] == 't' && nc > 1 && nm[nc - 2] == 'h') - state = 2; /* expecting height */ - else if (nc > 2 && state < 0 && nm[0] == '0' && nm[1] == 'x') { - int n = 0; - for (int p = 2; p < nc; p++) { - c = nm[p]; - if ('0' <= c && c <= '9') - c = c - '0'; - else if ('A' <= c && c <= 'Z') - c = c - 'A' + 10; - else if ('a' <= c && c <= 'z') - c = c - 'a' + 10; - else - c = 0; - n = n * 16 + c; + + if (state == 2) { + if (W <= 0 || H <= 0) { + error("Invalid values for width or height."); } - for (int mask = 1; mask <= 0x80; mask <<= 1) { - if (x < W) { - if ((n & mask) != 0) - raster[x] = 1; - else - raster[x] = 0; - } - x++; + if (multiplyExact(W, H) > MAX_XBM_SIZE) { + error("Large XBM file size." + + " Maximum allowed size: " + MAX_XBM_SIZE); } - if (x >= W) { - if (setPixels(0, y, W, 1, model, raster, 0, W) <= 0) { - return; - } - x = 0; - if (y++ >= H) { - break; - } + model = new IndexColorModel(8, 2, XbmColormap, + 0, false, 0); + setDimensions(W, H); + setColorModel(model); + setHints(XbmHints); + headerComplete(); + raster = new byte[W]; + state = 3; + break; + } + } + + if (state != 3) { + error("Width or Height of XBM file not defined"); + } + + boolean contFlag = false; + StringBuilder sb = new StringBuilder(); + + // loop to process image data + while (!aborted && (line = br.readLine()) != null) { + lineNum++; + + if (!contFlag) { + if (line.contains("[]")) { + contFlag = true; + } else { + continue; } + } + + int end = line.indexOf(';'); + if (end >= 0) { + sb.append(line, 0, end + 1); + break; } else { - int n = 0; - for (int p = 0; p < nc; p++) - if ('0' <= (c = nm[p]) && c <= '9') - n = n * 10 + c - '0'; - else { - n = -1; - break; - } - if (n > 0 && state > 0) { - if (state == 1) - W = n; + sb.append(line).append(System.lineSeparator()); + } + } + + String resultLine = sb.toString(); + int cutOffIndex = resultLine.indexOf('{'); + resultLine = resultLine.substring(cutOffIndex + 1); + + Matcher matcher = Pattern.compile(matchRegex).matcher(resultLine); + while (matcher.find()) { + if (y >= H) { + error("Scan size of XBM file exceeds" + + " the defined width x height"); + } + + int startIndex = matcher.start(); + int endIndex = matcher.end(); + String hexByte = resultLine.substring(startIndex, endIndex); + hexByte = hexByte.replaceAll("^\\s+", ""); + + if (!(hexByte.startsWith("0x") + || hexByte.startsWith("0X"))) { + error("Invalid hexadecimal number at Ln#:" + lineNum + + " Col#:" + (startIndex + 1)); + } + hexByte = hexByte.replaceAll(replaceRegex, ""); + if (hexByte.length() != 2) { + error("Invalid hexadecimal number at Ln#:" + lineNum + + " Col#:" + (startIndex + 1)); + } + + try { + n = Integer.parseInt(hexByte, 16); + } catch (NumberFormatException nfe) { + error("Error parsing hexadecimal at Ln#:" + lineNum + + " Col#:" + (startIndex + 1)); + } + for (int mask = 1; mask <= 0x80; mask <<= 1) { + if (x < W) { + if ((n & mask) != 0) + raster[x] = 1; else - H = n; - if (W == 0 || H == 0) - state = 0; - else { - model = new IndexColorModel(8, 2, XbmColormap, - 0, false, 0); - setDimensions(W, H); - setColorModel(model); - setHints(XbmHints); - headerComplete(); - raster = new byte[W]; - state = -1; - } + raster[x] = 0; + } + x++; + } + + if (x >= W) { + int result = setPixels(0, y, W, 1, model, raster, 0, W); + if (result <= 0) { + error("Unexpected error occurred during setPixel()"); } + x = 0; + y++; } } + imageComplete(ImageConsumer.STATICIMAGEDONE, true); } - input.close(); - imageComplete(ImageConsumer.STATICIMAGEDONE, true); } } diff --git a/src/java.desktop/share/classes/sun/font/CompositeFont.java b/src/java.desktop/share/classes/sun/font/CompositeFont.java index bc136d75cfa..8feb96a2948 100644 --- a/src/java.desktop/share/classes/sun/font/CompositeFont.java +++ b/src/java.desktop/share/classes/sun/font/CompositeFont.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,7 +88,7 @@ public CompositeFont(String name, String[] compFileNames, /* * See if this is a windows locale which has a system EUDC font. - * If so add it as the final fallback component of the composite. + * If so add it as the first fallback component of the composite. * The caller could be responsible for this, but for now it seems * better that it is handled internally to the CompositeFont class. */ @@ -114,8 +114,8 @@ public CompositeFont(String name, String[] compFileNames, components[msCnt] = fm.getEUDCFont(); deferredInitialisation = new boolean[numSlots]; if (defer) { - for (int i=0; i clusterExtraGlyphs))) { + (indices[gx] <= maxIndex))) { - ++clusterExtraGlyphs; // have an extra glyph in this cluster if (DEBUG) { System.err.println("gp=" +gp +" adv=" + glyphinfo[gp + advx] + - " gx="+ gx+ " i[gx]="+indices[gx] + - " clusterExtraGlyphs="+clusterExtraGlyphs); + " gx="+ gx+ " i[gx]="+indices[gx]); } // adjust advance only if new glyph has non-zero advance diff --git a/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java b/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java index 1bebf379997..9815d657eee 100644 --- a/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java +++ b/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, 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 @@ -1898,14 +1898,16 @@ public boolean hitClip(int x, int y, int width, int height) { protected void validateCompClip() { int origClipState = clipState; - if (usrClip == null) { + final Shape clip = usrClip; + + if (clip == null) { clipState = CLIP_DEVICE; clipRegion = devClip; - } else if (usrClip instanceof Rectangle2D) { + } else if (clip instanceof Rectangle2D rect2d) { clipState = CLIP_RECTANGULAR; - clipRegion = devClip.getIntersection((Rectangle2D) usrClip); + clipRegion = devClip.getIntersection(rect2d); } else { - PathIterator cpi = usrClip.getPathIterator(null); + PathIterator cpi = clip.getPathIterator(null); int[] box = new int[4]; ShapeSpanIterator sr = LoopPipe.getFillSSI(this); try { diff --git a/src/java.desktop/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java b/src/java.desktop/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java index cfe488fee72..663e11ff172 100644 --- a/src/java.desktop/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java +++ b/src/java.desktop/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2023, 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 @@ -125,7 +125,9 @@ private LCMSImageLayout() { static LCMSImageLayout createImageLayout(BufferedImage image) { LCMSImageLayout l = new LCMSImageLayout(); - switch (image.getType()) { + Raster raster = image.getRaster(); + int type = image.getType(); + switch (type) { case BufferedImage.TYPE_INT_RGB, BufferedImage.TYPE_INT_ARGB: l.pixelType = PT_ARGB_8 ^ SWAP_ENDIAN; break; @@ -164,7 +166,7 @@ static LCMSImageLayout createImageLayout(BufferedImage image) { return null; } } - return createImageLayout(image.getRaster(), cm); + return createImageLayout(raster, cm); } return null; } @@ -172,11 +174,13 @@ static LCMSImageLayout createImageLayout(BufferedImage image) { l.width = image.getWidth(); l.height = image.getHeight(); - switch (image.getType()) { + switch (type) { case BufferedImage.TYPE_INT_RGB, BufferedImage.TYPE_INT_ARGB, BufferedImage.TYPE_INT_ARGB_PRE, BufferedImage.TYPE_INT_BGR -> { - var intRaster = (IntegerComponentRaster) image.getRaster(); + if (!(raster instanceof IntegerComponentRaster intRaster)) { + return null; + } l.nextRowOffset = safeMult(4, intRaster.getScanlineStride()); l.nextPixelOffset = safeMult(4, intRaster.getPixelStride()); l.offset = safeMult(4, intRaster.getDataOffset(0)); @@ -188,7 +192,9 @@ static LCMSImageLayout createImageLayout(BufferedImage image) { BufferedImage.TYPE_4BYTE_ABGR, BufferedImage.TYPE_4BYTE_ABGR_PRE -> { - var byteRaster = (ByteComponentRaster) image.getRaster(); + if (!(raster instanceof ByteComponentRaster byteRaster)) { + return null; + } l.nextRowOffset = byteRaster.getScanlineStride(); l.nextPixelOffset = byteRaster.getPixelStride(); int firstBand = byteRaster.getSampleModel().getNumBands() - 1; @@ -198,7 +204,9 @@ static LCMSImageLayout createImageLayout(BufferedImage image) { l.dataType = DT_BYTE; } case BufferedImage.TYPE_USHORT_GRAY -> { - var shortRaster = (ShortComponentRaster) image.getRaster(); + if (!(raster instanceof ShortComponentRaster shortRaster)) { + return null; + } l.nextRowOffset = safeMult(2, shortRaster.getScanlineStride()); l.nextPixelOffset = safeMult(2, shortRaster.getPixelStride()); l.offset = safeMult(2, shortRaster.getDataOffset(0)); diff --git a/src/java.desktop/share/classes/sun/java2d/pipe/SpanClipRenderer.java b/src/java.desktop/share/classes/sun/java2d/pipe/SpanClipRenderer.java index 62d1f119f33..69c4954cac4 100644 --- a/src/java.desktop/share/classes/sun/java2d/pipe/SpanClipRenderer.java +++ b/src/java.desktop/share/classes/sun/java2d/pipe/SpanClipRenderer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,8 @@ import java.awt.Rectangle; import java.awt.Shape; + +import sun.java2d.InvalidPipeException; import sun.java2d.SunGraphics2D; /** @@ -67,7 +69,9 @@ public SCRcontext(RegionIterator ri, Object outctx) { public Object startSequence(SunGraphics2D sg, Shape s, Rectangle devR, int[] abox) { RegionIterator ri = sg.clipRegion.getIterator(); - + if (ri.region.isRectangular()) { + throw new InvalidPipeException("Invalid clip data"); + } return new SCRcontext(ri, outpipe.startSequence(sg, s, devR, abox)); } diff --git a/src/java.desktop/share/legal/libpng.md b/src/java.desktop/share/legal/libpng.md index d43ccf2e8e4..80d12248ec4 100644 --- a/src/java.desktop/share/legal/libpng.md +++ b/src/java.desktop/share/legal/libpng.md @@ -1,4 +1,4 @@ -## libpng v1.6.47 +## libpng v1.6.54 ### libpng License
@@ -9,8 +9,8 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
 PNG Reference Library License version 2
 ---------------------------------------
 
-Copyright (c) 1995-2025 The PNG Reference Library Authors.
-Copyright (C) 2018-2025 Cosmin Truta
+Copyright (C) 1995-2026 The PNG Reference Library Authors.
+Copyright (C) 2018-2026 Cosmin Truta
 Copyright (C) 1998-2018 Glenn Randers-Pehrson
 Copyright (C) 1996-1997 Andreas Dilger
 Copyright (C) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -158,6 +158,7 @@ This is the list of PNG Reference Library ("libpng") Contributing
 Authors, for copyright and licensing purposes.
 
  * Adam Richter
+ * Alexander Smorkalov
  * Andreas Dilger
  * Chris Blume
  * Cosmin Truta
@@ -173,17 +174,20 @@ Authors, for copyright and licensing purposes.
  * Lucas Chollet
  * Magnus Holmgren
  * Mandar Sahastrabuddhe
+ * Manfred Schlaegl
  * Mans Rullgard
  * Matt Sarett
  * Mike Klein
  * Pascal Massimino
  * Paul Schmidt
+ * Petr Simecek
  * Philippe Antoine
  * Qiang Zhou
  * Sam Bushell
  * Samuel Williams
  * Simon-Pierre Cadieux
  * Tim Wegner
+ * Tobias Stoeckmann
  * Tom Lane
  * Tom Tanner
  * Vadim Barkov
@@ -193,8 +197,9 @@ Authors, for copyright and licensing purposes.
     - Zixu Wang (王子旭)
  * Arm Holdings
     - Richard Townsend
- * Google Inc.
+ * Google LLC
     - Dan Field
+    - Dragoș Tiselice
     - Leon Scroggins III
     - Matt Sarett
     - Mike Klein
@@ -204,6 +209,10 @@ Authors, for copyright and licensing purposes.
     - GuXiWei (顾希伟)
     - JinBo (金波)
     - ZhangLixia (张利霞)
+ * Samsung Group
+    - Filip Wasil
+ * SpacemiT Hangzhou Technology, Co.
+    - Liang Junzhao (梁俊钊)
 
 The build projects, the build scripts, the test scripts, and other
 files in the "projects", "scripts" and "tests" directories, have
@@ -214,3 +223,4 @@ of the tools-generated files that are distributed with libpng, have
 other copyright owners, and are released under other open source
 licenses.
 ```
+
diff --git a/src/java.desktop/share/native/common/java2d/opengl/OGLContext.c b/src/java.desktop/share/native/common/java2d/opengl/OGLContext.c
index 89c3af32b1d..ce294e9b4aa 100644
--- a/src/java.desktop/share/native/common/java2d/opengl/OGLContext.c
+++ b/src/java.desktop/share/native/common/java2d/opengl/OGLContext.c
@@ -484,6 +484,7 @@ OGLContext_SetTransform(OGLContext *oglc,
     if (oglc->xformMatrix == NULL) {
         size_t arrsize = 16 * sizeof(GLdouble);
         oglc->xformMatrix = (GLdouble *)malloc(arrsize);
+        RETURN_IF_NULL(oglc->xformMatrix);
         memset(oglc->xformMatrix, 0, arrsize);
         oglc->xformMatrix[10] = 1.0;
         oglc->xformMatrix[15] = 1.0;
diff --git a/src/java.desktop/share/native/libmlib_image/mlib_ImageConvMxN_Fp.c b/src/java.desktop/share/native/libmlib_image/mlib_ImageConvMxN_Fp.c
index fa9a186d6d7..bc2df9b0b1a 100644
--- a/src/java.desktop/share/native/libmlib_image/mlib_ImageConvMxN_Fp.c
+++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageConvMxN_Fp.c
@@ -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
@@ -76,6 +76,7 @@
 #include "mlib_ImageCheck.h"
 #include "mlib_SysMath.h"
 #include "mlib_ImageConv.h"
+#include "safe_math.h"
 
 /***************************************************************/
 static void mlib_ImageConvMxNMulAdd_F32(mlib_f32       *dst,
@@ -272,6 +273,9 @@ mlib_status mlib_convMxNext_f32(mlib_image       *dst,
   mlib_s32 nch = mlib_ImageGetChannels(dst);
   mlib_s32 i, j, j1, k;
 
+  if (!SAFE_TO_MULT(3, wid_e) || !SAFE_TO_ADD(3 * wid_e, m)) {
+    return MLIB_FAILURE;
+  }
   if (3 * wid_e + m > 1024) {
     dsa = mlib_malloc((3 * wid_e + m) * sizeof(mlib_d64));
 
@@ -629,6 +633,9 @@ mlib_status mlib_convMxNext_d64(mlib_image       *dst,
   mlib_s32 nch = mlib_ImageGetChannels(dst);
   mlib_s32 i, j, j1, k;
 
+  if (!SAFE_TO_MULT(3, wid_e) || !SAFE_TO_ADD(3 * wid_e, m)) {
+    return MLIB_FAILURE;
+  }
   if (3 * wid_e + m > 1024) {
     dsa = mlib_malloc((3 * wid_e + m) * sizeof(mlib_d64));
 
diff --git a/src/java.desktop/share/native/libmlib_image/mlib_ImageConvMxN_ext.c b/src/java.desktop/share/native/libmlib_image/mlib_ImageConvMxN_ext.c
index ee15935dcfe..5869b0a54af 100644
--- a/src/java.desktop/share/native/libmlib_image/mlib_ImageConvMxN_ext.c
+++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageConvMxN_ext.c
@@ -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
@@ -82,6 +82,7 @@
 
 #include "mlib_image.h"
 #include "mlib_ImageConv.h"
+#include "safe_math.h"
 
 /***************************************************************/
 static void mlib_ImageConvMxNMulAdd_S32(mlib_d64       *dst,
@@ -229,6 +230,9 @@ mlib_status mlib_convMxNext_s32(mlib_image       *dst,
 
   /* internal buffer */
 
+  if (!SAFE_TO_MULT(3, wid_e) || !SAFE_TO_ADD(3 * wid_e, m)) {
+    return MLIB_FAILURE;
+  }
   if (3 * wid_e + m > 1024) {
     dsa = mlib_malloc((3 * wid_e + m) * sizeof(mlib_d64));
 
diff --git a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_16ext.c b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_16ext.c
index 57486b1cae5..00469d25719 100644
--- a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_16ext.c
+++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_16ext.c
@@ -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
@@ -33,6 +33,7 @@
 #include "mlib_image.h"
 #include "mlib_ImageConv.h"
 #include "mlib_c_ImageConv.h"
+#include "safe_math.h"
 
 /*
  * This define switches between functions of different data types
@@ -260,8 +261,14 @@ static mlib_status mlib_ImageConv1xN_ext(mlib_image       *dst,
   if (max_hsize > hgt) max_hsize = hgt;
 
   shgt = hgt + (n - 1);
+  if (!SAFE_TO_ADD(max_hsize, (n - 1))) {
+    return MLIB_FAILURE;
+  }
   smax_hsize = max_hsize + (n - 1);
 
+  if (!SAFE_TO_ADD(smax_hsize, 1) || !SAFE_TO_MULT(2, (smax_hsize + 1))) {
+    return MLIB_FAILURE;
+  }
   bsize = 2 * (smax_hsize + 1);
 
   if (bsize > BUFF_SIZE) {
@@ -509,8 +516,16 @@ mlib_status CONV_FUNC_MxN
     FREE_AND_RETURN_STATUS;
   }
 
+  if (!SAFE_TO_ADD(wid, (m - 1))) {
+    status = MLIB_FAILURE;
+    FREE_AND_RETURN_STATUS;
+  }
   swid = wid + (m - 1);
 
+  if (!SAFE_TO_MULT((n + 3), swid)) {
+    status = MLIB_FAILURE;
+    FREE_AND_RETURN_STATUS;
+  }
   bsize = (n + 3)*swid;
 
   if ((bsize > BUFF_SIZE) || (n > MAX_N)) {
@@ -919,8 +934,14 @@ mlib_status CONV_FUNC_MxN_I
   chan1 = nchannel;
   chan2 = chan1 + chan1;
 
+  if (!SAFE_TO_ADD(wid, (m - 1))) {
+    return MLIB_FAILURE;
+  }
   swid = wid + (m - 1);
 
+  if (!SAFE_TO_MULT((n + 2), swid)) {
+    return MLIB_FAILURE;
+  }
   bsize = (n + 2)*swid;
 
   if ((bsize > BUFF_SIZE) || (n > MAX_N)) {
diff --git a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_16nw.c b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_16nw.c
index 3b6985b7876..2e035d12453 100644
--- a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_16nw.c
+++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_16nw.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@
 
 #include "mlib_image.h"
 #include "mlib_c_ImageConv.h"
+#include "safe_math.h"
 
 /*
   This define switches between functions of different data types
@@ -466,6 +467,10 @@ mlib_status CONV_FUNC(MxN)(mlib_image       *dst,
     FREE_AND_RETURN_STATUS;
   }
 
+  if (!SAFE_TO_MULT((n + 3), wid)) {
+    status = MLIB_FAILURE;
+    FREE_AND_RETURN_STATUS;
+  }
   bsize = (n + 3)*wid;
 
   if ((bsize > BUFF_SIZE) || (n > MAX_N)) {
diff --git a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_32nw.c b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_32nw.c
index 380ed044878..bb264d9dcd2 100644
--- a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_32nw.c
+++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_32nw.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@
 
 #include "mlib_image.h"
 #include "mlib_ImageConv.h"
+#include "safe_math.h"
 
 /***************************************************************/
 #define CACHE_SIZE (64*1024)
@@ -335,6 +336,10 @@ mlib_status CONV_FUNC(MxN)(mlib_image       *dst,
     FREE_AND_RETURN_STATUS;
   }
 
+  if (!SAFE_TO_MULT((n + 2), wid)) {
+    status = MLIB_FAILURE;
+    FREE_AND_RETURN_STATUS;
+  }
   bsize = (n + 2)*wid;
 
   if ((bsize > BUFF_SIZE) || (n > MAX_N)) {
diff --git a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_8ext.c b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_8ext.c
index c8b58e6f138..136d5a2b814 100644
--- a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_8ext.c
+++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_8ext.c
@@ -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
@@ -33,6 +33,7 @@
 #include "mlib_image.h"
 #include "mlib_ImageConv.h"
 #include "mlib_c_ImageConv.h"
+#include "safe_math.h"
 
 /*
  * This define switches between functions of different data types
@@ -245,8 +246,14 @@ static mlib_status mlib_ImageConv1xN_ext(mlib_image       *dst,
   if (max_hsize > hgt) max_hsize = hgt;
 
   shgt = hgt + (n - 1);
+  if (!SAFE_TO_ADD(max_hsize, (n - 1))) {
+    return MLIB_FAILURE;
+  }
   smax_hsize = max_hsize + (n - 1);
 
+  if (!SAFE_TO_ADD(smax_hsize, 1) || !SAFE_TO_MULT(2, (smax_hsize + 1))) {
+    return MLIB_FAILURE;
+  }
   bsize = 2 * (smax_hsize + 1);
 
   if (bsize > BUFF_SIZE) {
@@ -494,8 +501,16 @@ mlib_status CONV_FUNC_MxN
     FREE_AND_RETURN_STATUS;
   }
 
+  if (!SAFE_TO_ADD(wid, (m - 1))) {
+    status = MLIB_FAILURE;
+    FREE_AND_RETURN_STATUS;
+  }
   swid = wid + (m - 1);
 
+  if (!SAFE_TO_MULT((n + 3), swid)) {
+    status = MLIB_FAILURE;
+    FREE_AND_RETURN_STATUS;
+  }
   bsize = (n + 3)*swid;
 
   if ((bsize > BUFF_SIZE) || (n > MAX_N)) {
@@ -904,8 +919,14 @@ mlib_status CONV_FUNC_MxN_I
   chan1 = nchannel;
   chan2 = chan1 + chan1;
 
+  if (!SAFE_TO_ADD(wid, (m - 1))) {
+    return MLIB_FAILURE;
+  }
   swid = wid + (m - 1);
 
+  if (!SAFE_TO_MULT((n + 2), swid)) {
+    return MLIB_FAILURE;
+  }
   bsize = (n + 2)*swid;
 
   if ((bsize > BUFF_SIZE) || (n > MAX_N)) {
diff --git a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_8nw.c b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_8nw.c
index f65fda45c58..c144404b0f4 100644
--- a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_8nw.c
+++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_8nw.c
@@ -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
@@ -33,6 +33,7 @@
 #include "mlib_image.h"
 #include "mlib_ImageConv.h"
 #include "mlib_c_ImageConv.h"
+#include "safe_math.h"
 
 /*
   This define switches between functions of different data types
@@ -467,6 +468,10 @@ mlib_status CONV_FUNC(MxN)(mlib_image       *dst,
     FREE_AND_RETURN_STATUS;
   }
 
+  if (!SAFE_TO_MULT((n + 3), wid)) {
+    status = MLIB_FAILURE;
+    FREE_AND_RETURN_STATUS;
+  }
   bsize = (n + 3)*wid;
 
   if ((bsize > BUFF_SIZE) || (n > MAX_N)) {
diff --git a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_u16ext.c b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_u16ext.c
index b2757979a84..81a06f2fc28 100644
--- a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_u16ext.c
+++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_u16ext.c
@@ -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
@@ -33,6 +33,7 @@
 #include "mlib_image.h"
 #include "mlib_ImageConv.h"
 #include "mlib_c_ImageConv.h"
+#include "safe_math.h"
 
 /*
  * This define switches between functions of different data types
@@ -270,8 +271,14 @@ static mlib_status mlib_ImageConv1xN_ext(mlib_image       *dst,
   if (max_hsize > hgt) max_hsize = hgt;
 
   shgt = hgt + (n - 1);
+  if (!SAFE_TO_ADD(max_hsize, (n - 1))) {
+    return MLIB_FAILURE;
+  }
   smax_hsize = max_hsize + (n - 1);
 
+  if (!SAFE_TO_ADD(smax_hsize, 1) || !SAFE_TO_MULT(2, (smax_hsize + 1))) {
+    return MLIB_FAILURE;
+  }
   bsize = 2 * (smax_hsize + 1);
 
   if (bsize > BUFF_SIZE) {
@@ -519,8 +526,16 @@ mlib_status CONV_FUNC_MxN
     FREE_AND_RETURN_STATUS;
   }
 
+  if (!SAFE_TO_ADD(wid, (m - 1))) {
+    status = MLIB_FAILURE;
+    FREE_AND_RETURN_STATUS;
+  }
   swid = wid + (m - 1);
 
+  if (!SAFE_TO_MULT((n + 3), swid)) {
+    status = MLIB_FAILURE;
+    FREE_AND_RETURN_STATUS;
+  }
   bsize = (n + 3)*swid;
 
   if ((bsize > BUFF_SIZE) || (n > MAX_N)) {
@@ -927,8 +942,14 @@ mlib_status CONV_FUNC_MxN_I
   chan1 = nchannel;
   chan2 = chan1 + chan1;
 
+  if (!SAFE_TO_ADD(wid, (m - 1))) {
+    return MLIB_FAILURE;
+  }
   swid = wid + (m - 1);
 
+  if (!SAFE_TO_MULT((n + 2), swid)) {
+    return MLIB_FAILURE;
+  }
   bsize = (n + 2)*swid;
 
   if ((bsize > BUFF_SIZE) || (n > MAX_N)) {
diff --git a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_u16nw.c b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_u16nw.c
index a3234cf8959..49412c7d7ef 100644
--- a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_u16nw.c
+++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_u16nw.c
@@ -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
@@ -32,6 +32,7 @@
 
 #include "mlib_image.h"
 #include "mlib_c_ImageConv.h"
+#include "safe_math.h"
 
 /*
   This define switches between functions of different data types
@@ -466,6 +467,10 @@ mlib_status CONV_FUNC(MxN)(mlib_image       *dst,
     FREE_AND_RETURN_STATUS;
   }
 
+  if (!SAFE_TO_MULT((n + 3), wid)) {
+    status = MLIB_FAILURE;
+    FREE_AND_RETURN_STATUS;
+  }
   bsize = (n + 3)*wid;
 
   if ((bsize > BUFF_SIZE) || (n > MAX_N)) {
diff --git a/src/java.desktop/share/native/libmlib_image/mlib_ImageLookUp_Bit.c b/src/java.desktop/share/native/libmlib_image/mlib_ImageLookUp_Bit.c
index 2e77c20aa57..cfd5e3e671e 100644
--- a/src/java.desktop/share/native/libmlib_image/mlib_ImageLookUp_Bit.c
+++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageLookUp_Bit.c
@@ -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
@@ -50,6 +50,7 @@
 
 #include "mlib_image.h"
 #include "mlib_ImageLookUp.h"
+#include "safe_math.h"
 
 /***************************************************************/
 #define MAX_WIDTH  512
@@ -302,6 +303,9 @@ mlib_status mlib_ImageLookUp_Bit_U8_2(const mlib_u8 *src,
   mlib_u8  *buff = (mlib_u8*)buff_lcl, *buffs;
   mlib_u32 val0, val1;
 
+  if (!SAFE_TO_MULT(xsize, 2)) {
+    return MLIB_FAILURE;
+  }
   size = xsize * 2;
 
   if (size > MAX_WIDTH) {
@@ -440,6 +444,9 @@ mlib_status mlib_ImageLookUp_Bit_U8_3(const mlib_u8 *src,
   mlib_u8  *buff = (mlib_u8*)buff_lcl, *buffs;
   mlib_u32 l0, h0, v0, l1, h1, v1, l2, h2, v2;
 
+  if (!SAFE_TO_MULT(3, xsize)) {
+    return MLIB_FAILURE;
+  }
   size = 3 * xsize;
 
   if (size > MAX_WIDTH) {
@@ -583,6 +590,9 @@ mlib_status mlib_ImageLookUp_Bit_U8_4(const mlib_u8 *src,
   mlib_u8  *buff = (mlib_u8*)buff_lcl, *buffs;
   mlib_u32 l, h;
 
+  if (!SAFE_TO_MULT(xsize, 4)) {
+    return MLIB_FAILURE;
+  }
   size = xsize * 4;
 
   if (size > MAX_WIDTH) {
diff --git a/src/java.desktop/share/native/libmlib_image/mlib_ImageScanPoly.c b/src/java.desktop/share/native/libmlib_image/mlib_ImageScanPoly.c
index a6f4cfdd36e..72adc212af6 100644
--- a/src/java.desktop/share/native/libmlib_image/mlib_ImageScanPoly.c
+++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageScanPoly.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2024, 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
@@ -101,6 +101,11 @@ mlib_status mlib_AffineEdges(mlib_affine_param *param,
     return MLIB_FAILURE;
   }
 
+  int intSize = sizeof(mlib_s32);
+  if (!SAFE_TO_MULT(dstHeight, intSize) ||
+      !SAFE_TO_ADD(dstHeight * intSize, 7)) {
+    return MLIB_FAILURE;
+  }
   bsize0 = (dstHeight * sizeof(mlib_s32) + 7) & ~7;
 
   if (lineAddr == NULL) {
@@ -109,6 +114,10 @@ mlib_status mlib_AffineEdges(mlib_affine_param *param,
 
   param->buff_malloc = NULL;
 
+  if (!SAFE_TO_MULT(4, bsize0) || !SAFE_TO_ADD(4 * bsize0, bsize1)) {
+    return MLIB_FAILURE;
+  }
+
   if ((4 * bsize0 + bsize1) > buff_size) {
     buff = param->buff_malloc = mlib_malloc(4 * bsize0 + bsize1);
 
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES b/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES
index 834b5e19277..3bb1baecd23 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES
@@ -6251,6 +6251,86 @@ Version 1.6.47 [February 18, 2025]
     colorspace precedence rules, due to pre-existing colorspace checks.
     (Reported by Bob Friesenhahn; fixed by John Bowler)
 
+Version 1.6.48 [April 30, 2025]
+  Fixed the floating-point version of the mDCv setter `png_set_mDCv`.
+    (Reported by Mohit Bakshi; fixed by John Bowler)
+  Added #error directives to discourage the inclusion of private
+    libpng implementation header files in PNG-supporting applications.
+  Added the CMake build option `PNG_LIBCONF_HEADER`, to be used as an
+    alternative to `DFA_XTRA`.
+  Removed the Travis CI configuration files, with heartfelt thanks for
+    their generous support of our project over the past five years!
+
+Version 1.6.49 [June 12, 2025]
+  Added SIMD-optimized code for the RISC-V Vector Extension (RVV).
+    (Contributed by Manfred Schlaegl, Dragos Tiselice and Filip Wasil)
+  Added various fixes and improvements to the build scripts and to
+    the sample code.
+
+Version 1.6.50 [July 1, 2025]
+  Improved the detection of the RVV Extension on the RISC-V platform.
+    (Contributed by Filip Wasil)
+  Replaced inline ASM with C intrinsics in the RVV code.
+    (Contributed by Filip Wasil)
+  Fixed a decoder defect in which unknown chunks trailing IDAT, set
+    to go through the unknown chunk handler, incorrectly triggered
+    out-of-place IEND errors.
+    (Contributed by John Bowler)
+  Fixed the CMake file for cross-platform builds that require `libm`.
+
+Version 1.6.51 [November 21, 2025]
+  Fixed CVE-2025-64505 (moderate severity):
+    Heap buffer overflow in `png_do_quantize` via malformed palette index.
+    (Reported by Samsung; analyzed by Fabio Gritti.)
+  Fixed CVE-2025-64506 (moderate severity):
+    Heap buffer over-read in `png_write_image_8bit` with 8-bit input and
+    `convert_to_8bit` enabled.
+    (Reported by Samsung and ;
+    analyzed by Fabio Gritti.)
+  Fixed CVE-2025-64720 (high severity):
+    Buffer overflow in `png_image_read_composite` via incorrect palette
+    premultiplication.
+    (Reported by Samsung; analyzed by John Bowler.)
+  Fixed CVE-2025-65018 (high severity):
+    Heap buffer overflow in `png_combine_row` triggered via
+    `png_image_finish_read`.
+    (Reported by .)
+  Fixed a memory leak in `png_set_quantize`.
+    (Reported by Samsung; analyzed by Fabio Gritti.)
+  Removed the experimental and incomplete ERROR_NUMBERS code.
+    (Contributed by Tobias Stoeckmann.)
+  Improved the RISC-V vector extension support; required RVV 1.0 or newer.
+    (Contributed by Filip Wasil.)
+  Added GitHub Actions workflows for automated testing.
+  Performed various refactorings and cleanups.
+
+Version 1.6.52 [December 3, 2025]
+  Fixed CVE-2025-66293 (high severity):
+    Out-of-bounds read in `png_image_read_composite`.
+    (Reported by flyfish101 .)
+  Fixed the Paeth filter handling in the RISC-V RVV implementation.
+    (Reported by Filip Wasil; fixed by Liang Junzhao.)
+  Improved the performance of the RISC-V RVV implementation.
+    (Contributed by Liang Junzhao.)
+  Added allocation failure fuzzing to oss-fuzz.
+    (Contributed by Philippe Antoine.)
+
+Version 1.6.53 [December 5, 2025]
+  Fixed a build failure on RISC-V RVV caused by a misspelled intrinsic.
+    (Contributed by Alexander Smorkalov.)
+  Fixed a build failure with CMake 4.1 or newer, on Windows, when using
+    Visual C++ without MASM installed.
+
+Version 1.6.54 [January 12, 2026]
+  Fixed CVE-2026-22695 (medium severity):
+    Heap buffer over-read in `png_image_read_direct_scaled.
+    (Reported and fixed by Petr Simecek.)
+  Fixed CVE-2026-22801 (medium severity):
+    Integer truncation causing heap buffer over-read in `png_image_write_*`.
+  Implemented various improvements in oss-fuzz.
+    (Contributed by Philippe Antoine.)
+
+
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net.
 Subscription is required; visit
 https://lists.sourceforge.net/lists/listinfo/png-mng-implement
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE b/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE
index ea6df986cb6..1b765ae9f96 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE
@@ -4,8 +4,8 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
 PNG Reference Library License version 2
 ---------------------------------------
 
- * Copyright (c) 1995-2025 The PNG Reference Library Authors.
- * Copyright (c) 2018-2025 Cosmin Truta.
+ * Copyright (c) 1995-2026 The PNG Reference Library Authors.
+ * Copyright (c) 2018-2026 Cosmin Truta.
  * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
  * Copyright (c) 1996-1997 Andreas Dilger.
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/README b/src/java.desktop/share/native/libsplashscreen/libpng/README
index 57952fb215a..63d1376edf7 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/README
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/README
@@ -1,4 +1,4 @@
-README for libpng version 1.6.47
+README for libpng version 1.6.54
 ================================
 
 See the note about version numbers near the top of `png.h`.
@@ -147,6 +147,7 @@ Files included in this distribution
     loongarch/    =>  Optimized code for LoongArch LSX
     mips/         =>  Optimized code for MIPS MSA and MIPS MMI
     powerpc/      =>  Optimized code for PowerPC VSX
+    riscv/        =>  Optimized code for the RISC-V platform
     ci/           =>  Scripts for continuous integration
     contrib/      =>  External contributions
         arm-neon/     =>  Optimized code for the ARM-NEON platform
@@ -162,6 +163,7 @@ Files included in this distribution
                           programs demonstrating the use of pngusr.dfa
         pngminus/     =>  Simple pnm2png and png2pnm programs
         pngsuite/     =>  Test images
+        riscv-rvv/    =>  Optimized code for the RISC-V Vector platform
         testpngs/     =>  Test images
         tools/        =>  Various tools
         visupng/      =>  VisualPng, a Windows viewer for PNG images
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/png.c b/src/java.desktop/share/native/libsplashscreen/libpng/png.c
index 7b6de2f8ec3..5636b4a754e 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/png.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/png.c
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018-2025 Cosmin Truta
+ * Copyright (c) 2018-2026 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -42,7 +42,7 @@
 #include "pngpriv.h"
 
 /* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_47 Your_png_h_is_not_version_1_6_47;
+typedef png_libpng_version_1_6_54 Your_png_h_is_not_version_1_6_54;
 
 /* Sanity check the chunks definitions - PNG_KNOWN_CHUNKS from pngpriv.h and the
  * corresponding macro definitions.  This causes a compile time failure if
@@ -130,17 +130,24 @@ png_sig_cmp(png_const_bytep sig, size_t start, size_t num_to_check)
 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
 /* Function to allocate memory for zlib */
 PNG_FUNCTION(voidpf /* PRIVATE */,
-png_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED)
+png_zalloc,(voidpf png_ptr, uInt items, uInt size),
+    PNG_ALLOCATED)
 {
    png_alloc_size_t num_bytes = size;
 
    if (png_ptr == NULL)
       return NULL;
 
-   if (items >= (~(png_alloc_size_t)0)/size)
+   /* This check against overflow is vestigial, dating back from
+    * the old times when png_zalloc used to be an exported function.
+    * We're still keeping it here for now, as an extra-cautious
+    * prevention against programming errors inside zlib, although it
+    * should rather be a debug-time assertion instead.
+    */
+   if (size != 0 && items >= (~(png_alloc_size_t)0) / size)
    {
-      png_warning (png_voidcast(png_structrp, png_ptr),
-          "Potential overflow in png_zalloc()");
+      png_warning(png_voidcast(png_structrp, png_ptr),
+                  "Potential overflow in png_zalloc()");
       return NULL;
    }
 
@@ -267,10 +274,6 @@ png_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver)
       png_warning(png_ptr, m);
 #endif
 
-#ifdef PNG_ERROR_NUMBERS_SUPPORTED
-      png_ptr->flags = 0;
-#endif
-
       return 0;
    }
 
@@ -284,7 +287,8 @@ png_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver)
 PNG_FUNCTION(png_structp /* PRIVATE */,
 png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
     png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
-    png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
+    png_malloc_ptr malloc_fn, png_free_ptr free_fn),
+    PNG_ALLOCATED)
 {
    png_struct create_struct;
 #  ifdef PNG_SETJMP_SUPPORTED
@@ -388,7 +392,8 @@ png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
 
 /* Allocate the memory for an info_struct for the application. */
 PNG_FUNCTION(png_infop,PNGAPI
-png_create_info_struct,(png_const_structrp png_ptr),PNG_ALLOCATED)
+png_create_info_struct,(png_const_structrp png_ptr),
+    PNG_ALLOCATED)
 {
    png_inforp info_ptr;
 
@@ -729,7 +734,7 @@ png_get_io_ptr(png_const_structrp png_ptr)
  * function of your own because "FILE *" isn't necessarily available.
  */
 void PNGAPI
-png_init_io(png_structrp png_ptr, png_FILE_p fp)
+png_init_io(png_structrp png_ptr, FILE *fp)
 {
    png_debug(1, "in png_init_io");
 
@@ -844,8 +849,8 @@ png_get_copyright(png_const_structrp png_ptr)
    return PNG_STRING_COPYRIGHT
 #else
    return PNG_STRING_NEWLINE \
-      "libpng version 1.6.47" PNG_STRING_NEWLINE \
-      "Copyright (c) 2018-2025 Cosmin Truta" PNG_STRING_NEWLINE \
+      "libpng version 1.6.54" PNG_STRING_NEWLINE \
+      "Copyright (c) 2018-2026 Cosmin Truta" PNG_STRING_NEWLINE \
       "Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \
       PNG_STRING_NEWLINE \
       "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
@@ -1520,7 +1525,7 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
 }
 #endif /* COLORSPACE */
 
-#ifdef PNG_iCCP_SUPPORTED
+#ifdef PNG_READ_iCCP_SUPPORTED
 /* Error message generation */
 static char
 png_icc_tag_char(png_uint_32 byte)
@@ -1596,9 +1601,7 @@ png_icc_profile_error(png_const_structrp png_ptr, png_const_charp name,
 
    return 0;
 }
-#endif /* iCCP */
 
-#ifdef PNG_READ_iCCP_SUPPORTED
 /* Encoded value of D50 as an ICC XYZNumber.  From the ICC 2010 spec the value
  * is XYZ(0.9642,1.0,0.8249), which scales to:
  *
@@ -2286,8 +2289,8 @@ png_check_fp_number(png_const_charp string, size_t size, int *statep,
 int
 png_check_fp_string(png_const_charp string, size_t size)
 {
-   int        state=0;
-   size_t char_index=0;
+   int state = 0;
+   size_t char_index = 0;
 
    if (png_check_fp_number(string, size, &state, &char_index) != 0 &&
       (char_index == size || string[char_index] == 0))
@@ -3998,7 +4001,7 @@ png_image_free_function(png_voidp argument)
 #  ifdef PNG_STDIO_SUPPORTED
       if (cp->owned_file != 0)
       {
-         FILE *fp = png_voidcast(FILE*, cp->png_ptr->io_ptr);
+         FILE *fp = png_voidcast(FILE *, cp->png_ptr->io_ptr);
          cp->owned_file = 0;
 
          /* Ignore errors here. */
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/png.h b/src/java.desktop/share/native/libsplashscreen/libpng/png.h
index ede12c34fe6..ab8876a9626 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/png.h
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/png.h
@@ -29,9 +29,9 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * libpng version 1.6.47
+ * libpng version 1.6.54
  *
- * Copyright (c) 2018-2025 Cosmin Truta
+ * Copyright (c) 2018-2026 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -43,7 +43,7 @@
  *   libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
  *   libpng versions 0.97, January 1998, through 1.6.35, July 2018:
  *     Glenn Randers-Pehrson
- *   libpng versions 1.6.36, December 2018, through 1.6.47, February 2025:
+ *   libpng versions 1.6.36, December 2018, through 1.6.54, January 2026:
  *     Cosmin Truta
  *   See also "Contributing Authors", below.
  */
@@ -55,8 +55,8 @@
  * PNG Reference Library License version 2
  * ---------------------------------------
  *
- *  * Copyright (c) 1995-2025 The PNG Reference Library Authors.
- *  * Copyright (c) 2018-2025 Cosmin Truta.
+ *  * Copyright (c) 1995-2026 The PNG Reference Library Authors.
+ *  * Copyright (c) 2018-2026 Cosmin Truta.
  *  * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
  *  * Copyright (c) 1996-1997 Andreas Dilger.
  *  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -267,7 +267,7 @@
  *    ...
  *    1.5.30                  15    10530  15.so.15.30[.0]
  *    ...
- *    1.6.47                  16    10647  16.so.16.47[.0]
+ *    1.6.54                  16    10654  16.so.16.54[.0]
  *
  *    Henceforth the source version will match the shared-library major and
  *    minor numbers; the shared-library major version number will be used for
@@ -303,7 +303,7 @@
  */
 
 /* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.6.47"
+#define PNG_LIBPNG_VER_STRING "1.6.54"
 #define PNG_HEADER_VERSION_STRING " libpng version " PNG_LIBPNG_VER_STRING "\n"
 
 /* The versions of shared library builds should stay in sync, going forward */
@@ -314,7 +314,7 @@
 /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
 #define PNG_LIBPNG_VER_MAJOR   1
 #define PNG_LIBPNG_VER_MINOR   6
-#define PNG_LIBPNG_VER_RELEASE 47
+#define PNG_LIBPNG_VER_RELEASE 54
 
 /* This should be zero for a public release, or non-zero for a
  * development version.
@@ -345,7 +345,7 @@
  * From version 1.0.1 it is:
  * XXYYZZ, where XX=major, YY=minor, ZZ=release
  */
-#define PNG_LIBPNG_VER 10647 /* 1.6.47 */
+#define PNG_LIBPNG_VER 10654 /* 1.6.54 */
 
 /* Library configuration: these options cannot be changed after
  * the library has been built.
@@ -455,7 +455,7 @@ extern "C" {
 /* This triggers a compiler error in png.c, if png.c and png.h
  * do not agree upon the version number.
  */
-typedef char* png_libpng_version_1_6_47;
+typedef char *png_libpng_version_1_6_54;
 
 /* Basic control structions.  Read libpng-manual.txt or libpng.3 for more info.
  *
@@ -814,17 +814,22 @@ typedef png_row_info * * png_row_infopp;
  * modify the buffer it is passed. The 'read' function, on the other hand, is
  * expected to return the read data in the buffer.
  */
-typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp));
-typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, size_t));
-typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp));
-typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32,
-    int));
-typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32,
-    int));
+typedef PNG_CALLBACK(void, *png_error_ptr,
+   (png_structp, png_const_charp));
+typedef PNG_CALLBACK(void, *png_rw_ptr,
+   (png_structp, png_bytep, size_t));
+typedef PNG_CALLBACK(void, *png_flush_ptr,
+   (png_structp));
+typedef PNG_CALLBACK(void, *png_read_status_ptr,
+   (png_structp, png_uint_32, int));
+typedef PNG_CALLBACK(void, *png_write_status_ptr,
+   (png_structp, png_uint_32, int));
 
 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop));
-typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop));
+typedef PNG_CALLBACK(void, *png_progressive_info_ptr,
+   (png_structp, png_infop));
+typedef PNG_CALLBACK(void, *png_progressive_end_ptr,
+   (png_structp, png_infop));
 
 /* The following callback receives png_uint_32 row_number, int pass for the
  * png_bytep data of the row.  When transforming an interlaced image the
@@ -836,19 +841,19 @@ typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop));
  * find the output pixel (x,y) given an interlaced sub-image pixel
  * (row,col,pass).  (See below for these macros.)
  */
-typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep,
-    png_uint_32, int));
+typedef PNG_CALLBACK(void, *png_progressive_row_ptr,
+   (png_structp, png_bytep, png_uint_32, int));
 #endif
 
 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
     defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
-typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop,
-    png_bytep));
+typedef PNG_CALLBACK(void, *png_user_transform_ptr,
+   (png_structp, png_row_infop, png_bytep));
 #endif
 
 #ifdef PNG_USER_CHUNKS_SUPPORTED
-typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp,
-    png_unknown_chunkp));
+typedef PNG_CALLBACK(int, *png_user_chunk_ptr,
+   (png_structp, png_unknown_chunkp));
 #endif
 #ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
 /* not used anywhere */
@@ -906,9 +911,10 @@ PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), (jmp_buf, int), typedef);
  * ignores the first argument) should be completely compatible with the
  * following.
  */
-typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp,
-    png_alloc_size_t));
-typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp));
+typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr,
+   (png_structp, png_alloc_size_t));
+typedef PNG_CALLBACK(void, *png_free_ptr,
+   (png_structp, png_voidp));
 
 /* Section 4: exported functions
  * Here are the function definitions most commonly used.  This is not
@@ -940,20 +946,22 @@ typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp));
  */
 
 /* Returns the version number of the library */
-PNG_EXPORT(1, png_uint_32, png_access_version_number, (void));
+PNG_EXPORT(1, png_uint_32, png_access_version_number,
+   (void));
 
 /* Tell lib we have already handled the first  magic bytes.
  * Handling more than 8 bytes from the beginning of the file is an error.
  */
-PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes));
+PNG_EXPORT(2, void, png_set_sig_bytes,
+   (png_structrp png_ptr, int num_bytes));
 
 /* Check sig[start] through sig[start + num_to_check - 1] to see if it's a
  * PNG file.  Returns zero if the supplied bytes match the 8-byte PNG
  * signature, and non-zero otherwise.  Having num_to_check == 0 or
  * start > 7 will always fail (i.e. return non-zero).
  */
-PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, size_t start,
-    size_t num_to_check));
+PNG_EXPORT(3, int, png_sig_cmp,
+   (png_const_bytep sig, size_t start, size_t num_to_check));
 
 /* Simple signature checking function.  This is the same as calling
  * png_check_sig(sig, n) := (png_sig_cmp(sig, 0, n) == 0).
@@ -962,21 +970,21 @@ PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, size_t start,
 
 /* Allocate and initialize png_ptr struct for reading, and any other memory. */
 PNG_EXPORTA(4, png_structp, png_create_read_struct,
-    (png_const_charp user_png_ver, png_voidp error_ptr,
-    png_error_ptr error_fn, png_error_ptr warn_fn),
-    PNG_ALLOCATED);
+   (png_const_charp user_png_ver,
+    png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn),
+   PNG_ALLOCATED);
 
 /* Allocate and initialize png_ptr struct for writing, and any other memory */
 PNG_EXPORTA(5, png_structp, png_create_write_struct,
-    (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn,
-    png_error_ptr warn_fn),
-    PNG_ALLOCATED);
+   (png_const_charp user_png_ver,
+    png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn),
+   PNG_ALLOCATED);
 
 PNG_EXPORT(6, size_t, png_get_compression_buffer_size,
-    (png_const_structrp png_ptr));
+   (png_const_structrp png_ptr));
 
-PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr,
-    size_t size));
+PNG_EXPORT(7, void, png_set_compression_buffer_size,
+   (png_structrp png_ptr, size_t size));
 
 /* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp
  * match up.
@@ -989,8 +997,8 @@ PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr,
  * allocated by the library - the call will return NULL on a mismatch
  * indicating an ABI mismatch.
  */
-PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structrp png_ptr,
-    png_longjmp_ptr longjmp_fn, size_t jmp_buf_size));
+PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn,
+   (png_structrp png_ptr, png_longjmp_ptr longjmp_fn, size_t jmp_buf_size));
 #  define png_jmpbuf(png_ptr) \
       (*png_set_longjmp_fn((png_ptr), longjmp, (sizeof (jmp_buf))))
 #else
@@ -1002,67 +1010,77 @@ PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structrp png_ptr,
  * will use it; otherwise it will call PNG_ABORT().  This function was
  * added in libpng-1.5.0.
  */
-PNG_EXPORTA(9, void, png_longjmp, (png_const_structrp png_ptr, int val),
-    PNG_NORETURN);
+PNG_EXPORTA(9, void, png_longjmp,
+   (png_const_structrp png_ptr, int val),
+   PNG_NORETURN);
 
 #ifdef PNG_READ_SUPPORTED
 /* Reset the compression stream */
-PNG_EXPORTA(10, int, png_reset_zstream, (png_structrp png_ptr), PNG_DEPRECATED);
+PNG_EXPORTA(10, int, png_reset_zstream,
+   (png_structrp png_ptr),
+   PNG_DEPRECATED);
 #endif
 
 /* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */
 #ifdef PNG_USER_MEM_SUPPORTED
 PNG_EXPORTA(11, png_structp, png_create_read_struct_2,
-    (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn,
-    png_error_ptr warn_fn,
+   (png_const_charp user_png_ver,
+    png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn,
     png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn),
-    PNG_ALLOCATED);
+   PNG_ALLOCATED);
 PNG_EXPORTA(12, png_structp, png_create_write_struct_2,
-    (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn,
-    png_error_ptr warn_fn,
+   (png_const_charp user_png_ver,
+    png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn,
     png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn),
-    PNG_ALLOCATED);
+   PNG_ALLOCATED);
 #endif
 
 /* Write the PNG file signature. */
-PNG_EXPORT(13, void, png_write_sig, (png_structrp png_ptr));
+PNG_EXPORT(13, void, png_write_sig,
+   (png_structrp png_ptr));
 
 /* Write a PNG chunk - size, type, (optional) data, CRC. */
-PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep
-    chunk_name, png_const_bytep data, size_t length));
+PNG_EXPORT(14, void, png_write_chunk,
+   (png_structrp png_ptr,
+    png_const_bytep chunk_name, png_const_bytep data, size_t length));
 
 /* Write the start of a PNG chunk - length and chunk name. */
-PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr,
+PNG_EXPORT(15, void, png_write_chunk_start,
+   (png_structrp png_ptr,
     png_const_bytep chunk_name, png_uint_32 length));
 
 /* Write the data of a PNG chunk started with png_write_chunk_start(). */
-PNG_EXPORT(16, void, png_write_chunk_data, (png_structrp png_ptr,
+PNG_EXPORT(16, void, png_write_chunk_data,
+   (png_structrp png_ptr,
     png_const_bytep data, size_t length));
 
 /* Finish a chunk started with png_write_chunk_start() (includes CRC). */
-PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr));
+PNG_EXPORT(17, void, png_write_chunk_end,
+   (png_structrp png_ptr));
 
 /* Allocate and initialize the info structure */
-PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_const_structrp png_ptr),
-    PNG_ALLOCATED);
+PNG_EXPORTA(18, png_infop, png_create_info_struct,
+   (png_const_structrp png_ptr),
+   PNG_ALLOCATED);
 
 /* DEPRECATED: this function allowed init structures to be created using the
  * default allocation method (typically malloc).  Use is deprecated in 1.6.0 and
  * the API will be removed in the future.
  */
-PNG_EXPORTA(19, void, png_info_init_3, (png_infopp info_ptr,
-    size_t png_info_struct_size), PNG_DEPRECATED);
+PNG_EXPORTA(19, void, png_info_init_3,
+   (png_infopp info_ptr, size_t png_info_struct_size),
+   PNG_DEPRECATED);
 
 /* Writes all the PNG information before the image. */
 PNG_EXPORT(20, void, png_write_info_before_PLTE,
-    (png_structrp png_ptr, png_const_inforp info_ptr));
+   (png_structrp png_ptr, png_const_inforp info_ptr));
 PNG_EXPORT(21, void, png_write_info,
-    (png_structrp png_ptr, png_const_inforp info_ptr));
+   (png_structrp png_ptr, png_const_inforp info_ptr));
 
 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
 /* Read the information before the actual image data. */
 PNG_EXPORT(22, void, png_read_info,
-    (png_structrp png_ptr, png_inforp info_ptr));
+   (png_structrp png_ptr, png_inforp info_ptr));
 #endif
 
 #ifdef PNG_TIME_RFC1123_SUPPORTED
@@ -1072,45 +1090,54 @@ PNG_EXPORT(22, void, png_read_info,
     */
 #if PNG_LIBPNG_VER < 10700
 /* To do: remove this from libpng17 (and from libpng17/png.c and pngstruct.h) */
-PNG_EXPORTA(23, png_const_charp, png_convert_to_rfc1123, (png_structrp png_ptr,
-    png_const_timep ptime),PNG_DEPRECATED);
+PNG_EXPORTA(23, png_const_charp, png_convert_to_rfc1123,
+   (png_structrp png_ptr, png_const_timep ptime),
+   PNG_DEPRECATED);
 #endif
-PNG_EXPORT(241, int, png_convert_to_rfc1123_buffer, (char out[29],
-    png_const_timep ptime));
+PNG_EXPORT(241, int, png_convert_to_rfc1123_buffer,
+   (char out[29], png_const_timep ptime));
 #endif
 
 #ifdef PNG_CONVERT_tIME_SUPPORTED
 /* Convert from a struct tm to png_time */
-PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime,
-    const struct tm * ttime));
+PNG_EXPORT(24, void, png_convert_from_struct_tm,
+   (png_timep ptime, const struct tm * ttime));
 
 /* Convert from time_t to png_time.  Uses gmtime() */
-PNG_EXPORT(25, void, png_convert_from_time_t, (png_timep ptime, time_t ttime));
+PNG_EXPORT(25, void, png_convert_from_time_t,
+   (png_timep ptime, time_t ttime));
 #endif /* CONVERT_tIME */
 
 #ifdef PNG_READ_EXPAND_SUPPORTED
 /* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */
-PNG_EXPORT(26, void, png_set_expand, (png_structrp png_ptr));
-PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structrp png_ptr));
-PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structrp png_ptr));
-PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structrp png_ptr));
+PNG_EXPORT(26, void, png_set_expand,
+   (png_structrp png_ptr));
+PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8,
+   (png_structrp png_ptr));
+PNG_EXPORT(28, void, png_set_palette_to_rgb,
+   (png_structrp png_ptr));
+PNG_EXPORT(29, void, png_set_tRNS_to_alpha,
+   (png_structrp png_ptr));
 #endif
 
 #ifdef PNG_READ_EXPAND_16_SUPPORTED
 /* Expand to 16-bit channels, forces conversion of palette to RGB and expansion
  * of a tRNS chunk if present.
  */
-PNG_EXPORT(221, void, png_set_expand_16, (png_structrp png_ptr));
+PNG_EXPORT(221, void, png_set_expand_16,
+   (png_structrp png_ptr));
 #endif
 
 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
 /* Use blue, green, red order for pixels. */
-PNG_EXPORT(30, void, png_set_bgr, (png_structrp png_ptr));
+PNG_EXPORT(30, void, png_set_bgr,
+   (png_structrp png_ptr));
 #endif
 
 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
 /* Expand the grayscale to 24-bit RGB if necessary. */
-PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structrp png_ptr));
+PNG_EXPORT(31, void, png_set_gray_to_rgb,
+   (png_structrp png_ptr));
 #endif
 
 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
@@ -1120,18 +1147,20 @@ PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structrp png_ptr));
 #define PNG_ERROR_ACTION_ERROR 3
 #define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/
 
-PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structrp png_ptr,
+PNG_FP_EXPORT(32, void, png_set_rgb_to_gray,
+   (png_structrp png_ptr,
     int error_action, double red, double green))
-PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structrp png_ptr,
+PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed,
+   (png_structrp png_ptr,
     int error_action, png_fixed_point red, png_fixed_point green))
 
-PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structrp
-    png_ptr));
+PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status,
+   (png_const_structrp png_ptr));
 #endif
 
 #ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
-PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth,
-    png_colorp palette));
+PNG_EXPORT(35, void, png_build_grayscale_palette,
+   (int bit_depth, png_colorp palette));
 #endif
 
 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
@@ -1176,10 +1205,10 @@ PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth,
 #define PNG_ALPHA_OPTIMIZED     2 /* 'PNG' for opaque pixels, else 'STANDARD' */
 #define PNG_ALPHA_BROKEN        3 /* the alpha channel is gamma encoded */
 
-PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structrp png_ptr, int mode,
-    double output_gamma))
-PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr,
-    int mode, png_fixed_point output_gamma))
+PNG_FP_EXPORT(227, void, png_set_alpha_mode,
+   (png_structrp png_ptr, int mode, double output_gamma))
+PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed,
+   (png_structrp png_ptr, int mode, png_fixed_point output_gamma))
 #endif
 
 #if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED)
@@ -1269,51 +1298,57 @@ PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr,
  */
 
 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
-PNG_EXPORT(36, void, png_set_strip_alpha, (png_structrp png_ptr));
+PNG_EXPORT(36, void, png_set_strip_alpha,
+   (png_structrp png_ptr));
 #endif
 
 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
     defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
-PNG_EXPORT(37, void, png_set_swap_alpha, (png_structrp png_ptr));
+PNG_EXPORT(37, void, png_set_swap_alpha,
+   (png_structrp png_ptr));
 #endif
 
 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
     defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
-PNG_EXPORT(38, void, png_set_invert_alpha, (png_structrp png_ptr));
+PNG_EXPORT(38, void, png_set_invert_alpha,
+   (png_structrp png_ptr));
 #endif
 
 #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
 /* Add a filler byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */
-PNG_EXPORT(39, void, png_set_filler, (png_structrp png_ptr, png_uint_32 filler,
-    int flags));
+PNG_EXPORT(39, void, png_set_filler,
+   (png_structrp png_ptr, png_uint_32 filler, int flags));
 /* The values of the PNG_FILLER_ defines should NOT be changed */
 #  define PNG_FILLER_BEFORE 0
 #  define PNG_FILLER_AFTER 1
 /* Add an alpha byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */
-PNG_EXPORT(40, void, png_set_add_alpha, (png_structrp png_ptr,
-    png_uint_32 filler, int flags));
+PNG_EXPORT(40, void, png_set_add_alpha,
+   (png_structrp png_ptr, png_uint_32 filler, int flags));
 #endif /* READ_FILLER || WRITE_FILLER */
 
 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
 /* Swap bytes in 16-bit depth files. */
-PNG_EXPORT(41, void, png_set_swap, (png_structrp png_ptr));
+PNG_EXPORT(41, void, png_set_swap,
+   (png_structrp png_ptr));
 #endif
 
 #if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
 /* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */
-PNG_EXPORT(42, void, png_set_packing, (png_structrp png_ptr));
+PNG_EXPORT(42, void, png_set_packing,
+   (png_structrp png_ptr));
 #endif
 
 #if defined(PNG_READ_PACKSWAP_SUPPORTED) || \
     defined(PNG_WRITE_PACKSWAP_SUPPORTED)
 /* Swap packing order of pixels in bytes. */
-PNG_EXPORT(43, void, png_set_packswap, (png_structrp png_ptr));
+PNG_EXPORT(43, void, png_set_packswap,
+   (png_structrp png_ptr));
 #endif
 
 #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
 /* Converts files to legal bit depths. */
-PNG_EXPORT(44, void, png_set_shift, (png_structrp png_ptr, png_const_color_8p
-    true_bits));
+PNG_EXPORT(44, void, png_set_shift,
+   (png_structrp png_ptr, png_const_color_8p true_bits));
 #endif
 
 #if defined(PNG_READ_INTERLACING_SUPPORTED) || \
@@ -1324,12 +1359,14 @@ PNG_EXPORT(44, void, png_set_shift, (png_structrp png_ptr, png_const_color_8p
  * necessary to call png_read_row or png_read_rows png_get_image_height
  * times for each pass.
 */
-PNG_EXPORT(45, int, png_set_interlace_handling, (png_structrp png_ptr));
+PNG_EXPORT(45, int, png_set_interlace_handling,
+   (png_structrp png_ptr));
 #endif
 
 #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
 /* Invert monochrome files */
-PNG_EXPORT(46, void, png_set_invert_mono, (png_structrp png_ptr));
+PNG_EXPORT(46, void, png_set_invert_mono,
+   (png_structrp png_ptr));
 #endif
 
 #ifdef PNG_READ_BACKGROUND_SUPPORTED
@@ -1338,10 +1375,12 @@ PNG_EXPORT(46, void, png_set_invert_mono, (png_structrp png_ptr));
  * read.  Doing so will result in unexpected behavior and possible warnings or
  * errors if the PNG file contains a bKGD chunk.
  */
-PNG_FP_EXPORT(47, void, png_set_background, (png_structrp png_ptr,
+PNG_FP_EXPORT(47, void, png_set_background,
+   (png_structrp png_ptr,
     png_const_color_16p background_color, int background_gamma_code,
     int need_expand, double background_gamma))
-PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structrp png_ptr,
+PNG_FIXED_EXPORT(215, void, png_set_background_fixed,
+   (png_structrp png_ptr,
     png_const_color_16p background_color, int background_gamma_code,
     int need_expand, png_fixed_point background_gamma))
 #endif
@@ -1354,20 +1393,23 @@ PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structrp png_ptr,
 
 #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
 /* Scale a 16-bit depth file down to 8-bit, accurately. */
-PNG_EXPORT(229, void, png_set_scale_16, (png_structrp png_ptr));
+PNG_EXPORT(229, void, png_set_scale_16,
+   (png_structrp png_ptr));
 #endif
 
 #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
 #define PNG_READ_16_TO_8_SUPPORTED /* Name prior to 1.5.4 */
 /* Strip the second byte of information from a 16-bit depth file. */
-PNG_EXPORT(48, void, png_set_strip_16, (png_structrp png_ptr));
+PNG_EXPORT(48, void, png_set_strip_16,
+   (png_structrp png_ptr));
 #endif
 
 #ifdef PNG_READ_QUANTIZE_SUPPORTED
 /* Turn on quantizing, and reduce the palette to the number of colors
  * available.
  */
-PNG_EXPORT(49, void, png_set_quantize, (png_structrp png_ptr,
+PNG_EXPORT(49, void, png_set_quantize,
+   (png_structrp png_ptr,
     png_colorp palette, int num_palette, int maximum_colors,
     png_const_uint_16p histogram, int full_quantize));
 #endif
@@ -1389,82 +1431,92 @@ PNG_EXPORT(49, void, png_set_quantize, (png_structrp png_ptr,
  * API (floating point or fixed.)  Notice, however, that the 'file_gamma' value
  * is the inverse of a 'screen gamma' value.
  */
-PNG_FP_EXPORT(50, void, png_set_gamma, (png_structrp png_ptr,
+PNG_FP_EXPORT(50, void, png_set_gamma,
+   (png_structrp png_ptr,
     double screen_gamma, double override_file_gamma))
-PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structrp png_ptr,
+PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed,
+   (png_structrp png_ptr,
     png_fixed_point screen_gamma, png_fixed_point override_file_gamma))
 #endif
 
 #ifdef PNG_WRITE_FLUSH_SUPPORTED
 /* Set how many lines between output flushes - 0 for no flushing */
-PNG_EXPORT(51, void, png_set_flush, (png_structrp png_ptr, int nrows));
+PNG_EXPORT(51, void, png_set_flush,
+   (png_structrp png_ptr, int nrows));
 /* Flush the current PNG output buffer */
-PNG_EXPORT(52, void, png_write_flush, (png_structrp png_ptr));
+PNG_EXPORT(52, void, png_write_flush,
+   (png_structrp png_ptr));
 #endif
 
 /* Optional update palette with requested transformations */
-PNG_EXPORT(53, void, png_start_read_image, (png_structrp png_ptr));
+PNG_EXPORT(53, void, png_start_read_image,
+   (png_structrp png_ptr));
 
 /* Optional call to update the users info structure */
-PNG_EXPORT(54, void, png_read_update_info, (png_structrp png_ptr,
-    png_inforp info_ptr));
+PNG_EXPORT(54, void, png_read_update_info,
+   (png_structrp png_ptr, png_inforp info_ptr));
 
 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
 /* Read one or more rows of image data. */
-PNG_EXPORT(55, void, png_read_rows, (png_structrp png_ptr, png_bytepp row,
+PNG_EXPORT(55, void, png_read_rows,
+   (png_structrp png_ptr, png_bytepp row,
     png_bytepp display_row, png_uint_32 num_rows));
 #endif
 
 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
 /* Read a row of data. */
-PNG_EXPORT(56, void, png_read_row, (png_structrp png_ptr, png_bytep row,
-    png_bytep display_row));
+PNG_EXPORT(56, void, png_read_row,
+   (png_structrp png_ptr, png_bytep row, png_bytep display_row));
 #endif
 
 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
 /* Read the whole image into memory at once. */
-PNG_EXPORT(57, void, png_read_image, (png_structrp png_ptr, png_bytepp image));
+PNG_EXPORT(57, void, png_read_image,
+   (png_structrp png_ptr, png_bytepp image));
 #endif
 
 /* Write a row of image data */
-PNG_EXPORT(58, void, png_write_row, (png_structrp png_ptr,
-    png_const_bytep row));
+PNG_EXPORT(58, void, png_write_row,
+   (png_structrp png_ptr, png_const_bytep row));
 
 /* Write a few rows of image data: (*row) is not written; however, the type
  * is declared as writeable to maintain compatibility with previous versions
  * of libpng and to allow the 'display_row' array from read_rows to be passed
  * unchanged to write_rows.
  */
-PNG_EXPORT(59, void, png_write_rows, (png_structrp png_ptr, png_bytepp row,
-    png_uint_32 num_rows));
+PNG_EXPORT(59, void, png_write_rows,
+   (png_structrp png_ptr, png_bytepp row, png_uint_32 num_rows));
 
 /* Write the image data */
-PNG_EXPORT(60, void, png_write_image, (png_structrp png_ptr, png_bytepp image));
+PNG_EXPORT(60, void, png_write_image,
+   (png_structrp png_ptr, png_bytepp image));
 
 /* Write the end of the PNG file. */
-PNG_EXPORT(61, void, png_write_end, (png_structrp png_ptr,
-    png_inforp info_ptr));
+PNG_EXPORT(61, void, png_write_end,
+   (png_structrp png_ptr, png_inforp info_ptr));
 
 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
 /* Read the end of the PNG file. */
-PNG_EXPORT(62, void, png_read_end, (png_structrp png_ptr, png_inforp info_ptr));
+PNG_EXPORT(62, void, png_read_end,
+   (png_structrp png_ptr, png_inforp info_ptr));
 #endif
 
 /* Free any memory associated with the png_info_struct */
-PNG_EXPORT(63, void, png_destroy_info_struct, (png_const_structrp png_ptr,
-    png_infopp info_ptr_ptr));
+PNG_EXPORT(63, void, png_destroy_info_struct,
+   (png_const_structrp png_ptr, png_infopp info_ptr_ptr));
 
 /* Free any memory associated with the png_struct and the png_info_structs */
-PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr,
+PNG_EXPORT(64, void, png_destroy_read_struct,
+   (png_structpp png_ptr_ptr,
     png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr));
 
 /* Free any memory associated with the png_struct and the png_info_structs */
-PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr,
-    png_infopp info_ptr_ptr));
+PNG_EXPORT(65, void, png_destroy_write_struct,
+   (png_structpp png_ptr_ptr, png_infopp info_ptr_ptr));
 
 /* Set the libpng method of handling chunk CRC errors */
-PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action,
-    int ancil_action));
+PNG_EXPORT(66, void, png_set_crc_action,
+   (png_structrp png_ptr, int crit_action, int ancil_action));
 
 /* Values for png_set_crc_action() say how to handle CRC errors in
  * ancillary and critical chunks, and whether to use the data contained
@@ -1494,8 +1546,8 @@ PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action,
 /* Set the filtering method(s) used by libpng.  Currently, the only valid
  * value for "method" is 0.
  */
-PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method,
-    int filters));
+PNG_EXPORT(67, void, png_set_filter,
+   (png_structrp png_ptr, int method, int filters));
 #endif /* WRITE */
 
 /* Flags for png_set_filter() to say which filters to use.  The flags
@@ -1524,11 +1576,14 @@ PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method,
 
 #ifdef PNG_WRITE_SUPPORTED
 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */
-PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structrp png_ptr,
-    int heuristic_method, int num_weights, png_const_doublep filter_weights,
+PNG_FP_EXPORT(68, void, png_set_filter_heuristics,
+   (png_structrp png_ptr,
+    int heuristic_method, int num_weights,
+    png_const_doublep filter_weights,
     png_const_doublep filter_costs))
 PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed,
-    (png_structrp png_ptr, int heuristic_method, int num_weights,
+   (png_structrp png_ptr,
+    int heuristic_method, int num_weights,
     png_const_fixed_point_p filter_weights,
     png_const_fixed_point_p filter_costs))
 #endif /* WRITE_WEIGHTED_FILTER */
@@ -1547,44 +1602,44 @@ PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed,
  * these values may not correspond directly to the zlib compression levels.
  */
 #ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
-PNG_EXPORT(69, void, png_set_compression_level, (png_structrp png_ptr,
-    int level));
+PNG_EXPORT(69, void, png_set_compression_level,
+   (png_structrp png_ptr, int level));
 
-PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structrp png_ptr,
-    int mem_level));
+PNG_EXPORT(70, void, png_set_compression_mem_level,
+   (png_structrp png_ptr, int mem_level));
 
-PNG_EXPORT(71, void, png_set_compression_strategy, (png_structrp png_ptr,
-    int strategy));
+PNG_EXPORT(71, void, png_set_compression_strategy,
+   (png_structrp png_ptr, int strategy));
 
 /* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
  * smaller value of window_bits if it can do so safely.
  */
-PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structrp png_ptr,
-    int window_bits));
+PNG_EXPORT(72, void, png_set_compression_window_bits,
+   (png_structrp png_ptr, int window_bits));
 
-PNG_EXPORT(73, void, png_set_compression_method, (png_structrp png_ptr,
-    int method));
+PNG_EXPORT(73, void, png_set_compression_method,
+   (png_structrp png_ptr, int method));
 #endif /* WRITE_CUSTOMIZE_COMPRESSION */
 
 #ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
 /* Also set zlib parameters for compressing non-IDAT chunks */
-PNG_EXPORT(222, void, png_set_text_compression_level, (png_structrp png_ptr,
-    int level));
+PNG_EXPORT(222, void, png_set_text_compression_level,
+   (png_structrp png_ptr, int level));
 
-PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structrp png_ptr,
-    int mem_level));
+PNG_EXPORT(223, void, png_set_text_compression_mem_level,
+   (png_structrp png_ptr, int mem_level));
 
-PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structrp png_ptr,
-    int strategy));
+PNG_EXPORT(224, void, png_set_text_compression_strategy,
+   (png_structrp png_ptr, int strategy));
 
 /* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
  * smaller value of window_bits if it can do so safely.
  */
 PNG_EXPORT(225, void, png_set_text_compression_window_bits,
-    (png_structrp png_ptr, int window_bits));
+   (png_structrp png_ptr, int window_bits));
 
-PNG_EXPORT(226, void, png_set_text_compression_method, (png_structrp png_ptr,
-    int method));
+PNG_EXPORT(226, void, png_set_text_compression_method,
+   (png_structrp png_ptr, int method));
 #endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */
 #endif /* WRITE */
 
@@ -1599,7 +1654,8 @@ PNG_EXPORT(226, void, png_set_text_compression_method, (png_structrp png_ptr,
 
 #ifdef PNG_STDIO_SUPPORTED
 /* Initialize the input/output for the PNG file to the default functions. */
-PNG_EXPORT(74, void, png_init_io, (png_structrp png_ptr, png_FILE_p fp));
+PNG_EXPORT(74, void, png_init_io,
+   (png_structrp png_ptr, FILE *fp));
 #endif
 
 /* Replace the (error and abort), and warning functions with user
@@ -1610,11 +1666,13 @@ PNG_EXPORT(74, void, png_init_io, (png_structrp png_ptr, png_FILE_p fp));
  * default function will be used.
  */
 
-PNG_EXPORT(75, void, png_set_error_fn, (png_structrp png_ptr,
+PNG_EXPORT(75, void, png_set_error_fn,
+   (png_structrp png_ptr,
     png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn));
 
 /* Return the user pointer associated with the error functions */
-PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structrp png_ptr));
+PNG_EXPORT(76, png_voidp, png_get_error_ptr,
+   (png_const_structrp png_ptr));
 
 /* Replace the default data output functions with a user supplied one(s).
  * If buffered output is not used, then output_flush_fn can be set to NULL.
@@ -1626,47 +1684,54 @@ PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structrp png_ptr));
  * default flush function, which uses the standard *FILE structure, will
  * be used.
  */
-PNG_EXPORT(77, void, png_set_write_fn, (png_structrp png_ptr, png_voidp io_ptr,
+PNG_EXPORT(77, void, png_set_write_fn,
+   (png_structrp png_ptr,
+    png_voidp io_ptr,
     png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn));
 
 /* Replace the default data input function with a user supplied one. */
-PNG_EXPORT(78, void, png_set_read_fn, (png_structrp png_ptr, png_voidp io_ptr,
-    png_rw_ptr read_data_fn));
+PNG_EXPORT(78, void, png_set_read_fn,
+   (png_structrp png_ptr,
+    png_voidp io_ptr, png_rw_ptr read_data_fn));
 
 /* Return the user pointer associated with the I/O functions */
-PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_const_structrp png_ptr));
+PNG_EXPORT(79, png_voidp, png_get_io_ptr,
+   (png_const_structrp png_ptr));
 
-PNG_EXPORT(80, void, png_set_read_status_fn, (png_structrp png_ptr,
-    png_read_status_ptr read_row_fn));
+PNG_EXPORT(80, void, png_set_read_status_fn,
+   (png_structrp png_ptr, png_read_status_ptr read_row_fn));
 
-PNG_EXPORT(81, void, png_set_write_status_fn, (png_structrp png_ptr,
-    png_write_status_ptr write_row_fn));
+PNG_EXPORT(81, void, png_set_write_status_fn,
+   (png_structrp png_ptr, png_write_status_ptr write_row_fn));
 
 #ifdef PNG_USER_MEM_SUPPORTED
 /* Replace the default memory allocation functions with user supplied one(s). */
-PNG_EXPORT(82, void, png_set_mem_fn, (png_structrp png_ptr, png_voidp mem_ptr,
-    png_malloc_ptr malloc_fn, png_free_ptr free_fn));
+PNG_EXPORT(82, void, png_set_mem_fn,
+   (png_structrp png_ptr,
+    png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn));
 /* Return the user pointer associated with the memory functions */
-PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structrp png_ptr));
+PNG_EXPORT(83, png_voidp, png_get_mem_ptr,
+   (png_const_structrp png_ptr));
 #endif
 
 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
-PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structrp png_ptr,
-    png_user_transform_ptr read_user_transform_fn));
+PNG_EXPORT(84, void, png_set_read_user_transform_fn,
+   (png_structrp png_ptr, png_user_transform_ptr read_user_transform_fn));
 #endif
 
 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
-PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structrp png_ptr,
-    png_user_transform_ptr write_user_transform_fn));
+PNG_EXPORT(85, void, png_set_write_user_transform_fn,
+   (png_structrp png_ptr, png_user_transform_ptr write_user_transform_fn));
 #endif
 
 #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
-PNG_EXPORT(86, void, png_set_user_transform_info, (png_structrp png_ptr,
-    png_voidp user_transform_ptr, int user_transform_depth,
-    int user_transform_channels));
+PNG_EXPORT(86, void, png_set_user_transform_info,
+   (png_structrp png_ptr,
+    png_voidp user_transform_ptr,
+    int user_transform_depth, int user_transform_channels));
 /* Return the user pointer associated with the user transform functions */
 PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr,
-    (png_const_structrp png_ptr));
+   (png_const_structrp png_ptr));
 #endif
 
 #ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
@@ -1681,8 +1746,10 @@ PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr,
  * find the output pixel (x,y) given an interlaced sub-image pixel
  * (row,col,pass).  (See below for these macros.)
  */
-PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structrp));
-PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp));
+PNG_EXPORT(217, png_uint_32, png_get_current_row_number,
+   (png_const_structrp));
+PNG_EXPORT(218, png_byte, png_get_current_pass_number,
+   (png_const_structrp));
 #endif
 
 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
@@ -1705,28 +1772,32 @@ PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp));
  * See "INTERACTION WITH USER CHUNK CALLBACKS" below for important notes about
  * how this behavior will change in libpng 1.7
  */
-PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr,
+PNG_EXPORT(88, void, png_set_read_user_chunk_fn,
+   (png_structrp png_ptr,
     png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn));
 #endif
 
 #ifdef PNG_USER_CHUNKS_SUPPORTED
-PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structrp png_ptr));
+PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr,
+   (png_const_structrp png_ptr));
 #endif
 
 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
 /* Sets the function callbacks for the push reader, and a pointer to a
  * user-defined structure available to the callback functions.
  */
-PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structrp png_ptr,
+PNG_EXPORT(90, void, png_set_progressive_read_fn,
+   (png_structrp png_ptr,
     png_voidp progressive_ptr, png_progressive_info_ptr info_fn,
     png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn));
 
 /* Returns the user pointer associated with the push read functions */
 PNG_EXPORT(91, png_voidp, png_get_progressive_ptr,
-    (png_const_structrp png_ptr));
+   (png_const_structrp png_ptr));
 
 /* Function to be called when data becomes available */
-PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr,
+PNG_EXPORT(92, void, png_process_data,
+   (png_structrp png_ptr,
     png_inforp info_ptr, png_bytep buffer, size_t buffer_size));
 
 /* A function which may be called *only* within png_process_data to stop the
@@ -1736,7 +1807,8 @@ PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr,
  * 'save' is set to true the routine will first save all the pending data and
  * will always return 0.
  */
-PNG_EXPORT(219, size_t, png_process_data_pause, (png_structrp, int save));
+PNG_EXPORT(219, size_t, png_process_data_pause,
+   (png_structrp, int save));
 
 /* A function which may be called *only* outside (after) a call to
  * png_process_data.  It returns the number of bytes of data to skip in the
@@ -1744,45 +1816,53 @@ PNG_EXPORT(219, size_t, png_process_data_pause, (png_structrp, int save));
  * application must skip than number of bytes of input data and pass the
  * following data to the next call to png_process_data.
  */
-PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structrp));
+PNG_EXPORT(220, png_uint_32, png_process_data_skip,
+   (png_structrp));
 
 /* Function that combines rows.  'new_row' is a flag that should come from
  * the callback and be non-NULL if anything needs to be done; the library
  * stores its own version of the new data internally and ignores the passed
  * in value.
  */
-PNG_EXPORT(93, void, png_progressive_combine_row, (png_const_structrp png_ptr,
+PNG_EXPORT(93, void, png_progressive_combine_row,
+   (png_const_structrp png_ptr,
     png_bytep old_row, png_const_bytep new_row));
 #endif /* PROGRESSIVE_READ */
 
-PNG_EXPORTA(94, png_voidp, png_malloc, (png_const_structrp png_ptr,
-    png_alloc_size_t size), PNG_ALLOCATED);
+PNG_EXPORTA(94, png_voidp, png_malloc,
+   (png_const_structrp png_ptr, png_alloc_size_t size),
+   PNG_ALLOCATED);
 /* Added at libpng version 1.4.0 */
-PNG_EXPORTA(95, png_voidp, png_calloc, (png_const_structrp png_ptr,
-    png_alloc_size_t size), PNG_ALLOCATED);
+PNG_EXPORTA(95, png_voidp, png_calloc,
+   (png_const_structrp png_ptr, png_alloc_size_t size),
+   PNG_ALLOCATED);
 
 /* Added at libpng version 1.2.4 */
-PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_const_structrp png_ptr,
-    png_alloc_size_t size), PNG_ALLOCATED);
+PNG_EXPORTA(96, png_voidp, png_malloc_warn,
+   (png_const_structrp png_ptr, png_alloc_size_t size),
+   PNG_ALLOCATED);
 
 /* Frees a pointer allocated by png_malloc() */
-PNG_EXPORT(97, void, png_free, (png_const_structrp png_ptr, png_voidp ptr));
+PNG_EXPORT(97, void, png_free,
+   (png_const_structrp png_ptr, png_voidp ptr));
 
 /* Free data that was allocated internally */
-PNG_EXPORT(98, void, png_free_data, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 free_me, int num));
+PNG_EXPORT(98, void, png_free_data,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_uint_32 free_me, int num));
 
 /* Reassign the responsibility for freeing existing data, whether allocated
  * by libpng or by the application; this works on the png_info structure passed
  * in, without changing the state for other png_info structures.
  */
-PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr,
-    png_inforp info_ptr, int freer, png_uint_32 mask));
+PNG_EXPORT(99, void, png_data_freer,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    int freer, png_uint_32 mask));
 
 /* Assignments for png_data_freer */
 #define PNG_DESTROY_WILL_FREE_DATA 1
-#define PNG_SET_WILL_FREE_DATA 1
-#define PNG_USER_WILL_FREE_DATA 2
+#define PNG_SET_WILL_FREE_DATA     1
+#define PNG_USER_WILL_FREE_DATA    2
 /* Flags for png_ptr->free_me and info_ptr->free_me */
 #define PNG_FREE_HIST 0x0008U
 #define PNG_FREE_ICCP 0x0010U
@@ -1802,36 +1882,42 @@ PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr,
 #define PNG_FREE_MUL  0x4220U /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */
 
 #ifdef PNG_USER_MEM_SUPPORTED
-PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_const_structrp png_ptr,
-    png_alloc_size_t size), PNG_ALLOCATED PNG_DEPRECATED);
-PNG_EXPORTA(101, void, png_free_default, (png_const_structrp png_ptr,
-    png_voidp ptr), PNG_DEPRECATED);
+PNG_EXPORTA(100, png_voidp, png_malloc_default,
+   (png_const_structrp png_ptr, png_alloc_size_t size),
+   PNG_ALLOCATED PNG_DEPRECATED);
+PNG_EXPORTA(101, void, png_free_default,
+   (png_const_structrp png_ptr, png_voidp ptr),
+   PNG_DEPRECATED);
 #endif
 
 #ifdef PNG_ERROR_TEXT_SUPPORTED
 /* Fatal error in PNG image of libpng - can't continue */
-PNG_EXPORTA(102, void, png_error, (png_const_structrp png_ptr,
-    png_const_charp error_message), PNG_NORETURN);
+PNG_EXPORTA(102, void, png_error,
+   (png_const_structrp png_ptr, png_const_charp error_message),
+   PNG_NORETURN);
 
 /* The same, but the chunk name is prepended to the error string. */
-PNG_EXPORTA(103, void, png_chunk_error, (png_const_structrp png_ptr,
-    png_const_charp error_message), PNG_NORETURN);
+PNG_EXPORTA(103, void, png_chunk_error,
+   (png_const_structrp png_ptr, png_const_charp error_message),
+   PNG_NORETURN);
 
 #else
 /* Fatal error in PNG image of libpng - can't continue */
-PNG_EXPORTA(104, void, png_err, (png_const_structrp png_ptr), PNG_NORETURN);
+PNG_EXPORTA(104, void, png_err,
+   (png_const_structrp png_ptr),
+   PNG_NORETURN);
 #  define png_error(s1,s2) png_err(s1)
 #  define png_chunk_error(s1,s2) png_err(s1)
 #endif
 
 #ifdef PNG_WARNINGS_SUPPORTED
 /* Non-fatal error in libpng.  Can continue, but may have a problem. */
-PNG_EXPORT(105, void, png_warning, (png_const_structrp png_ptr,
-    png_const_charp warning_message));
+PNG_EXPORT(105, void, png_warning,
+   (png_const_structrp png_ptr, png_const_charp warning_message));
 
 /* Non-fatal error in libpng, chunk name is prepended to message. */
-PNG_EXPORT(106, void, png_chunk_warning, (png_const_structrp png_ptr,
-    png_const_charp warning_message));
+PNG_EXPORT(106, void, png_chunk_warning,
+   (png_const_structrp png_ptr, png_const_charp warning_message));
 #else
 #  define png_warning(s1,s2) ((void)(s1))
 #  define png_chunk_warning(s1,s2) ((void)(s1))
@@ -1840,17 +1926,17 @@ PNG_EXPORT(106, void, png_chunk_warning, (png_const_structrp png_ptr,
 #ifdef PNG_BENIGN_ERRORS_SUPPORTED
 /* Benign error in libpng.  Can continue, but may have a problem.
  * User can choose whether to handle as a fatal error or as a warning. */
-PNG_EXPORT(107, void, png_benign_error, (png_const_structrp png_ptr,
-    png_const_charp warning_message));
+PNG_EXPORT(107, void, png_benign_error,
+   (png_const_structrp png_ptr, png_const_charp warning_message));
 
 #ifdef PNG_READ_SUPPORTED
 /* Same, chunk name is prepended to message (only during read) */
-PNG_EXPORT(108, void, png_chunk_benign_error, (png_const_structrp png_ptr,
-    png_const_charp warning_message));
+PNG_EXPORT(108, void, png_chunk_benign_error,
+   (png_const_structrp png_ptr, png_const_charp warning_message));
 #endif
 
 PNG_EXPORT(109, void, png_set_benign_errors,
-    (png_structrp png_ptr, int allowed));
+   (png_structrp png_ptr, int allowed));
 #else
 #  ifdef PNG_ALLOW_BENIGN_ERRORS
 #    define png_benign_error png_warning
@@ -1874,169 +1960,181 @@ PNG_EXPORT(109, void, png_set_benign_errors,
  * png_info_struct.
  */
 /* Returns "flag" if chunk data is valid in info_ptr. */
-PNG_EXPORT(110, png_uint_32, png_get_valid, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr, png_uint_32 flag));
+PNG_EXPORT(110, png_uint_32, png_get_valid,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr, png_uint_32 flag));
 
 /* Returns number of bytes needed to hold a transformed row. */
-PNG_EXPORT(111, size_t, png_get_rowbytes, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr));
+PNG_EXPORT(111, size_t, png_get_rowbytes,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr));
 
 #ifdef PNG_INFO_IMAGE_SUPPORTED
 /* Returns row_pointers, which is an array of pointers to scanlines that was
  * returned from png_read_png().
  */
-PNG_EXPORT(112, png_bytepp, png_get_rows, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr));
+PNG_EXPORT(112, png_bytepp, png_get_rows,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr));
 
 /* Set row_pointers, which is an array of pointers to scanlines for use
  * by png_write_png().
  */
-PNG_EXPORT(113, void, png_set_rows, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_bytepp row_pointers));
+PNG_EXPORT(113, void, png_set_rows,
+   (png_const_structrp png_ptr, png_inforp info_ptr, png_bytepp row_pointers));
 #endif
 
 /* Returns number of color channels in image. */
-PNG_EXPORT(114, png_byte, png_get_channels, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr));
+PNG_EXPORT(114, png_byte, png_get_channels,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr));
 
 #ifdef PNG_EASY_ACCESS_SUPPORTED
 /* Returns image width in pixels. */
-PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr));
+PNG_EXPORT(115, png_uint_32, png_get_image_width,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr));
 
 /* Returns image height in pixels. */
-PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr));
+PNG_EXPORT(116, png_uint_32, png_get_image_height,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr));
 
 /* Returns image bit_depth. */
-PNG_EXPORT(117, png_byte, png_get_bit_depth, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr));
+PNG_EXPORT(117, png_byte, png_get_bit_depth,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr));
 
 /* Returns image color_type. */
-PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr));
+PNG_EXPORT(118, png_byte, png_get_color_type,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr));
 
 /* Returns image filter_type. */
-PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr));
+PNG_EXPORT(119, png_byte, png_get_filter_type,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr));
 
 /* Returns image interlace_type. */
-PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr));
+PNG_EXPORT(120, png_byte, png_get_interlace_type,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr));
 
 /* Returns image compression_type. */
-PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr));
+PNG_EXPORT(121, png_byte, png_get_compression_type,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr));
 
 /* Returns image resolution in pixels per meter, from pHYs chunk data. */
 PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr));
+   (png_const_structrp png_ptr, png_const_inforp info_ptr));
 PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr));
+   (png_const_structrp png_ptr, png_const_inforp info_ptr));
 PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr));
+   (png_const_structrp png_ptr, png_const_inforp info_ptr));
 
 /* Returns pixel aspect ratio, computed from pHYs chunk data.  */
 PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr))
+   (png_const_structrp png_ptr, png_const_inforp info_ptr))
 PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr))
+   (png_const_structrp png_ptr, png_const_inforp info_ptr))
 
 /* Returns image x, y offset in pixels or microns, from oFFs chunk data. */
 PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr));
+   (png_const_structrp png_ptr, png_const_inforp info_ptr));
 PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr));
+   (png_const_structrp png_ptr, png_const_inforp info_ptr));
 PNG_EXPORT(128, png_int_32, png_get_x_offset_microns,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr));
+   (png_const_structrp png_ptr, png_const_inforp info_ptr));
 PNG_EXPORT(129, png_int_32, png_get_y_offset_microns,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr));
+   (png_const_structrp png_ptr, png_const_inforp info_ptr));
 
 #endif /* EASY_ACCESS */
 
 #ifdef PNG_READ_SUPPORTED
 /* Returns pointer to signature string read from PNG header */
-PNG_EXPORT(130, png_const_bytep, png_get_signature, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr));
+PNG_EXPORT(130, png_const_bytep, png_get_signature,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr));
 #endif
 
 #ifdef PNG_bKGD_SUPPORTED
-PNG_EXPORT(131, png_uint_32, png_get_bKGD, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_color_16p *background));
+PNG_EXPORT(131, png_uint_32, png_get_bKGD,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_color_16p *background));
 #endif
 
 #ifdef PNG_bKGD_SUPPORTED
-PNG_EXPORT(132, void, png_set_bKGD, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_const_color_16p background));
+PNG_EXPORT(132, void, png_set_bKGD,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_const_color_16p background));
 #endif
 
 #ifdef PNG_cHRM_SUPPORTED
-PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr, double *white_x, double *white_y, double *red_x,
-    double *red_y, double *green_x, double *green_y, double *blue_x,
-    double *blue_y))
-PNG_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr, double *red_X, double *red_Y, double *red_Z,
-    double *green_X, double *green_Y, double *green_Z, double *blue_X,
-    double *blue_Y, double *blue_Z))
+PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr,
+    double *white_x, double *white_y,
+    double *red_x, double *red_y,
+    double *green_x, double *green_y,
+    double *blue_x, double *blue_y))
+PNG_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr,
+    double *red_X, double *red_Y, double *red_Z,
+    double *green_X, double *green_Y, double *green_Z,
+    double *blue_X, double *blue_Y, double *blue_Z))
 PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr,
     png_fixed_point *int_white_x, png_fixed_point *int_white_y,
     png_fixed_point *int_red_x, png_fixed_point *int_red_y,
     png_fixed_point *int_green_x, png_fixed_point *int_green_y,
     png_fixed_point *int_blue_x, png_fixed_point *int_blue_y))
 PNG_FIXED_EXPORT(231, png_uint_32, png_get_cHRM_XYZ_fixed,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr,
     png_fixed_point *int_red_X, png_fixed_point *int_red_Y,
-    png_fixed_point *int_red_Z, png_fixed_point *int_green_X,
-    png_fixed_point *int_green_Y, png_fixed_point *int_green_Z,
+    png_fixed_point *int_red_Z,
+    png_fixed_point *int_green_X, png_fixed_point *int_green_Y,
+    png_fixed_point *int_green_Z,
     png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y,
     png_fixed_point *int_blue_Z))
 #endif
 
 #ifdef PNG_cHRM_SUPPORTED
-PNG_FP_EXPORT(135, void, png_set_cHRM, (png_const_structrp png_ptr,
-    png_inforp info_ptr,
-    double white_x, double white_y, double red_x, double red_y, double green_x,
-    double green_y, double blue_x, double blue_y))
-PNG_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_const_structrp png_ptr,
-    png_inforp info_ptr, double red_X, double red_Y, double red_Z,
-    double green_X, double green_Y, double green_Z, double blue_X,
-    double blue_Y, double blue_Z))
-PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_fixed_point int_white_x,
-    png_fixed_point int_white_y, png_fixed_point int_red_x,
-    png_fixed_point int_red_y, png_fixed_point int_green_x,
-    png_fixed_point int_green_y, png_fixed_point int_blue_x,
-    png_fixed_point int_blue_y))
-PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y,
-    png_fixed_point int_red_Z, png_fixed_point int_green_X,
-    png_fixed_point int_green_Y, png_fixed_point int_green_Z,
+PNG_FP_EXPORT(135, void, png_set_cHRM,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    double white_x, double white_y,
+    double red_x, double red_y,
+    double green_x, double green_y,
+    double blue_x, double blue_y))
+PNG_FP_EXPORT(232, void, png_set_cHRM_XYZ,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    double red_X, double red_Y, double red_Z,
+    double green_X, double green_Y, double green_Z,
+    double blue_X, double blue_Y, double blue_Z))
+PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_fixed_point int_white_x, png_fixed_point int_white_y,
+    png_fixed_point int_red_x, png_fixed_point int_red_y,
+    png_fixed_point int_green_x, png_fixed_point int_green_y,
+    png_fixed_point int_blue_x, png_fixed_point int_blue_y))
+PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_fixed_point int_red_X, png_fixed_point int_red_Y,
+    png_fixed_point int_red_Z,
+    png_fixed_point int_green_X, png_fixed_point int_green_Y,
+    png_fixed_point int_green_Z,
     png_fixed_point int_blue_X, png_fixed_point int_blue_Y,
     png_fixed_point int_blue_Z))
 #endif
 
 #ifdef PNG_cICP_SUPPORTED
-PNG_EXPORT(250, png_uint_32, png_get_cICP, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr, png_bytep colour_primaries,
-    png_bytep transfer_function, png_bytep matrix_coefficients,
-    png_bytep video_full_range_flag));
+PNG_EXPORT(250, png_uint_32, png_get_cICP,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr,
+    png_bytep colour_primaries, png_bytep transfer_function,
+    png_bytep matrix_coefficients, png_bytep video_full_range_flag));
 #endif
 
 #ifdef PNG_cICP_SUPPORTED
-PNG_EXPORT(251, void, png_set_cICP, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_byte colour_primaries,
-    png_byte transfer_function, png_byte matrix_coefficients,
-    png_byte video_full_range_flag));
+PNG_EXPORT(251, void, png_set_cICP,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_byte colour_primaries, png_byte transfer_function,
+    png_byte matrix_coefficients, png_byte video_full_range_flag));
 #endif
 
 #ifdef PNG_cLLI_SUPPORTED
-PNG_FP_EXPORT(252, png_uint_32, png_get_cLLI, (png_const_structrp png_ptr,
-         png_const_inforp info_ptr, double *maximum_content_light_level,
-         double *maximum_frame_average_light_level))
+PNG_FP_EXPORT(252, png_uint_32, png_get_cLLI,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr,
+    double *maximum_content_light_level,
+    double *maximum_frame_average_light_level))
 PNG_FIXED_EXPORT(253, png_uint_32, png_get_cLLI_fixed,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr,
     /* The values below are in cd/m2 (nits) and are scaled by 10,000; not
      * 100,000 as in the case of png_fixed_point.
      */
@@ -2045,11 +2143,12 @@ PNG_FIXED_EXPORT(253, png_uint_32, png_get_cLLI_fixed,
 #endif
 
 #ifdef PNG_cLLI_SUPPORTED
-PNG_FP_EXPORT(254, void, png_set_cLLI, (png_const_structrp png_ptr,
-         png_inforp info_ptr, double maximum_content_light_level,
-         double maximum_frame_average_light_level))
-PNG_FIXED_EXPORT(255, void, png_set_cLLI_fixed, (png_const_structrp png_ptr,
-    png_inforp info_ptr,
+PNG_FP_EXPORT(254, void, png_set_cLLI,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    double maximum_content_light_level,
+    double maximum_frame_average_light_level))
+PNG_FIXED_EXPORT(255, void, png_set_cLLI_fixed,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
     /* The values below are in cd/m2 (nits) and are scaled by 10,000; not
      * 100,000 as in the case of png_fixed_point.
      */
@@ -2058,64 +2157,73 @@ PNG_FIXED_EXPORT(255, void, png_set_cLLI_fixed, (png_const_structrp png_ptr,
 #endif
 
 #ifdef PNG_eXIf_SUPPORTED
-PNG_EXPORT(246, png_uint_32, png_get_eXIf, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_bytep *exif));
-PNG_EXPORT(247, void, png_set_eXIf, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_bytep exif));
+PNG_EXPORT(246, png_uint_32, png_get_eXIf,
+   (png_const_structrp png_ptr, png_inforp info_ptr, png_bytep *exif));
+PNG_EXPORT(247, void, png_set_eXIf,
+   (png_const_structrp png_ptr, png_inforp info_ptr, png_bytep exif));
 
-PNG_EXPORT(248, png_uint_32, png_get_eXIf_1, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr, png_uint_32 *num_exif, png_bytep *exif));
-PNG_EXPORT(249, void, png_set_eXIf_1, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 num_exif, png_bytep exif));
+PNG_EXPORT(248, png_uint_32, png_get_eXIf_1,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr,
+    png_uint_32 *num_exif, png_bytep *exif));
+PNG_EXPORT(249, void, png_set_eXIf_1,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_uint_32 num_exif, png_bytep exif));
 #endif
 
 #ifdef PNG_gAMA_SUPPORTED
-PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr, double *file_gamma))
+PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr,
+    double *file_gamma))
 PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr,
     png_fixed_point *int_file_gamma))
 #endif
 
 #ifdef PNG_gAMA_SUPPORTED
-PNG_FP_EXPORT(139, void, png_set_gAMA, (png_const_structrp png_ptr,
-    png_inforp info_ptr, double file_gamma))
-PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_fixed_point int_file_gamma))
+PNG_FP_EXPORT(139, void, png_set_gAMA,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    double file_gamma))
+PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_fixed_point int_file_gamma))
 #endif
 
 #ifdef PNG_hIST_SUPPORTED
-PNG_EXPORT(141, png_uint_32, png_get_hIST, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_uint_16p *hist));
-PNG_EXPORT(142, void, png_set_hIST, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_const_uint_16p hist));
+PNG_EXPORT(141, png_uint_32, png_get_hIST,
+   (png_const_structrp png_ptr, png_inforp info_ptr, png_uint_16p *hist));
+PNG_EXPORT(142, void, png_set_hIST,
+   (png_const_structrp png_ptr, png_inforp info_ptr, png_const_uint_16p hist));
 #endif
 
-PNG_EXPORT(143, png_uint_32, png_get_IHDR, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr, png_uint_32 *width, png_uint_32 *height,
-    int *bit_depth, int *color_type, int *interlace_method,
-    int *compression_method, int *filter_method));
+PNG_EXPORT(143, png_uint_32, png_get_IHDR,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr,
+    png_uint_32 *width, png_uint_32 *height,
+    int *bit_depth, int *color_type,
+    int *interlace_method, int *compression_method, int *filter_method));
 
-PNG_EXPORT(144, void, png_set_IHDR, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth,
-    int color_type, int interlace_method, int compression_method,
-    int filter_method));
+PNG_EXPORT(144, void, png_set_IHDR,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_uint_32 width, png_uint_32 height,
+    int bit_depth, int color_type,
+    int interlace_method, int compression_method, int filter_method));
 
 #ifdef PNG_mDCV_SUPPORTED
-PNG_FP_EXPORT(256, png_uint_32, png_get_mDCV, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr,
+PNG_FP_EXPORT(256, png_uint_32, png_get_mDCV,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr,
     /* The chromaticities of the mastering display.  As cHRM, but independent of
      * the encoding endpoints in cHRM, or cICP, or iCCP.  These values will
      * always be in the range 0 to 1.3107.
      */
-    double *white_x, double *white_y, double *red_x, double *red_y,
-    double *green_x, double *green_y, double *blue_x, double *blue_y,
+    double *white_x, double *white_y,
+    double *red_x, double *red_y,
+    double *green_x, double *green_y,
+    double *blue_x, double *blue_y,
     /* Mastering display luminance in cd/m2 (nits). */
     double *mastering_display_maximum_luminance,
     double *mastering_display_minimum_luminance))
 
 PNG_FIXED_EXPORT(257, png_uint_32, png_get_mDCV_fixed,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr,
     png_fixed_point *int_white_x, png_fixed_point *int_white_y,
     png_fixed_point *int_red_x, png_fixed_point *int_red_y,
     png_fixed_point *int_green_x, png_fixed_point *int_green_y,
@@ -2128,19 +2236,21 @@ PNG_FIXED_EXPORT(257, png_uint_32, png_get_mDCV_fixed,
 #endif
 
 #ifdef PNG_mDCV_SUPPORTED
-PNG_FP_EXPORT(258, void, png_set_mDCV, (png_const_structrp png_ptr,
-    png_inforp info_ptr,
+PNG_FP_EXPORT(258, void, png_set_mDCV,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
     /* The chromaticities of the mastering display.  As cHRM, but independent of
      * the encoding endpoints in cHRM, or cICP, or iCCP.
      */
-    double white_x, double white_y, double red_x, double red_y, double green_x,
-    double green_y, double blue_x, double blue_y,
+    double white_x, double white_y,
+    double red_x, double red_y,
+    double green_x, double green_y,
+    double blue_x, double blue_y,
     /* Mastering display luminance in cd/m2 (nits). */
     double mastering_display_maximum_luminance,
     double mastering_display_minimum_luminance))
 
-PNG_FIXED_EXPORT(259, void, png_set_mDCV_fixed, (png_const_structrp png_ptr,
-    png_inforp info_ptr,
+PNG_FIXED_EXPORT(259, void, png_set_mDCV_fixed,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
     /* The admissible range of these values is not the full range of a PNG
      * fixed point value.  Negative values cannot be encoded and the maximum
      * value is about 1.3 */
@@ -2156,95 +2266,107 @@ PNG_FIXED_EXPORT(259, void, png_set_mDCV_fixed, (png_const_structrp png_ptr,
 #endif
 
 #ifdef PNG_oFFs_SUPPORTED
-PNG_EXPORT(145, png_uint_32, png_get_oFFs, (png_const_structrp png_ptr,
-   png_const_inforp info_ptr, png_int_32 *offset_x, png_int_32 *offset_y,
-   int *unit_type));
+PNG_EXPORT(145, png_uint_32, png_get_oFFs,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr,
+    png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type));
 #endif
 
 #ifdef PNG_oFFs_SUPPORTED
-PNG_EXPORT(146, void, png_set_oFFs, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_int_32 offset_x, png_int_32 offset_y,
-    int unit_type));
+PNG_EXPORT(146, void, png_set_oFFs,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_int_32 offset_x, png_int_32 offset_y, int unit_type));
 #endif
 
 #ifdef PNG_pCAL_SUPPORTED
-PNG_EXPORT(147, png_uint_32, png_get_pCAL, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_charp *purpose, png_int_32 *X0,
-    png_int_32 *X1, int *type, int *nparams, png_charp *units,
-    png_charpp *params));
+PNG_EXPORT(147, png_uint_32, png_get_pCAL,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_charp *purpose, png_int_32 *X0, png_int_32 *X1,
+    int *type, int *nparams, png_charp *units, png_charpp *params));
 #endif
 
 #ifdef PNG_pCAL_SUPPORTED
-PNG_EXPORT(148, void, png_set_pCAL, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_const_charp purpose, png_int_32 X0, png_int_32 X1,
+PNG_EXPORT(148, void, png_set_pCAL,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_const_charp purpose, png_int_32 X0, png_int_32 X1,
     int type, int nparams, png_const_charp units, png_charpp params));
 #endif
 
 #ifdef PNG_pHYs_SUPPORTED
-PNG_EXPORT(149, png_uint_32, png_get_pHYs, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y,
-    int *unit_type));
+PNG_EXPORT(149, png_uint_32, png_get_pHYs,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr,
+    png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type));
 #endif
 
 #ifdef PNG_pHYs_SUPPORTED
-PNG_EXPORT(150, void, png_set_pHYs, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type));
+PNG_EXPORT(150, void, png_set_pHYs,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_uint_32 res_x, png_uint_32 res_y, int unit_type));
 #endif
 
-PNG_EXPORT(151, png_uint_32, png_get_PLTE, (png_const_structrp png_ptr,
-   png_inforp info_ptr, png_colorp *palette, int *num_palette));
+PNG_EXPORT(151, png_uint_32, png_get_PLTE,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_colorp *palette, int *num_palette));
 
-PNG_EXPORT(152, void, png_set_PLTE, (png_structrp png_ptr,
-    png_inforp info_ptr, png_const_colorp palette, int num_palette));
+PNG_EXPORT(152, void, png_set_PLTE,
+   (png_structrp png_ptr, png_inforp info_ptr,
+    png_const_colorp palette, int num_palette));
 
 #ifdef PNG_sBIT_SUPPORTED
-PNG_EXPORT(153, png_uint_32, png_get_sBIT, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_color_8p *sig_bit));
+PNG_EXPORT(153, png_uint_32, png_get_sBIT,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_color_8p *sig_bit));
 #endif
 
 #ifdef PNG_sBIT_SUPPORTED
-PNG_EXPORT(154, void, png_set_sBIT, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_const_color_8p sig_bit));
+PNG_EXPORT(154, void, png_set_sBIT,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_const_color_8p sig_bit));
 #endif
 
 #ifdef PNG_sRGB_SUPPORTED
-PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr, int *file_srgb_intent));
+PNG_EXPORT(155, png_uint_32, png_get_sRGB,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr,
+    int *file_srgb_intent));
 #endif
 
 #ifdef PNG_sRGB_SUPPORTED
-PNG_EXPORT(156, void, png_set_sRGB, (png_const_structrp png_ptr,
-    png_inforp info_ptr, int srgb_intent));
-PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_const_structrp png_ptr,
-    png_inforp info_ptr, int srgb_intent));
+PNG_EXPORT(156, void, png_set_sRGB,
+   (png_const_structrp png_ptr, png_inforp info_ptr, int srgb_intent));
+PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM,
+   (png_const_structrp png_ptr, png_inforp info_ptr, int srgb_intent));
 #endif
 
 #ifdef PNG_iCCP_SUPPORTED
-PNG_EXPORT(158, png_uint_32, png_get_iCCP, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_charpp name, int *compression_type,
+PNG_EXPORT(158, png_uint_32, png_get_iCCP,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_charpp name, int *compression_type,
     png_bytepp profile, png_uint_32 *proflen));
 #endif
 
 #ifdef PNG_iCCP_SUPPORTED
-PNG_EXPORT(159, void, png_set_iCCP, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_const_charp name, int compression_type,
+PNG_EXPORT(159, void, png_set_iCCP,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_const_charp name, int compression_type,
     png_const_bytep profile, png_uint_32 proflen));
 #endif
 
 #ifdef PNG_sPLT_SUPPORTED
-PNG_EXPORT(160, int, png_get_sPLT, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_sPLT_tpp entries));
+PNG_EXPORT(160, int, png_get_sPLT,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_sPLT_tpp entries));
 #endif
 
 #ifdef PNG_sPLT_SUPPORTED
-PNG_EXPORT(161, void, png_set_sPLT, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_const_sPLT_tp entries, int nentries));
+PNG_EXPORT(161, void, png_set_sPLT,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_const_sPLT_tp entries, int nentries));
 #endif
 
 #ifdef PNG_TEXT_SUPPORTED
 /* png_get_text also returns the number of text chunks in *num_text */
-PNG_EXPORT(162, int, png_get_text, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_textp *text_ptr, int *num_text));
+PNG_EXPORT(162, int, png_get_text,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_textp *text_ptr, int *num_text));
 #endif
 
 /* Note while png_set_text() will accept a structure whose text,
@@ -2255,35 +2377,41 @@ PNG_EXPORT(162, int, png_get_text, (png_const_structrp png_ptr,
  */
 
 #ifdef PNG_TEXT_SUPPORTED
-PNG_EXPORT(163, void, png_set_text, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_const_textp text_ptr, int num_text));
+PNG_EXPORT(163, void, png_set_text,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_const_textp text_ptr, int num_text));
 #endif
 
 #ifdef PNG_tIME_SUPPORTED
-PNG_EXPORT(164, png_uint_32, png_get_tIME, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_timep *mod_time));
+PNG_EXPORT(164, png_uint_32, png_get_tIME,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_timep *mod_time));
 #endif
 
 #ifdef PNG_tIME_SUPPORTED
-PNG_EXPORT(165, void, png_set_tIME, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_const_timep mod_time));
+PNG_EXPORT(165, void, png_set_tIME,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_const_timep mod_time));
 #endif
 
 #ifdef PNG_tRNS_SUPPORTED
-PNG_EXPORT(166, png_uint_32, png_get_tRNS, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_bytep *trans_alpha, int *num_trans,
+PNG_EXPORT(166, png_uint_32, png_get_tRNS,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_bytep *trans_alpha, int *num_trans,
     png_color_16p *trans_color));
 #endif
 
 #ifdef PNG_tRNS_SUPPORTED
-PNG_EXPORT(167, void, png_set_tRNS, (png_structrp png_ptr,
-    png_inforp info_ptr, png_const_bytep trans_alpha, int num_trans,
+PNG_EXPORT(167, void, png_set_tRNS,
+   (png_structrp png_ptr, png_inforp info_ptr,
+    png_const_bytep trans_alpha, int num_trans,
     png_const_color_16p trans_color));
 #endif
 
 #ifdef PNG_sCAL_SUPPORTED
-PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr, int *unit, double *width, double *height))
+PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr,
+    int *unit, double *width, double *height))
 #if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \
    defined(PNG_FLOATING_POINT_SUPPORTED)
 /* NOTE: this API is currently implemented using floating point arithmetic,
@@ -2292,21 +2420,22 @@ PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, (png_const_structrp png_ptr,
  * is highly recommended that png_get_sCAL_s be used instead.
  */
 PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit,
-    png_fixed_point *width, png_fixed_point *height))
+   (png_const_structrp png_ptr, png_const_inforp info_ptr,
+    int *unit, png_fixed_point *width, png_fixed_point *height))
 #endif
 PNG_EXPORT(169, png_uint_32, png_get_sCAL_s,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit,
-    png_charpp swidth, png_charpp sheight));
-
-PNG_FP_EXPORT(170, void, png_set_sCAL, (png_const_structrp png_ptr,
-    png_inforp info_ptr, int unit, double width, double height))
-PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_const_structrp png_ptr,
-   png_inforp info_ptr, int unit, png_fixed_point width,
-   png_fixed_point height))
-PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr,
-    png_inforp info_ptr, int unit,
-    png_const_charp swidth, png_const_charp sheight));
+   (png_const_structrp png_ptr, png_const_inforp info_ptr,
+    int *unit, png_charpp swidth, png_charpp sheight));
+
+PNG_FP_EXPORT(170, void, png_set_sCAL,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    int unit, double width, double height))
+PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    int unit, png_fixed_point width, png_fixed_point height))
+PNG_EXPORT(171, void, png_set_sCAL_s,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    int unit, png_const_charp swidth, png_const_charp sheight));
 #endif /* sCAL */
 
 #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
@@ -2409,7 +2538,8 @@ PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr,
  *    be processed by libpng.
  */
 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr,
+PNG_EXPORT(172, void, png_set_keep_unknown_chunks,
+   (png_structrp png_ptr,
     int keep, png_const_bytep chunk_list, int num_chunks));
 #endif /* HANDLE_AS_UNKNOWN */
 
@@ -2417,14 +2547,14 @@ PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr,
  * the result is therefore true (non-zero) if special handling is required,
  * false for the default handling.
  */
-PNG_EXPORT(173, int, png_handle_as_unknown, (png_const_structrp png_ptr,
-    png_const_bytep chunk_name));
+PNG_EXPORT(173, int, png_handle_as_unknown,
+   (png_const_structrp png_ptr, png_const_bytep chunk_name));
 #endif /* SET_UNKNOWN_CHUNKS */
 
 #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
-PNG_EXPORT(174, void, png_set_unknown_chunks, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_const_unknown_chunkp unknowns,
-    int num_unknowns));
+PNG_EXPORT(174, void, png_set_unknown_chunks,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_const_unknown_chunkp unknowns, int num_unknowns));
    /* NOTE: prior to 1.6.0 this routine set the 'location' field of the added
     * unknowns to the location currently stored in the png_struct.  This is
     * invariably the wrong value on write.  To fix this call the following API
@@ -2435,43 +2565,47 @@ PNG_EXPORT(174, void, png_set_unknown_chunks, (png_const_structrp png_ptr,
     */
 
 PNG_EXPORT(175, void, png_set_unknown_chunk_location,
-    (png_const_structrp png_ptr, png_inforp info_ptr, int chunk, int location));
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    int chunk, int location));
 
-PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_unknown_chunkpp entries));
+PNG_EXPORT(176, int, png_get_unknown_chunks,
+   (png_const_structrp png_ptr, png_inforp info_ptr,
+    png_unknown_chunkpp entries));
 #endif
 
 /* Png_free_data() will turn off the "valid" flag for anything it frees.
  * If you need to turn it off for a chunk that your application has freed,
  * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK);
  */
-PNG_EXPORT(177, void, png_set_invalid, (png_const_structrp png_ptr,
-    png_inforp info_ptr, int mask));
+PNG_EXPORT(177, void, png_set_invalid,
+   (png_const_structrp png_ptr, png_inforp info_ptr, int mask));
 
 #ifdef PNG_INFO_IMAGE_SUPPORTED
 /* The "params" pointer is currently not used and is for future expansion. */
 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-PNG_EXPORT(178, void, png_read_png, (png_structrp png_ptr, png_inforp info_ptr,
+PNG_EXPORT(178, void, png_read_png,
+   (png_structrp png_ptr, png_inforp info_ptr,
     int transforms, png_voidp params));
 #endif
 #ifdef PNG_WRITE_SUPPORTED
-PNG_EXPORT(179, void, png_write_png, (png_structrp png_ptr, png_inforp info_ptr,
+PNG_EXPORT(179, void, png_write_png,
+   (png_structrp png_ptr, png_inforp info_ptr,
     int transforms, png_voidp params));
 #endif
 #endif
 
 PNG_EXPORT(180, png_const_charp, png_get_copyright,
-    (png_const_structrp png_ptr));
+   (png_const_structrp png_ptr));
 PNG_EXPORT(181, png_const_charp, png_get_header_ver,
-    (png_const_structrp png_ptr));
+   (png_const_structrp png_ptr));
 PNG_EXPORT(182, png_const_charp, png_get_header_version,
-    (png_const_structrp png_ptr));
+   (png_const_structrp png_ptr));
 PNG_EXPORT(183, png_const_charp, png_get_libpng_ver,
-    (png_const_structrp png_ptr));
+   (png_const_structrp png_ptr));
 
 #ifdef PNG_MNG_FEATURES_SUPPORTED
-PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structrp png_ptr,
-    png_uint_32 mng_features_permitted));
+PNG_EXPORT(184, png_uint_32, png_permit_mng_features,
+   (png_structrp png_ptr, png_uint_32 mng_features_permitted));
 #endif
 
 /* For use in png_set_keep_unknown, added to version 1.2.6 */
@@ -2485,71 +2619,74 @@ PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structrp png_ptr,
  * messages before passing them to the error or warning handler.
  */
 #ifdef PNG_ERROR_NUMBERS_SUPPORTED
-PNG_EXPORT(185, void, png_set_strip_error_numbers, (png_structrp png_ptr,
-    png_uint_32 strip_mode));
+PNG_EXPORT(185, void, png_set_strip_error_numbers,
+   (png_structrp png_ptr, png_uint_32 strip_mode));
 #endif
 
 /* Added in libpng-1.2.6 */
 #ifdef PNG_SET_USER_LIMITS_SUPPORTED
-PNG_EXPORT(186, void, png_set_user_limits, (png_structrp png_ptr,
+PNG_EXPORT(186, void, png_set_user_limits,
+   (png_structrp png_ptr,
     png_uint_32 user_width_max, png_uint_32 user_height_max));
 PNG_EXPORT(187, png_uint_32, png_get_user_width_max,
-    (png_const_structrp png_ptr));
+   (png_const_structrp png_ptr));
 PNG_EXPORT(188, png_uint_32, png_get_user_height_max,
-    (png_const_structrp png_ptr));
+   (png_const_structrp png_ptr));
 /* Added in libpng-1.4.0 */
-PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structrp png_ptr,
-    png_uint_32 user_chunk_cache_max));
+PNG_EXPORT(189, void, png_set_chunk_cache_max,
+   (png_structrp png_ptr, png_uint_32 user_chunk_cache_max));
 PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max,
-    (png_const_structrp png_ptr));
+   (png_const_structrp png_ptr));
 /* Added in libpng-1.4.1 */
-PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structrp png_ptr,
-    png_alloc_size_t user_chunk_cache_max));
+PNG_EXPORT(191, void, png_set_chunk_malloc_max,
+   (png_structrp png_ptr, png_alloc_size_t user_chunk_cache_max));
 PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max,
-    (png_const_structrp png_ptr));
+   (png_const_structrp png_ptr));
 #endif
 
 #if defined(PNG_INCH_CONVERSIONS_SUPPORTED)
 PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr));
+   (png_const_structrp png_ptr, png_const_inforp info_ptr));
 
 PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr));
+   (png_const_structrp png_ptr, png_const_inforp info_ptr));
 
 PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr));
+   (png_const_structrp png_ptr, png_const_inforp info_ptr));
 
 PNG_FP_EXPORT(196, float, png_get_x_offset_inches,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr))
+   (png_const_structrp png_ptr, png_const_inforp info_ptr))
 #ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */
 PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr))
+   (png_const_structrp png_ptr, png_const_inforp info_ptr))
 #endif
 
-PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr))
+PNG_FP_EXPORT(197, float, png_get_y_offset_inches,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr))
 #ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */
 PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr))
+   (png_const_structrp png_ptr, png_const_inforp info_ptr))
 #endif
 
 #  ifdef PNG_pHYs_SUPPORTED
-PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y,
-    int *unit_type));
+PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi,
+   (png_const_structrp png_ptr, png_const_inforp info_ptr,
+    png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type));
 #  endif /* pHYs */
 #endif  /* INCH_CONVERSIONS */
 
 /* Added in libpng-1.4.0 */
 #ifdef PNG_IO_STATE_SUPPORTED
-PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_const_structrp png_ptr));
+PNG_EXPORT(199, png_uint_32, png_get_io_state,
+   (png_const_structrp png_ptr));
 
 /* Removed from libpng 1.6; use png_get_io_chunk_type. */
-PNG_REMOVED(200, png_const_bytep, png_get_io_chunk_name, (png_structrp png_ptr),
-    PNG_DEPRECATED)
+PNG_REMOVED(200, png_const_bytep, png_get_io_chunk_name,
+   (png_structrp png_ptr),
+   PNG_DEPRECATED)
 
 PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type,
-    (png_const_structrp png_ptr));
+   (png_const_structrp png_ptr));
 
 /* The flags returned by png_get_io_state() are the following: */
 #  define PNG_IO_NONE        0x0000   /* no I/O at this moment */
@@ -2674,21 +2811,26 @@ PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type,
 #endif /* READ_COMPOSITE_NODIV */
 
 #ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED
-PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf));
-PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf));
-PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf));
+PNG_EXPORT(201, png_uint_32, png_get_uint_32,
+   (png_const_bytep buf));
+PNG_EXPORT(202, png_uint_16, png_get_uint_16,
+   (png_const_bytep buf));
+PNG_EXPORT(203, png_int_32, png_get_int_32,
+   (png_const_bytep buf));
 #endif
 
-PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_const_structrp png_ptr,
-    png_const_bytep buf));
+PNG_EXPORT(204, png_uint_32, png_get_uint_31,
+   (png_const_structrp png_ptr, png_const_bytep buf));
 /* No png_get_int_16 -- may be added if there's a real need for it. */
 
 /* Place a 32-bit number into a buffer in PNG byte order (big-endian). */
 #ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED
-PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i));
+PNG_EXPORT(205, void, png_save_uint_32,
+   (png_bytep buf, png_uint_32 i));
 #endif
 #ifdef PNG_SAVE_INT_32_SUPPORTED
-PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i));
+PNG_EXPORT(206, void, png_save_int_32,
+   (png_bytep buf, png_int_32 i));
 #endif
 
 /* Place a 16-bit number into a buffer in PNG byte order.
@@ -2696,7 +2838,8 @@ PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i));
  * just to avoid potential problems on pre-ANSI C compilers.
  */
 #ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED
-PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i));
+PNG_EXPORT(207, void, png_save_uint_16,
+   (png_bytep buf, unsigned int i));
 /* No png_save_int_16 -- may be added if there's a real need for it. */
 #endif
 
@@ -2743,10 +2886,10 @@ PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i));
 
 #ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
 PNG_EXPORT(242, void, png_set_check_for_invalid_index,
-    (png_structrp png_ptr, int allowed));
+   (png_structrp png_ptr, int allowed));
 #  ifdef PNG_GET_PALETTE_MAX_SUPPORTED
-PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr,
-    png_const_infop info_ptr));
+PNG_EXPORT(243, int, png_get_palette_max,
+   (png_const_structp png_ptr, png_const_infop info_ptr));
 #  endif
 #endif /* CHECK_FOR_INVALID_INDEX */
 
@@ -3110,24 +3253,25 @@ typedef struct
  * the png_controlp field 'opaque' to NULL (or, safer, memset the whole thing.)
  */
 #ifdef PNG_STDIO_SUPPORTED
-PNG_EXPORT(234, int, png_image_begin_read_from_file, (png_imagep image,
-   const char *file_name));
+PNG_EXPORT(234, int, png_image_begin_read_from_file,
+   (png_imagep image, const char *file_name));
    /* The named file is opened for read and the image header is filled in
     * from the PNG header in the file.
     */
 
-PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image,
-   FILE* file));
+PNG_EXPORT(235, int, png_image_begin_read_from_stdio,
+   (png_imagep image, FILE *file));
    /* The PNG header is read from the stdio FILE object. */
 #endif /* STDIO */
 
-PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image,
-   png_const_voidp memory, size_t size));
+PNG_EXPORT(236, int, png_image_begin_read_from_memory,
+   (png_imagep image, png_const_voidp memory, size_t size));
    /* The PNG header is read from the given memory buffer. */
 
-PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image,
-   png_const_colorp background, void *buffer, png_int_32 row_stride,
-   void *colormap));
+PNG_EXPORT(237, int, png_image_finish_read,
+   (png_imagep image,
+    png_const_colorp background, void *buffer, png_int_32 row_stride,
+    void *colormap));
    /* Finish reading the image into the supplied buffer and clean up the
     * png_image structure.
     *
@@ -3160,7 +3304,8 @@ PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image,
     * written to the colormap; this may be less than the original value.
     */
 
-PNG_EXPORT(238, void, png_image_free, (png_imagep image));
+PNG_EXPORT(238, void, png_image_free,
+   (png_imagep image));
    /* Free any data allocated by libpng in image->opaque, setting the pointer to
     * NULL.  May be called at any time after the structure is initialized.
     */
@@ -3184,15 +3329,17 @@ PNG_EXPORT(238, void, png_image_free, (png_imagep image));
  * colormap_entries: set to the number of entries in the color-map (0 to 256)
  */
 #ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
-PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image,
-   const char *file, int convert_to_8bit, const void *buffer,
-   png_int_32 row_stride, const void *colormap));
+PNG_EXPORT(239, int, png_image_write_to_file,
+   (png_imagep image,
+    const char *file, int convert_to_8bit, const void *buffer,
+    png_int_32 row_stride, const void *colormap));
    /* Write the image to the named file. */
 
-PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file,
-   int convert_to_8_bit, const void *buffer, png_int_32 row_stride,
-   const void *colormap));
-   /* Write the image to the given (FILE*). */
+PNG_EXPORT(240, int, png_image_write_to_stdio,
+   (png_imagep image,
+    FILE *file, int convert_to_8_bit, const void *buffer,
+    png_int_32 row_stride, const void *colormap));
+   /* Write the image to the given FILE object. */
 #endif /* SIMPLIFIED_WRITE_STDIO */
 
 /* With all write APIs if image is in one of the linear formats with 16-bit
@@ -3216,9 +3363,11 @@ PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file,
  * notices) you need to use one of the other APIs.
  */
 
-PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory,
-   png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8_bit,
-   const void *buffer, png_int_32 row_stride, const void *colormap));
+PNG_EXPORT(245, int, png_image_write_to_memory,
+   (png_imagep image,
+    void *memory, png_alloc_size_t * PNG_RESTRICT memory_bytes,
+    int convert_to_8_bit,
+    const void *buffer, png_int_32 row_stride, const void *colormap));
    /* Write the image to the given memory buffer.  The function both writes the
     * whole PNG data stream to *memory and updates *memory_bytes with the count
     * of bytes written.
@@ -3332,26 +3481,45 @@ PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory,
  *           selected at run time.
  */
 #ifdef PNG_SET_OPTION_SUPPORTED
+
+/* HARDWARE: ARM Neon SIMD instructions supported */
 #ifdef PNG_ARM_NEON_API_SUPPORTED
-#  define PNG_ARM_NEON   0 /* HARDWARE: ARM Neon SIMD instructions supported */
+#  define PNG_ARM_NEON 0
 #endif
-#define PNG_MAXIMUM_INFLATE_WINDOW 2 /* SOFTWARE: force maximum window */
-#define PNG_SKIP_sRGB_CHECK_PROFILE 4 /* SOFTWARE: Check ICC profile for sRGB */
+
+/* SOFTWARE: Force maximum window */
+#define PNG_MAXIMUM_INFLATE_WINDOW 2
+
+/* SOFTWARE: Check ICC profile for sRGB */
+#define PNG_SKIP_sRGB_CHECK_PROFILE 4
+
+/* HARDWARE: MIPS MSA SIMD instructions supported */
 #ifdef PNG_MIPS_MSA_API_SUPPORTED
-#  define PNG_MIPS_MSA   6 /* HARDWARE: MIPS Msa SIMD instructions supported */
+#  define PNG_MIPS_MSA 6
 #endif
+
+/* SOFTWARE: Disable Adler32 check on IDAT */
 #ifdef PNG_DISABLE_ADLER32_CHECK_SUPPORTED
-#  define PNG_IGNORE_ADLER32 8 /* SOFTWARE: disable Adler32 check on IDAT */
+#  define PNG_IGNORE_ADLER32 8
 #endif
+
+/* HARDWARE: PowerPC VSX SIMD instructions supported */
 #ifdef PNG_POWERPC_VSX_API_SUPPORTED
-#  define PNG_POWERPC_VSX   10 /* HARDWARE: PowerPC VSX SIMD instructions
-                                * supported */
+#  define PNG_POWERPC_VSX 10
 #endif
+
+/* HARDWARE: MIPS MMI SIMD instructions supported */
 #ifdef PNG_MIPS_MMI_API_SUPPORTED
-#  define PNG_MIPS_MMI   12 /* HARDWARE: MIPS MMI SIMD instructions supported */
+#  define PNG_MIPS_MMI 12
+#endif
+
+/* HARDWARE: RISC-V RVV SIMD instructions supported */
+#ifdef PNG_RISCV_RVV_API_SUPPORTED
+#  define PNG_RISCV_RVV 14
 #endif
 
-#define PNG_OPTION_NEXT  14 /* Next option - numbers must be even */
+/* Next option - numbers must be even */
+#define PNG_OPTION_NEXT 16
 
 /* Return values: NOTE: there are four values and 'off' is *not* zero */
 #define PNG_OPTION_UNSET   0 /* Unset - defaults to off */
@@ -3375,7 +3543,7 @@ PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option,
  * one to use is one more than this.)
  */
 #ifdef PNG_EXPORT_LAST_ORDINAL
-  PNG_EXPORT_LAST_ORDINAL(259);
+   PNG_EXPORT_LAST_ORDINAL(259);
 #endif
 
 #ifdef __cplusplus
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h b/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h
index 70bca6fa1c9..959c604edbc 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h
@@ -29,9 +29,9 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * libpng version 1.6.47
+ * libpng version 1.6.54
  *
- * Copyright (c) 2018-2025 Cosmin Truta
+ * Copyright (c) 2018-2026 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -248,25 +248,13 @@
   /* NOTE: PNGCBAPI always defaults to PNGCAPI. */
 
 #  if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD)
-#     error "PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed"
+#     error PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed
 #  endif
 
-#  if (defined(_MSC_VER) && _MSC_VER < 800) ||\
-      (defined(__BORLANDC__) && __BORLANDC__ < 0x500)
-   /* older Borland and MSC
-    * compilers used '__export' and required this to be after
-    * the type.
-    */
-#    ifndef PNG_EXPORT_TYPE
-#      define PNG_EXPORT_TYPE(type) type PNG_IMPEXP
-#    endif
-#    define PNG_DLL_EXPORT __export
-#  else /* newer compiler */
-#    define PNG_DLL_EXPORT __declspec(dllexport)
-#    ifndef PNG_DLL_IMPORT
-#      define PNG_DLL_IMPORT __declspec(dllimport)
-#    endif
-#  endif /* compiler */
+#  define PNG_DLL_EXPORT __declspec(dllexport)
+#  ifndef PNG_DLL_IMPORT
+#    define PNG_DLL_IMPORT __declspec(dllimport)
+#  endif
 
 #else /* !Windows */
 #  if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__)
@@ -508,7 +496,7 @@
 #if CHAR_BIT == 8 && UCHAR_MAX == 255
    typedef unsigned char png_byte;
 #else
-#  error "libpng requires 8-bit bytes"
+#  error libpng requires 8-bit bytes
 #endif
 
 #if INT_MIN == -32768 && INT_MAX == 32767
@@ -516,7 +504,7 @@
 #elif SHRT_MIN == -32768 && SHRT_MAX == 32767
    typedef short png_int_16;
 #else
-#  error "libpng requires a signed 16-bit type"
+#  error libpng requires a signed 16-bit integer type
 #endif
 
 #if UINT_MAX == 65535
@@ -524,7 +512,7 @@
 #elif USHRT_MAX == 65535
    typedef unsigned short png_uint_16;
 #else
-#  error "libpng requires an unsigned 16-bit type"
+#  error libpng requires an unsigned 16-bit integer type
 #endif
 
 #if INT_MIN < -2147483646 && INT_MAX > 2147483646
@@ -532,7 +520,7 @@
 #elif LONG_MIN < -2147483646 && LONG_MAX > 2147483646
    typedef long int png_int_32;
 #else
-#  error "libpng requires a signed 32-bit (or more) type"
+#  error libpng requires a signed 32-bit (or longer) integer type
 #endif
 
 #if UINT_MAX > 4294967294U
@@ -540,7 +528,7 @@
 #elif ULONG_MAX > 4294967294U
    typedef unsigned long int png_uint_32;
 #else
-#  error "libpng requires an unsigned 32-bit (or more) type"
+#  error libpng requires an unsigned 32-bit (or longer) integer type
 #endif
 
 /* Prior to 1.6.0, it was possible to disable the use of size_t and ptrdiff_t.
@@ -621,10 +609,6 @@ typedef const png_fixed_point * png_const_fixed_point_p;
 typedef size_t                * png_size_tp;
 typedef const size_t          * png_const_size_tp;
 
-#ifdef PNG_STDIO_SUPPORTED
-typedef FILE            * png_FILE_p;
-#endif
-
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 typedef double       * png_doublep;
 typedef const double * png_const_doublep;
@@ -646,6 +630,15 @@ typedef double          * * png_doublepp;
 /* Pointers to pointers to pointers; i.e., pointer to array */
 typedef char            * * * png_charppp;
 
+#ifdef PNG_STDIO_SUPPORTED
+/* With PNG_STDIO_SUPPORTED it was possible to use I/O streams that were
+ * not necessarily stdio FILE streams, to allow building Windows applications
+ * before Win32 and Windows CE applications before WinCE 3.0, but that kind
+ * of support has long been discontinued.
+ */
+typedef FILE            * png_FILE_p; /* [Deprecated] */
+#endif
+
 #endif /* PNG_BUILDING_SYMBOL_TABLE */
 
 #endif /* PNGCONF_H */
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngdebug.h b/src/java.desktop/share/native/libsplashscreen/libpng/pngdebug.h
index 8eb5400ea9a..6ea2644dfcd 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngdebug.h
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngdebug.h
@@ -22,14 +22,14 @@
  * questions.
  */
 
-/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c
+/* pngdebug.h - internal debugging macros for libpng
  *
  * This file is available under and governed by the GNU General Public
  * License version 2 only, as published by the Free Software Foundation.
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018 Cosmin Truta
+ * Copyright (c) 2018-2025 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -39,6 +39,10 @@
  * and license in png.h
  */
 
+#ifndef PNGPRIV_H
+#  error This file must not be included by applications; please include 
+#endif
+
 /* Define PNG_DEBUG at compile time for debugging information.  Higher
  * numbers for PNG_DEBUG mean more debugging information.  This has
  * only been added since version 0.95 so it is not implemented throughout
@@ -63,9 +67,6 @@
 #define PNGDEBUG_H
 /* These settings control the formatting of messages in png.c and pngerror.c */
 /* Moved to pngdebug.h at 1.5.0 */
-#  ifndef PNG_LITERAL_SHARP
-#    define PNG_LITERAL_SHARP 0x23
-#  endif
 #  ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET
 #    define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b
 #  endif
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngerror.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngerror.c
index ea0103331d3..324d1951a52 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngerror.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngerror.c
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018-2024 Cosmin Truta
+ * Copyright (c) 2018-2025 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -68,46 +68,6 @@ PNG_FUNCTION(void,PNGAPI
 png_error,(png_const_structrp png_ptr, png_const_charp error_message),
     PNG_NORETURN)
 {
-#ifdef PNG_ERROR_NUMBERS_SUPPORTED
-   char msg[16];
-   if (png_ptr != NULL)
-   {
-      if ((png_ptr->flags &
-         (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0)
-      {
-         if (*error_message == PNG_LITERAL_SHARP)
-         {
-            /* Strip "#nnnn " from beginning of error message. */
-            int offset;
-            for (offset = 1; offset<15; offset++)
-               if (error_message[offset] == ' ')
-                  break;
-
-            if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0)
-            {
-               int i;
-               for (i = 0; i < offset - 1; i++)
-                  msg[i] = error_message[i + 1];
-               msg[i - 1] = '\0';
-               error_message = msg;
-            }
-
-            else
-               error_message += offset;
-         }
-
-         else
-         {
-            if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0)
-            {
-               msg[0] = '0';
-               msg[1] = '\0';
-               error_message = msg;
-            }
-         }
-      }
-   }
-#endif
    if (png_ptr != NULL && png_ptr->error_fn != NULL)
       (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr),
           error_message);
@@ -118,7 +78,8 @@ png_error,(png_const_structrp png_ptr, png_const_charp error_message),
 }
 #else
 PNG_FUNCTION(void,PNGAPI
-png_err,(png_const_structrp png_ptr),PNG_NORETURN)
+png_err,(png_const_structrp png_ptr),
+    PNG_NORETURN)
 {
    /* Prior to 1.5.2 the error_fn received a NULL pointer, expressed
     * erroneously as '\0', instead of the empty string "".  This was
@@ -245,21 +206,6 @@ void PNGAPI
 png_warning(png_const_structrp png_ptr, png_const_charp warning_message)
 {
    int offset = 0;
-   if (png_ptr != NULL)
-   {
-#ifdef PNG_ERROR_NUMBERS_SUPPORTED
-   if ((png_ptr->flags &
-       (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0)
-#endif
-      {
-         if (*warning_message == PNG_LITERAL_SHARP)
-         {
-            for (offset = 1; offset < 15; offset++)
-               if (warning_message[offset] == ' ')
-                  break;
-         }
-      }
-   }
    if (png_ptr != NULL && png_ptr->warning_fn != NULL)
       (*(png_ptr->warning_fn))(png_constcast(png_structrp,png_ptr),
           warning_message + offset);
@@ -460,8 +406,8 @@ static const char png_digit[16] = {
 };
 
 static void /* PRIVATE */
-png_format_buffer(png_const_structrp png_ptr, png_charp buffer, png_const_charp
-    error_message)
+png_format_buffer(png_const_structrp png_ptr, png_charp buffer,
+    png_const_charp error_message)
 {
    png_uint_32 chunk_name = png_ptr->chunk_name;
    int iout = 0, ishift = 24;
@@ -540,8 +486,8 @@ png_chunk_warning(png_const_structrp png_ptr, png_const_charp warning_message)
 #ifdef PNG_READ_SUPPORTED
 #ifdef PNG_BENIGN_ERRORS_SUPPORTED
 void PNGAPI
-png_chunk_benign_error(png_const_structrp png_ptr, png_const_charp
-    error_message)
+png_chunk_benign_error(png_const_structrp png_ptr,
+    png_const_charp error_message)
 {
    if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0)
       png_chunk_warning(png_ptr, error_message);
@@ -598,7 +544,8 @@ png_chunk_report(png_const_structrp png_ptr, png_const_charp message, int error)
 #ifdef PNG_ERROR_TEXT_SUPPORTED
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 PNG_FUNCTION(void,
-png_fixed_error,(png_const_structrp png_ptr, png_const_charp name),PNG_NORETURN)
+png_fixed_error,(png_const_structrp png_ptr, png_const_charp name),
+    PNG_NORETURN)
 {
 #  define fixed_message "fixed point overflow in "
 #  define fixed_message_ln ((sizeof fixed_message)-1)
@@ -741,42 +688,9 @@ png_default_error,(png_const_structrp png_ptr, png_const_charp error_message),
     PNG_NORETURN)
 {
 #ifdef PNG_CONSOLE_IO_SUPPORTED
-#ifdef PNG_ERROR_NUMBERS_SUPPORTED
-   /* Check on NULL only added in 1.5.4 */
-   if (error_message != NULL && *error_message == PNG_LITERAL_SHARP)
-   {
-      /* Strip "#nnnn " from beginning of error message. */
-      int offset;
-      char error_number[16];
-      for (offset = 0; offset<15; offset++)
-      {
-         error_number[offset] = error_message[offset + 1];
-         if (error_message[offset] == ' ')
-            break;
-      }
-
-      if ((offset > 1) && (offset < 15))
-      {
-         error_number[offset - 1] = '\0';
-         fprintf(stderr, "libpng error no. %s: %s",
-             error_number, error_message + offset + 1);
-         fprintf(stderr, PNG_STRING_NEWLINE);
-      }
-
-      else
-      {
-         fprintf(stderr, "libpng error: %s, offset=%d",
-             error_message, offset);
-         fprintf(stderr, PNG_STRING_NEWLINE);
-      }
-   }
-   else
-#endif
-   {
-      fprintf(stderr, "libpng error: %s", error_message ? error_message :
-         "undefined");
-      fprintf(stderr, PNG_STRING_NEWLINE);
-   }
+   fprintf(stderr, "libpng error: %s", error_message ? error_message :
+      "undefined");
+   fprintf(stderr, PNG_STRING_NEWLINE);
 #else
    PNG_UNUSED(error_message) /* Make compiler happy */
 #endif
@@ -784,7 +698,8 @@ png_default_error,(png_const_structrp png_ptr, png_const_charp error_message),
 }
 
 PNG_FUNCTION(void,PNGAPI
-png_longjmp,(png_const_structrp png_ptr, int val),PNG_NORETURN)
+png_longjmp,(png_const_structrp png_ptr, int val),
+    PNG_NORETURN)
 {
 #ifdef PNG_SETJMP_SUPPORTED
    if (png_ptr != NULL && png_ptr->longjmp_fn != NULL &&
@@ -814,40 +729,8 @@ static void /* PRIVATE */
 png_default_warning(png_const_structrp png_ptr, png_const_charp warning_message)
 {
 #ifdef PNG_CONSOLE_IO_SUPPORTED
-#  ifdef PNG_ERROR_NUMBERS_SUPPORTED
-   if (*warning_message == PNG_LITERAL_SHARP)
-   {
-      int offset;
-      char warning_number[16];
-      for (offset = 0; offset < 15; offset++)
-      {
-         warning_number[offset] = warning_message[offset + 1];
-         if (warning_message[offset] == ' ')
-            break;
-      }
-
-      if ((offset > 1) && (offset < 15))
-      {
-         warning_number[offset + 1] = '\0';
-         fprintf(stderr, "libpng warning no. %s: %s",
-             warning_number, warning_message + offset);
-         fprintf(stderr, PNG_STRING_NEWLINE);
-      }
-
-      else
-      {
-         fprintf(stderr, "libpng warning: %s",
-             warning_message);
-         fprintf(stderr, PNG_STRING_NEWLINE);
-      }
-   }
-   else
-#  endif
-
-   {
-      fprintf(stderr, "libpng warning: %s", warning_message);
-      fprintf(stderr, PNG_STRING_NEWLINE);
-   }
+   fprintf(stderr, "libpng warning: %s", warning_message);
+   fprintf(stderr, PNG_STRING_NEWLINE);
 #else
    PNG_UNUSED(warning_message) /* Make compiler happy */
 #endif
@@ -895,12 +778,8 @@ png_get_error_ptr(png_const_structrp png_ptr)
 void PNGAPI
 png_set_strip_error_numbers(png_structrp png_ptr, png_uint_32 strip_mode)
 {
-   if (png_ptr != NULL)
-   {
-      png_ptr->flags &=
-         ((~(PNG_FLAG_STRIP_ERROR_NUMBERS |
-         PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode);
-   }
+   PNG_UNUSED(png_ptr)
+   PNG_UNUSED(strip_mode)
 }
 #endif
 
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngget.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngget.c
index d67adbae247..a5bdcd1b524 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngget.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngget.c
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018-2024 Cosmin Truta
+ * Copyright (c) 2018-2025 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -151,8 +151,8 @@ png_get_compression_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
 }
 
 png_uint_32 PNGAPI
-png_get_x_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp
-   info_ptr)
+png_get_x_pixels_per_meter(png_const_structrp png_ptr,
+    png_const_inforp info_ptr)
 {
 #ifdef PNG_pHYs_SUPPORTED
    png_debug(1, "in png_get_x_pixels_per_meter");
@@ -172,8 +172,8 @@ png_get_x_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp
 }
 
 png_uint_32 PNGAPI
-png_get_y_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp
-    info_ptr)
+png_get_y_pixels_per_meter(png_const_structrp png_ptr,
+    png_const_inforp info_ptr)
 {
 #ifdef PNG_pHYs_SUPPORTED
    png_debug(1, "in png_get_y_pixels_per_meter");
@@ -215,8 +215,8 @@ png_get_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp info_ptr)
 
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 float PNGAPI
-png_get_pixel_aspect_ratio(png_const_structrp png_ptr, png_const_inforp
-   info_ptr)
+png_get_pixel_aspect_ratio(png_const_structrp png_ptr,
+    png_const_inforp info_ptr)
 {
 #ifdef PNG_READ_pHYs_SUPPORTED
    png_debug(1, "in png_get_pixel_aspect_ratio");
@@ -766,7 +766,6 @@ png_get_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
    }
 
    return 0;
-
 }
 #endif
 
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pnginfo.h b/src/java.desktop/share/native/libsplashscreen/libpng/pnginfo.h
index bc6ed3d09c9..c79c6cc780f 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pnginfo.h
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pnginfo.h
@@ -22,14 +22,14 @@
  * questions.
  */
 
-/* pnginfo.h - header file for PNG reference library
+/* pnginfo.h - internal structures for libpng
  *
  * This file is available under and governed by the GNU General Public
  * License version 2 only, as published by the Free Software Foundation.
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018 Cosmin Truta
+ * Copyright (c) 2018-2025 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2013,2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -39,43 +39,20 @@
  * and license in png.h
  */
 
- /* png_info is a structure that holds the information in a PNG file so
- * that the application can find out the characteristics of the image.
- * If you are reading the file, this structure will tell you what is
- * in the PNG file.  If you are writing the file, fill in the information
- * you want to put into the PNG file, using png_set_*() functions, then
- * call png_write_info().
- *
- * The names chosen should be very close to the PNG specification, so
- * consult that document for information about the meaning of each field.
- *
- * With libpng < 0.95, it was only possible to directly set and read the
- * the values in the png_info_struct, which meant that the contents and
- * order of the values had to remain fixed.  With libpng 0.95 and later,
- * however, there are now functions that abstract the contents of
- * png_info_struct from the application, so this makes it easier to use
- * libpng with dynamic libraries, and even makes it possible to use
- * libraries that don't have all of the libpng ancillary chunk-handing
- * functionality.  In libpng-1.5.0 this was moved into a separate private
- * file that is not visible to applications.
+#ifndef PNGPRIV_H
+#  error This file must not be included by applications; please include 
+#endif
+
+/* INTERNAL, PRIVATE definition of a PNG.
  *
- * The following members may have allocated storage attached that should be
- * cleaned up before the structure is discarded: palette, trans, text,
- * pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile,
- * splt_palettes, scal_unit, row_pointers, and unknowns.   By default, these
- * are automatically freed when the info structure is deallocated, if they were
- * allocated internally by libpng.  This behavior can be changed by means
- * of the png_data_freer() function.
+ * png_info is a modifiable description of a PNG datastream.  The fields inside
+ * this structure are accessed through png_get_() functions and modified
+ * using png_set_() functions.
  *
- * More allocation details: all the chunk-reading functions that
- * change these members go through the corresponding png_set_*
- * functions.  A function to clear these members is available: see
- * png_free_data().  The png_set_* functions do not depend on being
- * able to point info structure members to any of the storage they are
- * passed (they make their own copies), EXCEPT that the png_set_text
- * functions use the same storage passed to them in the text_ptr or
- * itxt_ptr structure argument, and the png_set_rows and png_set_unknowns
- * functions do not make their own copies.
+ * Some functions in libpng do directly access members of png_info.  However,
+ * this should be avoided.  png_struct objects contain members which hold
+ * caches, sometimes optimised, of the values from png_info objects, and
+ * png_info is not passed to the functions which read and write image data.
  */
 #ifndef PNGINFO_H
 #define PNGINFO_H
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h b/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h
index 906f855db0e..b413b510acf 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h
@@ -31,9 +31,9 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  */
-/* libpng version 1.6.47 */
+/* libpng version 1.6.54 */
 
-/* Copyright (c) 2018-2025 Cosmin Truta */
+/* Copyright (c) 2018-2026 Cosmin Truta */
 /* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */
 
 /* This code is released under the libpng license. */
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngmem.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngmem.c
index ba9eb4df402..8ec703616ec 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngmem.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngmem.c
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018 Cosmin Truta
+ * Copyright (c) 2018-2025 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2014,2016 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -75,7 +75,8 @@ png_destroy_png_struct(png_structrp png_ptr)
  * have the ability to do that.
  */
 PNG_FUNCTION(png_voidp,PNGAPI
-png_calloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
+png_calloc,(png_const_structrp png_ptr, png_alloc_size_t size),
+    PNG_ALLOCATED)
 {
    png_voidp ret;
 
@@ -147,7 +148,8 @@ png_malloc_array_checked(png_const_structrp png_ptr, int nelements,
 
 PNG_FUNCTION(png_voidp /* PRIVATE */,
 png_malloc_array,(png_const_structrp png_ptr, int nelements,
-    size_t element_size),PNG_ALLOCATED)
+    size_t element_size),
+    PNG_ALLOCATED)
 {
    if (nelements <= 0 || element_size == 0)
       png_error(png_ptr, "internal error: array alloc");
@@ -157,7 +159,8 @@ png_malloc_array,(png_const_structrp png_ptr, int nelements,
 
 PNG_FUNCTION(png_voidp /* PRIVATE */,
 png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array,
-    int old_elements, int add_elements, size_t element_size),PNG_ALLOCATED)
+    int old_elements, int add_elements, size_t element_size),
+    PNG_ALLOCATED)
 {
    /* These are internal errors: */
    if (add_elements <= 0 || element_size == 0 || old_elements < 0 ||
@@ -196,7 +199,8 @@ png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array,
  * function png_malloc_default is also provided.
  */
 PNG_FUNCTION(png_voidp,PNGAPI
-png_malloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
+png_malloc,(png_const_structrp png_ptr, png_alloc_size_t size),
+    PNG_ALLOCATED)
 {
    png_voidp ret;
 
@@ -270,7 +274,8 @@ png_free(png_const_structrp png_ptr, png_voidp ptr)
 }
 
 PNG_FUNCTION(void,PNGAPI
-png_free_default,(png_const_structrp png_ptr, png_voidp ptr),PNG_DEPRECATED)
+png_free_default,(png_const_structrp png_ptr, png_voidp ptr),
+    PNG_DEPRECATED)
 {
    if (png_ptr == NULL || ptr == NULL)
       return;
@@ -284,8 +289,8 @@ png_free_default,(png_const_structrp png_ptr, png_voidp ptr),PNG_DEPRECATED)
  * of allocating and freeing memory.
  */
 void PNGAPI
-png_set_mem_fn(png_structrp png_ptr, png_voidp mem_ptr, png_malloc_ptr
-  malloc_fn, png_free_ptr free_fn)
+png_set_mem_fn(png_structrp png_ptr, png_voidp mem_ptr,
+    png_malloc_ptr malloc_fn, png_free_ptr free_fn)
 {
    if (png_ptr != NULL)
    {
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngpread.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngpread.c
index 86d0c7aaa64..3bfa913000f 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngpread.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngpread.c
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018-2024 Cosmin Truta
+ * Copyright (c) 2018-2025 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -258,6 +258,14 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
          png_benign_error(png_ptr, "Too many IDATs found");
    }
 
+   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
+   {
+      /* These flags must be set consistently for all non-IDAT chunks,
+       * including the unknown chunks.
+       */
+      png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT | PNG_AFTER_IDAT;
+   }
+
    if (chunk_name == png_IHDR)
    {
       if (png_ptr->push_length != 13)
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h b/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h
index 25bac4b9e69..ee91f58d4ba 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018-2024 Cosmin Truta
+ * Copyright (c) 2018-2025 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -48,8 +48,20 @@
  * they should be well aware of the issues that may arise from doing so.
  */
 
+
+/* pngpriv.h must be included first in each translation unit inside libpng.
+ * On the other hand, it must not be included at all, directly or indirectly,
+ * by any application code that uses the libpng API.
+ */
 #ifndef PNGPRIV_H
-#define PNGPRIV_H
+#  define PNGPRIV_H
+#else
+#  error Duplicate inclusion of pngpriv.h; please check the libpng source files
+#endif
+
+#if defined(PNG_H) || defined(PNGCONF_H) || defined(PNGLCONF_H)
+#  error This file must not be included by applications; please include 
+#endif
 
 /* Feature Test Macros.  The following are defined here to ensure that correctly
  * implemented libraries reveal the APIs libpng needs to build and hide those
@@ -86,7 +98,6 @@
  */
 #if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H)
 #  include 
-
    /* Pick up the definition of 'restrict' from config.h if it was read: */
 #  define PNG_RESTRICT restrict
 #endif
@@ -96,9 +107,7 @@
  * are not internal definitions may be required.  This is handled below just
  * before png.h is included, but load the configuration now if it is available.
  */
-#ifndef PNGLCONF_H
-#  include "pnglibconf.h"
-#endif
+#include "pnglibconf.h"
 
 /* Local renames may change non-exported API functions from png.h */
 #if defined(PNG_PREFIX) && !defined(PNGPREFIX_H)
@@ -163,6 +172,20 @@
 #  endif
 #endif
 
+#ifndef PNG_RISCV_RVV_OPT
+   /* RISCV_RVV optimizations are being controlled by the compiler settings,
+    * typically the target compiler will define __riscv but the rvv extension
+    * availability has to be explicitly stated. This is why if no
+    * PNG_RISCV_RVV_OPT was defined then a runtime check will be executed.
+    *
+    * To enable RISCV_RVV optimizations unconditionally, and compile the
+    * associated code, pass --enable-riscv-rvv=yes or --enable-riscv-rvv=on
+    * to configure or put -DPNG_RISCV_RVV_OPT=2 in CPPFLAGS.
+    */
+
+#  define PNG_RISCV_RVV_OPT 0
+#endif
+
 #if PNG_ARM_NEON_OPT > 0
    /* NEON optimizations are to be at least considered by libpng, so enable the
     * callbacks to do this.
@@ -308,6 +331,16 @@
 #   define PNG_LOONGARCH_LSX_IMPLEMENTATION 0
 #endif
 
+#if PNG_RISCV_RVV_OPT > 0 && __riscv_v >= 1000000
+#  define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_rvv
+#  ifndef PNG_RISCV_RVV_IMPLEMENTATION
+      /* Use the intrinsics code by default. */
+#     define PNG_RISCV_RVV_IMPLEMENTATION 1
+#  endif
+#else
+#  define PNG_RISCV_RVV_IMPLEMENTATION 0
+#endif /* PNG_RISCV_RVV_OPT > 0 && __riscv_v >= 1000000 */
+
 /* Is this a build of a DLL where compilation of the object modules requires
  * different preprocessor settings to those required for a simple library?  If
  * so PNG_BUILD_DLL must be set.
@@ -706,7 +739,7 @@
 /* #define PNG_FLAG_KEEP_UNKNOWN_CHUNKS      0x8000U */
 /* #define PNG_FLAG_KEEP_UNSAFE_CHUNKS      0x10000U */
 #define PNG_FLAG_LIBRARY_MISMATCH        0x20000U
-#define PNG_FLAG_STRIP_ERROR_NUMBERS     0x40000U
+                                  /*     0x40000U    unused */
 #define PNG_FLAG_STRIP_ERROR_TEXT        0x80000U
 #define PNG_FLAG_BENIGN_ERRORS_WARN     0x100000U /* Added to libpng-1.4.0 */
 #define PNG_FLAG_APP_WARNINGS_WARN      0x200000U /* Added to libpng-1.6.0 */
@@ -1020,17 +1053,15 @@
  * must match that used in the build, or we must be using pnglibconf.h.prebuilt:
  */
 #if PNG_ZLIB_VERNUM != 0 && PNG_ZLIB_VERNUM != ZLIB_VERNUM
-#  error ZLIB_VERNUM != PNG_ZLIB_VERNUM \
-      "-I (include path) error: see the notes in pngpriv.h"
-   /* This means that when pnglibconf.h was built the copy of zlib.h that it
-    * used is not the same as the one being used here.  Because the build of
-    * libpng makes decisions to use inflateInit2 and inflateReset2 based on the
-    * zlib version number and because this affects handling of certain broken
-    * PNG files the -I directives must match.
+#  error The include path of  is incorrect
+   /* When pnglibconf.h was built, the copy of zlib.h that it used was not the
+    * same as the one being used here.  Considering how libpng makes decisions
+    * to use the zlib API based on the zlib version number, the -I options must
+    * match.
     *
-    * The most likely explanation is that you passed a -I in CFLAGS. This will
-    * not work; all the preprocessor directives and in particular all the -I
-    * directives must be in CPPFLAGS.
+    * A possible cause of this mismatch is that you passed an -I option in
+    * CFLAGS, which is unlikely to work.  All the preprocessor options, and all
+    * the -I options in particular, should be in CPPFLAGS.
     */
 #endif
 
@@ -1073,15 +1104,17 @@ extern "C" {
  */
 /* Zlib support */
 #define PNG_UNEXPECTED_ZLIB_RETURN (-7)
-PNG_INTERNAL_FUNCTION(void, png_zstream_error,(png_structrp png_ptr, int ret),
+PNG_INTERNAL_FUNCTION(void, png_zstream_error,
+   (png_structrp png_ptr, int ret),
    PNG_EMPTY);
    /* Used by the zlib handling functions to ensure that z_stream::msg is always
     * set before they return.
     */
 
 #ifdef PNG_WRITE_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_free_buffer_list,(png_structrp png_ptr,
-   png_compression_bufferp *list),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_free_buffer_list,
+   (png_structrp png_ptr, png_compression_bufferp *list),
+   PNG_EMPTY);
    /* Free the buffer list used by the compressed write code. */
 #endif
 
@@ -1093,22 +1126,25 @@ PNG_INTERNAL_FUNCTION(void,png_free_buffer_list,(png_structrp png_ptr,
    defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \
    (defined(PNG_sCAL_SUPPORTED) && \
    defined(PNG_FLOATING_ARITHMETIC_SUPPORTED))
-PNG_INTERNAL_FUNCTION(png_fixed_point,png_fixed,(png_const_structrp png_ptr,
-   double fp, png_const_charp text),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(png_fixed_point, png_fixed,
+   (png_const_structrp png_ptr, double fp, png_const_charp text),
+   PNG_EMPTY);
 #endif
 
 #if defined(PNG_FLOATING_POINT_SUPPORTED) && \
    !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \
    (defined(PNG_cLLI_SUPPORTED) || defined(PNG_mDCV_SUPPORTED))
-PNG_INTERNAL_FUNCTION(png_uint_32,png_fixed_ITU,(png_const_structrp png_ptr,
-   double fp, png_const_charp text),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(png_uint_32, png_fixed_ITU,
+   (png_const_structrp png_ptr, double fp, png_const_charp text),
+   PNG_EMPTY);
 #endif
 
 /* Check the user version string for compatibility, returns false if the version
  * numbers aren't compatible.
  */
-PNG_INTERNAL_FUNCTION(int,png_user_version_check,(png_structrp png_ptr,
-   png_const_charp user_png_ver),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(int, png_user_version_check,
+   (png_structrp png_ptr, png_const_charp user_png_ver),
+   PNG_EMPTY);
 
 #ifdef PNG_READ_SUPPORTED /* should only be used on read */
 /* Security: read limits on the largest allocations while reading a PNG.  This
@@ -1133,24 +1169,28 @@ PNG_INTERNAL_FUNCTION(int,png_user_version_check,(png_structrp png_ptr,
  * does, however, call the application provided allocator and that could call
  * png_error (although that would be a bug in the application implementation.)
  */
-PNG_INTERNAL_FUNCTION(png_voidp,png_malloc_base,(png_const_structrp png_ptr,
-   png_alloc_size_t size),PNG_ALLOCATED);
+PNG_INTERNAL_FUNCTION(png_voidp, png_malloc_base,
+   (png_const_structrp png_ptr, png_alloc_size_t size),
+   PNG_ALLOCATED);
 
 #if defined(PNG_TEXT_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) ||\
    defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED)
 /* Internal array allocator, outputs no error or warning messages on failure,
  * just returns NULL.
  */
-PNG_INTERNAL_FUNCTION(png_voidp,png_malloc_array,(png_const_structrp png_ptr,
-   int nelements, size_t element_size),PNG_ALLOCATED);
+PNG_INTERNAL_FUNCTION(png_voidp, png_malloc_array,
+   (png_const_structrp png_ptr, int nelements, size_t element_size),
+   PNG_ALLOCATED);
 
 /* The same but an existing array is extended by add_elements.  This function
  * also memsets the new elements to 0 and copies the old elements.  The old
  * array is not freed or altered.
  */
-PNG_INTERNAL_FUNCTION(png_voidp,png_realloc_array,(png_const_structrp png_ptr,
-   png_const_voidp array, int old_elements, int add_elements,
-   size_t element_size),PNG_ALLOCATED);
+PNG_INTERNAL_FUNCTION(png_voidp, png_realloc_array,
+   (png_const_structrp png_ptr,
+    png_const_voidp array, int old_elements, int add_elements,
+    size_t element_size),
+   PNG_ALLOCATED);
 #endif /* text, sPLT or unknown chunks */
 
 /* Magic to create a struct when there is no struct to call the user supplied
@@ -1159,84 +1199,106 @@ PNG_INTERNAL_FUNCTION(png_voidp,png_realloc_array,(png_const_structrp png_ptr,
  * restriction so libpng has to assume that the 'free' handler, at least, might
  * call png_error.
  */
-PNG_INTERNAL_FUNCTION(png_structp,png_create_png_struct,
-   (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn,
-    png_error_ptr warn_fn, png_voidp mem_ptr, png_malloc_ptr malloc_fn,
-    png_free_ptr free_fn),PNG_ALLOCATED);
+PNG_INTERNAL_FUNCTION(png_structp, png_create_png_struct,
+   (png_const_charp user_png_ver,
+    png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn,
+    png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn),
+   PNG_ALLOCATED);
 
 /* Free memory from internal libpng struct */
-PNG_INTERNAL_FUNCTION(void,png_destroy_png_struct,(png_structrp png_ptr),
+PNG_INTERNAL_FUNCTION(void, png_destroy_png_struct,
+   (png_structrp png_ptr),
    PNG_EMPTY);
 
 /* Free an allocated jmp_buf (always succeeds) */
-PNG_INTERNAL_FUNCTION(void,png_free_jmpbuf,(png_structrp png_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_free_jmpbuf,
+   (png_structrp png_ptr),
+   PNG_EMPTY);
 
 /* Function to allocate memory for zlib.  PNGAPI is disallowed. */
-PNG_INTERNAL_FUNCTION(voidpf,png_zalloc,(voidpf png_ptr, uInt items, uInt size),
+PNG_INTERNAL_FUNCTION(voidpf, png_zalloc,
+   (voidpf png_ptr, uInt items, uInt size),
    PNG_ALLOCATED);
 
 /* Function to free memory for zlib.  PNGAPI is disallowed. */
-PNG_INTERNAL_FUNCTION(void,png_zfree,(voidpf png_ptr, voidpf ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_zfree,
+   (voidpf png_ptr, voidpf ptr),
+   PNG_EMPTY);
 
 /* Next four functions are used internally as callbacks.  PNGCBAPI is required
  * but not PNG_EXPORT.  PNGAPI added at libpng version 1.2.3, changed to
  * PNGCBAPI at 1.5.0
  */
 
-PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_read_data,(png_structp png_ptr,
-    png_bytep data, size_t length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void PNGCBAPI, png_default_read_data,
+   (png_structp png_ptr, png_bytep data, size_t length),
+   PNG_EMPTY);
 
 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_push_fill_buffer,(png_structp png_ptr,
-    png_bytep buffer, size_t length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void PNGCBAPI, png_push_fill_buffer,
+   (png_structp png_ptr, png_bytep buffer, size_t length),
+   PNG_EMPTY);
 #endif
 
-PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_write_data,(png_structp png_ptr,
-    png_bytep data, size_t length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void PNGCBAPI, png_default_write_data,
+   (png_structp png_ptr, png_bytep data, size_t length),
+   PNG_EMPTY);
 
 #ifdef PNG_WRITE_FLUSH_SUPPORTED
 #  ifdef PNG_STDIO_SUPPORTED
-PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_flush,(png_structp png_ptr),
+PNG_INTERNAL_FUNCTION(void PNGCBAPI, png_default_flush,
+   (png_structp png_ptr),
    PNG_EMPTY);
 #  endif
 #endif
 
 /* Reset the CRC variable */
-PNG_INTERNAL_FUNCTION(void,png_reset_crc,(png_structrp png_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_reset_crc,
+   (png_structrp png_ptr),
+   PNG_EMPTY);
 
 /* Write the "data" buffer to whatever output you are using */
-PNG_INTERNAL_FUNCTION(void,png_write_data,(png_structrp png_ptr,
-    png_const_bytep data, size_t length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_write_data,
+   (png_structrp png_ptr, png_const_bytep data, size_t length),
+   PNG_EMPTY);
 
 /* Read and check the PNG file signature */
-PNG_INTERNAL_FUNCTION(void,png_read_sig,(png_structrp png_ptr,
-   png_inforp info_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_sig,
+   (png_structrp png_ptr, png_inforp info_ptr),
+   PNG_EMPTY);
 
 /* Read the chunk header (length + type name) */
-PNG_INTERNAL_FUNCTION(png_uint_32,png_read_chunk_header,(png_structrp png_ptr),
+PNG_INTERNAL_FUNCTION(png_uint_32, png_read_chunk_header,
+   (png_structrp png_ptr),
    PNG_EMPTY);
 
 /* Read data from whatever input you are using into the "data" buffer */
-PNG_INTERNAL_FUNCTION(void,png_read_data,(png_structrp png_ptr, png_bytep data,
-    size_t length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_data,
+   (png_structrp png_ptr, png_bytep data, size_t length),
+   PNG_EMPTY);
 
 /* Read bytes into buf, and update png_ptr->crc */
-PNG_INTERNAL_FUNCTION(void,png_crc_read,(png_structrp png_ptr, png_bytep buf,
-    png_uint_32 length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_crc_read,
+   (png_structrp png_ptr, png_bytep buf, png_uint_32 length),
+   PNG_EMPTY);
 
 /* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */
-PNG_INTERNAL_FUNCTION(int,png_crc_finish,(png_structrp png_ptr,
-   png_uint_32 skip),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(int, png_crc_finish,
+   (png_structrp png_ptr, png_uint_32 skip),
+   PNG_EMPTY);
 
 /* Calculate the CRC over a section of data.  Note that we are only
  * passing a maximum of 64K on systems that have this as a memory limit,
  * since this is the maximum buffer size we can specify.
  */
-PNG_INTERNAL_FUNCTION(void,png_calculate_crc,(png_structrp png_ptr,
-   png_const_bytep ptr, size_t length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_calculate_crc,
+   (png_structrp png_ptr, png_const_bytep ptr, size_t length),
+   PNG_EMPTY);
 
 #ifdef PNG_WRITE_FLUSH_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_flush,(png_structrp png_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_flush,
+   (png_structrp png_ptr),
+   PNG_EMPTY);
 #endif
 
 /* Write various chunks */
@@ -1244,68 +1306,86 @@ PNG_INTERNAL_FUNCTION(void,png_flush,(png_structrp png_ptr),PNG_EMPTY);
 /* Write the IHDR chunk, and update the png_struct with the necessary
  * information.
  */
-PNG_INTERNAL_FUNCTION(void,png_write_IHDR,(png_structrp png_ptr,
-   png_uint_32 width, png_uint_32 height, int bit_depth, int color_type,
-   int compression_method, int filter_method, int interlace_method),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_write_IHDR,
+   (png_structrp png_ptr,
+    png_uint_32 width, png_uint_32 height, int bit_depth, int color_type,
+    int compression_method, int filter_method, int interlace_method),
+   PNG_EMPTY);
 
-PNG_INTERNAL_FUNCTION(void,png_write_PLTE,(png_structrp png_ptr,
-   png_const_colorp palette, png_uint_32 num_pal),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_write_PLTE,
+   (png_structrp png_ptr,
+    png_const_colorp palette, png_uint_32 num_pal),
+   PNG_EMPTY);
 
-PNG_INTERNAL_FUNCTION(void,png_compress_IDAT,(png_structrp png_ptr,
-   png_const_bytep row_data, png_alloc_size_t row_data_length, int flush),
+PNG_INTERNAL_FUNCTION(void, png_compress_IDAT,
+   (png_structrp png_ptr,
+    png_const_bytep row_data, png_alloc_size_t row_data_length, int flush),
    PNG_EMPTY);
 
-PNG_INTERNAL_FUNCTION(void,png_write_IEND,(png_structrp png_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_write_IEND,
+   (png_structrp png_ptr),
+   PNG_EMPTY);
 
 #ifdef PNG_WRITE_gAMA_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_gAMA_fixed,(png_structrp png_ptr,
-    png_fixed_point file_gamma),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_write_gAMA_fixed,
+   (png_structrp png_ptr, png_fixed_point file_gamma),
+   PNG_EMPTY);
 #endif
 
 #ifdef PNG_WRITE_sBIT_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_sBIT,(png_structrp png_ptr,
-    png_const_color_8p sbit, int color_type),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_write_sBIT,
+   (png_structrp png_ptr, png_const_color_8p sbit, int color_type),
+   PNG_EMPTY);
 #endif
 
 #ifdef PNG_WRITE_cHRM_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_cHRM_fixed,(png_structrp png_ptr,
-    const png_xy *xy), PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_write_cHRM_fixed,
+   (png_structrp png_ptr, const png_xy *xy),
+   PNG_EMPTY);
    /* The xy value must have been previously validated */
 #endif
 
 #ifdef PNG_WRITE_cICP_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_cICP,(png_structrp png_ptr,
+PNG_INTERNAL_FUNCTION(void, png_write_cICP,
+   (png_structrp png_ptr,
     png_byte colour_primaries, png_byte transfer_function,
-    png_byte matrix_coefficients, png_byte video_full_range_flag), PNG_EMPTY);
+    png_byte matrix_coefficients, png_byte video_full_range_flag),
+   PNG_EMPTY);
 #endif
 
 #ifdef PNG_WRITE_cLLI_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_cLLI_fixed,(png_structrp png_ptr,
-   png_uint_32 maxCLL, png_uint_32 maxFALL), PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_write_cLLI_fixed,
+   (png_structrp png_ptr, png_uint_32 maxCLL, png_uint_32 maxFALL),
+   PNG_EMPTY);
 #endif
 
 #ifdef PNG_WRITE_mDCV_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_mDCV_fixed,(png_structrp png_ptr,
-   png_uint_16 red_x, png_uint_16 red_y,
-   png_uint_16 green_x, png_uint_16 green_y,
-   png_uint_16 blue_x, png_uint_16 blue_y,
-   png_uint_16 white_x, png_uint_16 white_y,
-   png_uint_32 maxDL, png_uint_32 minDL), PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_write_mDCV_fixed,
+   (png_structrp png_ptr,
+    png_uint_16 red_x, png_uint_16 red_y,
+    png_uint_16 green_x, png_uint_16 green_y,
+    png_uint_16 blue_x, png_uint_16 blue_y,
+    png_uint_16 white_x, png_uint_16 white_y,
+    png_uint_32 maxDL, png_uint_32 minDL),
+   PNG_EMPTY);
 #endif
 
 #ifdef PNG_WRITE_sRGB_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_sRGB,(png_structrp png_ptr,
-    int intent),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_write_sRGB,
+   (png_structrp png_ptr, int intent),
+   PNG_EMPTY);
 #endif
 
 #ifdef PNG_WRITE_eXIf_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_eXIf,(png_structrp png_ptr,
-    png_bytep exif, int num_exif),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_write_eXIf,
+   (png_structrp png_ptr, png_bytep exif, int num_exif),
+   PNG_EMPTY);
 #endif
 
 #ifdef PNG_WRITE_iCCP_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_iCCP,(png_structrp png_ptr,
-   png_const_charp name, png_const_bytep profile, png_uint_32 proflen),
+PNG_INTERNAL_FUNCTION(void, png_write_iCCP,
+   (png_structrp png_ptr,
+    png_const_charp name, png_const_bytep profile, png_uint_32 proflen),
    PNG_EMPTY);
    /* Writes a previously 'set' profile.  The profile argument is **not**
     * compressed.
@@ -1313,82 +1393,106 @@ PNG_INTERNAL_FUNCTION(void,png_write_iCCP,(png_structrp png_ptr,
 #endif
 
 #ifdef PNG_WRITE_sPLT_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_sPLT,(png_structrp png_ptr,
-    png_const_sPLT_tp palette),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_write_sPLT,
+   (png_structrp png_ptr, png_const_sPLT_tp palette),
+   PNG_EMPTY);
 #endif
 
 #ifdef PNG_WRITE_tRNS_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_tRNS,(png_structrp png_ptr,
+PNG_INTERNAL_FUNCTION(void, png_write_tRNS,
+   (png_structrp png_ptr,
     png_const_bytep trans, png_const_color_16p values, int number,
-    int color_type),PNG_EMPTY);
+    int color_type),
+   PNG_EMPTY);
 #endif
 
 #ifdef PNG_WRITE_bKGD_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_bKGD,(png_structrp png_ptr,
-    png_const_color_16p values, int color_type),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_write_bKGD,
+   (png_structrp png_ptr, png_const_color_16p values, int color_type),
+   PNG_EMPTY);
 #endif
 
 #ifdef PNG_WRITE_hIST_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_hIST,(png_structrp png_ptr,
-    png_const_uint_16p hist, int num_hist),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_write_hIST,
+   (png_structrp png_ptr, png_const_uint_16p hist, int num_hist),
+   PNG_EMPTY);
 #endif
 
 /* Chunks that have keywords */
 #ifdef PNG_WRITE_tEXt_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_tEXt,(png_structrp png_ptr,
-   png_const_charp key, png_const_charp text, size_t text_len),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_write_tEXt,
+   (png_structrp png_ptr,
+    png_const_charp key, png_const_charp text, size_t text_len),
+   PNG_EMPTY);
 #endif
 
 #ifdef PNG_WRITE_zTXt_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_zTXt,(png_structrp png_ptr, png_const_charp
-    key, png_const_charp text, int compression),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_write_zTXt,
+   (png_structrp png_ptr,
+    png_const_charp key, png_const_charp text, int compression),
+   PNG_EMPTY);
 #endif
 
 #ifdef PNG_WRITE_iTXt_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_iTXt,(png_structrp png_ptr,
+PNG_INTERNAL_FUNCTION(void, png_write_iTXt,
+   (png_structrp png_ptr,
     int compression, png_const_charp key, png_const_charp lang,
-    png_const_charp lang_key, png_const_charp text),PNG_EMPTY);
+    png_const_charp lang_key, png_const_charp text),
+   PNG_EMPTY);
 #endif
 
 #ifdef PNG_TEXT_SUPPORTED  /* Added at version 1.0.14 and 1.2.4 */
-PNG_INTERNAL_FUNCTION(int,png_set_text_2,(png_const_structrp png_ptr,
-    png_inforp info_ptr, png_const_textp text_ptr, int num_text),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(int, png_set_text_2,
+   (png_const_structrp png_ptr,
+    png_inforp info_ptr, png_const_textp text_ptr, int num_text),
+   PNG_EMPTY);
 #endif
 
 #ifdef PNG_WRITE_oFFs_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_oFFs,(png_structrp png_ptr,
-    png_int_32 x_offset, png_int_32 y_offset, int unit_type),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_write_oFFs,
+   (png_structrp png_ptr,
+    png_int_32 x_offset, png_int_32 y_offset, int unit_type),
+   PNG_EMPTY);
 #endif
 
 #ifdef PNG_WRITE_pCAL_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_pCAL,(png_structrp png_ptr,
-    png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams,
-    png_const_charp units, png_charpp params),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_write_pCAL,
+   (png_structrp png_ptr,
+    png_charp purpose, png_int_32 X0, png_int_32 X1,
+    int type, int nparams, png_const_charp units, png_charpp params),
+   PNG_EMPTY);
 #endif
 
 #ifdef PNG_WRITE_pHYs_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_pHYs,(png_structrp png_ptr,
+PNG_INTERNAL_FUNCTION(void, png_write_pHYs,
+   (png_structrp png_ptr,
     png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit,
-    int unit_type),PNG_EMPTY);
+    int unit_type),
+   PNG_EMPTY);
 #endif
 
 #ifdef PNG_WRITE_tIME_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_tIME,(png_structrp png_ptr,
-    png_const_timep mod_time),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_write_tIME,
+   (png_structrp png_ptr, png_const_timep mod_time),
+   PNG_EMPTY);
 #endif
 
 #ifdef PNG_WRITE_sCAL_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_sCAL_s,(png_structrp png_ptr,
-    int unit, png_const_charp width, png_const_charp height),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_write_sCAL_s,
+   (png_structrp png_ptr,
+    int unit, png_const_charp width, png_const_charp height),
+   PNG_EMPTY);
 #endif
 
 /* Called when finished processing a row of data */
-PNG_INTERNAL_FUNCTION(void,png_write_finish_row,(png_structrp png_ptr),
-    PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_write_finish_row,
+   (png_structrp png_ptr),
+   PNG_EMPTY);
 
 /* Internal use only.   Called before first row of data */
-PNG_INTERNAL_FUNCTION(void,png_write_start_row,(png_structrp png_ptr),
-    PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_write_start_row,
+   (png_structrp png_ptr),
+   PNG_EMPTY);
 
 /* Combine a row of data, dealing with alpha, etc. if requested.  'row' is an
  * array of png_ptr->width pixels.  If the image is not interlaced or this
@@ -1416,8 +1520,9 @@ PNG_INTERNAL_FUNCTION(void,png_write_start_row,(png_structrp png_ptr),
 #ifndef PNG_USE_COMPILE_TIME_MASKS
 #  define PNG_USE_COMPILE_TIME_MASKS 1
 #endif
-PNG_INTERNAL_FUNCTION(void,png_combine_row,(png_const_structrp png_ptr,
-    png_bytep row, int display),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_combine_row,
+   (png_const_structrp png_ptr, png_bytep row, int display),
+   PNG_EMPTY);
 
 #ifdef PNG_READ_INTERLACING_SUPPORTED
 /* Expand an interlaced row: the 'row_info' describes the pass data that has
@@ -1426,153 +1531,230 @@ PNG_INTERNAL_FUNCTION(void,png_combine_row,(png_const_structrp png_ptr,
  * the pixels are *replicated* to the intervening space.  This is essential for
  * the correct operation of png_combine_row, above.
  */
-PNG_INTERNAL_FUNCTION(void,png_do_read_interlace,(png_row_infop row_info,
-    png_bytep row, int pass, png_uint_32 transformations),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_do_read_interlace,
+   (png_row_infop row_info,
+    png_bytep row, int pass, png_uint_32 transformations),
+   PNG_EMPTY);
 #endif
 
 /* GRR TO DO (2.0 or whenever):  simplify other internal calling interfaces */
 
 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
 /* Grab pixels out of a row for an interlaced pass */
-PNG_INTERNAL_FUNCTION(void,png_do_write_interlace,(png_row_infop row_info,
-    png_bytep row, int pass),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_do_write_interlace,
+   (png_row_infop row_info, png_bytep row, int pass),
+   PNG_EMPTY);
 #endif
 
 /* Unfilter a row: check the filter value before calling this, there is no point
  * calling it for PNG_FILTER_VALUE_NONE.
  */
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row,(png_structrp pp, png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row, int filter),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row,
+   (png_structrp pp, png_row_infop row_info,
+    png_bytep row, png_const_bytep prev_row, int filter),
+   PNG_EMPTY);
 
 #if PNG_ARM_NEON_OPT > 0
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_neon,(png_row_infop row_info,
-    png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_neon,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_neon,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_neon,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_neon,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_neon,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_up_neon,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_sub3_neon,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_sub4_neon,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_avg3_neon,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_avg4_neon,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_paeth3_neon,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_paeth4_neon,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
 #endif
 
 #if PNG_MIPS_MSA_IMPLEMENTATION == 1
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_msa,(png_row_infop row_info,
-    png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_msa,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_msa,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_msa,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_msa,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_msa,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_msa,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_up_msa,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_sub3_msa,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_sub4_msa,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_avg3_msa,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_avg4_msa,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_paeth3_msa,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_paeth4_msa,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
 #endif
 
 #if PNG_MIPS_MMI_IMPLEMENTATION > 0
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_mmi,(png_row_infop row_info,
-    png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_mmi,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_mmi,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_mmi,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_mmi,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_mmi,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_mmi,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_up_mmi,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_sub3_mmi,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_sub4_mmi,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_avg3_mmi,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_avg4_mmi,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_paeth3_mmi,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_paeth4_mmi,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
 #endif
 
 #if PNG_POWERPC_VSX_OPT > 0
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_vsx,(png_row_infop row_info,
-    png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_vsx,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_vsx,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_vsx,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_vsx,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_vsx,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_vsx,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_up_vsx,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_sub3_vsx,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_sub4_vsx,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_avg3_vsx,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_avg4_vsx,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_paeth3_vsx,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_paeth4_vsx,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
 #endif
 
 #if PNG_INTEL_SSE_IMPLEMENTATION > 0
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_sse2,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_sse2,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_sse2,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_sse2,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_sse2,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_sse2,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_sub3_sse2,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_sub4_sse2,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_avg3_sse2,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_avg4_sse2,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_paeth3_sse2,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_paeth4_sse2,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
 #endif
 
 #if PNG_LOONGARCH_LSX_IMPLEMENTATION == 1
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_lsx,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_lsx,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_lsx,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_lsx,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_lsx,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_lsx,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_lsx,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_up_lsx,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_sub3_lsx,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_sub4_lsx,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_avg3_lsx,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_avg4_lsx,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_paeth3_lsx,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_paeth4_lsx,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+#endif
+
+#if PNG_RISCV_RVV_IMPLEMENTATION == 1
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_up_rvv,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_sub3_rvv,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_sub4_rvv,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_avg3_rvv,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_avg4_rvv,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_paeth3_rvv,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_filter_row_paeth4_rvv,
+   (png_row_infop row_info, png_bytep row, png_const_bytep prev_row),
+   PNG_EMPTY);
 #endif
 
 /* Choose the best filter to use and filter the row data */
-PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr,
-    png_row_infop row_info),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_write_find_filter,
+   (png_structrp png_ptr, png_row_infop row_info),
+   PNG_EMPTY);
 
 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_read_IDAT_data,(png_structrp png_ptr,
-   png_bytep output, png_alloc_size_t avail_out),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_IDAT_data,
+   (png_structrp png_ptr, png_bytep output, png_alloc_size_t avail_out),
+   PNG_EMPTY);
    /* Read 'avail_out' bytes of data from the IDAT stream.  If the output buffer
     * is NULL the function checks, instead, for the end of the stream.  In this
     * case a benign error will be issued if the stream end is not found or if
     * extra data has to be consumed.
     */
-PNG_INTERNAL_FUNCTION(void,png_read_finish_IDAT,(png_structrp png_ptr),
+PNG_INTERNAL_FUNCTION(void, png_read_finish_IDAT,
+   (png_structrp png_ptr),
    PNG_EMPTY);
    /* This cleans up when the IDAT LZ stream does not end when the last image
     * byte is read; there is still some pending input.
     */
 
-PNG_INTERNAL_FUNCTION(void,png_read_finish_row,(png_structrp png_ptr),
+PNG_INTERNAL_FUNCTION(void, png_read_finish_row,
+   (png_structrp png_ptr),
    PNG_EMPTY);
    /* Finish a row while reading, dealing with interlacing passes, etc. */
 #endif /* SEQUENTIAL_READ */
 
 /* Initialize the row buffers, etc. */
-PNG_INTERNAL_FUNCTION(void,png_read_start_row,(png_structrp png_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_start_row,
+   (png_structrp png_ptr),
+   PNG_EMPTY);
 
 #if ZLIB_VERNUM >= 0x1240
-PNG_INTERNAL_FUNCTION(int,png_zlib_inflate,(png_structrp png_ptr, int flush),
-      PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(int, png_zlib_inflate,
+   (png_structrp png_ptr, int flush),
+   PNG_EMPTY);
 #  define PNG_INFLATE(pp, flush) png_zlib_inflate(pp, flush)
 #else /* Zlib < 1.2.4 */
 #  define PNG_INFLATE(pp, flush) inflate(&(pp)->zstream, flush)
@@ -1580,38 +1762,44 @@ PNG_INTERNAL_FUNCTION(int,png_zlib_inflate,(png_structrp png_ptr, int flush),
 
 #ifdef PNG_READ_TRANSFORMS_SUPPORTED
 /* Optional call to update the users info structure */
-PNG_INTERNAL_FUNCTION(void,png_read_transform_info,(png_structrp png_ptr,
-    png_inforp info_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_transform_info,
+   (png_structrp png_ptr, png_inforp info_ptr),
+   PNG_EMPTY);
 #endif
 
 /* Shared transform functions, defined in pngtran.c */
 #if defined(PNG_WRITE_FILLER_SUPPORTED) || \
     defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
-PNG_INTERNAL_FUNCTION(void,png_do_strip_channel,(png_row_infop row_info,
-    png_bytep row, int at_start),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_do_strip_channel,
+   (png_row_infop row_info, png_bytep row, int at_start),
+   PNG_EMPTY);
 #endif
 
 #ifdef PNG_16BIT_SUPPORTED
 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
-PNG_INTERNAL_FUNCTION(void,png_do_swap,(png_row_infop row_info,
-    png_bytep row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_do_swap,
+   (png_row_infop row_info, png_bytep row),
+   PNG_EMPTY);
 #endif
 #endif
 
 #if defined(PNG_READ_PACKSWAP_SUPPORTED) || \
     defined(PNG_WRITE_PACKSWAP_SUPPORTED)
-PNG_INTERNAL_FUNCTION(void,png_do_packswap,(png_row_infop row_info,
-    png_bytep row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_do_packswap,
+   (png_row_infop row_info, png_bytep row),
+   PNG_EMPTY);
 #endif
 
 #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
-PNG_INTERNAL_FUNCTION(void,png_do_invert,(png_row_infop row_info,
-    png_bytep row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_do_invert,
+   (png_row_infop row_info, png_bytep row),
+   PNG_EMPTY);
 #endif
 
 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
-PNG_INTERNAL_FUNCTION(void,png_do_bgr,(png_row_infop row_info,
-    png_bytep row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_do_bgr,
+   (png_row_infop row_info, png_bytep row),
+   PNG_EMPTY);
 #endif
 
 /* The following decodes the appropriate chunks, and does error correction,
@@ -1632,25 +1820,27 @@ typedef enum
    handled_ok          /* known, supported and handled without error */
 } png_handle_result_code;
 
-PNG_INTERNAL_FUNCTION(png_handle_result_code,png_handle_unknown,
-    (png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length, int keep),
-    PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(png_handle_result_code, png_handle_unknown,
+   (png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length, int keep),
+   PNG_EMPTY);
    /* This is the function that gets called for unknown chunks.  The 'keep'
     * argument is either non-zero for a known chunk that has been set to be
     * handled as unknown or zero for an unknown chunk.  By default the function
     * just skips the chunk or errors out if it is critical.
     */
 
-PNG_INTERNAL_FUNCTION(png_handle_result_code,png_handle_chunk,
-    (png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(png_handle_result_code, png_handle_chunk,
+   (png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length),
+   PNG_EMPTY);
    /* This handles the current chunk png_ptr->chunk_name with unread
     * data[length] and returns one of the above result codes.
     */
 
 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) ||\
     defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
-PNG_INTERNAL_FUNCTION(int,png_chunk_unknown_handling,
-    (png_const_structrp png_ptr, png_uint_32 chunk_name),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(int, png_chunk_unknown_handling,
+   (png_const_structrp png_ptr, png_uint_32 chunk_name),
+   PNG_EMPTY);
    /* Exactly as the API png_handle_as_unknown() except that the argument is a
     * 32-bit chunk name, not a string.
     */
@@ -1658,93 +1848,122 @@ PNG_INTERNAL_FUNCTION(int,png_chunk_unknown_handling,
 
 /* Handle the transformations for reading and writing */
 #ifdef PNG_READ_TRANSFORMS_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_do_read_transformations,(png_structrp png_ptr,
-   png_row_infop row_info),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_do_read_transformations,
+   (png_structrp png_ptr, png_row_infop row_info),
+   PNG_EMPTY);
 #endif
 #ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_do_write_transformations,(png_structrp png_ptr,
-   png_row_infop row_info),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_do_write_transformations,
+   (png_structrp png_ptr, png_row_infop row_info),
+   PNG_EMPTY);
 #endif
 
 #ifdef PNG_READ_TRANSFORMS_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_init_read_transformations,(png_structrp png_ptr),
-    PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_init_read_transformations,
+   (png_structrp png_ptr),
+   PNG_EMPTY);
 #endif
 
 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_push_read_chunk,(png_structrp png_ptr,
-    png_inforp info_ptr),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_read_sig,(png_structrp png_ptr,
-    png_inforp info_ptr),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_check_crc,(png_structrp png_ptr),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_save_buffer,(png_structrp png_ptr),
-    PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_restore_buffer,(png_structrp png_ptr,
-    png_bytep buffer, size_t buffer_length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_read_IDAT,(png_structrp png_ptr),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_process_IDAT_data,(png_structrp png_ptr,
-    png_bytep buffer, size_t buffer_length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_process_row,(png_structrp png_ptr),
-    PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_have_info,(png_structrp png_ptr,
-   png_inforp info_ptr),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_have_end,(png_structrp png_ptr,
-   png_inforp info_ptr),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_have_row,(png_structrp png_ptr,
-    png_bytep row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_read_end,(png_structrp png_ptr,
-    png_inforp info_ptr),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_process_some_data,(png_structrp png_ptr,
-    png_inforp info_ptr),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_push_finish_row,(png_structrp png_ptr),
-    PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_push_read_chunk,
+   (png_structrp png_ptr, png_inforp info_ptr),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_push_read_sig,
+   (png_structrp png_ptr, png_inforp info_ptr),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_push_check_crc,
+   (png_structrp png_ptr),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_push_save_buffer,
+   (png_structrp png_ptr),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_push_restore_buffer,
+   (png_structrp png_ptr, png_bytep buffer, size_t buffer_length),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_push_read_IDAT,
+   (png_structrp png_ptr),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_process_IDAT_data,
+   (png_structrp png_ptr, png_bytep buffer, size_t buffer_length),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_push_process_row,
+   (png_structrp png_ptr),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_push_have_info,
+   (png_structrp png_ptr, png_inforp info_ptr),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_push_have_end,
+   (png_structrp png_ptr, png_inforp info_ptr),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_push_have_row,
+   (png_structrp png_ptr, png_bytep row),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_push_read_end,
+   (png_structrp png_ptr, png_inforp info_ptr),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_process_some_data,
+   (png_structrp png_ptr, png_inforp info_ptr),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_read_push_finish_row,
+   (png_structrp png_ptr),
+   PNG_EMPTY);
 #endif /* PROGRESSIVE_READ */
 
 #ifdef PNG_iCCP_SUPPORTED
 /* Routines for checking parts of an ICC profile. */
 #ifdef PNG_READ_iCCP_SUPPORTED
-PNG_INTERNAL_FUNCTION(int,png_icc_check_length,(png_const_structrp png_ptr,
-   png_const_charp name, png_uint_32 profile_length), PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(int, png_icc_check_length,
+   (png_const_structrp png_ptr,
+    png_const_charp name, png_uint_32 profile_length),
+   PNG_EMPTY);
 #endif /* READ_iCCP */
-PNG_INTERNAL_FUNCTION(int,png_icc_check_header,(png_const_structrp png_ptr,
-   png_const_charp name, png_uint_32 profile_length,
-   png_const_bytep profile /* first 132 bytes only */, int color_type),
+PNG_INTERNAL_FUNCTION(int, png_icc_check_header,
+   (png_const_structrp png_ptr,
+    png_const_charp name, png_uint_32 profile_length,
+    png_const_bytep profile /* first 132 bytes only */, int color_type),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(int, png_icc_check_tag_table,
+   (png_const_structrp png_ptr,
+    png_const_charp name, png_uint_32 profile_length,
+    png_const_bytep profile /* header plus whole tag table */),
    PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(int,png_icc_check_tag_table,(png_const_structrp png_ptr,
-   png_const_charp name, png_uint_32 profile_length,
-   png_const_bytep profile /* header plus whole tag table */), PNG_EMPTY);
 #endif /* iCCP */
 
 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_set_rgb_coefficients, (png_structrp png_ptr),
+PNG_INTERNAL_FUNCTION(void, png_set_rgb_coefficients,
+   (png_structrp png_ptr),
    PNG_EMPTY);
    /* Set the rgb_to_gray coefficients from the cHRM Y values (if unset) */
 #endif /* READ_RGB_TO_GRAY */
 
 /* Added at libpng version 1.4.0 */
-PNG_INTERNAL_FUNCTION(void,png_check_IHDR,(png_const_structrp png_ptr,
-    png_uint_32 width, png_uint_32 height, int bit_depth,
-    int color_type, int interlace_type, int compression_type,
-    int filter_type),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_check_IHDR,
+   (png_const_structrp png_ptr,
+    png_uint_32 width, png_uint_32 height, int bit_depth, int color_type,
+    int interlace_type, int compression_type, int filter_type),
+   PNG_EMPTY);
 
 /* Added at libpng version 1.5.10 */
 #if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
     defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
-PNG_INTERNAL_FUNCTION(void,png_do_check_palette_indexes,
-   (png_structrp png_ptr, png_row_infop row_info),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_do_check_palette_indexes,
+   (png_structrp png_ptr, png_row_infop row_info),
+   PNG_EMPTY);
 #endif
 
 #if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED)
-PNG_INTERNAL_FUNCTION(void,png_fixed_error,(png_const_structrp png_ptr,
-   png_const_charp name),PNG_NORETURN);
+PNG_INTERNAL_FUNCTION(void, png_fixed_error,
+   (png_const_structrp png_ptr, png_const_charp name),
+   PNG_NORETURN);
 #endif
 
 /* Puts 'string' into 'buffer' at buffer[pos], taking care never to overwrite
  * the end.  Always leaves the buffer nul terminated.  Never errors out (and
  * there is no error code.)
  */
-PNG_INTERNAL_FUNCTION(size_t,png_safecat,(png_charp buffer, size_t bufsize,
-   size_t pos, png_const_charp string),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(size_t, png_safecat,
+   (png_charp buffer, size_t bufsize, size_t pos, png_const_charp string),
+   PNG_EMPTY);
 
 /* Various internal functions to handle formatted warning messages, currently
  * only implemented for warnings.
@@ -1755,8 +1974,9 @@ PNG_INTERNAL_FUNCTION(size_t,png_safecat,(png_charp buffer, size_t bufsize,
  * Returns the pointer to the start of the formatted string.  This utility only
  * does unsigned values.
  */
-PNG_INTERNAL_FUNCTION(png_charp,png_format_number,(png_const_charp start,
-   png_charp end, int format, png_alloc_size_t number),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(png_charp, png_format_number,
+   (png_const_charp start, png_charp end, int format, png_alloc_size_t number),
+   PNG_EMPTY);
 
 /* Convenience macro that takes an array: */
 #define PNG_FORMAT_NUMBER(buffer,format,number) \
@@ -1788,23 +2008,26 @@ PNG_INTERNAL_FUNCTION(png_charp,png_format_number,(png_const_charp start,
 typedef char png_warning_parameters[PNG_WARNING_PARAMETER_COUNT][
    PNG_WARNING_PARAMETER_SIZE];
 
-PNG_INTERNAL_FUNCTION(void,png_warning_parameter,(png_warning_parameters p,
-   int number, png_const_charp string),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_warning_parameter,
+   (png_warning_parameters p, int number, png_const_charp string),
+   PNG_EMPTY);
    /* Parameters are limited in size to PNG_WARNING_PARAMETER_SIZE characters,
     * including the trailing '\0'.
     */
-PNG_INTERNAL_FUNCTION(void,png_warning_parameter_unsigned,
+PNG_INTERNAL_FUNCTION(void, png_warning_parameter_unsigned,
    (png_warning_parameters p, int number, int format, png_alloc_size_t value),
    PNG_EMPTY);
    /* Use png_alloc_size_t because it is an unsigned type as big as any we
     * need to output.  Use the following for a signed value.
     */
-PNG_INTERNAL_FUNCTION(void,png_warning_parameter_signed,
+PNG_INTERNAL_FUNCTION(void, png_warning_parameter_signed,
    (png_warning_parameters p, int number, int format, png_int_32 value),
    PNG_EMPTY);
 
-PNG_INTERNAL_FUNCTION(void,png_formatted_warning,(png_const_structrp png_ptr,
-   png_warning_parameters p, png_const_charp message),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_formatted_warning,
+   (png_const_structrp png_ptr,
+    png_warning_parameters p, png_const_charp message),
+   PNG_EMPTY);
    /* 'message' follows the X/Open approach of using @1, @2 to insert
     * parameters previously supplied using the above functions.  Errors in
     * specifying the parameters will simply result in garbage substitutions.
@@ -1826,14 +2049,16 @@ PNG_INTERNAL_FUNCTION(void,png_formatted_warning,(png_const_structrp png_ptr,
  * If benign errors aren't supported they end up as the corresponding base call
  * (png_warning or png_error.)
  */
-PNG_INTERNAL_FUNCTION(void,png_app_warning,(png_const_structrp png_ptr,
-   png_const_charp message),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_app_warning,
+   (png_const_structrp png_ptr, png_const_charp message),
+   PNG_EMPTY);
    /* The application provided invalid parameters to an API function or called
     * an API function at the wrong time, libpng can completely recover.
     */
 
-PNG_INTERNAL_FUNCTION(void,png_app_error,(png_const_structrp png_ptr,
-   png_const_charp message),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_app_error,
+   (png_const_structrp png_ptr, png_const_charp message),
+   PNG_EMPTY);
    /* As above but libpng will ignore the call, or attempt some other partial
     * recovery from the error.
     */
@@ -1842,8 +2067,9 @@ PNG_INTERNAL_FUNCTION(void,png_app_error,(png_const_structrp png_ptr,
 #  define png_app_error(pp,s) png_error(pp,s)
 #endif
 
-PNG_INTERNAL_FUNCTION(void,png_chunk_report,(png_const_structrp png_ptr,
-   png_const_charp message, int error),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_chunk_report,
+   (png_const_structrp png_ptr, png_const_charp message, int error),
+   PNG_EMPTY);
    /* Report a recoverable issue in chunk data.  On read this is used to report
     * a problem found while reading a particular chunk and the
     * png_chunk_benign_error or png_chunk_warning function is used as
@@ -1869,14 +2095,17 @@ PNG_INTERNAL_FUNCTION(void,png_chunk_report,(png_const_structrp png_ptr,
 #define PNG_sCAL_MAX_DIGITS (PNG_sCAL_PRECISION+1/*.*/+1/*E*/+10/*exponent*/)
 
 #ifdef PNG_FLOATING_POINT_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_ascii_from_fp,(png_const_structrp png_ptr,
-   png_charp ascii, size_t size, double fp, unsigned int precision),
+PNG_INTERNAL_FUNCTION(void, png_ascii_from_fp,
+   (png_const_structrp png_ptr,
+    png_charp ascii, size_t size, double fp, unsigned int precision),
    PNG_EMPTY);
 #endif /* FLOATING_POINT */
 
 #ifdef PNG_FIXED_POINT_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr,
-   png_charp ascii, size_t size, png_fixed_point fp),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_ascii_from_fixed,
+   (png_const_structrp png_ptr,
+    png_charp ascii, size_t size, png_fixed_point fp),
+   PNG_EMPTY);
 #endif /* FIXED_POINT */
 #endif /* sCAL */
 
@@ -1968,8 +2197,9 @@ PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr,
  * that omits the last character (i.e. set the size to the index of
  * the problem character.)  This has not been tested within libpng.
  */
-PNG_INTERNAL_FUNCTION(int,png_check_fp_number,(png_const_charp string,
-   size_t size, int *statep, size_t *whereami),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(int, png_check_fp_number,
+   (png_const_charp string, size_t size, int *statep, size_t *whereami),
+   PNG_EMPTY);
 
 /* This is the same but it checks a complete string and returns true
  * only if it just contains a floating point number.  As of 1.5.4 this
@@ -1977,8 +2207,9 @@ PNG_INTERNAL_FUNCTION(int,png_check_fp_number,(png_const_charp string,
  * it was valid (otherwise it returns 0.)  This can be used for testing
  * for negative or zero values using the sticky flag.
  */
-PNG_INTERNAL_FUNCTION(int,png_check_fp_string,(png_const_charp string,
-   size_t size),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(int, png_check_fp_string,
+   (png_const_charp string, size_t size),
+   PNG_EMPTY);
 #endif /* pCAL || sCAL */
 
 #if defined(PNG_READ_GAMMA_SUPPORTED) ||\
@@ -1991,14 +2222,17 @@ PNG_INTERNAL_FUNCTION(int,png_check_fp_string,(png_const_charp string,
  * for overflow, true (1) if no overflow, in which case *res
  * holds the result.
  */
-PNG_INTERNAL_FUNCTION(int,png_muldiv,(png_fixed_point_p res, png_fixed_point a,
-   png_int_32 multiplied_by, png_int_32 divided_by),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(int, png_muldiv,
+   (png_fixed_point_p res, png_fixed_point a,
+    png_int_32 multiplied_by, png_int_32 divided_by),
+   PNG_EMPTY);
 
 /* Calculate a reciprocal - used for gamma values.  This returns
  * 0 if the argument is 0 in order to maintain an undefined value;
  * there are no warnings.
  */
-PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal,(png_fixed_point a),
+PNG_INTERNAL_FUNCTION(png_fixed_point, png_reciprocal,
+   (png_fixed_point a),
    PNG_EMPTY);
 #endif
 
@@ -2007,11 +2241,13 @@ PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal,(png_fixed_point a),
  * values.  Accuracy is suitable for gamma calculations but this is
  * not exact - use png_muldiv for that.  Only required at present on read.
  */
-PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal2,(png_fixed_point a,
-   png_fixed_point b),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(png_fixed_point, png_reciprocal2,
+   (png_fixed_point a, png_fixed_point b),
+   PNG_EMPTY);
 
 /* Return true if the gamma value is significantly different from 1.0 */
-PNG_INTERNAL_FUNCTION(int,png_gamma_significant,(png_fixed_point gamma_value),
+PNG_INTERNAL_FUNCTION(int, png_gamma_significant,
+   (png_fixed_point gamma_value),
    PNG_EMPTY);
 
 /* PNGv3: 'resolve' the file gamma according to the new PNGv3 rules for colour
@@ -2022,8 +2258,9 @@ PNG_INTERNAL_FUNCTION(int,png_gamma_significant,(png_fixed_point gamma_value),
  * transforms.  For this reason a gamma specified by png_set_gamma always takes
  * precedence.
  */
-PNG_INTERNAL_FUNCTION(png_fixed_point,png_resolve_file_gamma,
-   (png_const_structrp png_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(png_fixed_point, png_resolve_file_gamma,
+   (png_const_structrp png_ptr),
+   PNG_EMPTY);
 
 /* Internal fixed point gamma correction.  These APIs are called as
  * required to convert single values - they don't need to be fast,
@@ -2032,37 +2269,45 @@ PNG_INTERNAL_FUNCTION(png_fixed_point,png_resolve_file_gamma,
  * While the input is an 'unsigned' value it must actually be the
  * correct bit value - 0..255 or 0..65535 as required.
  */
-PNG_INTERNAL_FUNCTION(png_uint_16,png_gamma_correct,(png_structrp png_ptr,
-   unsigned int value, png_fixed_point gamma_value),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(png_uint_16,png_gamma_16bit_correct,(unsigned int value,
-   png_fixed_point gamma_value),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(png_byte,png_gamma_8bit_correct,(unsigned int value,
-   png_fixed_point gamma_value),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_destroy_gamma_table,(png_structrp png_ptr),
+PNG_INTERNAL_FUNCTION(png_uint_16, png_gamma_correct,
+   (png_structrp png_ptr, unsigned int value, png_fixed_point gamma_value),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(png_uint_16, png_gamma_16bit_correct,
+   (unsigned int value, png_fixed_point gamma_value),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(png_byte, png_gamma_8bit_correct,
+   (unsigned int value, png_fixed_point gamma_value),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_destroy_gamma_table,
+   (png_structrp png_ptr),
+   PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_build_gamma_table,
+   (png_structrp png_ptr, int bit_depth),
    PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_build_gamma_table,(png_structrp png_ptr,
-   int bit_depth),PNG_EMPTY);
 #endif /* READ_GAMMA */
 
 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
 /* Set the RGB coefficients if not already set by png_set_rgb_to_gray */
-PNG_INTERNAL_FUNCTION(void,png_set_rgb_coefficients,(png_structrp png_ptr),
+PNG_INTERNAL_FUNCTION(void, png_set_rgb_coefficients,
+   (png_structrp png_ptr),
    PNG_EMPTY);
 #endif
 
 #if defined(PNG_cHRM_SUPPORTED) || defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
-PNG_INTERNAL_FUNCTION(int,png_XYZ_from_xy,(png_XYZ *XYZ, const png_xy *xy),
+PNG_INTERNAL_FUNCTION(int, png_XYZ_from_xy,
+   (png_XYZ *XYZ, const png_xy *xy),
    PNG_EMPTY);
 #endif /* cHRM || READ_RGB_TO_GRAY */
 
 #ifdef PNG_COLORSPACE_SUPPORTED
-PNG_INTERNAL_FUNCTION(int,png_xy_from_XYZ,(png_xy *xy, const png_XYZ *XYZ),
+PNG_INTERNAL_FUNCTION(int, png_xy_from_XYZ,
+   (png_xy *xy, const png_XYZ *XYZ),
    PNG_EMPTY);
 #endif
 
 /* SIMPLIFIED READ/WRITE SUPPORT */
 #if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
-   defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
+    defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
 /* The internal structure that png_image::opaque points to. */
 typedef struct png_control
 {
@@ -2090,28 +2335,34 @@ typedef struct png_control
  * errors that might occur.  Returns true on success, false on failure (either
  * of the function or as a result of a png_error.)
  */
-PNG_INTERNAL_CALLBACK(void,png_safe_error,(png_structp png_ptr,
-   png_const_charp error_message),PNG_NORETURN);
+PNG_INTERNAL_CALLBACK(void, png_safe_error,
+   (png_structp png_ptr, png_const_charp error_message),
+   PNG_NORETURN);
 
 #ifdef PNG_WARNINGS_SUPPORTED
-PNG_INTERNAL_CALLBACK(void,png_safe_warning,(png_structp png_ptr,
-   png_const_charp warning_message),PNG_EMPTY);
+PNG_INTERNAL_CALLBACK(void, png_safe_warning,
+   (png_structp png_ptr, png_const_charp warning_message),
+   PNG_EMPTY);
 #else
 #  define png_safe_warning 0/*dummy argument*/
 #endif
 
-PNG_INTERNAL_FUNCTION(int,png_safe_execute,(png_imagep image,
-   int (*function)(png_voidp), png_voidp arg),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(int, png_safe_execute,
+   (png_imagep image, int (*function)(png_voidp), png_voidp arg),
+   PNG_EMPTY);
 
 /* Utility to log an error; this also cleans up the png_image; the function
  * always returns 0 (false).
  */
-PNG_INTERNAL_FUNCTION(int,png_image_error,(png_imagep image,
-   png_const_charp error_message),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(int, png_image_error,
+   (png_imagep image, png_const_charp error_message),
+   PNG_EMPTY);
 
 #ifndef PNG_SIMPLIFIED_READ_SUPPORTED
 /* png_image_free is used by the write code but not exported */
-PNG_INTERNAL_FUNCTION(void, png_image_free, (png_imagep image), PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_image_free,
+   (png_imagep image),
+   PNG_EMPTY);
 #endif /* !SIMPLIFIED_READ */
 
 #endif /* SIMPLIFIED READ/WRITE */
@@ -2122,8 +2373,9 @@ PNG_INTERNAL_FUNCTION(void, png_image_free, (png_imagep image), PNG_EMPTY);
  * the generic code is used.
  */
 #ifdef PNG_FILTER_OPTIMIZATIONS
-PNG_INTERNAL_FUNCTION(void, PNG_FILTER_OPTIMIZATIONS, (png_structp png_ptr,
-   unsigned int bpp), PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, PNG_FILTER_OPTIMIZATIONS,
+   (png_structp png_ptr, unsigned int bpp),
+   PNG_EMPTY);
    /* Just declare the optimization that will be used */
 #else
    /* List *all* the possible optimizations here - this branch is required if
@@ -2132,32 +2384,44 @@ PNG_INTERNAL_FUNCTION(void, PNG_FILTER_OPTIMIZATIONS, (png_structp png_ptr,
     */
 #  if PNG_ARM_NEON_OPT > 0
 PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon,
-   (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
+   (png_structp png_ptr, unsigned int bpp),
+   PNG_EMPTY);
 #endif
 
 #if PNG_MIPS_MSA_IMPLEMENTATION == 1
 PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_mips,
-   (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
+   (png_structp png_ptr, unsigned int bpp),
+   PNG_EMPTY);
 #endif
 
 #  if PNG_MIPS_MMI_IMPLEMENTATION > 0
 PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_mips,
-   (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
+   (png_structp png_ptr, unsigned int bpp),
+   PNG_EMPTY);
 #  endif
 
 #  if PNG_INTEL_SSE_IMPLEMENTATION > 0
 PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2,
-   (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
+   (png_structp png_ptr, unsigned int bpp),
+   PNG_EMPTY);
 #  endif
 #endif
 
 #if PNG_LOONGARCH_LSX_OPT > 0
 PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_lsx,
-    (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
+   (png_structp png_ptr, unsigned int bpp),
+   PNG_EMPTY);
 #endif
 
-PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr,
-   png_const_charp key, png_bytep new_key), PNG_EMPTY);
+#  if PNG_RISCV_RVV_IMPLEMENTATION == 1
+PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_rvv,
+   (png_structp png_ptr, unsigned int bpp),
+   PNG_EMPTY);
+#endif
+
+PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword,
+   (png_structrp png_ptr, png_const_charp key, png_bytep new_key),
+   PNG_EMPTY);
 
 #if PNG_ARM_NEON_IMPLEMENTATION == 1
 PNG_INTERNAL_FUNCTION(void,
@@ -2191,4 +2455,3 @@ PNG_INTERNAL_FUNCTION(int,
 #endif
 
 #endif /* PNG_VERSION_INFO_ONLY */
-#endif /* PNGPRIV_H */
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c
index 8a6381e1b3e..79fd9ad6a82 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018-2025 Cosmin Truta
+ * Copyright (c) 2018-2026 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -52,7 +52,8 @@
 /* Create a PNG structure for reading, and allocate any memory needed. */
 PNG_FUNCTION(png_structp,PNGAPI
 png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
-    png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED)
+    png_error_ptr error_fn, png_error_ptr warn_fn),
+    PNG_ALLOCATED)
 {
 #ifndef PNG_USER_MEM_SUPPORTED
    png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
@@ -68,7 +69,8 @@ png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
 PNG_FUNCTION(png_structp,PNGAPI
 png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
     png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
-    png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
+    png_malloc_ptr malloc_fn, png_free_ptr free_fn),
+    PNG_ALLOCATED)
 {
    png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
        error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
@@ -548,7 +550,6 @@ png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row)
 
    if (png_ptr->read_row_fn != NULL)
       (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
-
 }
 #endif /* SEQUENTIAL_READ */
 
@@ -731,7 +732,12 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr)
       png_uint_32 chunk_name = png_ptr->chunk_name;
 
       if (chunk_name != png_IDAT)
-         png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
+      {
+         /* These flags must be set consistently for all non-IDAT chunks,
+          * including the unknown chunks.
+          */
+         png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT | PNG_AFTER_IDAT;
+      }
 
       if (chunk_name == png_IEND)
          png_handle_chunk(png_ptr, info_ptr, length);
@@ -838,7 +844,8 @@ png_read_destroy(png_structrp png_ptr)
 #endif
 
 #if defined(PNG_READ_EXPAND_SUPPORTED) && \
-    defined(PNG_ARM_NEON_IMPLEMENTATION)
+    (defined(PNG_ARM_NEON_IMPLEMENTATION) || \
+     defined(PNG_RISCV_RVV_IMPLEMENTATION))
    png_free(png_ptr, png_ptr->riffled_palette);
    png_ptr->riffled_palette = NULL;
 #endif
@@ -890,7 +897,7 @@ png_set_read_status_fn(png_structrp png_ptr, png_read_status_ptr read_row_fn)
 #ifdef PNG_INFO_IMAGE_SUPPORTED
 void PNGAPI
 png_read_png(png_structrp png_ptr, png_inforp info_ptr,
-    int transforms, voidp params)
+    int transforms, png_voidp params)
 {
    png_debug(1, "in png_read_png");
 
@@ -1127,19 +1134,20 @@ png_read_png(png_structrp png_ptr, png_inforp info_ptr,
 
 typedef struct
 {
-   /* Arguments: */
+   /* Arguments */
    png_imagep image;
-   png_voidp  buffer;
+   png_voidp buffer;
    png_int_32 row_stride;
-   png_voidp  colormap;
+   png_voidp colormap;
    png_const_colorp background;
-   /* Local variables: */
-   png_voidp       local_row;
-   png_voidp       first_row;
-   ptrdiff_t       row_bytes;           /* step between rows */
-   int             file_encoding;       /* E_ values above */
-   png_fixed_point gamma_to_linear;     /* For P_FILE, reciprocal of gamma */
-   int             colormap_processing; /* PNG_CMAP_ values above */
+
+   /* Instance variables */
+   png_voidp local_row;
+   png_voidp first_row;
+   ptrdiff_t row_step;              /* step between rows */
+   int file_encoding;               /* E_ values above */
+   png_fixed_point gamma_to_linear; /* For P_FILE, reciprocal of gamma */
+   int colormap_processing;         /* PNG_CMAP_ values above */
 } png_image_read_control;
 
 /* Do all the *safe* initialization - 'safe' means that png_error won't be
@@ -1357,7 +1365,7 @@ png_image_read_header(png_voidp argument)
 
 #ifdef PNG_STDIO_SUPPORTED
 int PNGAPI
-png_image_begin_read_from_stdio(png_imagep image, FILE* file)
+png_image_begin_read_from_stdio(png_imagep image, FILE *file)
 {
    if (image != NULL && image->version == PNG_IMAGE_VERSION)
    {
@@ -2860,17 +2868,17 @@ png_image_read_and_map(png_voidp argument)
    }
 
    {
-      png_uint_32  height = image->height;
-      png_uint_32  width = image->width;
-      int          proc = display->colormap_processing;
-      png_bytep    first_row = png_voidcast(png_bytep, display->first_row);
-      ptrdiff_t    step_row = display->row_bytes;
+      png_uint_32 height = image->height;
+      png_uint_32 width = image->width;
+      int proc = display->colormap_processing;
+      png_bytep first_row = png_voidcast(png_bytep, display->first_row);
+      ptrdiff_t row_step = display->row_step;
       int pass;
 
       for (pass = 0; pass < passes; ++pass)
       {
-         unsigned int     startx, stepx, stepy;
-         png_uint_32      y;
+         unsigned int startx, stepx, stepy;
+         png_uint_32 y;
 
          if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
          {
@@ -2894,7 +2902,7 @@ png_image_read_and_map(png_voidp argument)
          for (; ylocal_row);
-            png_bytep outrow = first_row + y * step_row;
+            png_bytep outrow = first_row + y * row_step;
             png_const_bytep end_row = outrow + width;
 
             /* Read read the libpng data into the temporary buffer. */
@@ -3103,20 +3111,20 @@ png_image_read_colormapped(png_voidp argument)
     */
    {
       png_voidp first_row = display->buffer;
-      ptrdiff_t row_bytes = display->row_stride;
+      ptrdiff_t row_step = display->row_stride;
 
-      /* The following expression is designed to work correctly whether it gives
-       * a signed or an unsigned result.
+      /* The following adjustment is to ensure that calculations are correct,
+       * regardless whether row_step is positive or negative.
        */
-      if (row_bytes < 0)
+      if (row_step < 0)
       {
          char *ptr = png_voidcast(char*, first_row);
-         ptr += (image->height-1) * (-row_bytes);
+         ptr += (image->height-1) * (-row_step);
          first_row = png_voidcast(png_voidp, ptr);
       }
 
       display->first_row = first_row;
-      display->row_bytes = row_bytes;
+      display->row_step = row_step;
    }
 
    if (passes == 0)
@@ -3134,17 +3142,17 @@ png_image_read_colormapped(png_voidp argument)
 
    else
    {
-      png_alloc_size_t row_bytes = (png_alloc_size_t)display->row_bytes;
+      ptrdiff_t row_step = display->row_step;
 
       while (--passes >= 0)
       {
-         png_uint_32      y = image->height;
-         png_bytep        row = png_voidcast(png_bytep, display->first_row);
+         png_uint_32 y = image->height;
+         png_bytep row = png_voidcast(png_bytep, display->first_row);
 
          for (; y > 0; --y)
          {
             png_read_row(png_ptr, row, NULL);
-            row += row_bytes;
+            row += row_step;
          }
       }
 
@@ -3152,6 +3160,61 @@ png_image_read_colormapped(png_voidp argument)
    }
 }
 
+/* Row reading for interlaced 16-to-8 bit depth conversion with local buffer. */
+static int
+png_image_read_direct_scaled(png_voidp argument)
+{
+   png_image_read_control *display = png_voidcast(png_image_read_control*,
+       argument);
+   png_imagep image = display->image;
+   png_structrp png_ptr = image->opaque->png_ptr;
+   png_inforp info_ptr = image->opaque->info_ptr;
+   png_bytep local_row = png_voidcast(png_bytep, display->local_row);
+   png_bytep first_row = png_voidcast(png_bytep, display->first_row);
+   ptrdiff_t row_step = display->row_step;
+   size_t row_bytes = png_get_rowbytes(png_ptr, info_ptr);
+   int passes;
+
+   /* Handle interlacing. */
+   switch (png_ptr->interlaced)
+   {
+      case PNG_INTERLACE_NONE:
+         passes = 1;
+         break;
+
+      case PNG_INTERLACE_ADAM7:
+         passes = PNG_INTERLACE_ADAM7_PASSES;
+         break;
+
+      default:
+         png_error(png_ptr, "unknown interlace type");
+   }
+
+   /* Read each pass using local_row as intermediate buffer. */
+   while (--passes >= 0)
+   {
+      png_uint_32 y = image->height;
+      png_bytep output_row = first_row;
+
+      for (; y > 0; --y)
+      {
+         /* Read into local_row (gets transformed 8-bit data). */
+         png_read_row(png_ptr, local_row, NULL);
+
+         /* Copy from local_row to user buffer.
+          * Use row_bytes (i.e. the actual size in bytes of the row data) for
+          * copying into output_row. Use row_step for advancing output_row,
+          * to respect the caller's stride for padding or negative (bottom-up)
+          * layouts.
+          */
+         memcpy(output_row, local_row, row_bytes);
+         output_row += row_step;
+      }
+   }
+
+   return 1;
+}
+
 /* Just the row reading part of png_image_read. */
 static int
 png_image_read_composite(png_voidp argument)
@@ -3177,17 +3240,18 @@ png_image_read_composite(png_voidp argument)
    }
 
    {
-      png_uint_32  height = image->height;
-      png_uint_32  width = image->width;
-      ptrdiff_t    step_row = display->row_bytes;
+      png_uint_32 height = image->height;
+      png_uint_32 width = image->width;
+      ptrdiff_t row_step = display->row_step;
       unsigned int channels =
           (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
+      int optimize_alpha = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
       int pass;
 
       for (pass = 0; pass < passes; ++pass)
       {
-         unsigned int     startx, stepx, stepy;
-         png_uint_32      y;
+         unsigned int startx, stepx, stepy;
+         png_uint_32 y;
 
          if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
          {
@@ -3219,7 +3283,7 @@ png_image_read_composite(png_voidp argument)
             png_read_row(png_ptr, inrow, NULL);
 
             outrow = png_voidcast(png_bytep, display->first_row);
-            outrow += y * step_row;
+            outrow += y * row_step;
             end_row = outrow + width * channels;
 
             /* Now do the composition on each pixel in this row. */
@@ -3238,20 +3302,44 @@ png_image_read_composite(png_voidp argument)
 
                      if (alpha < 255) /* else just use component */
                      {
-                        /* This is PNG_OPTIMIZED_ALPHA, the component value
-                         * is a linear 8-bit value.  Combine this with the
-                         * current outrow[c] value which is sRGB encoded.
-                         * Arithmetic here is 16-bits to preserve the output
-                         * values correctly.
-                         */
-                        component *= 257*255; /* =65535 */
-                        component += (255-alpha)*png_sRGB_table[outrow[c]];
+                        if (optimize_alpha != 0)
+                        {
+                           /* This is PNG_OPTIMIZED_ALPHA, the component value
+                            * is a linear 8-bit value.  Combine this with the
+                            * current outrow[c] value which is sRGB encoded.
+                            * Arithmetic here is 16-bits to preserve the output
+                            * values correctly.
+                            */
+                           component *= 257*255; /* =65535 */
+                           component += (255-alpha)*png_sRGB_table[outrow[c]];
 
-                        /* So 'component' is scaled by 255*65535 and is
-                         * therefore appropriate for the sRGB to linear
-                         * conversion table.
-                         */
-                        component = PNG_sRGB_FROM_LINEAR(component);
+                           /* Clamp to the valid range to defend against
+                            * unforeseen cases where the data might be sRGB
+                            * instead of linear premultiplied.
+                            * (Belt-and-suspenders for CVE-2025-66293.)
+                            */
+                           if (component > 255*65535)
+                              component = 255*65535;
+
+                           /* So 'component' is scaled by 255*65535 and is
+                            * therefore appropriate for the sRGB-to-linear
+                            * conversion table.
+                            */
+                           component = PNG_sRGB_FROM_LINEAR(component);
+                        }
+                        else
+                        {
+                           /* Compositing was already done on the palette
+                            * entries.  The data is sRGB premultiplied on black.
+                            * Composite with the background in sRGB space.
+                            * This is not gamma-correct, but matches what was
+                            * done to the palette.
+                            */
+                           png_uint_32 background = outrow[c];
+                           component += ((255-alpha) * background + 127) / 255;
+                           if (component > 255)
+                              component = 255;
+                        }
                      }
 
                      outrow[c] = (png_byte)component;
@@ -3340,12 +3428,12 @@ png_image_read_background(png_voidp argument)
           */
          {
             png_bytep first_row = png_voidcast(png_bytep, display->first_row);
-            ptrdiff_t step_row = display->row_bytes;
+            ptrdiff_t row_step = display->row_step;
 
             for (pass = 0; pass < passes; ++pass)
             {
-               unsigned int     startx, stepx, stepy;
-               png_uint_32      y;
+               unsigned int startx, stepx, stepy;
+               png_uint_32 y;
 
                if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
                {
@@ -3372,7 +3460,7 @@ png_image_read_background(png_voidp argument)
                   {
                      png_bytep inrow = png_voidcast(png_bytep,
                          display->local_row);
-                     png_bytep outrow = first_row + y * step_row;
+                     png_bytep outrow = first_row + y * row_step;
                      png_const_bytep end_row = outrow + width;
 
                      /* Read the row, which is packed: */
@@ -3417,7 +3505,7 @@ png_image_read_background(png_voidp argument)
                   {
                      png_bytep inrow = png_voidcast(png_bytep,
                          display->local_row);
-                     png_bytep outrow = first_row + y * step_row;
+                     png_bytep outrow = first_row + y * row_step;
                      png_const_bytep end_row = outrow + width;
 
                      /* Read the row, which is packed: */
@@ -3463,9 +3551,9 @@ png_image_read_background(png_voidp argument)
             png_uint_16p first_row = png_voidcast(png_uint_16p,
                 display->first_row);
             /* The division by two is safe because the caller passed in a
-             * stride which was multiplied by 2 (below) to get row_bytes.
+             * stride which was multiplied by 2 (below) to get row_step.
              */
-            ptrdiff_t    step_row = display->row_bytes / 2;
+            ptrdiff_t row_step = display->row_step / 2;
             unsigned int preserve_alpha = (image->format &
                 PNG_FORMAT_FLAG_ALPHA) != 0;
             unsigned int outchannels = 1U+preserve_alpha;
@@ -3479,8 +3567,8 @@ png_image_read_background(png_voidp argument)
 
             for (pass = 0; pass < passes; ++pass)
             {
-               unsigned int     startx, stepx, stepy;
-               png_uint_32      y;
+               unsigned int startx, stepx, stepy;
+               png_uint_32 y;
 
                /* The 'x' start and step are adjusted to output components here.
                 */
@@ -3507,7 +3595,7 @@ png_image_read_background(png_voidp argument)
                for (; yinterlaced != 0)
+               do_local_scale = 1;
+         }
+
          change &= ~PNG_FORMAT_FLAG_LINEAR;
       }
 
@@ -3935,23 +4032,23 @@ png_image_read_direct(png_voidp argument)
     */
    {
       png_voidp first_row = display->buffer;
-      ptrdiff_t row_bytes = display->row_stride;
+      ptrdiff_t row_step = display->row_stride;
 
       if (linear != 0)
-         row_bytes *= 2;
+         row_step *= 2;
 
-      /* The following expression is designed to work correctly whether it gives
-       * a signed or an unsigned result.
+      /* The following adjustment is to ensure that calculations are correct,
+       * regardless whether row_step is positive or negative.
        */
-      if (row_bytes < 0)
+      if (row_step < 0)
       {
          char *ptr = png_voidcast(char*, first_row);
-         ptr += (image->height-1) * (-row_bytes);
+         ptr += (image->height - 1) * (-row_step);
          first_row = png_voidcast(png_voidp, ptr);
       }
 
       display->first_row = first_row;
-      display->row_bytes = row_bytes;
+      display->row_step = row_step;
    }
 
    if (do_local_compose != 0)
@@ -3980,19 +4077,37 @@ png_image_read_direct(png_voidp argument)
       return result;
    }
 
+   else if (do_local_scale != 0)
+   {
+      /* For interlaced 16-to-8 conversion, use an intermediate row buffer
+       * to avoid buffer overflows in png_combine_row. The local_row is sized
+       * for the transformed (8-bit) output, preventing the overflow that would
+       * occur if png_combine_row wrote 16-bit data directly to the user buffer.
+       */
+      int result;
+      png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
+
+      display->local_row = row;
+      result = png_safe_execute(image, png_image_read_direct_scaled, display);
+      display->local_row = NULL;
+      png_free(png_ptr, row);
+
+      return result;
+   }
+
    else
    {
-      png_alloc_size_t row_bytes = (png_alloc_size_t)display->row_bytes;
+      ptrdiff_t row_step = display->row_step;
 
       while (--passes >= 0)
       {
-         png_uint_32      y = image->height;
-         png_bytep        row = png_voidcast(png_bytep, display->first_row);
+         png_uint_32 y = image->height;
+         png_bytep row = png_voidcast(png_bytep, display->first_row);
 
          for (; y > 0; --y)
          {
             png_read_row(png_ptr, row, NULL);
-            row += row_bytes;
+            row += row_step;
          }
       }
 
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngrio.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngrio.c
index 961d010df42..50a424d0912 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngrio.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngrio.c
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018 Cosmin Truta
+ * Copyright (c) 2018-2025 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -85,7 +85,7 @@ png_default_read_data(png_structp png_ptr, png_bytep data, size_t length)
    /* fread() returns 0 on error, so it is OK to store this in a size_t
     * instead of an int, which is what fread() actually returns.
     */
-   check = fread(data, 1, length, png_voidcast(png_FILE_p, png_ptr->io_ptr));
+   check = fread(data, 1, length, png_voidcast(FILE *, png_ptr->io_ptr));
 
    if (check != length)
       png_error(png_ptr, "Read Error");
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c
index 4f31f8f07bc..7680fe64828 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018-2024 Cosmin Truta
+ * Copyright (c) 2018-2025 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -57,6 +57,12 @@
 #  endif
 #endif
 
+#ifdef PNG_RISCV_RVV_IMPLEMENTATION
+#  if PNG_RISCV_RVV_IMPLEMENTATION == 1
+#    define PNG_RISCV_RVV_INTRINSICS_AVAILABLE
+#  endif
+#endif
+
 #ifdef PNG_READ_SUPPORTED
 
 /* Set the action on getting a CRC error for an ancillary or critical chunk. */
@@ -524,9 +530,19 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
    {
       int i;
 
+      /* Initialize the array to index colors.
+       *
+       * Ensure quantize_index can fit 256 elements (PNG_MAX_PALETTE_LENGTH)
+       * rather than num_palette elements. This is to prevent buffer overflows
+       * caused by malformed PNG files with out-of-range palette indices.
+       *
+       * Be careful to avoid leaking memory. Applications are allowed to call
+       * this function more than once per png_struct.
+       */
+      png_free(png_ptr, png_ptr->quantize_index);
       png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
-          (png_alloc_size_t)num_palette);
-      for (i = 0; i < num_palette; i++)
+          PNG_MAX_PALETTE_LENGTH);
+      for (i = 0; i < PNG_MAX_PALETTE_LENGTH; i++)
          png_ptr->quantize_index[i] = (png_byte)i;
    }
 
@@ -538,15 +554,14 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
           * Perhaps not the best solution, but good enough.
           */
 
-         int i;
+         png_bytep quantize_sort;
+         int i, j;
 
-         /* Initialize an array to sort colors */
-         png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
+         /* Initialize the local array to sort colors. */
+         quantize_sort = (png_bytep)png_malloc(png_ptr,
              (png_alloc_size_t)num_palette);
-
-         /* Initialize the quantize_sort array */
          for (i = 0; i < num_palette; i++)
-            png_ptr->quantize_sort[i] = (png_byte)i;
+            quantize_sort[i] = (png_byte)i;
 
          /* Find the least used palette entries by starting a
           * bubble sort, and running it until we have sorted
@@ -558,19 +573,18 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
          for (i = num_palette - 1; i >= maximum_colors; i--)
          {
             int done; /* To stop early if the list is pre-sorted */
-            int j;
 
             done = 1;
             for (j = 0; j < i; j++)
             {
-               if (histogram[png_ptr->quantize_sort[j]]
-                   < histogram[png_ptr->quantize_sort[j + 1]])
+               if (histogram[quantize_sort[j]]
+                   < histogram[quantize_sort[j + 1]])
                {
                   png_byte t;
 
-                  t = png_ptr->quantize_sort[j];
-                  png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1];
-                  png_ptr->quantize_sort[j + 1] = t;
+                  t = quantize_sort[j];
+                  quantize_sort[j] = quantize_sort[j + 1];
+                  quantize_sort[j + 1] = t;
                   done = 0;
                }
             }
@@ -582,18 +596,18 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
          /* Swap the palette around, and set up a table, if necessary */
          if (full_quantize != 0)
          {
-            int j = num_palette;
+            j = num_palette;
 
             /* Put all the useful colors within the max, but don't
              * move the others.
              */
             for (i = 0; i < maximum_colors; i++)
             {
-               if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
+               if ((int)quantize_sort[i] >= maximum_colors)
                {
                   do
                      j--;
-                  while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
+                  while ((int)quantize_sort[j] >= maximum_colors);
 
                   palette[i] = palette[j];
                }
@@ -601,7 +615,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
          }
          else
          {
-            int j = num_palette;
+            j = num_palette;
 
             /* Move all the used colors inside the max limit, and
              * develop a translation table.
@@ -609,13 +623,13 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
             for (i = 0; i < maximum_colors; i++)
             {
                /* Only move the colors we need to */
-               if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
+               if ((int)quantize_sort[i] >= maximum_colors)
                {
                   png_color tmp_color;
 
                   do
                      j--;
-                  while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
+                  while ((int)quantize_sort[j] >= maximum_colors);
 
                   tmp_color = palette[j];
                   palette[j] = palette[i];
@@ -653,8 +667,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
                }
             }
          }
-         png_free(png_ptr, png_ptr->quantize_sort);
-         png_ptr->quantize_sort = NULL;
+         png_free(png_ptr, quantize_sort);
       }
       else
       {
@@ -1136,8 +1149,8 @@ png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red,
 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
     defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
 void PNGAPI
-png_set_read_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr
-    read_user_transform_fn)
+png_set_read_user_transform_fn(png_structrp png_ptr,
+    png_user_transform_ptr read_user_transform_fn)
 {
    png_debug(1, "in png_set_read_user_transform_fn");
 
@@ -1797,19 +1810,51 @@ png_init_read_transformations(png_structrp png_ptr)
                   }
                   else /* if (png_ptr->trans_alpha[i] != 0xff) */
                   {
-                     png_byte v, w;
-
-                     v = png_ptr->gamma_to_1[palette[i].red];
-                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.red);
-                     palette[i].red = png_ptr->gamma_from_1[w];
-
-                     v = png_ptr->gamma_to_1[palette[i].green];
-                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.green);
-                     palette[i].green = png_ptr->gamma_from_1[w];
-
-                     v = png_ptr->gamma_to_1[palette[i].blue];
-                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue);
-                     palette[i].blue = png_ptr->gamma_from_1[w];
+                     if ((png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0)
+                     {
+                        /* Premultiply only:
+                         * component = round((component * alpha) / 255)
+                         */
+                        png_uint_32 component;
+
+                        component = png_ptr->gamma_to_1[palette[i].red];
+                        component =
+                            (component * png_ptr->trans_alpha[i] + 128) / 255;
+                        palette[i].red = png_ptr->gamma_from_1[component];
+
+                        component = png_ptr->gamma_to_1[palette[i].green];
+                        component =
+                            (component * png_ptr->trans_alpha[i] + 128) / 255;
+                        palette[i].green = png_ptr->gamma_from_1[component];
+
+                        component = png_ptr->gamma_to_1[palette[i].blue];
+                        component =
+                            (component * png_ptr->trans_alpha[i] + 128) / 255;
+                        palette[i].blue = png_ptr->gamma_from_1[component];
+                     }
+                     else
+                     {
+                        /* Composite with background color:
+                         * component =
+                         *    alpha * component + (1 - alpha) * background
+                         */
+                        png_byte v, w;
+
+                        v = png_ptr->gamma_to_1[palette[i].red];
+                        png_composite(w, v,
+                            png_ptr->trans_alpha[i], back_1.red);
+                        palette[i].red = png_ptr->gamma_from_1[w];
+
+                        v = png_ptr->gamma_to_1[palette[i].green];
+                        png_composite(w, v,
+                            png_ptr->trans_alpha[i], back_1.green);
+                        palette[i].green = png_ptr->gamma_from_1[w];
+
+                        v = png_ptr->gamma_to_1[palette[i].blue];
+                        png_composite(w, v,
+                            png_ptr->trans_alpha[i], back_1.blue);
+                        palette[i].blue = png_ptr->gamma_from_1[w];
+                     }
                   }
                }
                else
@@ -1827,6 +1872,7 @@ png_init_read_transformations(png_structrp png_ptr)
              * transformations elsewhere.
              */
             png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA);
+            png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
          } /* color_type == PNG_COLOR_TYPE_PALETTE */
 
          /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
@@ -5032,13 +5078,8 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
 
 #ifdef PNG_READ_QUANTIZE_SUPPORTED
    if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
-   {
       png_do_quantize(row_info, png_ptr->row_buf + 1,
           png_ptr->palette_lookup, png_ptr->quantize_index);
-
-      if (row_info->rowbytes == 0)
-         png_error(png_ptr, "png_do_quantize returned rowbytes=0");
-   }
 #endif /* READ_QUANTIZE */
 
 #ifdef PNG_READ_EXPAND_16_SUPPORTED
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
index 6cf466d182a..01bb0c8bedc 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018-2024 Cosmin Truta
+ * Copyright (c) 2018-2025 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -2415,7 +2415,7 @@ png_handle_tIME(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 static png_handle_result_code /* PRIVATE */
 png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
-   png_text  text_info;
+   png_text text_info;
    png_bytep buffer;
    png_charp key;
    png_charp text;
@@ -2441,10 +2441,6 @@ png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
    }
 #endif
 
-   /* TODO: this doesn't work and shouldn't be necessary. */
-   if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
-      png_ptr->mode |= PNG_AFTER_IDAT;
-
    buffer = png_read_buffer(png_ptr, length+1);
 
    if (buffer == NULL)
@@ -2492,8 +2488,8 @@ static png_handle_result_code /* PRIVATE */
 png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
    png_const_charp errmsg = NULL;
-   png_bytep       buffer;
-   png_uint_32     keyword_length;
+   png_bytep buffer;
+   png_uint_32 keyword_length;
 
    png_debug(1, "in png_handle_zTXt");
 
@@ -2515,10 +2511,6 @@ png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
    }
 #endif
 
-   /* TODO: should not be necessary. */
-   if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
-      png_ptr->mode |= PNG_AFTER_IDAT;
-
    /* Note, "length" is sufficient here; we won't be adding
     * a null terminator later.  The limit check in png_handle_chunk should be
     * sufficient.
@@ -2635,10 +2627,6 @@ png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
    }
 #endif
 
-   /* TODO: should not be necessary. */
-   if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
-      png_ptr->mode |= PNG_AFTER_IDAT;
-
    buffer = png_read_buffer(png_ptr, length+1);
 
    if (buffer == NULL)
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c
index 1bfd292bd46..0b2844f1864 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c
@@ -329,17 +329,14 @@ png_set_mDCV(png_const_structrp png_ptr, png_inforp info_ptr,
     double maxDL, double minDL)
 {
    png_set_mDCV_fixed(png_ptr, info_ptr,
-      /* The ITU approach is to scale by 50,000, not 100,000 so just divide
-       * the input values by 2 and use png_fixed:
-       */
-      png_fixed(png_ptr, white_x / 2, "png_set_mDCV(white(x))"),
-      png_fixed(png_ptr, white_y / 2, "png_set_mDCV(white(y))"),
-      png_fixed(png_ptr, red_x / 2, "png_set_mDCV(red(x))"),
-      png_fixed(png_ptr, red_y / 2, "png_set_mDCV(red(y))"),
-      png_fixed(png_ptr, green_x / 2, "png_set_mDCV(green(x))"),
-      png_fixed(png_ptr, green_y / 2, "png_set_mDCV(green(y))"),
-      png_fixed(png_ptr, blue_x / 2, "png_set_mDCV(blue(x))"),
-      png_fixed(png_ptr, blue_y / 2, "png_set_mDCV(blue(y))"),
+      png_fixed(png_ptr, white_x, "png_set_mDCV(white(x))"),
+      png_fixed(png_ptr, white_y, "png_set_mDCV(white(y))"),
+      png_fixed(png_ptr, red_x, "png_set_mDCV(red(x))"),
+      png_fixed(png_ptr, red_y, "png_set_mDCV(red(y))"),
+      png_fixed(png_ptr, green_x, "png_set_mDCV(green(x))"),
+      png_fixed(png_ptr, green_y, "png_set_mDCV(green(y))"),
+      png_fixed(png_ptr, blue_x, "png_set_mDCV(blue(x))"),
+      png_fixed(png_ptr, blue_y, "png_set_mDCV(blue(y))"),
       png_fixed_ITU(png_ptr, maxDL, "png_set_mDCV(maxDL)"),
       png_fixed_ITU(png_ptr, minDL, "png_set_mDCV(minDL)"));
 }
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngstruct.h b/src/java.desktop/share/native/libsplashscreen/libpng/pngstruct.h
index d6c446564d1..8edb4bc393a 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngstruct.h
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngstruct.h
@@ -22,14 +22,14 @@
  * questions.
  */
 
-/* pngstruct.h - header file for PNG reference library
+/* pngstruct.h - internal structures for libpng
  *
  * This file is available under and governed by the GNU General Public
  * License version 2 only, as published by the Free Software Foundation.
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018-2022 Cosmin Truta
+ * Copyright (c) 2018-2025 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -39,11 +39,9 @@
  * and license in png.h
  */
 
-/* The structure that holds the information to read and write PNG files.
- * The only people who need to care about what is inside of this are the
- * people who will be modifying the library for their own special needs.
- * It should NOT be accessed directly by an application.
- */
+#ifndef PNGPRIV_H
+#  error This file must not be included by applications; please include 
+#endif
 
 #ifndef PNGSTRUCT_H
 #define PNGSTRUCT_H
@@ -406,7 +404,8 @@ struct png_struct_def
 
 /* New member added in libpng-1.6.36 */
 #if defined(PNG_READ_EXPAND_SUPPORTED) && \
-    defined(PNG_ARM_NEON_IMPLEMENTATION)
+    (defined(PNG_ARM_NEON_IMPLEMENTATION) || \
+     defined(PNG_RISCV_RVV_IMPLEMENTATION))
    png_bytep riffled_palette; /* buffer for accelerated palette expansion */
 #endif
 
@@ -435,7 +434,6 @@ struct png_struct_def
 
 #ifdef PNG_READ_QUANTIZE_SUPPORTED
 /* The following three members were added at version 1.0.14 and 1.2.4 */
-   png_bytep quantize_sort;          /* working sort array */
    png_bytep index_to_palette;       /* where the original index currently is
                                         in the palette */
    png_bytep palette_to_index;       /* which original index points to this
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngtrans.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngtrans.c
index 2350057e70e..b9f6cb5d437 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngtrans.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngtrans.c
@@ -831,8 +831,8 @@ png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
     defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
 #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
 void PNGAPI
-png_set_user_transform_info(png_structrp png_ptr, png_voidp
-   user_transform_ptr, int user_transform_depth, int user_transform_channels)
+png_set_user_transform_info(png_structrp png_ptr, png_voidp user_transform_ptr,
+    int user_transform_depth, int user_transform_channels)
 {
    png_debug(1, "in png_set_user_transform_info");
 
diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java b/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java
index eab0817af23..78cd4a7e57d 100644
--- a/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java
+++ b/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java
@@ -138,8 +138,6 @@
 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;
@@ -1523,21 +1521,16 @@ public int getNumberOfButtons(){
         awtLock();
         try {
             if (numberOfButtons == 0) {
-                if (XdgDesktopPortal.isRemoteDesktop()
-                        && ScreencastHelper.isAvailable()) {
+                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;
-                } else {
-                    numberOfButtons = getNumberOfButtonsImpl();
-                    numberOfButtons = (numberOfButtons > MAX_BUTTONS_SUPPORTED) ? MAX_BUTTONS_SUPPORTED : numberOfButtons;
-                    //4th and 5th buttons are for wheel and shouldn't be reported as buttons.
-                    //If we have more than 3 physical buttons and a wheel, we report N-2 buttons.
-                    //If we have 3 physical buttons and a wheel, we report 3 buttons.
-                    //If we have 1,2,3 physical buttons, we report it as is i.e. 1,2 or 3 respectively.
-                    if (numberOfButtons >= 5) {
-                        numberOfButtons -= 2;
-                    } else if (numberOfButtons == 4 || numberOfButtons == 5) {
-                        numberOfButtons = 3;
-                    }
                 }
             }
             //Assume don't have to re-query the number again and again.
diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java b/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java
index f2b7efc978f..4911dea5d97 100644
--- a/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java
+++ b/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java
@@ -1098,9 +1098,11 @@ public void setVisible(boolean vis) {
                 suppressWmTakeFocus(true);
             }
         }
-        updateFocusability();
-        promoteDefaultPosition();
         boolean refreshChildsTransientFor = isVisible() != vis;
+        if (refreshChildsTransientFor) {
+            updateFocusability();
+        }
+        promoteDefaultPosition();
         super.setVisible(vis);
         if (refreshChildsTransientFor) {
             for (Window child : ((Window) target).getOwnedWindows()) {
diff --git a/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java b/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java
index 77a67103fc3..ff25120b659 100644
--- a/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java
+++ b/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java
@@ -333,7 +333,7 @@ depth, getConfigColormap(0, screen),
 
     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);
@@ -350,10 +350,11 @@ private static native void configDisplayMode(int screen,
      */
     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 --git a/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java b/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java
index 33af39810d5..a8f7cd41a0e 100644
--- a/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java
+++ b/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java
@@ -63,9 +63,11 @@ public final class ScreencastHelper {
     private static final int DELAY_BEFORE_SESSION_CLOSE = 2000;
 
     private static volatile TimerTask timerTask = null;
-    private static final Timer timerCloseSession
-            = new Timer("auto-close screencast session", true);
 
+    private static class TimerHolder {
+        private static final Timer timerCloseSession =
+                new Timer("auto-close screencast session", true);
+    }
 
     private ScreencastHelper() {}
 
@@ -143,7 +145,7 @@ public void run() {
             }
         };
 
-        timerCloseSession.schedule(timerTask, DELAY_BEFORE_SESSION_CLOSE);
+        TimerHolder.timerCloseSession.schedule(timerTask, DELAY_BEFORE_SESSION_CLOSE);
     }
 
     public static synchronized void getRGBPixels(
diff --git a/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java b/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java
index 9db64725048..09dc84e74d0 100644
--- a/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java
+++ b/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java
@@ -238,6 +238,7 @@ public void run() {
     }
 
     private static WatchService watchService;
+    private static volatile boolean isWatcherThreadStarted = false;
 
     private static void setupWatch() {
         try {
@@ -257,10 +258,6 @@ private static void setupWatch() {
                         "file watch %s\n", e);
             }
         }
-
-        if (watchService != null) {
-            new WatcherThread(watchService).start();
-        }
     }
 
     // called from native
@@ -337,7 +334,27 @@ private static boolean readTokens(Path path) {
         return true;
     }
 
+    private static void startWatcherThreadIfNeeded() {
+        if (!isWatcherThreadStarted) {
+            // not sure if the double-checked locking is actually needed here
+            // the getTokens is only called from ScreencastHelper#getRGBPixels
+            // and ScreencastHelper#remoteDesktop* methods (which are synchronized),
+            // but it may change later.
+            synchronized (TokenStorage.class) {
+                if (!isWatcherThreadStarted) {
+                    readTokens(PROPS_PATH);
+                    if (watchService != null) {
+                        new WatcherThread(watchService).start();
+                    }
+                    isWatcherThreadStarted = true;
+                }
+            }
+        }
+    }
+
     static Set getTokens(List affectedScreenBounds) {
+        startWatcherThreadIfNeeded();
+
         // We need an ordered set to store tokens
         // with exact matches at the beginning.
         LinkedHashSet result = new LinkedHashSet<>();
diff --git a/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java b/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java
index d96894660b9..f9445a78ede 100644
--- a/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java
+++ b/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java
@@ -876,12 +876,16 @@ static String[] execCmd(final String command) {
                     FileReader reader = new FileReader(f);
                     bufferedReader = new BufferedReader(reader);
                     String line;
+                    results = new ArrayList<>();
                     while ((line = bufferedReader.readLine())
                            != null) {
                         results.add(line);
                     }
                 }
-            } finally {
+            } catch (Exception e) {
+                // Print exception for tracking printer command errors
+                IPPPrintService.debug_println("Printer command error: " + e);
+           } finally {
                 f.delete();
                 // promptly close all streams.
                 if (bufferedReader != null) {
diff --git a/src/java.desktop/unix/native/common/awt/awt_GraphicsEnv.h b/src/java.desktop/unix/native/common/awt/awt_GraphicsEnv.h
index da6ae0c8117..82e956d4074 100644
--- a/src/java.desktop/unix/native/common/awt/awt_GraphicsEnv.h
+++ b/src/java.desktop/unix/native/common/awt/awt_GraphicsEnv.h
@@ -62,4 +62,11 @@ struct X11GraphicsConfigIDs {
     jfieldID bitsPerPixel;
 };
 
+#define MAX_DISPLAY_MODES 256
+typedef struct {
+    unsigned int width;
+    unsigned int height;
+    jint refresh;
+} DisplayMode;
+
 #endif /* _AWT_GRAPHICSENV_H_ */
diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c
index fdb2bbb3ab9..423f0ee4bc9 100644
--- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c
+++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c
@@ -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 awtNotifyMID = NULL;
 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 { \
@@ -1505,6 +1508,20 @@ typedef XRRCrtcInfo* (*XRRGetCrtcInfoType)(Display *dpy,
 
 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;
@@ -1520,6 +1537,8 @@ static XRRGetOutputInfoType              awt_XRRGetOutputInfo;
 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 { \
@@ -1597,6 +1616,8 @@ X11GD_InitXrandrFuncs(JNIEnv *env)
     LOAD_XRANDR_FUNC(XRRFreeOutputInfo);
     LOAD_XRANDR_FUNC(XRRGetCrtcInfo);
     LOAD_XRANDR_FUNC(XRRFreeCrtcInfo);
+    LOAD_XRANDR_FUNC(XRRSetScreenSize);
+    LOAD_XRANDR_FUNC(XRRSetCrtcConfig);
 
     return JNI_TRUE;
 }
@@ -1697,11 +1718,11 @@ X11GD_SetFullscreenMode(Window win, jboolean enabled)
 /*
  * 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;
@@ -1717,10 +1738,305 @@ Java_sun_awt_X11GraphicsDevice_initXrandrExtension
     }
     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
@@ -1733,9 +2049,17 @@ Java_sun_awt_X11GraphicsDevice_getCurrentDisplayMode
 #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)) {
@@ -1786,7 +2110,12 @@ Java_sun_awt_X11GraphicsDevice_enumDisplayModes
 {
 #if !defined(NO_XRANDR)
 
-    AWT_LOCK();
+    if (useNewConfigDisplayMode) {
+        AWT_LOCK();
+        xrrEnumDisplayModes(env, arrayList, screen);
+        AWT_FLUSH_UNLOCK();
+        return;
+    }
 
     if (XScreenCount(awt_display) > 0) {
 
@@ -1836,6 +2165,15 @@ Java_sun_awt_X11GraphicsDevice_configDisplayMode
      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 --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c b/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c
index 916880873c6..09dacecba20 100644
--- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c
+++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c
@@ -42,7 +42,6 @@
 #include "debug_assert.h"
 
 static void *gtk3_libhandle = NULL;
-static void *gthread_libhandle = NULL;
 
 static void transform_detail_string (const gchar *detail,
                                      GtkStyleContext *context);
@@ -79,15 +78,6 @@ static void* dl_symbol(const char* name)
     return result;
 }
 
-static void* dl_symbol_gthread(const char* name)
-{
-    void* result = dlsym(gthread_libhandle, name);
-    if (!result)
-        longjmp(j, NO_SYMBOL_EXCEPTION);
-
-    return result;
-}
-
 gboolean gtk3_check(const char* lib_name, gboolean load)
 {
     if (gtk3_libhandle != NULL) {
@@ -264,13 +254,6 @@ GtkApi* gtk3_load(JNIEnv *env, const char* lib_name)
         return FALSE;
     }
 
-    gthread_libhandle = dlopen(GTHREAD_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL);
-    if (gthread_libhandle == NULL) {
-        gthread_libhandle = dlopen(GTHREAD_LIB, RTLD_LAZY | RTLD_LOCAL);
-        if (gthread_libhandle == NULL)
-            return FALSE;
-    }
-
     if (setjmp(j) == 0)
     {
         fp_gtk_check_version = dl_symbol("gtk_check_version");
@@ -637,9 +620,6 @@ GtkApi* gtk3_load(JNIEnv *env, const char* lib_name)
         dlclose(gtk3_libhandle);
         gtk3_libhandle = NULL;
 
-        dlclose(gthread_libhandle);
-        gthread_libhandle = NULL;
-
         return NULL;
     }
 
@@ -738,7 +718,6 @@ static int gtk3_unload()
 
     dlerror();
     dlclose(gtk3_libhandle);
-    dlclose(gthread_libhandle);
     if ((gtk3_error = dlerror()) != NULL)
     {
         return FALSE;
diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h b/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h
index 11ec245ce8b..39be6a735d7 100644
--- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h
+++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h
@@ -38,9 +38,6 @@
 #define TRUE            (!FALSE)
 #endif
 
-#define GTHREAD_LIB_VERSIONED VERSIONED_JNI_LIB_NAME("gthread-2.0", "0")
-#define GTHREAD_LIB JNI_LIB_NAME("gthread-2.0")
-
 #define _G_TYPE_CIC(ip, gt, ct)       ((ct*) ip)
 #define G_TYPE_CHECK_INSTANCE_CAST(instance, g_type, c_type)  \
                                     (_G_TYPE_CIC ((instance), (g_type), c_type))
@@ -850,9 +847,6 @@ typedef struct GtkApi {
 gboolean gtk_load(JNIEnv *env, GtkVersion version, gboolean verbose);
 gboolean gtk_check_version(GtkVersion version);
 
-typedef struct _GThreadFunctions GThreadFunctions;
-static gboolean (*fp_g_thread_get_initialized)(void);
-static void (*fp_g_thread_init)(GThreadFunctions *vtable);
 static void (*fp_gdk_threads_init)(void);
 static void (*fp_gdk_threads_enter)(void);
 static void (*fp_gdk_threads_leave)(void);
diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c b/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c
index ec12445c87b..e29c6bc4319 100644
--- a/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c
+++ b/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c
@@ -33,6 +33,7 @@
 
 #ifndef _AIX
 #include "screencast_pipewire.h"
+#include "java_awt_event_KeyEvent.h"
 
 struct pw_buffer *(*fp_pw_stream_dequeue_buffer)(struct pw_stream *stream);
 const char * (*fp_pw_stream_state_as_string)(enum pw_stream_state state);
@@ -1016,6 +1017,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_getRGBPixelsImpl
     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(
@@ -1121,7 +1123,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMou
     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);
 
@@ -1151,6 +1153,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMou
     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)
@@ -1178,6 +1181,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMou
     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)
@@ -1194,6 +1198,24 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMou
     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
@@ -1202,17 +1224,21 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMou
 JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopKeyImpl
         (JNIEnv *env, jclass cls, jboolean isPress, jint jkey, jstring jtoken) {
 
-    AWT_LOCK();
-    int key = awt_getX11KeySym(jkey);
-    AWT_UNLOCK();
+    int key = getNumpadKey(jkey);
+    if (!key) {
+        AWT_LOCK();
+        key = awt_getX11KeySym(jkey);
+        AWT_UNLOCK();
+    }
 
-    if (key == NoSymbol) {
+    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)
diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java
index f59a59a5125..02054575d77 100644
--- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java
+++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java
@@ -84,7 +84,9 @@ protected void paintMenuItem(Graphics g, JComponent c,
                                  int defaultTextIconGap) {
         if (WindowsMenuItemUI.isVistaPainting()) {
             WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon,
-                    arrowIcon, background, foreground, defaultTextIconGap,
+                    arrowIcon, background, foreground,
+                    disabledForeground, acceleratorSelectionForeground,
+                    acceleratorForeground, defaultTextIconGap,
                     menuItem, getPropertyPrefix());
             return;
         }
diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java
index efa710391d5..915a361a3a1 100644
--- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java
+++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java
@@ -914,8 +914,15 @@ public void paintIcon(Component c, Graphics g, int x, int y) {
                     }
                 }
                 if (icon != null) {
-                    icon.paintIcon(c, g, x + VistaMenuItemCheckIconFactory.getIconWidth(),
-                                   y + OFFSET);
+                    if (WindowsGraphicsUtils.isLeftToRight(c)) {
+                        icon.paintIcon(c, g,
+                                       x + VistaMenuItemCheckIconFactory.getIconWidth(),
+                                       y + OFFSET);
+                    } else {
+                        icon.paintIcon(c, g,
+                                       x - VistaMenuItemCheckIconFactory.getIconWidth() + 2 * OFFSET,
+                                       y + OFFSET);
+                    }
                 }
             }
             private static WindowsMenuItemUIAccessor getAccessor(
diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java
index a8bafc54c33..117d3b5fd08 100644
--- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java
+++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java
@@ -43,6 +43,7 @@
 import javax.swing.JComponent;
 import javax.swing.JMenu;
 import javax.swing.JMenuItem;
+import javax.swing.SwingConstants;
 import javax.swing.UIManager;
 import javax.swing.plaf.ComponentUI;
 import javax.swing.plaf.UIResource;
@@ -67,9 +68,6 @@ public final class WindowsMenuItemUI extends BasicMenuItemUI {
      * The instance of {@code PropertyChangeListener}.
      */
     private PropertyChangeListener changeListener;
-    private static Color disabledForeground;
-    private static Color acceleratorSelectionForeground;
-    private static Color acceleratorForeground;
 
     final WindowsMenuItemUIAccessor accessor =
         new  WindowsMenuItemUIAccessor() {
@@ -167,36 +165,6 @@ protected void uninstallListeners() {
         changeListener = null;
     }
 
-    private static void applyInsets(Rectangle rect, Insets insets) {
-        SwingUtilities3.applyInsets(rect, insets);
-    }
-
-    private static void paintCheckIcon(Graphics g, MenuItemLayoutHelper lh,
-                                MenuItemLayoutHelper.LayoutResult lr,
-                                Color holdc, Color foreground) {
-        SwingUtilities3.paintCheckIcon(g, lh, lr, holdc, foreground);
-    }
-
-    private static void paintIcon(Graphics g, MenuItemLayoutHelper lh,
-                           MenuItemLayoutHelper.LayoutResult lr, Color holdc) {
-        SwingUtilities3.paintIcon(g, lh, lr, holdc);
-    }
-
-    private static void paintAccText(Graphics g, MenuItemLayoutHelper lh,
-                              MenuItemLayoutHelper.LayoutResult lr) {
-        SwingUtilities3.setDisabledForeground(disabledForeground);
-        SwingUtilities3.setAcceleratorSelectionForeground(
-                        acceleratorSelectionForeground);
-        SwingUtilities3.setAcceleratorForeground(acceleratorForeground);
-        SwingUtilities3.paintAccText(g, lh, lr);
-    }
-
-    private static void paintArrowIcon(Graphics g, MenuItemLayoutHelper lh,
-                                MenuItemLayoutHelper.LayoutResult lr,
-                                Color foreground) {
-        SwingUtilities3.paintArrowIcon(g, lh, lr, foreground);
-    }
-
     protected void paintMenuItem(Graphics g, JComponent c,
                                  Icon checkIcon, Icon arrowIcon,
                                  Color background, Color foreground,
@@ -204,7 +172,8 @@ protected void paintMenuItem(Graphics g, JComponent c,
         if (WindowsMenuItemUI.isVistaPainting()) {
             WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon,
                                             arrowIcon, background, foreground,
-                                            defaultTextIconGap, menuItem,
+                                            disabledForeground, acceleratorSelectionForeground,
+                                            acceleratorForeground, defaultTextIconGap, menuItem,
                                             getPropertyPrefix());
             return;
         }
@@ -215,6 +184,9 @@ protected void paintMenuItem(Graphics g, JComponent c,
     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();
@@ -224,7 +196,7 @@ static void paintMenuItem(WindowsMenuItemUIAccessor accessor, Graphics g,
         g.setFont(mi.getFont());
 
         Rectangle viewRect = new Rectangle(0, 0, mi.getWidth(), mi.getHeight());
-        applyInsets(viewRect, mi.getInsets());
+        SwingUtilities3.applyInsets(viewRect, mi.getInsets());
 
         String acceleratorDelimiter =
                 UIManager.getString("MenuItem.acceleratorDelimiter");
@@ -242,13 +214,22 @@ static void paintMenuItem(WindowsMenuItemUIAccessor accessor, Graphics g,
         MenuItemLayoutHelper.LayoutResult lr = lh.layoutMenuItem();
 
         paintBackground(accessor, g, mi, background);
-        paintCheckIcon(g, lh, lr, holdc, foreground);
-        paintIcon(g, lh, lr, holdc);
+        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();
+            if (menuItem.getComponentOrientation().isLeftToRight()) {
+                if (menuItem.getHorizontalTextPosition() != SwingConstants.LEADING
+                    && menuItem.getHorizontalTextPosition() != SwingConstants.LEFT) {
+                    rect.x += lh.getAfterCheckIconGap();
+                }
+            } else {
+                if (menuItem.getHorizontalTextPosition() != SwingConstants.LEADING
+                    && menuItem.getHorizontalTextPosition() != SwingConstants.RIGHT) {
+                    rect.x -= lh.getAfterCheckIconGap();
+                }
+            }
 
             lr.setTextRect(rect);
         }
@@ -264,11 +245,17 @@ static void paintMenuItem(WindowsMenuItemUIAccessor accessor, Graphics g,
         }
         if (lh.getCheckIcon() != null && lh.useCheckAndArrow()) {
             Rectangle rect = lr.getAccRect();
-            rect.x += lh.getAfterCheckIconGap();
+            if (menuItem.getComponentOrientation().isLeftToRight()) {
+                rect.x += lh.getAfterCheckIconGap();
+            } else {
+                rect.x -= lh.getAfterCheckIconGap();
+            }
             lr.setAccRect(rect);
         }
-        paintAccText(g, lh, lr);
-        paintArrowIcon(g, lh, lr, foreground);
+        SwingUtilities3.paintAccText(g, lh, lr, disabledForeground,
+                                     acceleratorSelectionForeground,
+                                     acceleratorForeground);
+        SwingUtilities3.paintArrowIcon(g, lh, lr, foreground);
 
         // Restore original graphics font and color
         g.setColor(holdc);
diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java
index 81c01c11036..1476c6fc152 100644
--- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java
+++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java
@@ -140,7 +140,8 @@ protected void paintMenuItem(Graphics g, JComponent c,
         if (WindowsMenuItemUI.isVistaPainting()) {
             WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon, arrowIcon,
                                             background, foreground,
-                                            defaultTextIconGap, menuItem,
+                                            disabledForeground, acceleratorSelectionForeground,
+                                            acceleratorForeground, defaultTextIconGap, menuItem,
                                             getPropertyPrefix());
             return;
         }
diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java
index 385ab6b3634..628a4be1637 100644
--- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java
+++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java
@@ -84,7 +84,9 @@ protected void paintMenuItem(Graphics g, JComponent c,
                                  int defaultTextIconGap) {
         if (WindowsMenuItemUI.isVistaPainting()) {
             WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon,
-                    arrowIcon, background, foreground, defaultTextIconGap,
+                    arrowIcon, background, foreground,
+                    disabledForeground, acceleratorSelectionForeground,
+                    acceleratorForeground, defaultTextIconGap,
                     menuItem, getPropertyPrefix());
             return;
         }
diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WDesktopPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WDesktopPeer.java
index 788c1477265..e5b628dd74b 100644
--- a/src/java.desktop/windows/classes/sun/awt/windows/WDesktopPeer.java
+++ b/src/java.desktop/windows/classes/sun/awt/windows/WDesktopPeer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,6 +38,9 @@
 import java.io.IOException;
 import java.net.URI;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 import javax.swing.event.EventListenerList;
 
 import sun.awt.shell.ShellFolder;
@@ -50,9 +53,11 @@
  */
 final class WDesktopPeer implements DesktopPeer {
     /* Constants for the operation verbs */
-    private static String ACTION_OPEN_VERB = "open";
-    private static String ACTION_EDIT_VERB = "edit";
-    private static String ACTION_PRINT_VERB = "print";
+    private static final String ACTION_OPEN_VERB = "open";
+    private static final String ACTION_EDIT_VERB = "edit";
+    private static final String ACTION_PRINT_VERB = "print";
+    private static final String ACTION_BROWSE_VERB = "browse";
+    private static final String ACTION_MAIL_VERB = "mail";
 
     private static native void init();
 
@@ -95,12 +100,12 @@ public void print(File file) throws IOException {
 
     @Override
     public void mail(URI uri) throws IOException {
-        this.ShellExecute(uri, ACTION_OPEN_VERB);
+        this.ShellExecute(uri, ACTION_MAIL_VERB);
     }
 
     @Override
     public void browse(URI uri) throws IOException {
-        this.ShellExecute(uri, ACTION_OPEN_VERB);
+        this.launchUriInBrowser(uri);
     }
 
     private void ShellExecute(File file, String verb) throws IOException {
@@ -121,6 +126,42 @@ private void ShellExecute(URI uri, String verb) throws IOException {
         }
     }
 
+    private void launchUriInBrowser(URI uri) throws IOException {
+        String defaultBrowser = getDefaultBrowser();
+        if (defaultBrowser == null) {
+            throw new IOException("Failed to get default browser");
+        }
+
+        List cmdLineTokens = getCmdLineTokens(uri, defaultBrowser);
+        try {
+            ProcessBuilder pb = new ProcessBuilder(cmdLineTokens);
+            pb.start();
+        }  catch (Exception e) {
+            throw new IOException("Error launching Browser: ", e);
+        }
+    }
+
+    private static List getCmdLineTokens(URI uri, String defaultBrowser) {
+        if (defaultBrowser.contains("%1")) {
+            defaultBrowser = defaultBrowser.replace("%1", uri.toString());
+        } else {
+            defaultBrowser = defaultBrowser + " " + uri.toString();
+        }
+
+        List cmdLineTokens = new ArrayList<>();
+        int firstIndex = defaultBrowser.indexOf("\"");
+        int secondIndex = defaultBrowser.indexOf("\"", firstIndex + 1);
+
+        if (firstIndex == 0 && secondIndex != firstIndex) {
+            cmdLineTokens.add(defaultBrowser.substring(firstIndex, secondIndex + 1));
+            defaultBrowser = defaultBrowser.substring(secondIndex + 1).trim();
+        }
+        cmdLineTokens.addAll(Arrays.asList(defaultBrowser.split(" ")));
+        return cmdLineTokens;
+    }
+
+    private static native String getDefaultBrowser();
+
     private static native String ShellExecute(String fileOrUri, String verb);
 
     private static final EventListenerList listenerList = new EventListenerList();
diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Desktop.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Desktop.cpp
index ba79523249c..ebb43b2f078 100644
--- a/src/java.desktop/windows/native/libawt/windows/awt_Desktop.cpp
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Desktop.cpp
@@ -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
@@ -30,6 +30,12 @@
 #include 
 #include 
 #include "awt_Toolkit.h"
+#include 
+#include   // for AssocQueryStringW
+#include 
+#include 
+#include 
+#include  // for SaferiIsExecutableFileType
 
 #define BUFFER_LIMIT   MAX_PATH+1
 
@@ -78,14 +84,23 @@ JNIEXPORT jstring JNICALL Java_sun_awt_windows_WDesktopPeer_ShellExecute
     LPCWSTR fileOrUri_c = JNU_GetStringPlatformChars(env, fileOrUri_j, NULL);
     CHECK_NULL_RETURN(fileOrUri_c, NULL);
     LPCWSTR verb_c = JNU_GetStringPlatformChars(env, verb_j, NULL);
+
     if (verb_c == NULL) {
         JNU_ReleaseStringPlatformChars(env, fileOrUri_j, fileOrUri_c);
         return NULL;
     }
+    if (wcscmp(verb_c, L"open") == 0) {
+        BOOL isExecutable = SaferiIsExecutableFileType(fileOrUri_c, FALSE);
+        if (isExecutable) {
+            return env->NewStringUTF("Unsupported URI content");
+        }
+    }
+    // set action verb for mail() to open before calling ShellExecute
+    LPCWSTR actionVerb = wcscmp(verb_c, L"mail") == 0 ? L"open" : verb_c;
 
     // 6457572: ShellExecute possibly changes FPU control word - saving it here
     unsigned oldcontrol87 = _control87(0, 0);
-    HINSTANCE retval = ::ShellExecute(NULL, verb_c, fileOrUri_c, NULL, NULL,
+    HINSTANCE retval = ::ShellExecute(NULL, actionVerb, fileOrUri_c, NULL, NULL,
                                       SW_SHOWNORMAL);
     DWORD error = ::GetLastError();
     _control87(oldcontrol87, 0xffffffff);
@@ -113,10 +128,38 @@ JNIEXPORT jstring JNICALL Java_sun_awt_windows_WDesktopPeer_ShellExecute
             return errmsg;
         }
     }
-
     return NULL;
 }
 
+/*
+ * Class:     sun_awt_windows_WDesktopPeer
+ * Method:    getDefaultBrowser
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_sun_awt_windows_WDesktopPeer_getDefaultBrowser
+(JNIEnv *env, jclass cls)
+{
+    LPCWSTR fileExtension = L"https";
+    WCHAR defaultBrowser_c [MAX_PATH];
+    DWORD cchBuffer = MAX_PATH;
+
+    // Use AssocQueryString to get the default browser
+    HRESULT hr = AssocQueryStringW(
+        ASSOCF_NONE,            // No special flags
+        ASSOCSTR_COMMAND,       // Request the command string
+        fileExtension,          // File extension
+        NULL,                   // pszExtra (optional)
+        defaultBrowser_c,       // Output buffer - result
+        &cchBuffer              // Size of the output buffer
+    );
+
+    if (FAILED(hr)) {
+        return NULL;
+    }
+
+    return JNU_NewStringPlatform(env, defaultBrowser_c);
+}
+
 /*
  * Class:     sun_awt_windows_WDesktopPeer
  * Method:    moveToTrash
diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp
index d5bbdc51b0b..0e7e27b5e8c 100644
--- a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp
@@ -2498,32 +2498,22 @@ jint AwtWindow::_GetScreenImOn(void *param)
 
     jobject self = (jobject)param;
 
-    // It's entirely possible that our native resources have been destroyed
-    // before our java peer - if we're dispose()d, for instance.
-    // Alert caller w/ IllegalComponentStateException.
-    if (self == NULL) {
-        JNU_ThrowByName(env, "java/awt/IllegalComponentStateException",
-                        "Peer null in JNI");
-        return 0;
-    }
-    PDATA pData = JNI_GET_PDATA(self);
-    if (pData == NULL) {
-        JNU_ThrowByName(env, "java/awt/IllegalComponentStateException",
-                        "Native resources unavailable");
-        env->DeleteGlobalRef(self);
-        return 0;
-    }
+    jint result = -1;
+    AwtWindow* window = NULL;
 
-    jint result = 0;
-    AwtWindow *w = (AwtWindow *)pData;
-    if (::IsWindow(w->GetHWnd()))
+    // Our native resources may have been destroyed before the Java peer,
+    // e.g., if dispose() was called. In that case, return the default screen.
+    PDATA pData;
+    JNI_CHECK_PEER_GOTO(self, ret);
+    window = (AwtWindow *)pData;
+    if (::IsWindow(window->GetHWnd()))
     {
-        result = (jint)w->GetScreenImOn();
+        result = (jint)window->GetScreenImOn();
     }
 
+  ret:
     env->DeleteGlobalRef(self);
-
-    return result;
+    return (result != -1) ? result : AwtWin32GraphicsDevice::GetDefaultDeviceIndex();
 }
 
 void AwtWindow::_SetFocusableWindow(void *param)
diff --git a/src/java.management/share/classes/sun/management/ThreadImpl.java b/src/java.management/share/classes/sun/management/ThreadImpl.java
index be54ced066d..a246e01dd63 100644
--- a/src/java.management/share/classes/sun/management/ThreadImpl.java
+++ b/src/java.management/share/classes/sun/management/ThreadImpl.java
@@ -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
@@ -308,7 +308,7 @@ protected long[] getThreadUserTime(long[] ids) {
                 long id = ids[0];
                 Thread thread = Thread.currentThread();
                 if (id == thread.threadId()) {
-                    times[0] = thread.isVirtual() ? -1L : getThreadTotalCpuTime0(0);
+                    times[0] = thread.isVirtual() ? -1L : getThreadUserCpuTime0(0);
                 } else {
                     times[0] = getThreadUserCpuTime0(id);
                 }
diff --git a/src/java.rmi/share/classes/javax/rmi/ssl/SslRMIClientSocketFactory.java b/src/java.rmi/share/classes/javax/rmi/ssl/SslRMIClientSocketFactory.java
index ab6664b9d8f..a4475c8bd1e 100644
--- a/src/java.rmi/share/classes/javax/rmi/ssl/SslRMIClientSocketFactory.java
+++ b/src/java.rmi/share/classes/javax/rmi/ssl/SslRMIClientSocketFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2008, 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,7 @@
 import java.rmi.server.RMIClientSocketFactory;
 import java.util.StringTokenizer;
 import javax.net.SocketFactory;
+import javax.net.ssl.SSLParameters;
 import javax.net.ssl.SSLSocket;
 import javax.net.ssl.SSLSocketFactory;
 
@@ -119,6 +120,16 @@ public Socket createSocket(String host, int port) throws IOException {
         //
         final SSLSocket sslSocket = (SSLSocket)
             sslSocketFactory.createSocket(host, port);
+
+        if (Boolean.parseBoolean(
+                System.getProperty("jdk.rmi.ssl.client.enableEndpointIdentification", "true"))) {
+            SSLParameters params = sslSocket.getSSLParameters();
+            if (params == null) {
+                params = new SSLParameters();
+            }
+            params.setEndpointIdentificationAlgorithm("HTTPS");
+            sslSocket.setSSLParameters(params);
+        }
         // Set the SSLSocket Enabled Cipher Suites
         //
         final String enabledCipherSuites =
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Const.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Const.java
index bca72ab3f95..c6b97db142e 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Const.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Const.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -26,12 +26,12 @@
  * Constants for the project, mostly defined in the JVM specification.
  *
  * @since 6.0 (intended to replace the Constants interface)
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
  */
 public final class Const {
 
     /**
-     * Java class file format Magic number (0xCAFEBABE)
+     * Java class file format Magic number: {@value}.
      *
      * @see  The ClassFile Structure
      *      in The Java Virtual Machine Specification
@@ -39,201 +39,201 @@ public final class Const {
     public static final int JVM_CLASSFILE_MAGIC = 0xCAFEBABE;
 
     /**
-     * Major version number of class files for Java 1.1.
+     * Major version number of class files for Java 1.1: {@value}.
      *
      * @see #MINOR_1_1
      */
     public static final short MAJOR_1_1 = 45;
 
     /**
-     * Minor version number of class files for Java 1.1.
+     * Minor version number of class files for Java 1.1: {@value}.
      *
      * @see #MAJOR_1_1
      */
     public static final short MINOR_1_1 = 3;
 
     /**
-     * Major version number of class files for Java 1.2.
+     * Major version number of class files for Java 1.2: {@value}.
      *
      * @see #MINOR_1_2
      */
     public static final short MAJOR_1_2 = 46;
 
     /**
-     * Minor version number of class files for Java 1.2.
+     * Minor version number of class files for Java 1.2: {@value}.
      *
      * @see #MAJOR_1_2
      */
     public static final short MINOR_1_2 = 0;
 
     /**
-     * Major version number of class files for Java 1.2.
+     * Major version number of class files for Java 1.2: {@value}.
      *
      * @see #MINOR_1_2
      */
     public static final short MAJOR_1_3 = 47;
 
     /**
-     * Minor version number of class files for Java 1.3.
+     * Minor version number of class files for Java 1.3: {@value}.
      *
      * @see #MAJOR_1_3
      */
     public static final short MINOR_1_3 = 0;
 
     /**
-     * Major version number of class files for Java 1.3.
+     * Major version number of class files for Java 1.3: {@value}.
      *
      * @see #MINOR_1_3
      */
     public static final short MAJOR_1_4 = 48;
 
     /**
-     * Minor version number of class files for Java 1.4.
+     * Minor version number of class files for Java 1.4: {@value}.
      *
      * @see #MAJOR_1_4
      */
     public static final short MINOR_1_4 = 0;
 
     /**
-     * Major version number of class files for Java 1.4.
+     * Major version number of class files for Java 1.4: {@value}.
      *
      * @see #MINOR_1_4
      */
     public static final short MAJOR_1_5 = 49;
 
     /**
-     * Minor version number of class files for Java 1.5.
+     * Minor version number of class files for Java 1.5: {@value}.
      *
      * @see #MAJOR_1_5
      */
     public static final short MINOR_1_5 = 0;
 
     /**
-     * Major version number of class files for Java 1.6.
+     * Major version number of class files for Java 1.6: {@value}.
      *
      * @see #MINOR_1_6
      */
     public static final short MAJOR_1_6 = 50;
 
     /**
-     * Minor version number of class files for Java 1.6.
+     * Minor version number of class files for Java 1.6: {@value}.
      *
      * @see #MAJOR_1_6
      */
     public static final short MINOR_1_6 = 0;
 
     /**
-     * Major version number of class files for Java 1.7.
+     * Major version number of class files for Java 1.7: {@value}.
      *
      * @see #MINOR_1_7
      */
     public static final short MAJOR_1_7 = 51;
 
     /**
-     * Minor version number of class files for Java 1.7.
+     * Minor version number of class files for Java 1.7: {@value}.
      *
      * @see #MAJOR_1_7
      */
     public static final short MINOR_1_7 = 0;
 
     /**
-     * Major version number of class files for Java 1.8.
+     * Major version number of class files for Java 1.8: {@value}.
      *
      * @see #MINOR_1_8
      */
     public static final short MAJOR_1_8 = 52;
 
     /**
-     * Minor version number of class files for Java 1.8.
+     * Minor version number of class files for Java 1.8: {@value}.
      *
      * @see #MAJOR_1_8
      */
     public static final short MINOR_1_8 = 0;
 
     /**
-     * Major version number of class files for Java 9.
+     * Major version number of class files for Java 9: {@value}.
      *
      * @see #MINOR_9
      */
     public static final short MAJOR_9 = 53;
 
     /**
-     * Minor version number of class files for Java 9.
+     * Minor version number of class files for Java 9: {@value}.
      *
      * @see #MAJOR_9
      */
     public static final short MINOR_9 = 0;
 
     /**
-     * @deprecated Use {@link #MAJOR_9} instead
+     * @deprecated Use {@link #MAJOR_9} ({@value}) instead.
      */
     @Deprecated
     public static final short MAJOR_1_9 = MAJOR_9;
 
     /**
-     * @deprecated Use {@link #MINOR_9} instead
+     * @deprecated Use {@link #MINOR_9} ({@value}) instead.
      */
     @Deprecated
     public static final short MINOR_1_9 = MINOR_9;
 
     /**
-     * Major version number of class files for Java 10.
+     * Major version number of class files for Java 10: {@value}.
      *
      * @see #MINOR_10
      */
     public static final short MAJOR_10 = 54;
 
     /**
-     * Minor version number of class files for Java 10.
+     * Minor version number of class files for Java 10: {@value}.
      *
      * @see #MAJOR_10
      */
     public static final short MINOR_10 = 0;
 
     /**
-     * Major version number of class files for Java 11.
+     * Major version number of class files for Java 11: {@value}.
      *
      * @see #MINOR_11
      */
     public static final short MAJOR_11 = 55;
 
     /**
-     * Minor version number of class files for Java 11.
+     * Minor version number of class files for Java 11: {@value}.
      *
      * @see #MAJOR_11
      */
     public static final short MINOR_11 = 0;
 
     /**
-     * Major version number of class files for Java 12.
+     * Major version number of class files for Java 12: {@value}.
      *
      * @see #MINOR_12
      */
     public static final short MAJOR_12 = 56;
 
     /**
-     * Minor version number of class files for Java 12.
+     * Minor version number of class files for Java 12: {@value}.
      *
      * @see #MAJOR_12
      */
     public static final short MINOR_12 = 0;
 
     /**
-     * Major version number of class files for Java 13.
+     * Major version number of class files for Java 13: {@value}.
      *
      * @see #MINOR_13
      */
     public static final short MAJOR_13 = 57;
 
     /**
-     * Minor version number of class files for Java 13.
+     * Minor version number of class files for Java 13: {@value}.
      *
      * @see #MAJOR_13
      */
     public static final short MINOR_13 = 0;
 
     /**
-     * Minor version number of class files for Java 14.
+     * Minor version number of class files for Java 14: {@value}.
      *
      * @see #MAJOR_14
      * @since 6.4.0
@@ -241,7 +241,7 @@ public final class Const {
     public static final short MINOR_14 = 0;
 
     /**
-     * Minor version number of class files for Java 15.
+     * Minor version number of class files for Java 15: {@value}.
      *
      * @see #MAJOR_15
      * @since 6.6.0
@@ -249,7 +249,7 @@ public final class Const {
     public static final short MINOR_15 = 0;
 
     /**
-     * Minor version number of class files for Java 16.
+     * Minor version number of class files for Java 16: {@value}.
      *
      * @see #MAJOR_16
      * @since 6.6.0
@@ -257,7 +257,7 @@ public final class Const {
     public static final short MINOR_16 = 0;
 
     /**
-     * Minor version number of class files for Java 17.
+     * Minor version number of class files for Java 17: {@value}.
      *
      * @see #MAJOR_17
      * @since 6.6.0
@@ -265,7 +265,7 @@ public final class Const {
     public static final short MINOR_17 = 0;
 
     /**
-     * Minor version number of class files for Java 18.
+     * Minor version number of class files for Java 18: {@value}.
      *
      * @see #MAJOR_18
      * @since 6.6.0
@@ -273,7 +273,7 @@ public final class Const {
     public static final short MINOR_18 = 0;
 
     /**
-     * Minor version number of class files for Java 19.
+     * Minor version number of class files for Java 19: {@value}.
      *
      * @see #MAJOR_19
      * @since 6.6.0
@@ -281,7 +281,47 @@ public final class Const {
     public static final short MINOR_19 = 0;
 
     /**
-     * Major version number of class files for Java 14.
+     * Minor version number of class files for Java 20: {@value}.
+     *
+     * @see #MAJOR_20
+     * @since 6.8.0
+     */
+    public static final short MINOR_20 = 0;
+
+    /**
+     * Minor version number of class files for Java 21: {@value}.
+     *
+     * @see #MAJOR_21
+     * @since 6.8.0
+     */
+    public static final short MINOR_21 = 0;
+
+    /**
+     * Minor version number of class files for Java 22: {@value}.
+     *
+     * @see #MAJOR_22
+     * @since 6.10.0
+     */
+    public static final short MINOR_22 = 0;
+
+    /**
+     * Minor version number of class files for Java 23: {@value}.
+     *
+     * @see #MAJOR_23
+     * @since 6.10.0
+     */
+    public static final short MINOR_23 = 0;
+
+    /**
+     * Minor version number of class files for Java 24: {@value}.
+     *
+     * @see #MAJOR_24
+     * @since 6.10.0
+     */
+    public static final short MINOR_24 = 0;
+
+    /**
+     * Major version number of class files for Java 14: {@value}.
      *
      * @see #MINOR_14
      * @since 6.4.0
@@ -289,7 +329,7 @@ public final class Const {
     public static final short MAJOR_14 = 58;
 
     /**
-     * Major version number of class files for Java 15.
+     * Major version number of class files for Java 15: {@value}.
      *
      * @see #MINOR_15
      * @since 6.6.0
@@ -297,7 +337,7 @@ public final class Const {
     public static final short MAJOR_15 = 59;
 
     /**
-     * Major version number of class files for Java 16.
+     * Major version number of class files for Java 16: {@value}.
      *
      * @see #MINOR_16
      * @since 6.6.0
@@ -305,7 +345,7 @@ public final class Const {
     public static final short MAJOR_16 = 60;
 
     /**
-     * Major version number of class files for Java 17.
+     * Major version number of class files for Java 17: {@value}.
      *
      * @see #MINOR_17
      * @since 6.6.0
@@ -313,7 +353,7 @@ public final class Const {
     public static final short MAJOR_17 = 61;
 
     /**
-     * Major version number of class files for Java 18.
+     * Major version number of class files for Java 18: {@value}.
      *
      * @see #MINOR_18
      * @since 6.6.0
@@ -321,7 +361,7 @@ public final class Const {
     public static final short MAJOR_18 = 62;
 
     /**
-     * Major version number of class files for Java 19.
+     * Major version number of class files for Java 19: {@value}.
      *
      * @see #MINOR_19
      * @since 6.6.0
@@ -329,31 +369,71 @@ public final class Const {
     public static final short MAJOR_19 = 63;
 
     /**
-     * Default major version number. Class file is for Java 1.1.
+     * Major version number of class files for Java 20: {@value}.
+     *
+     * @see #MINOR_20
+     * @since 6.8.0
+     */
+    public static final short MAJOR_20 = 64;
+
+    /**
+     * Major version number of class files for Java 21: {@value}.
+     *
+     * @see #MINOR_21
+     * @since 6.8.0
+     */
+    public static final short MAJOR_21 = 65;
+
+    /**
+     * Major version number of class files for Java 22: {@value}.
+     *
+     * @see #MINOR_22
+     * @since 6.10.0
+     */
+    public static final short MAJOR_22 = 66;
+
+    /**
+     * Major version number of class files for Java 23: {@value}.
+     *
+     * @see #MINOR_23
+     * @since 6.10.0
+     */
+    public static final short MAJOR_23 = 67;
+
+    /**
+     * Major version number of class files for Java 24: {@value}.
+     *
+     * @see #MINOR_24
+     * @since 6.10.0
+     */
+    public static final short MAJOR_24 = 68;
+
+    /**
+     * Default major version number. Class file is for Java 1.1: {@value}.
      *
      * @see #MAJOR_1_1
      */
     public static final short MAJOR = MAJOR_1_1;
 
     /**
-     * Default major version number. Class file is for Java 1.1.
+     * Default major version number. Class file is for Java 1.1: {@value}.
      *
      * @see #MAJOR_1_1
      */
     public static final short MINOR = MINOR_1_1;
 
     /**
-     * Maximum value for an unsigned short.
+     * Maximum value for an unsigned short: {@value}.
      */
     public static final int MAX_SHORT = 65535; // 2^16 - 1
 
     /**
-     * Maximum value for an unsigned byte.
+     * Maximum value for an unsigned byte: {@value}.
      */
     public static final int MAX_BYTE = 255; // 2^8 - 1
 
     /**
-     * One of the access flags for fields, methods, or classes.
+     * One of the access flags for fields, methods, or classes: {@value}.
      *
      * @see  Flag definitions for
      *      Classes in the Java Virtual Machine Specification (Java SE 9 Edition).
@@ -367,140 +447,140 @@ public final class Const {
     public static final short ACC_PUBLIC = 0x0001;
 
     /**
-     * One of the access flags for fields, methods, or classes.
+     * One of the access flags for fields, methods, or classes: {@value}.
      *
      * @see #ACC_PUBLIC
      */
     public static final short ACC_PRIVATE = 0x0002;
 
     /**
-     * One of the access flags for fields, methods, or classes.
+     * One of the access flags for fields, methods, or classes: {@value}.
      *
      * @see #ACC_PUBLIC
      */
     public static final short ACC_PROTECTED = 0x0004;
 
     /**
-     * One of the access flags for fields, methods, or classes.
+     * One of the access flags for fields, methods, or classes: {@value}.
      *
      * @see #ACC_PUBLIC
      */
     public static final short ACC_STATIC = 0x0008;
 
     /**
-     * One of the access flags for fields, methods, or classes.
+     * One of the access flags for fields, methods, or classes: {@value}.
      *
      * @see #ACC_PUBLIC
      */
     public static final short ACC_FINAL = 0x0010;
 
     /**
-     * One of the access flags for the Module attribute.
+     * One of the access flags for the Module attribute: {@value}.
      *
      * @see #ACC_PUBLIC
      */
     public static final short ACC_OPEN = 0x0020;
 
     /**
-     * One of the access flags for classes.
+     * One of the access flags for classes: {@value}.
      *
      * @see #ACC_PUBLIC
      */
     public static final short ACC_SUPER = 0x0020;
 
     /**
-     * One of the access flags for methods.
+     * One of the access flags for methods: {@value}.
      *
      * @see #ACC_PUBLIC
      */
     public static final short ACC_SYNCHRONIZED = 0x0020;
 
     /**
-     * One of the access flags for the Module attribute.
+     * One of the access flags for the Module attribute: {@value}.
      *
      * @see #ACC_PUBLIC
      */
     public static final short ACC_TRANSITIVE = 0x0020;
 
     /**
-     * One of the access flags for methods.
+     * One of the access flags for methods: {@value}.
      *
      * @see #ACC_PUBLIC
      */
     public static final short ACC_BRIDGE = 0x0040;
 
     /**
-     * One of the access flags for the Module attribute.
+     * One of the access flags for the Module attribute: {@value}.
      *
      * @see #ACC_PUBLIC
      */
     public static final short ACC_STATIC_PHASE = 0x0040;
 
     /**
-     * One of the access flags for fields.
+     * One of the access flags for fields: {@value}.
      *
      * @see #ACC_PUBLIC
      */
     public static final short ACC_VOLATILE = 0x0040;
 
     /**
-     * One of the access flags for fields.
+     * One of the access flags for fields: {@value}.
      *
      * @see #ACC_PUBLIC
      */
     public static final short ACC_TRANSIENT = 0x0080;
 
     /**
-     * One of the access flags for methods.
+     * One of the access flags for methods: {@value}.
      *
      * @see #ACC_PUBLIC
      */
     public static final short ACC_VARARGS = 0x0080;
 
     /**
-     * One of the access flags for methods.
+     * One of the access flags for methods: {@value}.
      *
      * @see #ACC_PUBLIC
      */
     public static final short ACC_NATIVE = 0x0100;
 
     /**
-     * One of the access flags for classes.
+     * One of the access flags for classes: {@value}.
      *
      * @see #ACC_PUBLIC
      */
     public static final short ACC_INTERFACE = 0x0200;
 
     /**
-     * One of the access flags for methods or classes.
+     * One of the access flags for methods or classes: {@value}.
      *
      * @see #ACC_PUBLIC
      */
     public static final short ACC_ABSTRACT = 0x0400;
 
     /**
-     * One of the access flags for methods.
+     * One of the access flags for methods: {@value}.
      *
      * @see #ACC_PUBLIC
      */
     public static final short ACC_STRICT = 0x0800;
 
     /**
-     * One of the access flags for fields, methods, classes, MethodParameter attribute, or Module attribute.
+     * One of the access flags for fields, methods, classes, MethodParameter attribute, or Module attribute: {@value}.
      *
      * @see #ACC_PUBLIC
      */
     public static final short ACC_SYNTHETIC = 0x1000;
 
     /**
-     * One of the access flags for classes.
+     * One of the access flags for classes: {@value}.
      *
      * @see #ACC_PUBLIC
      */
     public static final short ACC_ANNOTATION = 0x2000;
 
     /**
-     * One of the access flags for fields or classes.
+     * One of the access flags for fields or classes: {@value}.
      *
      * @see #ACC_PUBLIC
      */
@@ -508,21 +588,21 @@ public final class Const {
 
     // Applies to classes compiled by new compilers only
     /**
-     * One of the access flags for MethodParameter or Module attributes.
+     * One of the access flags for MethodParameter or Module attributes: {@value}.
      *
      * @see #ACC_PUBLIC
      */
     public static final short ACC_MANDATED = (short) 0x8000;
 
     /**
-     * One of the access flags for classes.
+     * One of the access flags for classes: {@value}.
      *
      * @see #ACC_PUBLIC
      */
     public static final short ACC_MODULE = (short) 0x8000;
 
     /**
-     * One of the access flags for fields, methods, or classes.
+     * One of the access flags for fields, methods, or classes: {@value}.
      *
      * @see #ACC_PUBLIC
      * @deprecated Use {@link #MAX_ACC_FLAG_I}
@@ -531,7 +611,7 @@ public final class Const {
     public static final short MAX_ACC_FLAG = ACC_ENUM;
 
     /**
-     * One of the access flags for fields, methods, or classes. ACC_MODULE is negative as a short.
+     * One of the access flags for fields, methods, or classes. ACC_MODULE is negative as a short: {@value}.
      *
      * @see #ACC_PUBLIC
      * @since 6.4.0
@@ -553,7 +633,7 @@ public final class Const {
     public static final int ACCESS_NAMES_LENGTH = ACCESS_NAMES.length;
 
     /**
-     * Marks a constant pool entry as type UTF-8.
+     * Marks a constant pool entry as type UTF-8: {@value}.
      *
      * @see  The Constant Pool in The
      *      Java Virtual Machine Specification
@@ -566,7 +646,7 @@ public final class Const {
      */
 
     /**
-     * Marks a constant pool entry as type Integer.
+     * Marks a constant pool entry as type Integer: {@value}.
      *
      * @see  The Constant Pool in The
      *      Java Virtual Machine Specification
@@ -574,7 +654,7 @@ public final class Const {
     public static final byte CONSTANT_Integer = 3;
 
     /**
-     * Marks a constant pool entry as type Float.
+     * Marks a constant pool entry as type Float: {@value}.
      *
      * @see  The Constant Pool in The
      *      Java Virtual Machine Specification
@@ -582,7 +662,7 @@ public final class Const {
     public static final byte CONSTANT_Float = 4;
 
     /**
-     * Marks a constant pool entry as type Long.
+     * Marks a constant pool entry as type Long: {@value}.
      *
      * @see  The Constant Pool in The
      *      Java Virtual Machine Specification
@@ -590,7 +670,7 @@ public final class Const {
     public static final byte CONSTANT_Long = 5;
 
     /**
-     * Marks a constant pool entry as type Double.
+     * Marks a constant pool entry as type Double: {@value}.
      *
      * @see  The Constant Pool in The
      *      Java Virtual Machine Specification
@@ -598,7 +678,7 @@ public final class Const {
     public static final byte CONSTANT_Double = 6;
 
     /**
-     * Marks a constant pool entry as a Class
+     * Marks a constant pool entry as a Class: {@value}.
      *
      * @see  The Constant Pool in The
      *      Java Virtual Machine Specification
@@ -606,7 +686,7 @@ public final class Const {
     public static final byte CONSTANT_Class = 7;
 
     /**
-     * Marks a constant pool entry as a Field Reference.
+     * Marks a constant pool entry as a Field Reference: {@value}.
      *
      * @see  The Constant Pool in The
      *      Java Virtual Machine Specification
@@ -614,7 +694,7 @@ public final class Const {
     public static final byte CONSTANT_Fieldref = 9;
 
     /**
-     * Marks a constant pool entry as type String
+     * Marks a constant pool entry as type String: {@value}.
      *
      * @see  The Constant Pool in The
      *      Java Virtual Machine Specification
@@ -622,7 +702,7 @@ public final class Const {
     public static final byte CONSTANT_String = 8;
 
     /**
-     * Marks a constant pool entry as a Method Reference.
+     * Marks a constant pool entry as a Method Reference: {@value}.
      *
      * @see  The Constant Pool in The
      *      Java Virtual Machine Specification
@@ -630,7 +710,7 @@ public final class Const {
     public static final byte CONSTANT_Methodref = 10;
 
     /**
-     * Marks a constant pool entry as an Interface Method Reference.
+     * Marks a constant pool entry as an Interface Method Reference: {@value}.
      *
      * @see  The Constant Pool in The
      *      Java Virtual Machine Specification
@@ -638,7 +718,7 @@ public final class Const {
     public static final byte CONSTANT_InterfaceMethodref = 11;
 
     /**
-     * Marks a constant pool entry as a name and type.
+     * Marks a constant pool entry as a name and type: {@value}.
      *
      * @see  The Constant Pool in The
      *      Java Virtual Machine Specification
@@ -646,7 +726,7 @@ public final class Const {
     public static final byte CONSTANT_NameAndType = 12;
 
     /**
-     * Marks a constant pool entry as a Method Handle.
+     * Marks a constant pool entry as a Method Handle: {@value}.
      *
      * @see  The Constant Pool in The
      *      Java Virtual Machine Specification
@@ -654,7 +734,7 @@ public final class Const {
     public static final byte CONSTANT_MethodHandle = 15;
 
     /**
-     * Marks a constant pool entry as a Method Type.
+     * Marks a constant pool entry as a Method Type: {@value}.
      *
      * @see  The Constant Pool in The
      *      Java Virtual Machine Specification
@@ -662,16 +742,16 @@ public final class Const {
     public static final byte CONSTANT_MethodType = 16;
 
     /**
-     * Marks a constant pool entry as dynamically computed.
+     * Marks a constant pool entry as dynamically computed: {@value}.
      *
-     * @see  Change request for JEP
-     *      309
+     * @see  The Constant Pool in The
+     *      Java Virtual Machine Specification
      * @since 6.3
      */
     public static final byte CONSTANT_Dynamic = 17;
 
     /**
-     * Marks a constant pool entry as an Invoke Dynamic
+     * Marks a constant pool entry as an Invoke Dynamic: {@value}.
      *
      * @see  The Constant Pool in The
      *      Java Virtual Machine Specification
@@ -679,7 +759,7 @@ public final class Const {
     public static final byte CONSTANT_InvokeDynamic = 18;
 
     /**
-     * Marks a constant pool entry as a Module Reference.
+     * Marks a constant pool entry as a Module Reference: {@value}.
      *
      * @see  The Constant Pool in The
      *      Java Virtual Machine Specification
@@ -688,7 +768,7 @@ public final class Const {
     public static final byte CONSTANT_Module = 19;
 
     /**
-     * Marks a constant pool entry as a Package Reference.
+     * Marks a constant pool entry as a Package Reference: {@value}.
      *
      * @see  The Constant Pool in The
      *      Java Virtual Machine Specification
@@ -705,23 +785,23 @@ public final class Const {
 
     /**
      * The name of the static initializer, also called "class initialization method" or "interface
-     * initialization method". This is "<clinit>".
+     * initialization method". This is {@value}.
      */
     public static final String STATIC_INITIALIZER_NAME = "";
 
     /**
      * The name of every constructor method in a class, also called "instance initialization method". This is
-     * "<init>".
+     * {@value}.
      */
     public static final String CONSTRUCTOR_NAME = "";
 
     /**
-     * The names of the interfaces implemented by arrays
+     * The names of the interfaces implemented by arrays.
      */
     private static final String[] INTERFACES_IMPLEMENTED_BY_ARRAYS = {"java.lang.Cloneable", "java.io.Serializable"};
 
     /**
-     * Maximum Constant Pool entries. One of the limitations of the Java Virtual Machine.
+     * Maximum Constant Pool entries: {@value}. One of the limitations of the Java Virtual Machine.
      *
      * @see  The Java Virtual
      *      Machine Specification, Java SE 8 Edition, page 330, chapter 4.11.
@@ -729,21 +809,25 @@ public final class Const {
     public static final int MAX_CP_ENTRIES = 65535;
 
     /**
-     * Maximum code size (plus one; the code size must be LESS than this) One of the limitations of the Java Virtual
-     * Machine. Note vmspec2 page 152 ("Limitations") says: "The amount of code per non-native, non-abstract method is
-     * limited to 65536 bytes by the sizes of the indices in the exception_table of the Code attribute (4.7.3), in the
-     * LineNumberTable attribute (4.7.8), and in the LocalVariableTable attribute (4.7.9)." However this should be taken
-     * as an upper limit rather than the defined maximum. On page 134 (4.8.1 Static Constants) of the same spec, it says:
-     * "The value of the code_length item must be less than 65536." The entry in the Limitations section has been removed
-     * from later versions of the spec; it is not present in the Java SE 8 edition.
+     * Maximum code size (plus one; the code size must be LESS than this): {@value}.
+     * 

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

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

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

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

- * Note that the detail message associated with {@code cause} is not automatically incorporated in this runtime exception's detail message. * * @param message the detail message (which is saved for later retrieval by the {@link #getMessage()} method). - * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method). (A {@code null} value is permitted, and indicates that - * the cause is nonexistent or unknown.) + * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method). A {@code null} value is permitted, and indicates that + * the cause is nonexistent or unknown. * @since 6.0 */ public ClassFormatException(final String message, final Throwable cause) { @@ -63,8 +61,8 @@ public ClassFormatException(final String message, final Throwable cause) { * Constructs a new instance with the specified cause and a detail message of {@code (cause==null ? null : cause.toString())} (which typically contains the * class and detail message of {@code cause}). This constructor is useful for runtime exceptions that are little more than wrappers for other throwables. * - * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method). (A {@code null} value is permitted, and indicates that the - * cause is nonexistent or unknown.) + * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method). A {@code null} value is permitted, and indicates that the + * cause is nonexistent or unknown. * @since 6.7.0 */ public ClassFormatException(final Throwable cause) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassParser.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassParser.java index c9daaeabf9b..0dbda722ec4 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassParser.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassParser.java @@ -37,7 +37,7 @@ * appropriate exception is propagated back to the caller. * * The structure and the names comply, except for a few conveniences, exactly with the - * JVM specification 1.0. See this paper for further details about + * JVM specification 1.0. See this paper for further details about * the structure of a bytecode file. */ public final class ClassParser { @@ -57,7 +57,7 @@ public final class ClassParser { private Field[] fields; // class fields, i.e., its variables private Method[] methods; // methods defined in the class private Attribute[] attributes; // attributes defined in the class - private final boolean isZip; // Loaded from zip file + private final boolean isZip; // Loaded from ZIP file /** * Parses class from the given stream. @@ -91,7 +91,7 @@ public ClassParser(final String fileName) { /** * Parses class from given .class file in a ZIP-archive * - * @param zipFile zip file name + * @param zipFile ZIP file name * @param fileName file name */ public ClassParser(final String zipFile, final String fileName) { @@ -104,7 +104,7 @@ public ClassParser(final String zipFile, final String fileName) { /** * Parses the given Java class file and return an object that represents the contained data, i.e., constants, methods, * fields and commands. A ClassFormatException is raised, if the file is not a valid .class file. (This does - * not include verification of the byte code as it is performed by the java interpreter). + * not include verification of the byte code as it is performed by the Java interpreter). * * @return Class object representing the parsed class file * @throws IOException if an I/O error occurs. @@ -151,11 +151,11 @@ public JavaClass parse() throws IOException, ClassFormatException { // for (int i=0; i < u.length; i++) // System.err.println("WARNING: " + u[i]); // Everything should have been read now - // if(file.available() > 0) { + // if (file.available() > 0) { // int bytes = file.available(); // byte[] buf = new byte[bytes]; // file.read(buf); - // if(!(isZip && (buf.length == 1))) { + // if (!(isZip && (buf.length == 1))) { // System.err.println("WARNING: Trailing garbage at end of " + fileName); // System.err.println(bytes + " extra bytes: " + Utility.toHexString(buf)); // } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Code.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Code.java index 498a8c71b18..7573a5412e7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Code.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Code.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -27,6 +27,7 @@ import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.util.Args; +import jdk.xml.internal.Utils; /** * This class represents a chunk of Java byte code contained in a method. It is instantiated by the @@ -59,7 +60,7 @@ * @see CodeException * @see LineNumberTable * @see LocalVariableTable - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public final class Code extends Attribute { @@ -93,7 +94,7 @@ public Code(final Code code) { code = new byte[codeLength]; // Read byte code file.readFully(code); /* - * Read exception table that contains all regions where an exception handler is active, i.e., a try { ... } catch() + * Read exception table that contains all regions where an exception handler is active, i.e., a try { ... } catch () * block. */ final int exceptionTableLength = file.readUnsignedShort(); @@ -107,7 +108,7 @@ public Code(final Code code) { final int attributesCount = file.readUnsignedShort(); attributes = new Attribute[attributesCount]; for (int i = 0; i < attributesCount; i++) { - attributes[i] = Attribute.readAttribute(file, constantPool); + attributes[i] = readAttribute(file, constantPool); } /* * Adjust length, because of setAttributes in this(), s.b. length is incorrect, because it didn't take the internal @@ -131,8 +132,8 @@ public Code(final int nameIndex, final int length, final int maxStack, final int super(Const.ATTR_CODE, nameIndex, length, constantPool); this.maxStack = Args.requireU2(maxStack, "maxStack"); this.maxLocals = Args.requireU2(maxLocals, "maxLocals"); - this.code = code != null ? code : Const.EMPTY_BYTE_ARRAY; - this.exceptionTable = exceptionTable != null ? exceptionTable : CodeException.EMPTY_CODE_EXCEPTION_ARRAY; + this.code = Utils.createEmptyArrayIfNull(code); + this.exceptionTable = Utils.createEmptyArrayIfNull(exceptionTable, CodeException[].class); Args.requireU2(this.exceptionTable.length, "exceptionTable.length"); this.attributes = attributes != null ? attributes : EMPTY_ARRAY; super.setLength(calculateLength()); // Adjust length @@ -263,6 +264,20 @@ public LocalVariableTable getLocalVariableTable() { return null; } + /** + * Gets the local variable type table attribute {@link LocalVariableTypeTable}. + * @return LocalVariableTypeTable of Code, if it has one, null otherwise. + * @since 6.10.0 + */ + public LocalVariableTypeTable getLocalVariableTypeTable() { + for (final Attribute attribute : attributes) { + if (attribute instanceof LocalVariableTypeTable) { + return (LocalVariableTypeTable) attribute; + } + } + return null; + } + /** * @return Number of local variables. */ @@ -277,6 +292,20 @@ public int getMaxStack() { return maxStack; } + /** + * Finds the attribute of {@link StackMap} instance. + * @return StackMap of Code, if it has one, else null. + * @since 6.8.0 + */ + public StackMap getStackMap() { + for (final Attribute attribute : attributes) { + if (attribute instanceof StackMap) { + return (StackMap) attribute; + } + } + return null; + } + /** * @param attributes the attributes to set for this Code */ @@ -289,7 +318,7 @@ public void setAttributes(final Attribute[] attributes) { * @param code byte code */ public void setCode(final byte[] code) { - this.code = code != null ? code : Const.EMPTY_BYTE_ARRAY; + this.code = Utils.createEmptyArrayIfNull(code); super.setLength(calculateLength()); // Adjust length } @@ -297,7 +326,7 @@ public void setCode(final byte[] code) { * @param exceptionTable exception table */ public void setExceptionTable(final CodeException[] exceptionTable) { - this.exceptionTable = exceptionTable != null ? exceptionTable : CodeException.EMPTY_CODE_EXCEPTION_ARRAY; + this.exceptionTable = exceptionTable != null ? exceptionTable : CodeException.EMPTY_ARRAY; super.setLength(calculateLength()); // Adjust length } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/CodeException.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/CodeException.java index ee224e6b348..b8bf109239e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/CodeException.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/CodeException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -52,19 +52,19 @@ *

* * @see Code - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public final class CodeException implements Cloneable, Node { /** * Empty array. */ - static final CodeException[] EMPTY_CODE_EXCEPTION_ARRAY = {}; + static final CodeException[] EMPTY_ARRAY = {}; /** Range in the code the exception handler. */ private int startPc; - /** active. startPc is inclusive, endPc exclusive. */ + /** Active. startPc is inclusive, endPc exclusive. */ private int endPc; /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Constant.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Constant.java index 885e1b599eb..9b3d6f31e17 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Constant.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Constant.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -32,30 +32,29 @@ * in the constant pool of a class file. The classes keep closely to * the JVM specification. * - * @LastModified: May 2021 + * @LastModified: Sept 2025 */ public abstract class Constant implements Cloneable, Node { - private static BCELComparator bcelComparator = new BCELComparator() { + static final Constant[] EMPTY_ARRAY = {}; + + private static BCELComparator bcelComparator = new BCELComparator() { @Override - public boolean equals(final Object o1, final Object o2) { - final Constant THIS = (Constant) o1; - final Constant THAT = (Constant) o2; - return Objects.equals(THIS.toString(), THAT.toString()); + public boolean equals(final Constant a, final Constant b) { + return a == b || a != null && b != null && Objects.equals(a.toString(), b.toString()); } @Override - public int hashCode(final Object o) { - final Constant THIS = (Constant) o; - return THIS.toString().hashCode(); + public int hashCode(final Constant o) { + return o != null ? Objects.hashCode(o.toString()) : 0; } }; /** - * @return Comparison strategy object + * @return Comparison strategy object. */ - public static BCELComparator getComparator() { + public static BCELComparator getComparator() { return bcelComparator; } @@ -113,7 +112,7 @@ public static Constant readConstant(final DataInput dataInput) throws IOExceptio /** * @param comparator Comparison strategy object */ - public static void setComparator(final BCELComparator comparator) { + public static void setComparator(final BCELComparator comparator) { bcelComparator = comparator; } @@ -148,7 +147,7 @@ public Object clone() { try { return super.clone(); } catch (final CloneNotSupportedException e) { - throw new Error("Clone Not Supported"); // never happens + throw new UnsupportedOperationException("Clone Not Supported", e); // never happens } } @@ -174,7 +173,7 @@ public Constant copy() { */ @Override public boolean equals(final Object obj) { - return bcelComparator.equals(this, obj); + return obj instanceof Constant && bcelComparator.equals(this, (Constant) obj); } /** @@ -185,7 +184,7 @@ public final byte getTag() { } /** - * Returns value as defined by given BCELComparator strategy. By default return the hashcode of the result of + * Returns value as defined by given BCELComparator strategy. By default return the hash code of the result of * toString(). * * @see Object#hashCode() diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantCP.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantCP.java index 71fd91b249a..51113a1aeaa 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantCP.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantCP.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -28,11 +28,11 @@ /** * Abstract super class for Fieldref, Methodref, InterfaceMethodref and InvokeDynamic constants. * - * @see ConstantFieldref - * @see ConstantMethodref - * @see ConstantInterfaceMethodref - * @see ConstantInvokeDynamic - * @LastModified: Jun 2019 + * @see ConstantFieldref + * @see ConstantMethodref + * @see ConstantInterfaceMethodref + * @see ConstantInvokeDynamic + * @LastModified: Sept 2025 */ public abstract class ConstantCP extends Constant { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java index ebb3d0af46a..14b43937c92 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -29,8 +29,8 @@ /** * This class is derived from the abstract {@link Constant} and represents a reference to a Double object. * - * @see Constant - * @LastModified: Jun 2019 + * @see Constant + * @LastModified: Sept 2025 */ public final class ConstantDouble extends Constant implements ConstantObject { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java index 9c30c9e4fdb..e86bbb94e66 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -29,8 +29,8 @@ /** * This class is derived from the abstract {@link Constant} and represents a reference to a float object. * - * @see Constant - * @LastModified: Jun 2019 + * @see Constant + * @LastModified: Sept 2025 */ public final class ConstantFloat extends Constant implements ConstantObject { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInteger.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInteger.java index cabd2e15b03..20c0717acb6 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInteger.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInteger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -29,8 +29,8 @@ /** * This class is derived from the abstract {@link Constant} and represents a reference to an int object. * - * @see Constant - * @LastModified: Jun 2019 + * @see Constant + * @LastModified: Sept 2025 */ public final class ConstantInteger extends Constant implements ConstantObject { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantLong.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantLong.java index c1e683abadb..6936162c264 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantLong.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantLong.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -29,8 +29,8 @@ /** * This class is derived from the abstract {@link Constant} and represents a reference to a long object. * - * @see Constant - * @LastModified: Jan 2020 + * @see Constant + * @LastModified: Sept 2025 */ public final class ConstantLong extends Constant implements ConstantObject { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantObject.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantObject.java index cb28f7dacb8..ab187b7e4f8 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantObject.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantObject.java @@ -29,7 +29,10 @@ public interface ConstantObject { /** - * @return object representing the constant, e.g., Long for ConstantLong + * Gets the object representing the constant, e.g., Long for ConstantLong. + * + * @param constantPool the constant. + * @return object representing the constant, e.g., Long for ConstantLong. */ - Object getConstantValue(ConstantPool cp); + Object getConstantValue(ConstantPool constantPool); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPool.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPool.java index 5fb4ef1b080..ae1e3977c99 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPool.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -35,7 +35,7 @@ * * @see Constant * @see com.sun.org.apache.bcel.internal.generic.ConstantPoolGen - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public class ConstantPool implements Cloneable, Node, Iterable { @@ -73,7 +73,7 @@ private static String escape(final String str) { * @param constantPool Array of constants */ public ConstantPool(final Constant[] constantPool) { - this.constantPool = constantPool; + setConstantPool(constantPool); } /** @@ -88,6 +88,7 @@ public ConstantPool(final DataInput input) throws IOException { constantPool = new Constant[constantPoolCount]; /* * constantPool[0] is unused by the compiler and may be used freely by the implementation. + * constantPool[0] is currently unused by the implementation. */ for (int i = 1; i < constantPoolCount; i++) { constantPool[i] = Constant.readConstant(input); @@ -288,7 +289,7 @@ public T getConstant(final int index, final byte tag) throw */ public T getConstant(final int index, final byte tag, final Class castTo) throws ClassFormatException { final T c = getConstant(index); - if (c.getTag() != tag) { + if (c == null || c.getTag() != tag) { throw new ClassFormatException("Expected class '" + Const.getConstantName(tag) + "' at index " + index + " and got " + c); } return c; @@ -313,16 +314,18 @@ public T getConstant(final int index, final Class castTo throw new ClassFormatException("Invalid constant pool reference at index: " + index + ". Expected " + castTo + " but was " + constantPool[index].getClass()); } - // Previous check ensures this won't throw a ClassCastException - final T c = castTo.cast(constantPool[index]); - if (c == null - // the 0th element is always null - && index != 0) { + if (index > 1) { final Constant prev = constantPool[index - 1]; - if (prev == null || prev.getTag() != Const.CONSTANT_Double && prev.getTag() != Const.CONSTANT_Long) { - throw new ClassFormatException("Constant pool at index " + index + " is null."); + if (prev != null && (prev.getTag() == Const.CONSTANT_Double || prev.getTag() == Const.CONSTANT_Long)) { + throw new ClassFormatException("Constant pool at index " + index + " is invalid. The index is unused due to the preceeding " + + Const.getConstantName(prev.getTag()) + "."); } } + // Previous check ensures this won't throw a ClassCastException + final T c = castTo.cast(constantPool[index]); + if (c == null) { + throw new ClassFormatException("Constant pool at index " + index + " is null."); + } return c; } @@ -402,7 +405,7 @@ public ConstantUtf8 getConstantUtf8(final int index) throws ClassFormatException * @return Length of constant pool. */ public int getLength() { - return constantPool == null ? 0 : constantPool.length; + return constantPool.length; } @Override @@ -421,7 +424,7 @@ public void setConstant(final int index, final Constant constant) { * @param constantPool */ public void setConstantPool(final Constant[] constantPool) { - this.constantPool = constantPool; + this.constantPool = constantPool != null ? constantPool : Constant.EMPTY_ARRAY; } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantUtf8.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantUtf8.java index ec875554c1a..90e45c807e5 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantUtf8.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantUtf8.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -36,11 +36,11 @@ * The following system properties govern caching this class performs. *

*
    - *
  • {@value #SYS_PROP_CACHE_MAX_ENTRIES} (since 6.4): The size of the cache, by default 0, meaning caching is + *
  • {@link #SYS_PROP_CACHE_MAX_ENTRIES} (since 6.4): The size of the cache, by default 0, meaning caching is * disabled.
  • - *
  • {@value #SYS_PROP_CACHE_MAX_ENTRY_SIZE} (since 6.0): The maximum size of the values to cache, by default 200, 0 + *
  • {@link #SYS_PROP_CACHE_MAX_ENTRY_SIZE} (since 6.0): The maximum size of the values to cache, by default 200, 0 * disables caching. Values larger than this are not cached.
  • - *
  • {@value #SYS_PROP_STATISTICS} (since 6.0): Prints statistics on the console when the JVM exits.
  • + *
  • {@link #SYS_PROP_STATISTICS} (since 6.0): Prints statistics on the console when the JVM exits.
  • *
*

* Here is a sample Maven invocation with caching disabled: @@ -58,11 +58,11 @@ * * * @see Constant - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public final class ConstantUtf8 extends Constant { - private static class Cache { + private static final class Cache { private static final boolean BCEL_STATISTICS = false; private static final int MAX_ENTRIES = 20000; @@ -82,7 +82,7 @@ protected boolean removeEldestEntry(final Map.Entry eldest private static final int MAX_ENTRY_SIZE = 200; static boolean isEnabled() { - return Cache.MAX_ENTRIES > 0 && MAX_ENTRY_SIZE > 0; + return MAX_ENTRIES > 0 && MAX_ENTRY_SIZE > 0; } } @@ -117,6 +117,11 @@ static synchronized void clearStats() { hits = considered = skipped = created = 0; } + // Avoid Spotbugs complaint about Write to static field + private static void countCreated() { + created++; + } + /** * Gets a new or cached instance of the given value. *

@@ -203,7 +208,7 @@ public ConstantUtf8(final ConstantUtf8 constantUtf8) { ConstantUtf8(final DataInput dataInput) throws IOException { super(Const.CONSTANT_Utf8); value = dataInput.readUTF(); - created++; + countCreated(); } /** @@ -212,7 +217,7 @@ public ConstantUtf8(final ConstantUtf8 constantUtf8) { public ConstantUtf8(final String value) { super(Const.CONSTANT_Utf8); this.value = Objects.requireNonNull(value, "value"); - created++; + countCreated(); } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantValue.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantValue.java index 311e9a33fa3..143c2a25544 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantValue.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantValue.java @@ -56,7 +56,7 @@ public ConstantValue(final ConstantValue c) { } /** - * Construct object from input stream. + * Constructs object from input stream. * * @param nameIndex Name index in constant pool * @param length Content length in bytes diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Deprecated.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Deprecated.java index 90841d96081..c561afe33c5 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Deprecated.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Deprecated.java @@ -59,7 +59,7 @@ public Deprecated(final int nameIndex, final int length, final byte[] bytes, fin } /** - * Construct object from input stream. + * Constructs object from input stream. * * @param nameIndex Index in constant pool to CONSTANT_Utf8 * @param length Content length in bytes diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java index 3c475891acd..934b608d6ac 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -22,12 +22,13 @@ import java.util.Objects; import java.util.Stack; import java.util.stream.Stream; +import jdk.xml.internal.Utils; /** - * Traverses a JavaClass with another Visitor object 'piggy-backed' that is - * applied to all components of a JavaClass object. I.e. this class supplies the - * traversal strategy, other classes can make use of it. + * Traverses a JavaClass with another Visitor object 'piggy-backed' that is applied to all components of a JavaClass + * object. I.e. this class supplies the traversal strategy, other classes can make use of it. * + * @LastModified: Sept 2025 */ public class DescendingVisitor implements Visitor { private final JavaClass clazz; @@ -46,7 +47,7 @@ public DescendingVisitor(final JavaClass clazz, final Visitor visitor) { } private void accept(final E[] node) { - Stream.of(node).forEach(e -> e.accept(this)); + Utils.streamOfIfNonNull(node).forEach(e -> e.accept(this)); } /** @@ -507,6 +508,21 @@ public void visitParameterAnnotationEntry(final ParameterAnnotationEntry obj) { stack.pop(); } + @Override + public void visitRecord(final Record record) { + stack.push(record); + record.accept(visitor); + accept(record.getComponents()); + stack.pop(); + } + + @Override + public void visitRecordComponent(final RecordComponentInfo recordComponentInfo) { + stack.push(recordComponentInfo); + recordComponentInfo.accept(visitor); + stack.pop(); + } + @Override public void visitSignature(final Signature attribute) { stack.push(attribute); @@ -531,6 +547,20 @@ public void visitStackMap(final StackMap table) { @Override public void visitStackMapEntry(final StackMapEntry var) { + stack.push(var); + var.accept(visitor); + accept(var.getTypesOfLocals()); + accept(var.getTypesOfStackItems()); + stack.pop(); + } + + /** + * Visits a {@link StackMapType} object. + * @param var object to visit + * @since 6.8.0 + */ + @Override + public void visitStackMapType(final StackMapType var) { stack.push(var); var.accept(visitor); stack.pop(); @@ -549,4 +579,5 @@ public void visitUnknown(final Unknown attribute) { attribute.accept(visitor); stack.pop(); } + } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValue.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValue.java index 5c3d9b3172b..d87307c0e7d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValue.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -50,7 +50,7 @@ *} * * @since 6.0 - * @LastModified: May 2021 + * @LastModified: Sept 2025 */ public abstract class ElementValue { @@ -67,6 +67,7 @@ public abstract class ElementValue { public static final byte PRIMITIVE_LONG = 'J'; public static final byte PRIMITIVE_SHORT = 'S'; public static final byte PRIMITIVE_BOOLEAN = 'Z'; + static final ElementValue[] EMPTY_ARRAY = {}; /** * Reads an {@code element_value} as an {@code ElementValue}. @@ -124,7 +125,7 @@ public static ElementValue readElementValue(final DataInput input, final Constan final int numArrayVals = input.readUnsignedShort(); final ElementValue[] evalues = new ElementValue[numArrayVals]; for (int j = 0; j < numArrayVals; j++) { - evalues[j] = ElementValue.readElementValue(input, cpool, arrayNesting); + evalues[j] = readElementValue(input, cpool, arrayNesting); } return new ArrayElementValue(ARRAY, evalues, cpool); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java index 826ba41af70..db33c871656 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java @@ -315,6 +315,15 @@ public void visitStackMap(final StackMap obj) { public void visitStackMapEntry(final StackMapEntry obj) { } + /** + * Visits a {@link StackMapType} object. + * @param obj object to visit + * @since 6.8.0 + */ + @Override + public void visitStackMapType(final StackMapType obj) { + } + @Override public void visitSynthetic(final Synthetic obj) { } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ExceptionTable.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ExceptionTable.java index 90eaa3eb062..1b6004b3740 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ExceptionTable.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ExceptionTable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -27,6 +27,7 @@ import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.util.Args; +import jdk.xml.internal.Utils; /** * This class represents the table of exceptions that are thrown by a method. This attribute may be used once per @@ -43,7 +44,7 @@ * } * * @see Code - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public final class ExceptionTable extends Attribute { @@ -60,7 +61,7 @@ public ExceptionTable(final ExceptionTable c) { } /** - * Construct object from input stream. + * Constructs object from input stream. * * @param nameIndex Index in constant pool * @param length Content length in bytes @@ -85,7 +86,7 @@ public ExceptionTable(final ExceptionTable c) { */ public ExceptionTable(final int nameIndex, final int length, final int[] exceptionIndexTable, final ConstantPool constantPool) { super(Const.ATTR_EXCEPTIONS, nameIndex, length, constantPool); - this.exceptionIndexTable = exceptionIndexTable != null ? exceptionIndexTable : Const.EMPTY_INT_ARRAY; + this.exceptionIndexTable = Utils.createEmptyArrayIfNull(exceptionIndexTable); Args.requireU2(this.exceptionIndexTable.length, "exceptionIndexTable.length"); } @@ -156,7 +157,7 @@ public int getNumberOfExceptions() { * length. */ public void setExceptionIndexTable(final int[] exceptionIndexTable) { - this.exceptionIndexTable = exceptionIndexTable != null ? exceptionIndexTable : Const.EMPTY_INT_ARRAY; + this.exceptionIndexTable = Utils.createEmptyArrayIfNull(exceptionIndexTable); } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Field.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Field.java index 7e6ccb2ecb5..8ffc796a0ea 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Field.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Field.java @@ -42,45 +42,37 @@ public final class Field extends FieldOrMethod { */ public static final Field[] EMPTY_ARRAY = {}; - private static BCELComparator bcelComparator = new BCELComparator() { + private static BCELComparator bcelComparator = new BCELComparator() { @Override - public boolean equals(final Object o1, final Object o2) { - final Field THIS = (Field) o1; - final Field THAT = (Field) o2; - return Objects.equals(THIS.getName(), THAT.getName()) && Objects.equals(THIS.getSignature(), THAT.getSignature()); + public boolean equals(final Field a, final Field b) { + return a == b || a != null && b != null && Objects.equals(a.getName(), b.getName()) && Objects.equals(a.getSignature(), b.getSignature()); } @Override - public int hashCode(final Object o) { - final Field THIS = (Field) o; - return THIS.getSignature().hashCode() ^ THIS.getName().hashCode(); + public int hashCode(final Field o) { + return o != null ? Objects.hash(o.getSignature(), o.getName()) : 0; } }; /** - * Empty array. + * @return Comparison strategy object. */ - static final Field[] EMPTY_FIELD_ARRAY = {}; - - /** - * @return Comparison strategy object - */ - public static BCELComparator getComparator() { + public static BCELComparator getComparator() { return bcelComparator; } /** - * @param comparator Comparison strategy object + * @param comparator Comparison strategy object. */ - public static void setComparator(final BCELComparator comparator) { + public static void setComparator(final BCELComparator comparator) { bcelComparator = comparator; } /** - * Construct object from file stream. + * Constructs object from file stream. * - * @param file Input stream + * @param file Input stream. */ Field(final DataInput file, final ConstantPool constantPool) throws IOException, ClassFormatException { super(file, constantPool); @@ -133,7 +125,7 @@ public Field copy(final ConstantPool constantPool) { */ @Override public boolean equals(final Object obj) { - return bcelComparator.equals(this, obj); + return obj instanceof Field && bcelComparator.equals(this, (Field) obj); } /** @@ -149,14 +141,16 @@ public ConstantValue getConstantValue() { } /** + * See https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.2.2 + * * @return type of field */ public Type getType() { - return Type.getReturnType(getSignature()); + return Type.getType(getSignature()); } /** - * Return value as defined by given BCELComparator strategy. By default return the hashcode of the field's name XOR + * Return value as defined by given BCELComparator strategy. By default return the hash code of the field's name XOR * signature. * * @see Object#hashCode() diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/FieldOrMethod.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/FieldOrMethod.java index 1daa6a62fd5..679d5a9eb7c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/FieldOrMethod.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/FieldOrMethod.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -28,7 +28,7 @@ /** * Abstract super class for fields and methods. * - * @LastModified: Jan 2020 + * @LastModified: Sept 2025 */ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, Node { @@ -72,7 +72,7 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, No } /** - * Construct object from file stream. + * Constructs object from file stream. * * @param file Input stream * @throws IOException if an I/O error occurs. @@ -88,7 +88,7 @@ protected FieldOrMethod(final DataInput file, final ConstantPool constantPool) t } /** - * Construct object from file stream. + * Constructs object from file stream. * * @param file Input stream * @throws IOException if an I/O error occurs. @@ -137,7 +137,7 @@ protected FieldOrMethod copy_(final ConstantPool constantPool) { Arrays.setAll(c.attributes, i -> attributes[i].copy(constantPool)); return c; } catch (final CloneNotSupportedException e) { - throw new IllegalStateException(e); + throw new UnsupportedOperationException(e); } } @@ -152,10 +152,8 @@ public final void dump(final DataOutputStream file) throws IOException { file.writeShort(name_index); file.writeShort(signature_index); file.writeShort(attributes_count); - if (attributes != null) { - for (final Attribute attribute : attributes) { - attribute.dump(file); - } + for (final Attribute attribute : attributes) { + attribute.dump(file); } } @@ -171,6 +169,22 @@ public AnnotationEntry[] getAnnotationEntries() { return annotationEntries; } + /** + * Gets attribute for given tag. + * @return Attribute for given tag, null if not found. + * Refer to {@link com.sun.org.apache.bcel.internal.Const#ATTR_UNKNOWN} constants named ATTR_* for possible values. + * @since 6.10.0 + */ + @SuppressWarnings("unchecked") + public final T getAttribute(final byte tag) { + for (final Attribute attribute : getAttributes()) { + if (attribute.getTag() == tag) { + return (T) attribute; + } + } + return null; + } + /** * @return Collection of object attributes. */ @@ -221,7 +235,7 @@ public final int getNameIndex() { } /** - * @return String representation of object's type signature (java style) + * @return String representation of object's type signature (Java style) */ public final String getSignature() { return constant_pool.getConstantUtf8(signature_index).getBytes(); @@ -238,8 +252,8 @@ public final int getSignatureIndex() { * @param attributes Collection of object attributes. */ public final void setAttributes(final Attribute[] attributes) { - this.attributes = attributes; - this.attributes_count = attributes != null ? attributes.length : 0; // init deprecated field + this.attributes = attributes != null ? attributes : Attribute.EMPTY_ARRAY; + this.attributes_count = this.attributes.length; // init deprecated field } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClass.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClass.java index d77582815b7..82900dcca10 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClass.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClass.java @@ -41,7 +41,7 @@ public final class InnerClass implements Cloneable, Node { private int innerAccessFlags; /** - * Construct object from file stream. + * Constructs object from file stream. * * @param file Input stream * @throws IOException if an I/O error occurs. diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClasses.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClasses.java index 2295ca5c625..b61be1effa0 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClasses.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClasses.java @@ -42,7 +42,7 @@ public final class InnerClasses extends Attribute implements Iterable iterator() { * @param innerClasses the array of inner classes */ public void setInnerClasses(final InnerClass[] innerClasses) { - this.innerClasses = innerClasses != null ? innerClasses : EMPTY_INNER_CLASSE_ARRAY; + this.innerClasses = innerClasses != null ? innerClasses : EMPTY_ARRAY; } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InvalidMethodSignatureException.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InvalidMethodSignatureException.java new file mode 100644 index 00000000000..eaf1da2d2e1 --- /dev/null +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InvalidMethodSignatureException.java @@ -0,0 +1,53 @@ +/* + * reserved comment block + * DO NOT REMOVE OR ALTER! + */ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.sun.org.apache.bcel.internal.classfile; + +/** + * Thrown when the BCEL attempts to read a class file and determines that a class is malformed or otherwise cannot be interpreted as a class file. + * + * @since 6.8.0 + */ +public class InvalidMethodSignatureException extends ClassFormatException { + + private static final long serialVersionUID = 1L; + + /** + * Constructs a new instance with the specified invalid signature as the message. + * + * @param signature The invalid signature is saved for later retrieval by the {@link #getMessage()} method. + */ + public InvalidMethodSignatureException(final String signature) { + super(signature); + } + + /** + * Constructs a new instance with the specified invalid signature as the message and a cause. + * + * @param signature The invalid signature is saved for later retrieval by the {@link #getMessage()} method. + * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method). A {@code null} value is permitted, and indicates that + * the cause is nonexistent or unknown. + */ + public InvalidMethodSignatureException(final String signature, final Throwable cause) { + super(signature, cause); + } + +} diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/JavaClass.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/JavaClass.java index d6c4cfa6a07..1b0e2ed1ce0 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/JavaClass.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/JavaClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -38,6 +38,7 @@ import com.sun.org.apache.bcel.internal.util.BCELComparator; import com.sun.org.apache.bcel.internal.util.ClassQueue; import com.sun.org.apache.bcel.internal.util.SyntheticRepository; +import jdk.xml.internal.Utils; /** * Represents a Java class, i.e., the data structures, constant pool, fields, methods and commands contained in a Java @@ -46,7 +47,7 @@ * classes should see the ClassGen class. * * @see com.sun.org.apache.bcel.internal.generic.ClassGen - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparable { @@ -67,26 +68,23 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl public static final byte HEAP = 1; public static final byte FILE = 2; public static final byte ZIP = 3; - private static BCELComparator bcelComparator = new BCELComparator() { + private static BCELComparator bcelComparator = new BCELComparator() { @Override - public boolean equals(final Object o1, final Object o2) { - final JavaClass THIS = (JavaClass) o1; - final JavaClass THAT = (JavaClass) o2; - return Objects.equals(THIS.getClassName(), THAT.getClassName()); + public boolean equals(final JavaClass a, final JavaClass b) { + return a == b || a != null && b != null && Objects.equals(a.getClassName(), b.getClassName()); } @Override - public int hashCode(final Object o) { - final JavaClass THIS = (JavaClass) o; - return THIS.getClassName().hashCode(); + public int hashCode(final JavaClass o) { + return o != null ? Objects.hashCode(o.getClassName()) : 0; } }; /** - * @return Comparison strategy object + * @return Comparison strategy object. */ - public static BCELComparator getComparator() { + public static BCELComparator getComparator() { return bcelComparator; } @@ -100,9 +98,9 @@ private static String indent(final Object obj) { } /** - * @param comparator Comparison strategy object + * @param comparator Comparison strategy object. */ - public static void setComparator(final BCELComparator comparator) { + public static void setComparator(final BCELComparator comparator) { bcelComparator = comparator; } @@ -128,8 +126,10 @@ public static void setComparator(final BCELComparator comparator) { private boolean isAnonymous; private boolean isNested; + private boolean isRecord; private boolean computedNestedTypeStatus; + private boolean computedRecord; /** * In cases where we go ahead and create something, use the default SyntheticRepository, because we don't know any @@ -177,17 +177,15 @@ public JavaClass(final int classNameIndex, final int superclassNameIndex, final public JavaClass(final int classNameIndex, final int superclassNameIndex, final String fileName, final int major, final int minor, final int accessFlags, final ConstantPool constantPool, int[] interfaces, Field[] fields, Method[] methods, Attribute[] attributes, final byte source) { super(accessFlags); - if (interfaces == null) { - interfaces = Const.EMPTY_INT_ARRAY; - } + interfaces = Utils.createEmptyArrayIfNull(interfaces); if (attributes == null) { attributes = Attribute.EMPTY_ARRAY; } if (fields == null) { - fields = Field.EMPTY_FIELD_ARRAY; + fields = Field.EMPTY_ARRAY; } if (methods == null) { - methods = Method.EMPTY_METHOD_ARRAY; + methods = Method.EMPTY_ARRAY; } this.classNameIndex = classNameIndex; this.superclassNameIndex = superclassNameIndex; @@ -254,6 +252,19 @@ public int compareTo(final JavaClass obj) { return getClassName().compareTo(obj.getClassName()); } + private void computeIsRecord() { + if (computedRecord) { + return; + } + for (final Attribute attribute : this.attributes) { + if (attribute instanceof Record) { + isRecord = true; + break; + } + } + this.computedRecord = true; + } + private void computeNestedTypeStatus() { if (computedNestedTypeStatus) { return; @@ -384,11 +395,51 @@ public void dump(final String fileName) throws IOException { */ @Override public boolean equals(final Object obj) { - return bcelComparator.equals(this, obj); + return obj instanceof JavaClass && bcelComparator.equals(this, (JavaClass) obj); + } + + /** + * Finds a visible field by name and type in this class and its super classes. + * @param fieldName the field name to find + * @param fieldType the field type to find + * @return field matching given name and type, null if field is not found or not accessible from this class. + * @throws ClassNotFoundException + * @since 6.8.0 + */ + public Field findField(final String fieldName, final Type fieldType) throws ClassNotFoundException { + for (final Field field : fields) { + if (field.getName().equals(fieldName)) { + final Type fType = Type.getType(field.getSignature()); + /* + * TODO: Check if assignment compatibility is sufficient. What does Sun do? + */ + if (fType.equals(fieldType)) { + return field; + } + } + } + + final JavaClass superclass = getSuperClass(); + if (superclass != null && !"java.lang.Object".equals(superclass.getClassName())) { + final Field f = superclass.findField(fieldName, fieldType); + if (f != null && (f.isPublic() || f.isProtected() || !f.isPrivate() && packageName.equals(superclass.getPackageName()))) { + return f; + } + } + final JavaClass[] implementedInterfaces = getInterfaces(); + if (implementedInterfaces != null) { + for (final JavaClass implementedInterface : implementedInterfaces) { + final Field f = implementedInterface.findField(fieldName, fieldType); + if (f != null) { + return f; + } + } + } + return null; } /** - * Get all interfaces implemented by this JavaClass (transitively). + * Gets all interfaces implemented by this JavaClass (transitively). * * @throws ClassNotFoundException if any of the class's superclasses or interfaces can't be found. */ @@ -409,7 +460,7 @@ public JavaClass[] getAllInterfaces() throws ClassNotFoundException { queue.enqueue(iface); } } - return allInterfaces.toArray(JavaClass.EMPTY_ARRAY); + return allInterfaces.toArray(EMPTY_ARRAY); } /** @@ -424,6 +475,22 @@ public AnnotationEntry[] getAnnotationEntries() { return annotations; } + /** + * Gets attribute for given tag. + * @return Attribute for given tag, null if not found. + * Refer to {@link com.sun.org.apache.bcel.internal.Const#ATTR_UNKNOWN} constants named ATTR_* for possible values. + * @since 6.10.0 + */ + @SuppressWarnings("unchecked") + public final T getAttribute(final byte tag) { + for (final Attribute attribute : getAttributes()) { + if (attribute.getTag() == tag) { + return (T) attribute; + } + } + return null; + } + /** * @return Attributes of the class. */ @@ -495,7 +562,7 @@ public String[] getInterfaceNames() { } /** - * Get interfaces directly implemented by this JavaClass. + * Gets interfaces directly implemented by this JavaClass. * * @throws ClassNotFoundException if any of the class's interfaces can't be found. */ @@ -587,7 +654,7 @@ public String getSourceFilePath() { } /** - * @return the superclass for this JavaClass object, or null if this is java.lang.Object + * @return the superclass for this JavaClass object, or null if this is {@link Object} * @throws ClassNotFoundException if the superclass can't be found */ public JavaClass getSuperClass() throws ClassNotFoundException { @@ -607,12 +674,12 @@ public JavaClass[] getSuperClasses() throws ClassNotFoundException { for (clazz = clazz.getSuperClass(); clazz != null; clazz = clazz.getSuperClass()) { allSuperClasses.add(clazz); } - return allSuperClasses.toArray(JavaClass.EMPTY_ARRAY); + return allSuperClasses.toArray(EMPTY_ARRAY); } /** - * returns the super class name of this class. In the case that this class is java.lang.Object, it will return itself - * (java.lang.Object). This is probably incorrect but isn't fixed at this time to not break existing clients. + * returns the super class name of this class. In the case that this class is {@link Object}, it will return itself + * ({@link Object}). This is probably incorrect but isn't fixed at this time to not break existing clients. * * @return Superclass name. */ @@ -628,7 +695,7 @@ public int getSuperclassNameIndex() { } /** - * Return value as defined by given BCELComparator strategy. By default return the hashcode of the class name. + * Return value as defined by given BCELComparator strategy. By default return the hash code of the class name. * * @see Object#hashCode() */ @@ -645,7 +712,7 @@ public boolean implementationOf(final JavaClass inter) throws ClassNotFoundExcep if (!inter.isInterface()) { throw new IllegalArgumentException(inter.getClassName() + " is no interface"); } - if (this.equals(inter)) { + if (equals(inter)) { return true; } final JavaClass[] superInterfaces = getAllInterfaces(); @@ -664,7 +731,7 @@ public boolean implementationOf(final JavaClass inter) throws ClassNotFoundExcep * @throws ClassNotFoundException if superclasses or superinterfaces of this object can't be found */ public final boolean instanceOf(final JavaClass superclass) throws ClassNotFoundException { - if (this.equals(superclass)) { + if (equals(superclass)) { return true; } for (final JavaClass clazz : getSuperClasses()) { @@ -698,6 +765,17 @@ public final boolean isNested() { return this.isNested; } + /** + * Tests whether this class was declared as a record + * + * @return true if a record attribute is present, false otherwise. + * @since 6.9.0 + */ + public boolean isRecord() { + computeIsRecord(); + return this.isRecord; + } + public final boolean isSuper() { return (super.getAccessFlags() & Const.ACC_SUPER) != 0; } @@ -706,7 +784,7 @@ public final boolean isSuper() { * @param attributes . */ public void setAttributes(final Attribute[] attributes) { - this.attributes = attributes; + this.attributes = attributes != null ? attributes : Attribute.EMPTY_ARRAY; } /** @@ -734,11 +812,11 @@ public void setConstantPool(final ConstantPool constantPool) { * @param fields . */ public void setFields(final Field[] fields) { - this.fields = fields; + this.fields = fields != null ? fields : Field.EMPTY_ARRAY; } /** - * Set File name of class, aka SourceFile attribute value + * Sets File name of class, aka SourceFile attribute value */ public void setFileName(final String fileName) { this.fileName = fileName; @@ -748,14 +826,14 @@ public void setFileName(final String fileName) { * @param interfaceNames . */ public void setInterfaceNames(final String[] interfaceNames) { - this.interfaceNames = interfaceNames; + this.interfaceNames = Utils.createEmptyArrayIfNull(interfaceNames, String[].class); } /** * @param interfaces . */ public void setInterfaces(final int[] interfaces) { - this.interfaces = interfaces; + this.interfaces = Utils.createEmptyArrayIfNull(interfaces); } /** @@ -769,7 +847,7 @@ public void setMajor(final int major) { * @param methods . */ public void setMethods(final Method[] methods) { - this.methods = methods; + this.methods = methods != null ? methods : Method.EMPTY_ARRAY; } /** @@ -787,7 +865,7 @@ public void setRepository(final com.sun.org.apache.bcel.internal.util.Repository } /** - * Set absolute path to file this class was read from. + * Sets absolute path to file this class was read from. */ public void setSourceFileName(final String sourceFileName) { this.sourceFileName = sourceFileName; diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumber.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumber.java index 4380d04bc06..dc41ad065f8 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumber.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumber.java @@ -40,11 +40,11 @@ public final class LineNumber implements Cloneable, Node { /** Program Counter (PC) corresponds to line */ private int startPc; - /** number in source file */ + /** Number in source file */ private int lineNumber; /** - * Construct object from file stream. + * Constructs object from file stream. * * @param file Input stream * @throws IOException if an I/O Exception occurs in readUnsignedShort diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumberTable.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumberTable.java index 6251fc514cc..96541f309bd 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumberTable.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumberTable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -36,7 +36,7 @@ * * @see Code * @see LineNumber - * @LastModified: May 2021 + * @LastModified: Sept 2025 */ public final class LineNumberTable extends Attribute implements Iterable { @@ -44,7 +44,7 @@ public final class LineNumberTable extends Attribute implements Iterable + * Note that both objects use the same references (shallow copy). Use copy() for a physical copy. + *

*/ public LineNumberTable(final LineNumberTable c) { this(c.getNameIndex(), c.getLength(), c.getLineNumberTable(), c.getConstantPool()); @@ -190,7 +191,7 @@ public Iterator iterator() { * @param lineNumberTable the line number entries for this table */ public void setLineNumberTable(final LineNumber[] lineNumberTable) { - this.lineNumberTable = lineNumberTable; + this.lineNumberTable = lineNumberTable != null ? lineNumberTable : LineNumber.EMPTY_ARRAY; } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTable.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTable.java index fd56e14a539..26fde9bdbdf 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTable.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTable.java @@ -40,10 +40,12 @@ */ public class LocalVariableTable extends Attribute implements Iterable { + private static final LocalVariable[] EMPTY_ARRAY = {}; + private LocalVariable[] localVariableTable; // variables /** - * Construct object from input stream. + * Constructs object from input stream. * * @param nameIndex Index in constant pool * @param length Content length in bytes @@ -68,7 +70,7 @@ public class LocalVariableTable extends Attribute implements Iterable iterator() { } public final void setLocalVariableTable(final LocalVariable[] localVariableTable) { - this.localVariableTable = localVariableTable; + this.localVariableTable = localVariableTable != null ? localVariableTable : EMPTY_ARRAY; } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java index 08868a82de8..ce327e20f52 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java @@ -63,14 +63,14 @@ */ public class LocalVariableTypeTable extends Attribute implements Iterable { + private static final LocalVariable[] EMPTY_ARRAY = {}; + private LocalVariable[] localVariableTypeTable; // variables LocalVariableTypeTable(final int nameIdx, final int len, final DataInput input, final ConstantPool cpool) throws IOException { this(nameIdx, len, (LocalVariable[]) null, cpool); - final int localVariableTypeTableLength = input.readUnsignedShort(); localVariableTypeTable = new LocalVariable[localVariableTypeTableLength]; - for (int i = 0; i < localVariableTypeTableLength; i++) { localVariableTypeTable[i] = new LocalVariable(input, cpool); } @@ -97,7 +97,6 @@ public void accept(final Visitor v) { @Override public Attribute copy(final ConstantPool constantPool) { final LocalVariableTypeTable c = (LocalVariableTypeTable) clone(); - c.localVariableTypeTable = new LocalVariable[localVariableTypeTable.length]; Arrays.setAll(c.localVariableTypeTable, i -> localVariableTypeTable[i].copy()); c.setConstantPool(constantPool); @@ -119,7 +118,6 @@ public final LocalVariable getLocalVariable(final int index) { return variable; } } - return null; } @@ -137,7 +135,7 @@ public Iterator iterator() { } public final void setLocalVariableTable(final LocalVariable[] localVariableTable) { - this.localVariableTypeTable = localVariableTable; + this.localVariableTypeTable = localVariableTable != null ? localVariableTable : EMPTY_ARRAY; } /** @@ -146,15 +144,12 @@ public final void setLocalVariableTable(final LocalVariable[] localVariableTable @Override public final String toString() { final StringBuilder buf = new StringBuilder(); - for (int i = 0; i < localVariableTypeTable.length; i++) { buf.append(localVariableTypeTable[i].toStringShared(true)); - if (i < localVariableTypeTable.length - 1) { buf.append('\n'); } } - return buf.toString(); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Method.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Method.java index ba2623eec08..643c820f366 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Method.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Method.java @@ -40,42 +40,34 @@ public final class Method extends FieldOrMethod { */ public static final Method[] EMPTY_ARRAY = {}; - private static BCELComparator bcelComparator = new BCELComparator() { + private static BCELComparator bcelComparator = new BCELComparator() { @Override - public boolean equals(final Object o1, final Object o2) { - final Method THIS = (Method) o1; - final Method THAT = (Method) o2; - return Objects.equals(THIS.getName(), THAT.getName()) && Objects.equals(THIS.getSignature(), THAT.getSignature()); + public boolean equals(final Method a, final Method b) { + return a == b || a != null && b != null && Objects.equals(a.getName(), b.getName()) && Objects.equals(a.getSignature(), b.getSignature()); } @Override - public int hashCode(final Object o) { - final Method THIS = (Method) o; - return THIS.getSignature().hashCode() ^ THIS.getName().hashCode(); + public int hashCode(final Method o) { + return o != null ? Objects.hash(o.getSignature(), o.getName()) : 0; } }; /** - * Empty array. + * @return Comparison strategy object. */ - static final Method[] EMPTY_METHOD_ARRAY = {}; - - /** - * @return Comparison strategy object - */ - public static BCELComparator getComparator() { + public static BCELComparator getComparator() { return bcelComparator; } /** - * @param comparator Comparison strategy object + * @param comparator Comparison strategy object. */ - public static void setComparator(final BCELComparator comparator) { + public static void setComparator(final BCELComparator comparator) { bcelComparator = comparator; } - // annotations defined on the parameters of a method + /** Annotations defined on the parameters of a method. */ private ParameterAnnotationEntry[] parameterAnnotationEntries; /** @@ -85,7 +77,7 @@ public Method() { } /** - * Construct object from file stream. + * Constructs object from file stream. * * @param file Input stream * @throws IOException if an I/O error occurs. @@ -142,7 +134,7 @@ public Method copy(final ConstantPool constantPool) { */ @Override public boolean equals(final Object obj) { - return bcelComparator.equals(this, obj); + return obj instanceof Method && bcelComparator.equals(this, (Method) obj); } /** @@ -189,7 +181,7 @@ public LineNumberTable getLineNumberTable() { } /** - * @return LocalVariableTable of code attribute if any, i.e. the call is forwarded to the Code atribute. + * @return LocalVariableTable of code attribute if any, i.e. the call is forwarded to the Code attribute. */ public LocalVariableTable getLocalVariableTable() { final Code code = getCode(); @@ -199,6 +191,19 @@ public LocalVariableTable getLocalVariableTable() { return code.getLocalVariableTable(); } + /** + * Gets the local variable type table attribute {@link LocalVariableTypeTable}. + * @return LocalVariableTypeTable of code attribute if any, i.e. the call is forwarded to the Code attribute. + * @since 6.10.0 + */ + public LocalVariableTypeTable getLocalVariableTypeTable() { + final Code code = getCode(); + if (code == null) { + return null; + } + return code.getLocalVariableTypeTable(); + } + /** * @return Annotations on the parameters of a method * @since 6.0 @@ -218,7 +223,7 @@ public Type getReturnType() { } /** - * Return value as defined by given BCELComparator strategy. By default return the hashcode of the method's name XOR + * Return value as defined by given BCELComparator strategy. By default return the hash code of the method's name XOR * signature. * * @see Object#hashCode() diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameter.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameter.java index ffc1a20f80a..865e154d334 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameter.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameter.java @@ -29,6 +29,9 @@ /** * Entry of the parameters table. + *

+ * Implements {@link Node} as of 6.7.0. + *

* * @see The class File Format : * The MethodParameters Attribute @@ -46,7 +49,7 @@ public MethodParameter() { } /** - * Construct object from input stream. + * Constructs an instance from a DataInput. * * @param input Input stream * @throws IOException if an I/O error occurs. @@ -75,7 +78,7 @@ public MethodParameter copy() { } /** - * Dump object to file stream on binary format. + * Dumps object to file stream on binary format. * * @param file Output file stream * @throws IOException if an I/O error occurs. @@ -94,7 +97,10 @@ public int getNameIndex() { } /** - * Returns the name of the parameter. + * Gets the name of the parameter. + * + * @param constantPool The pool to query. + * @return Constant from the given pool. */ public String getParameterName(final ConstantPool constantPool) { if (nameIndex == 0) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameters.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameters.java index 5b5d1d77f6f..2f5bffd8d3c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameters.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameters.java @@ -42,13 +42,12 @@ public class MethodParameters extends Attribute implements Iterable parameters[i].copy()); c.setConstantPool(constantPool); return c; @@ -96,6 +94,6 @@ public Iterator iterator() { } public void setParameters(final MethodParameter[] parameters) { - this.parameters = parameters; + this.parameters = parameters != null ? parameters : EMPTY_ARRAY; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Module.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Module.java index 00eebe18245..addf6f0aea3 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Module.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Module.java @@ -44,19 +44,27 @@ public final class Module extends Attribute { */ public static final String EXTENSION = ".jmod"; + private static String getClassNameAtIndex(final ConstantPool cp, final int index, final boolean compactClassName) { + final String className = cp.getConstantString(index, Const.CONSTANT_Class); + if (compactClassName) { + return Utility.compactClassName(className, false); + } + return className; + } private final int moduleNameIndex; private final int moduleFlags; - private final int moduleVersionIndex; + private final int moduleVersionIndex; private ModuleRequires[] requiresTable; private ModuleExports[] exportsTable; private ModuleOpens[] opensTable; private final int usesCount; private final int[] usesIndex; + private ModuleProvides[] providesTable; /** - * Construct object from input stream. + * Constructs object from input stream. * * @param nameIndex Index in constant pool * @param length Content length in bytes @@ -113,8 +121,6 @@ public void accept(final Visitor v) { v.visitModule(this); } - // TODO add more getters and setters? - /** * @return deep copy of this attribute */ @@ -186,6 +192,25 @@ public ModuleExports[] getExportsTable() { return exportsTable; } + /** + * Gets flags for this module. + * @return module flags + * @since 6.10.0 + */ + public int getModuleFlags() { + return moduleFlags; + } + + /** + * Gets module name. + * @param cp Array of constants + * @return module name + * @since 6.10.0 + */ + public String getModuleName(final ConstantPool cp) { + return cp.getConstantString(moduleNameIndex, Const.CONSTANT_Module); + } + /** * @return table of provided interfaces * @see ModuleOpens @@ -210,6 +235,31 @@ public ModuleRequires[] getRequiresTable() { return requiresTable; } + /** + * Gets the array of class names for this module's uses. + * @param constantPool Array of constants usually obtained from the ClassFile object + * @param compactClassName false for original constant pool value, true to replace '/' with '.' + * @return array of used class names + * @since 6.10.0 + */ + public String[] getUsedClassNames(final ConstantPool constantPool, final boolean compactClassName) { + final String[] usedClassNames = new String[usesCount]; + for (int i = 0; i < usesCount; i++) { + usedClassNames[i] = getClassNameAtIndex(constantPool, usesIndex[i], compactClassName); + } + return usedClassNames; + } + + /** + * Gets version for this module. + * @param cp Array of constants + * @return version from constant pool, "0" if version index is 0 + * @since 6.10.0 + */ + public String getVersion(final ConstantPool cp) { + return moduleVersionIndex == 0 ? "0" : cp.getConstantString(moduleVersionIndex, Const.CONSTANT_Utf8); + } + /** * @return String representation, i.e., a list of packages. */ @@ -218,9 +268,9 @@ public String toString() { final ConstantPool cp = super.getConstantPool(); final StringBuilder buf = new StringBuilder(); buf.append("Module:\n"); - buf.append(" name: ").append(Utility.pathToPackage(cp.getConstantString(moduleNameIndex, Const.CONSTANT_Module))).append("\n"); + buf.append(" name: ").append(Utility.pathToPackage(getModuleName(cp))).append("\n"); buf.append(" flags: ").append(String.format("%04x", moduleFlags)).append("\n"); - final String version = moduleVersionIndex == 0 ? "0" : cp.getConstantString(moduleVersionIndex, Const.CONSTANT_Utf8); + final String version = getVersion(cp); buf.append(" version: ").append(version).append("\n"); buf.append(" requires(").append(requiresTable.length).append("):\n"); @@ -240,8 +290,8 @@ public String toString() { buf.append(" uses(").append(usesIndex.length).append("):\n"); for (final int index : usesIndex) { - final String className = cp.getConstantString(index, Const.CONSTANT_Class); - buf.append(" ").append(Utility.compactClassName(className, false)).append("\n"); + final String className = getClassNameAtIndex(cp, index, true); + buf.append(" ").append(className).append("\n"); } buf.append(" provides(").append(providesTable.length).append("):\n"); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleExports.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleExports.java index 8a97f4b6d08..f92f508b862 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleExports.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleExports.java @@ -36,13 +36,17 @@ */ public final class ModuleExports implements Cloneable, Node { + private static String getToModuleNameAtIndex(final ConstantPool constantPool, final int index) { + return constantPool.getConstantString(index, Const.CONSTANT_Module); + } private final int exportsIndex; // points to CONSTANT_Package_info private final int exportsFlags; private final int exportsToCount; + private final int[] exportsToIndex; // points to CONSTANT_Module_info /** - * Construct object from file stream. + * Constructs object from file stream. * * @param file Input stream * @throws IOException if an I/O Exception occurs in readUnsignedShort @@ -68,8 +72,6 @@ public void accept(final Visitor v) { v.visitModuleExports(this); } - // TODO add more getters and setters? - /** * @return deep copy of this object */ @@ -97,6 +99,39 @@ public void dump(final DataOutputStream file) throws IOException { } } + /** + * Gets the flags for this ModuleExports. + * @return the exportsFlags + * @since 6.10.0 + */ + public int getExportsFlags() { + return exportsFlags; + } + + /** + * Gets the exported package name. + * @param constantPool the constant pool from the ClassFile + * @return the exported package name + * @since 6.10.0 + */ + public String getPackageName(final ConstantPool constantPool) { + return constantPool.constantToString(exportsIndex, Const.CONSTANT_Package); + } + + /** + * Gets an array of module names for this ModuleExports. + * @param constantPool Array of constants usually obtained from the ClassFile object + * @return array of module names following 'exports to' + * @since 6.10.0 + */ + public String[] getToModuleNames(final ConstantPool constantPool) { + final String[] toModuleNames = new String[exportsToCount]; + for (int i = 0; i < exportsToCount; i++) { + toModuleNames[i] = getToModuleNameAtIndex(constantPool, exportsToIndex[i]); + } + return toModuleNames; + } + /** * @return String representation */ @@ -110,13 +145,13 @@ public String toString() { */ public String toString(final ConstantPool constantPool) { final StringBuilder buf = new StringBuilder(); - final String packageName = constantPool.constantToString(exportsIndex, Const.CONSTANT_Package); - buf.append(Utility.compactClassName(packageName, false)); + final String packageName = getPackageName(constantPool); + buf.append(packageName); buf.append(", ").append(String.format("%04x", exportsFlags)); buf.append(", to(").append(exportsToCount).append("):\n"); for (final int index : exportsToIndex) { - final String moduleName = constantPool.getConstantString(index, Const.CONSTANT_Module); - buf.append(" ").append(Utility.compactClassName(moduleName, false)).append("\n"); + final String moduleName = getToModuleNameAtIndex(constantPool, index); + buf.append(" ").append(moduleName).append("\n"); } return buf.substring(0, buf.length() - 1); // remove the last newline } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleMainClass.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleMainClass.java index a6ffd882862..b73bd01f794 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleMainClass.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleMainClass.java @@ -39,7 +39,7 @@ public final class ModuleMainClass extends Attribute { private int mainClassIndex; /** - * Construct object from input stream. + * Constructs object from input stream. * * @param nameIndex Index in constant pool * @param length Content length in bytes diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleOpens.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleOpens.java index 06b404df72b..388370a45e7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleOpens.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleOpens.java @@ -36,13 +36,17 @@ */ public final class ModuleOpens implements Cloneable, Node { + private static String getToModuleNameAtIndex(final ConstantPool constantPool, final int index) { + return constantPool.getConstantString(index, Const.CONSTANT_Module); + } private final int opensIndex; // points to CONSTANT_Package_info private final int opensFlags; private final int opensToCount; + private final int[] opensToIndex; // points to CONSTANT_Module_info /** - * Construct object from file stream. + * Constructs object from file stream. * * @param file Input stream * @throws IOException if an I/O Exception occurs in readUnsignedShort @@ -68,8 +72,6 @@ public void accept(final Visitor v) { v.visitModuleOpens(this); } - // TODO add more getters and setters? - /** * @return deep copy of this object */ @@ -97,6 +99,39 @@ public void dump(final DataOutputStream file) throws IOException { } } + /** + * Gets the flags for this ModuleOpens. + * @return the opensFlags + * @since 6.10.0 + */ + public int getOpensFlags() { + return opensFlags; + } + + /** + * Gets the opened package name. + * @param constantPool the constant pool from the ClassFile + * @return the opened package name + * @since 6.10.0 + */ + public String getPackageName(final ConstantPool constantPool) { + return constantPool.constantToString(opensIndex, Const.CONSTANT_Package); + } + + /** + * Gets an array of module names for this ModuleOpens. + * @param constantPool Array of constants usually obtained from the ClassFile object + * @return array of module names following 'opens to' + * @since 6.10.0 + */ + public String[] getToModuleNames(final ConstantPool constantPool) { + final String[] toModuleNames = new String[opensToCount]; + for (int i = 0; i < opensToCount; i++) { + toModuleNames[i] = getToModuleNameAtIndex(constantPool, opensToIndex[i]); + } + return toModuleNames; + } + /** * @return String representation */ @@ -110,13 +145,13 @@ public String toString() { */ public String toString(final ConstantPool constantPool) { final StringBuilder buf = new StringBuilder(); - final String packageName = constantPool.constantToString(opensIndex, Const.CONSTANT_Package); - buf.append(Utility.compactClassName(packageName, false)); + final String packageName = getPackageName(constantPool); + buf.append(packageName); buf.append(", ").append(String.format("%04x", opensFlags)); buf.append(", to(").append(opensToCount).append("):\n"); for (final int index : opensToIndex) { - final String moduleName = constantPool.getConstantString(index, Const.CONSTANT_Module); - buf.append(" ").append(Utility.compactClassName(moduleName, false)).append("\n"); + final String moduleName = getToModuleNameAtIndex(constantPool, index); + buf.append(" ").append(moduleName).append("\n"); } return buf.substring(0, buf.length() - 1); // remove the last newline } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModulePackages.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModulePackages.java index 96367e02d2d..f48587e5455 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModulePackages.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModulePackages.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -27,20 +27,21 @@ import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.util.Args; +import jdk.xml.internal.Utils; /** * This class is derived from Attribute and represents the list of packages that are exported or opened by the * Module attribute. There may be at most one ModulePackages attribute in a ClassFile structure. * * @see Attribute - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public final class ModulePackages extends Attribute { private int[] packageIndexTable; /** - * Construct object from input stream. + * Constructs object from input stream. * * @param nameIndex Index in constant pool * @param length Content length in bytes @@ -65,7 +66,7 @@ public final class ModulePackages extends Attribute { */ public ModulePackages(final int nameIndex, final int length, final int[] packageIndexTable, final ConstantPool constantPool) { super(Const.ATTR_MODULE_PACKAGES, nameIndex, length, constantPool); - this.packageIndexTable = packageIndexTable != null ? packageIndexTable : Const.EMPTY_INT_ARRAY; + this.packageIndexTable = Utils.createEmptyArrayIfNull(packageIndexTable); Args.requireU2(this.packageIndexTable.length, "packageIndexTable.length"); } @@ -145,7 +146,7 @@ public String[] getPackageNames() { * @param packageIndexTable the list of package indexes Also redefines number_of_packages according to table length. */ public void setPackageIndexTable(final int[] packageIndexTable) { - this.packageIndexTable = packageIndexTable != null ? packageIndexTable : Const.EMPTY_INT_ARRAY; + this.packageIndexTable = Utils.createEmptyArrayIfNull(packageIndexTable); } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleProvides.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleProvides.java index f6c6058dfbb..490e9cd5d44 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleProvides.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleProvides.java @@ -36,12 +36,20 @@ */ public final class ModuleProvides implements Cloneable, Node { + private static String getImplementationClassNameAtIndex(final ConstantPool constantPool, final int index, final boolean compactClassName) { + final String className = constantPool.getConstantString(index, Const.CONSTANT_Class); + if (compactClassName) { + return Utility.compactClassName(className, false); + } + return className; + } private final int providesIndex; // points to CONSTANT_Class_info private final int providesWithCount; + private final int[] providesWithIndex; // points to CONSTANT_Class_info /** - * Construct object from file stream. + * Constructs object from file stream. * * @param file Input stream * @throws IOException if an I/O Exception occurs in readUnsignedShort @@ -66,8 +74,6 @@ public void accept(final Visitor v) { v.visitModuleProvides(this); } - // TODO add more getters and setters? - /** * @return deep copy of this object */ @@ -94,6 +100,31 @@ public void dump(final DataOutputStream file) throws IOException { } } + /** + * Gets the array of implementation class names for this ModuleProvides. + * @param constantPool Array of constants usually obtained from the ClassFile object + * @param compactClassName false for original constant pool value, true to replace '/' with '.' + * @return array of implementation class names + * @since 6.10.0 + */ + public String[] getImplementationClassNames(final ConstantPool constantPool, final boolean compactClassName) { + final String[] implementationClassNames = new String[providesWithCount]; + for (int i = 0; i < providesWithCount; i++) { + implementationClassNames[i] = getImplementationClassNameAtIndex(constantPool, providesWithIndex[i], compactClassName); + } + return implementationClassNames; + } + + /** + * Gets the interface name for this ModuleProvides. + * @param constantPool Array of constants usually obtained from the ClassFile object + * @return interface name + * @since 6.10.0 + */ + public String getInterfaceName(final ConstantPool constantPool) { + return constantPool.constantToString(providesIndex, Const.CONSTANT_Class); + } + /** * @return String representation */ @@ -107,12 +138,12 @@ public String toString() { */ public String toString(final ConstantPool constantPool) { final StringBuilder buf = new StringBuilder(); - final String interfaceName = constantPool.constantToString(providesIndex, Const.CONSTANT_Class); - buf.append(Utility.compactClassName(interfaceName, false)); + final String interfaceName = getInterfaceName(constantPool); + buf.append(interfaceName); buf.append(", with(").append(providesWithCount).append("):\n"); for (final int index : providesWithIndex) { - final String className = constantPool.getConstantString(index, Const.CONSTANT_Class); - buf.append(" ").append(Utility.compactClassName(className, false)).append("\n"); + final String className = getImplementationClassNameAtIndex(constantPool, index, true); + buf.append(" ").append(className).append("\n"); } return buf.substring(0, buf.length() - 1); // remove the last newline } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleRequires.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleRequires.java index c9c26c20649..3149a18290b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleRequires.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleRequires.java @@ -41,7 +41,7 @@ public final class ModuleRequires implements Cloneable, Node { private final int requiresVersionIndex; // either 0 or points to CONSTANT_Utf8_info /** - * Construct object from file stream. + * Constructs object from file stream. * * @param file Input stream * @throws IOException if an I/O Exception occurs in readUnsignedShort @@ -63,8 +63,6 @@ public void accept(final Visitor v) { v.visitModuleRequires(this); } - // TODO add more getters and setters? - /** * @return deep copy of this object */ @@ -89,6 +87,35 @@ public void dump(final DataOutputStream file) throws IOException { file.writeShort(requiresVersionIndex); } + /** + * Gets the module name from the constant pool. + * @param constantPool Array of constants usually obtained from the ClassFile object + * @return module name + * @since 6.10.0 + */ + public String getModuleName(final ConstantPool constantPool) { + return constantPool.constantToString(requiresIndex, Const.CONSTANT_Module); + } + + /** + * Gets the flags for this ModuleRequires. + * @return the requiresFlags + * @since 6.10.0 + */ + public int getRequiresFlags() { + return requiresFlags; + } + + /** + * Gets the required version from the constant pool. + * @param constantPool Array of constants usually obtained from the ClassFile object + * @return required version, "0" if version index is 0. + * @since 6.10.0 + */ + public String getVersion(final ConstantPool constantPool) { + return requiresVersionIndex == 0 ? "0" : constantPool.getConstantString(requiresVersionIndex, Const.CONSTANT_Utf8); + } + /** * @return String representation */ @@ -102,10 +129,10 @@ public String toString() { */ public String toString(final ConstantPool constantPool) { final StringBuilder buf = new StringBuilder(); - final String moduleName = constantPool.constantToString(requiresIndex, Const.CONSTANT_Module); - buf.append(Utility.compactClassName(moduleName, false)); + final String moduleName = getModuleName(constantPool); + buf.append(moduleName); buf.append(", ").append(String.format("%04x", requiresFlags)); - final String version = requiresVersionIndex == 0 ? "0" : constantPool.getConstantString(requiresVersionIndex, Const.CONSTANT_Utf8); + final String version = getVersion(constantPool); buf.append(", ").append(version); return buf.toString(); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestMembers.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestMembers.java index 05d982ca6e8..261f57d98a8 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestMembers.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestMembers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -27,6 +27,7 @@ import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.util.Args; +import jdk.xml.internal.Utils; /** * This class is derived from Attribute and records the classes and interfaces that are authorized to claim @@ -34,14 +35,14 @@ * ClassFile structure. * * @see Attribute - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public final class NestMembers extends Attribute { private int[] classes; /** - * Construct object from input stream. + * Constructs object from input stream. * * @param nameIndex Index in constant pool * @param length Content length in bytes @@ -66,7 +67,7 @@ public final class NestMembers extends Attribute { */ public NestMembers(final int nameIndex, final int length, final int[] classes, final ConstantPool constantPool) { super(Const.ATTR_NEST_MEMBERS, nameIndex, length, constantPool); - this.classes = classes != null ? classes : Const.EMPTY_INT_ARRAY; + this.classes = Utils.createEmptyArrayIfNull(classes); Args.requireU2(this.classes.length, "classes.length"); } @@ -146,7 +147,7 @@ public int getNumberClasses() { * @param classes the list of class indexes Also redefines number_of_classes according to table length. */ public void setClasses(final int[] classes) { - this.classes = classes != null ? classes : Const.EMPTY_INT_ARRAY; + this.classes = Utils.createEmptyArrayIfNull(classes); } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Node.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Node.java index c0395732d79..792ef31cb72 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Node.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Node.java @@ -26,5 +26,5 @@ */ public interface Node { - void accept(Visitor obj); + void accept(Visitor visitor); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/PMGClass.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/PMGClass.java index 9b1dd4c7b41..b7b5e1f1d99 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/PMGClass.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/PMGClass.java @@ -38,7 +38,7 @@ public final class PMGClass extends Attribute { private int pmgIndex; /** - * Construct object from input stream. + * Constructs object from input stream. * * @param nameIndex Index in constant pool to CONSTANT_Utf8 * @param length Content length in bytes diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotationEntry.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotationEntry.java index a3070fa7e0c..6ebe60c8049 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotationEntry.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotationEntry.java @@ -37,22 +37,28 @@ public class ParameterAnnotationEntry implements Node { static final ParameterAnnotationEntry[] EMPTY_ARRAY = {}; - public static ParameterAnnotationEntry[] createParameterAnnotationEntries(final Attribute[] attrs) { + public static ParameterAnnotationEntry[] createParameterAnnotationEntries(final Attribute[] attributes) { + if (attributes == null) { + return EMPTY_ARRAY; + } // Find attributes that contain parameter annotation data - final List accumulatedAnnotations = new ArrayList<>(attrs.length); - for (final Attribute attribute : attrs) { + final List accumulatedAnnotations = new ArrayList<>(attributes.length); + for (final Attribute attribute : attributes) { if (attribute instanceof ParameterAnnotations) { final ParameterAnnotations runtimeAnnotations = (ParameterAnnotations) attribute; - Collections.addAll(accumulatedAnnotations, runtimeAnnotations.getParameterAnnotationEntries()); + final ParameterAnnotationEntry[] parameterAnnotationEntries = runtimeAnnotations.getParameterAnnotationEntries(); + if (parameterAnnotationEntries != null) { + Collections.addAll(accumulatedAnnotations, parameterAnnotationEntries); + } } } - return accumulatedAnnotations.toArray(ParameterAnnotationEntry.EMPTY_ARRAY); + return accumulatedAnnotations.toArray(EMPTY_ARRAY); } private final AnnotationEntry[] annotationTable; /** - * Construct object from input stream. + * Constructs object from input stream. * * @param input Input stream * @throws IOException if an I/O error occurs. diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotations.java index 4817793120f..1e056b5d4f8 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotations.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotations.java @@ -34,10 +34,14 @@ */ public abstract class ParameterAnnotations extends Attribute implements Iterable { + private static final ParameterAnnotationEntry[] EMPTY_ARRAY = {}; + /** Table of parameter annotations */ private ParameterAnnotationEntry[] parameterAnnotationTable; /** + * Constructs a new instance. + * * @param parameterAnnotationType the subclass type of the parameter annotation * @param nameIndex Index pointing to the name Code * @param length Content length in bytes @@ -55,6 +59,8 @@ public abstract class ParameterAnnotations extends Attribute implements Iterable } /** + * Constructs a new instance. + * * @param parameterAnnotationType the subclass type of the parameter annotation * @param nameIndex Index pointing to the name Code * @param length Content length in bytes @@ -120,6 +126,6 @@ public Iterator iterator() { * @param parameterAnnotationTable the entries to set in this parameter annotation */ public final void setParameterAnnotationTable(final ParameterAnnotationEntry[] parameterAnnotationTable) { - this.parameterAnnotationTable = parameterAnnotationTable; + this.parameterAnnotationTable = parameterAnnotationTable != null ? parameterAnnotationTable : EMPTY_ARRAY; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Record.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Record.java new file mode 100644 index 00000000000..f59cfa37ca4 --- /dev/null +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Record.java @@ -0,0 +1,153 @@ +/* + * reserved comment block + * DO NOT REMOVE OR ALTER! + */ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.sun.org.apache.bcel.internal.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +import com.sun.org.apache.bcel.internal.Const; +import com.sun.org.apache.bcel.internal.util.Args; + +/** + * Extends {@link Attribute} and records the classes and + * interfaces that are authorized to claim membership in the nest hosted by the + * current class or interface. There may be at most one Record attribute in a + * ClassFile structure. + * + * @see Attribute + * @since 6.9.0 + */ +public final class Record extends Attribute { + + private static final RecordComponentInfo[] EMPTY_RCI_ARRAY = {}; + + private static RecordComponentInfo[] readComponents(final DataInput input, final ConstantPool constantPool) + throws IOException { + final int classCount = input.readUnsignedShort(); + final RecordComponentInfo[] components = new RecordComponentInfo[classCount]; + for (int i = 0; i < classCount; i++) { + components[i] = new RecordComponentInfo(input, constantPool); + } + return components; + } + + private RecordComponentInfo[] components; + + /** + * Constructs object from input stream. + * + * @param nameIndex Index in constant pool + * @param length Content length in bytes + * @param input Input stream + * @param constantPool Array of constants + * @throws IOException if an I/O error occurs. + */ + Record(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) + throws IOException { + this(nameIndex, length, readComponents(input, constantPool), constantPool); + } + + /** + * Constructs a new instance using components. + * + * @param nameIndex Index in constant pool + * @param length Content length in bytes + * @param classes Array of Record Component Info elements + * @param constantPool Array of constants + */ + public Record(final int nameIndex, final int length, final RecordComponentInfo[] classes, + final ConstantPool constantPool) { + super(Const.ATTR_RECORD, nameIndex, length, constantPool); + this.components = classes != null ? classes : EMPTY_RCI_ARRAY; + Args.requireU2(this.components.length, "attributes.length"); + } + + /** + * Called by objects that are traversing the nodes of the tree implicitly + * defined by the contents of a Java class. For example, the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + @Override + public void accept(final Visitor v) { + v.visitRecord(this); + } + + /** + * Copies this instance and its components. + * + * @return a deep copy of this instance and its components. + */ + @Override + public Attribute copy(final ConstantPool constantPool) { + final Record c = (Record) clone(); + if (components.length > 0) { + c.components = components.clone(); + } + c.setConstantPool(constantPool); + return c; + } + + /** + * Dumps this instance into a file stream in binary format. + * + * @param file output stream. + * @throws IOException if an I/O error occurs. + */ + @Override + public void dump(final DataOutputStream file) throws IOException { + super.dump(file); + file.writeShort(components.length); + for (final RecordComponentInfo component : components) { + component.dump(file); + } + } + + /** + * Gets all the record components. + * + * @return array of Record Component Info elements. + */ + public RecordComponentInfo[] getComponents() { + return components; + } + + /** + * Converts this instance to a String suitable for debugging. + * + * @return String a String suitable for debugging. + */ + @Override + public String toString() { + final StringBuilder buf = new StringBuilder(); + buf.append("Record("); + buf.append(components.length); + buf.append("):\n"); + for (final RecordComponentInfo component : components) { + buf.append(" ").append(component.toString()).append("\n"); + } + return buf.substring(0, buf.length() - 1); // remove the last newline + } + +} diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RecordComponentInfo.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RecordComponentInfo.java new file mode 100644 index 00000000000..3679647d409 --- /dev/null +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RecordComponentInfo.java @@ -0,0 +1,139 @@ +/* + * reserved comment block + * DO NOT REMOVE OR ALTER! + */ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.sun.org.apache.bcel.internal.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +import com.sun.org.apache.bcel.internal.Const; + +/** + * Record component info from a record. Instances from this class maps + * every component from a given record. + * + * @see + * The Java Virtual Machine Specification, Java SE 14 Edition, Records (preview) + * @since 6.9.0 + */ +public class RecordComponentInfo implements Node { + + private final int index; + private final int descriptorIndex; + private final Attribute[] attributes; + private final ConstantPool constantPool; + + /** + * Constructs a new instance from an input stream. + * + * @param input Input stream + * @param constantPool Array of constants + * @throws IOException if an I/O error occurs. + */ + public RecordComponentInfo(final DataInput input, final ConstantPool constantPool) throws IOException { + this.index = input.readUnsignedShort(); + this.descriptorIndex = input.readUnsignedShort(); + final int attributesCount = input.readUnsignedShort(); + this.attributes = new Attribute[attributesCount]; + for (int j = 0; j < attributesCount; j++) { + attributes[j] = Attribute.readAttribute(input, constantPool); + } + this.constantPool = constantPool; + } + + @Override + public void accept(final Visitor v) { + v.visitRecordComponent(this); + } + + /** + * Dumps contents into a file stream in binary format. + * + * @param file Output file stream + * @throws IOException if an I/O error occurs. + */ + public void dump(final DataOutputStream file) throws IOException { + file.writeShort(index); + file.writeShort(descriptorIndex); + file.writeShort(attributes.length); + for (final Attribute attribute : attributes) { + attribute.dump(file); + } + } + + /** + * Gets all attributes. + * + * @return all attributes. + */ + public Attribute[] getAttributes() { + return attributes; + } + + /** + * Gets the constant pool. + * + * @return Constant pool. + */ + public ConstantPool getConstantPool() { + return constantPool; + } + + /** + * Gets the description index. + * + * @return index in constant pool of this record component descriptor. + */ + public int getDescriptorIndex() { + return descriptorIndex; + } + + /** + * Gets the name index. + * + * @return index in constant pool of this record component name. + */ + public int getIndex() { + return index; + } + + /** + * Converts this instance to a String suitable for debugging. + * + * @return a String suitable for debugging. + */ + @Override + public String toString() { + final StringBuilder buf = new StringBuilder(); + buf.append("RecordComponentInfo("); + buf.append(constantPool.getConstantString(index, Const.CONSTANT_Utf8)); + buf.append(","); + buf.append(constantPool.getConstantString(descriptorIndex, Const.CONSTANT_Utf8)); + buf.append(","); + buf.append(attributes.length); + buf.append("):\n"); + for (final Attribute attribute : attributes) { + buf.append(" ").append(attribute.toString()).append("\n"); + } + return buf.substring(0, buf.length() - 1); // remove the last newline + } + +} diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleAnnotations.java index 7afb8719559..7a7c539f15a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleAnnotations.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleAnnotations.java @@ -28,13 +28,15 @@ import com.sun.org.apache.bcel.internal.Const; /** - * represents an annotation that is represented in the class file but is not provided to the JVM. + * An annotation that is represented in the class file but is not provided to the JVM. * * @since 6.0 */ public class RuntimeInvisibleAnnotations extends Annotations { /** + * Constructs a new instance. + * * @param nameIndex Index pointing to the name Code * @param length Content length in bytes * @param input Input stream @@ -46,7 +48,9 @@ public RuntimeInvisibleAnnotations(final int nameIndex, final int length, final } /** - * @return deep copy of this attribute + * Creates a deep copy of this attribute. + * + * @return deep copy of this attribute. */ @Override public Attribute copy(final ConstantPool constantPool) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleParameterAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleParameterAnnotations.java index e4c3276f968..3d50ce16d40 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleParameterAnnotations.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleParameterAnnotations.java @@ -34,6 +34,8 @@ public class RuntimeInvisibleParameterAnnotations extends ParameterAnnotations { /** + * Constructs a new instance. + * * @param nameIndex Index pointing to the name Code * @param length Content length in bytes * @param input Input stream diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleAnnotations.java index c91c77387b9..4bf8e6f7197 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleAnnotations.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleAnnotations.java @@ -28,13 +28,15 @@ import com.sun.org.apache.bcel.internal.Const; /** - * represents an annotation that is represented in the class file and is provided to the JVM. + * An annotation that is represented in the class file and is provided to the JVM. * * @since 6.0 */ public class RuntimeVisibleAnnotations extends Annotations { /** + * Constructs a new instance. + * * @param nameIndex Index pointing to the name Code * @param length Content length in bytes * @param input Input stream @@ -46,7 +48,9 @@ public RuntimeVisibleAnnotations(final int nameIndex, final int length, final Da } /** - * @return deep copy of this attribute + * Creates a deep copy of this attribute. + * + * @return deep copy of this attribute. */ @Override public Attribute copy(final ConstantPool constantPool) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleParameterAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleParameterAnnotations.java index 7e5d7eaaca3..ab5355235f6 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleParameterAnnotations.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleParameterAnnotations.java @@ -34,6 +34,8 @@ public class RuntimeVisibleParameterAnnotations extends ParameterAnnotations { /** + * Constructs a new instance. + * * @param nameIndex Index pointing to the name Code * @param length Content length in bytes * @param input Input stream diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Signature.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Signature.java index 4f5d3a341b3..2161bbcb6ec 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Signature.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Signature.java @@ -110,7 +110,7 @@ private static void matchIdent(final MyByteArrayInputStream in, final StringBuil if ((ch = in.read()) == -1) { throw new IllegalArgumentException("Illegal signature: " + in.getData() + " no ident, reaching EOF"); } - // System.out.println("return from ident:" + (char)ch); + // System.out.println("return from ident:" + (char) ch); if (!identStart(ch)) { final StringBuilder buf2 = new StringBuilder(); int count = 1; @@ -128,7 +128,7 @@ private static void matchIdent(final MyByteArrayInputStream in, final StringBuil buf.append(buf2); ch = in.read(); in.unread(); - // System.out.println("so far:" + buf2 + ":next:" +(char)ch); + // System.out.println("so far:" + buf2 + ":next:" +(char) ch); } else { for (int i = 0; i < count; i++) { in.unread(); @@ -141,10 +141,10 @@ private static void matchIdent(final MyByteArrayInputStream in, final StringBuil do { buf2.append((char) ch); ch = in.read(); - // System.out.println("within ident:"+ (char)ch); + // System.out.println("within ident:"+ (char) ch); } while (ch != -1 && (Character.isJavaIdentifierPart((char) ch) || ch == '/')); buf.append(Utility.pathToPackage(buf2.toString())); - // System.out.println("regular return ident:"+ (char)ch + ":" + buf2); + // System.out.println("regular return ident:"+ (char) ch + ":" + buf2); if (ch != -1) { in.unread(); } @@ -160,7 +160,7 @@ public static String translate(final String s) { private int signatureIndex; /** - * Construct object from file stream. + * Constructs object from file stream. * * @param nameIndex Index in constant pool to CONSTANT_Utf8 * @param length Content length in bytes diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SimpleElementValue.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SimpleElementValue.java index 5e4e98d94df..e3e1cf40031 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SimpleElementValue.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SimpleElementValue.java @@ -54,7 +54,7 @@ public void dump(final DataOutputStream dos) throws IOException { dos.writeShort(getIndex()); break; default: - throw new ClassFormatException("SimpleElementValue doesnt know how to write out type " + type); + throw new ClassFormatException("SimpleElementValue doesn't know how to write out type " + type); } } @@ -67,7 +67,7 @@ public int getIndex() { public boolean getValueBoolean() { if (super.getType() != PRIMITIVE_BOOLEAN) { - throw new IllegalStateException("Dont call getValueBoolean() on a non BOOLEAN ElementValue"); + throw new IllegalStateException("Don't call getValueBoolean() on a non BOOLEAN ElementValue"); } final ConstantInteger bo = (ConstantInteger) super.getConstantPool().getConstant(getIndex()); return bo.getBytes() != 0; @@ -75,21 +75,21 @@ public boolean getValueBoolean() { public byte getValueByte() { if (super.getType() != PRIMITIVE_BYTE) { - throw new IllegalStateException("Dont call getValueByte() on a non BYTE ElementValue"); + throw new IllegalStateException("Don't call getValueByte() on a non BYTE ElementValue"); } return (byte) super.getConstantPool().getConstantInteger(getIndex()).getBytes(); } public char getValueChar() { if (super.getType() != PRIMITIVE_CHAR) { - throw new IllegalStateException("Dont call getValueChar() on a non CHAR ElementValue"); + throw new IllegalStateException("Don't call getValueChar() on a non CHAR ElementValue"); } return (char) super.getConstantPool().getConstantInteger(getIndex()).getBytes(); } public double getValueDouble() { if (super.getType() != PRIMITIVE_DOUBLE) { - throw new IllegalStateException("Dont call getValueDouble() on a non DOUBLE ElementValue"); + throw new IllegalStateException("Don't call getValueDouble() on a non DOUBLE ElementValue"); } final ConstantDouble d = (ConstantDouble) super.getConstantPool().getConstant(getIndex()); return d.getBytes(); @@ -97,7 +97,7 @@ public double getValueDouble() { public float getValueFloat() { if (super.getType() != PRIMITIVE_FLOAT) { - throw new IllegalStateException("Dont call getValueFloat() on a non FLOAT ElementValue"); + throw new IllegalStateException("Don't call getValueFloat() on a non FLOAT ElementValue"); } final ConstantFloat f = (ConstantFloat) super.getConstantPool().getConstant(getIndex()); return f.getBytes(); @@ -105,14 +105,14 @@ public float getValueFloat() { public int getValueInt() { if (super.getType() != PRIMITIVE_INT) { - throw new IllegalStateException("Dont call getValueInt() on a non INT ElementValue"); + throw new IllegalStateException("Don't call getValueInt() on a non INT ElementValue"); } return super.getConstantPool().getConstantInteger(getIndex()).getBytes(); } public long getValueLong() { if (super.getType() != PRIMITIVE_LONG) { - throw new IllegalStateException("Dont call getValueLong() on a non LONG ElementValue"); + throw new IllegalStateException("Don't call getValueLong() on a non LONG ElementValue"); } final ConstantLong j = (ConstantLong) super.getConstantPool().getConstant(getIndex()); return j.getBytes(); @@ -120,7 +120,7 @@ public long getValueLong() { public short getValueShort() { if (super.getType() != PRIMITIVE_SHORT) { - throw new IllegalStateException("Dont call getValueShort() on a non SHORT ElementValue"); + throw new IllegalStateException("Don't call getValueShort() on a non SHORT ElementValue"); } final ConstantInteger s = (ConstantInteger) super.getConstantPool().getConstant(getIndex()); return (short) s.getBytes(); @@ -128,7 +128,7 @@ public short getValueShort() { public String getValueString() { if (super.getType() != STRING) { - throw new IllegalStateException("Dont call getValueString() on a non STRING ElementValue"); + throw new IllegalStateException("Don't call getValueString() on a non STRING ElementValue"); } return super.getConstantPool().getConstantUtf8(getIndex()).getBytes(); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SourceFile.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SourceFile.java index e9ceed21957..bfa9cbf8fcb 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SourceFile.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SourceFile.java @@ -40,7 +40,7 @@ public final class SourceFile extends Attribute { private int sourceFileIndex; /** - * Construct object from input stream. + * Constructs object from input stream. * * @param nameIndex Index in constant pool to CONSTANT_Utf8 * @param length Content length in bytes diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMap.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMap.java index 1f8ce5ea410..317638e6b2d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMap.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -30,8 +30,8 @@ /** * This class represents a stack map attribute used for preverification of Java classes for the - * Java 2 Micro Edition (J2ME). This attribute is used by the - * KVM and contained within the Code attribute of a method. See CLDC + * Java 2 Micro Edition (J2ME). This attribute is used by the + * KVM and contained within the Code attribute of a method. See CLDC * specification 5.3.1.2 * *
@@ -46,14 +46,14 @@
  * @see Code
  * @see StackMapEntry
  * @see StackMapType
- * @LastModified: Oct 2020
+ * @LastModified: Sept 2025
  */
 public final class StackMap extends Attribute {
 
     private StackMapEntry[] table; // Table of stack map entries
 
     /**
-     * Construct object from input stream.
+     * Constructs object from input stream.
      *
      * @param nameIndex Index of name
      * @param length Content length in bytes
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapEntry.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapEntry.java
index 110e30392ab..015083dd066 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapEntry.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapEntry.java
@@ -59,7 +59,7 @@ public final class StackMapEntry implements Node, Cloneable {
     private ConstantPool constantPool;
 
     /**
-     * Construct object from input stream.
+     * Constructs object from input stream.
      *
      * @param dataInput Input stream
      * @throws IOException if an I/O error occurs.
@@ -75,9 +75,7 @@ public final class StackMapEntry implements Node, Cloneable {
         } else if (frameType == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
             byteCodeOffset = dataInput.readUnsignedShort();
             typesOfStackItems = new StackMapType[] { new StackMapType(dataInput, constantPool) };
-        } else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX) {
-            byteCodeOffset = dataInput.readUnsignedShort();
-        } else if (frameType == Const.SAME_FRAME_EXTENDED) {
+        } else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX || frameType == Const.SAME_FRAME_EXTENDED) {
             byteCodeOffset = dataInput.readUnsignedShort();
         } else if (frameType >= Const.APPEND_FRAME && frameType <= Const.APPEND_FRAME_MAX) {
             byteCodeOffset = dataInput.readUnsignedShort();
@@ -167,7 +165,7 @@ public StackMapEntry copy() {
         try {
             e = (StackMapEntry) clone();
         } catch (final CloneNotSupportedException ex) {
-            throw new Error("Clone Not Supported");
+            throw new UnsupportedOperationException("Clone Not Supported", ex);
         }
 
         e.typesOfLocals = new StackMapType[typesOfLocals.length];
@@ -190,9 +188,7 @@ public void dump(final DataOutputStream file) throws IOException {
         } else if (frameType == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
             file.writeShort(byteCodeOffset);
             typesOfStackItems[0].dump(file);
-        } else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX) {
-            file.writeShort(byteCodeOffset);
-        } else if (frameType == Const.SAME_FRAME_EXTENDED) {
+        } else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX || frameType == Const.SAME_FRAME_EXTENDED) {
             file.writeShort(byteCodeOffset);
         } else if (frameType >= Const.APPEND_FRAME && frameType <= Const.APPEND_FRAME_MAX) {
             file.writeShort(byteCodeOffset);
@@ -232,7 +228,6 @@ public int getFrameType() {
 
     /**
      * Calculate stack map entry size
-     *
      */
     int getMapEntrySize() {
         if (frameType >= Const.SAME_FRAME && frameType <= Const.SAME_FRAME_MAX) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapType.java
index 4575b31dfce..b93066d53b7 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapType.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapType.java
@@ -34,9 +34,9 @@
  * @see StackMap
  * @see Const
  */
-public final class StackMapType implements Cloneable {
+public final class StackMapType implements Node, Cloneable {
 
-    public static final StackMapType[] EMPTY_ARRAY = {}; // must be public because BCELifier code generator writes calls to it
+    public static final StackMapType[] EMPTY_ARRAY = {}; // BCELifier code generator writes calls to constructor translating null to EMPTY_ARRAY
 
     private byte type;
     private int index = -1; // Index to CONSTANT_Class or offset
@@ -53,7 +53,7 @@ public StackMapType(final byte type, final int index, final ConstantPool constan
     }
 
     /**
-     * Construct object from file stream.
+     * Constructs object from file stream.
      *
      * @param file Input stream
      * @throws IOException if an I/O error occurs.
@@ -66,6 +66,18 @@ public StackMapType(final byte type, final int index, final ConstantPool constan
         this.constantPool = constantPool;
     }
 
+    /**
+     * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
+     * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
+     *
+     * @param v Visitor object
+     * @since 6.8.0
+     */
+    @Override
+    public void accept(final Visitor v) {
+        v.visitStackMapType(this);
+    }
+
     private byte checkType(final byte type) {
         if (type < Const.ITEM_Bogus || type > Const.ITEM_NewObject) {
             throw new ClassFormatException("Illegal type for StackMapType: " + type);
@@ -98,6 +110,15 @@ public void dump(final DataOutputStream file) throws IOException {
         }
     }
 
+    /**
+     * Gets the class name of this StackMapType from the constant pool at index position.
+     * @return the fully qualified name of the class for this StackMapType.
+     * @since 6.8.0
+     */
+    public String getClassName() {
+        return constantPool.constantToString(index, Const.CONSTANT_Class);
+    }
+
     /**
      * @return Constant pool used by this object.
      */
@@ -129,7 +150,7 @@ private String printIndex() {
             if (index < 0) {
                 return ", class=";
             }
-            return ", class=" + constantPool.constantToString(index, Const.CONSTANT_Class);
+            return ", class=" + getClassName();
         }
         if (type == Const.ITEM_NewObject) {
             return ", offset=" + index;
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Synthetic.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Synthetic.java
index 3683fd6437e..c7fef8fcebc 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Synthetic.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Synthetic.java
@@ -52,7 +52,7 @@ public Synthetic(final int nameIndex, final int length, final byte[] bytes, fina
     }
 
     /**
-     * Construct object from input stream.
+     * Constructs object from input stream.
      *
      * @param nameIndex Index in constant pool to CONSTANT_Utf8
      * @param length Content length in bytes
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Utility.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Utility.java
index 12dbbe4828a..6967dcefd94 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Utility.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Utility.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -43,7 +43,7 @@
 /**
  * Utility functions that do not really belong to any class in particular.
  *
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
  */
 // @since 6.0 methods are no longer final
 public abstract class Utility {
@@ -51,7 +51,7 @@ public abstract class Utility {
     /**
      * Decode characters into bytes. Used by decode()
      */
-    private static class JavaReader extends FilterReader {
+    private static final class JavaReader extends FilterReader {
 
         public JavaReader(final Reader in) {
             super(in);
@@ -88,10 +88,10 @@ public int read(final char[] cbuf, final int off, final int len) throws IOExcept
     }
 
     /**
-     * Encode bytes into valid java identifier characters. Used by
+     * Encode bytes into valid Java identifier characters. Used by
      * encode()
      */
-    private static class JavaWriter extends FilterWriter {
+    private static final class JavaWriter extends FilterWriter {
 
         public JavaWriter(final Writer out) {
             super(out);
@@ -437,7 +437,9 @@ public static String codeToString(final ByteSequence bytes, final ConstantPool c
         case Const.NEW:
         case Const.CHECKCAST:
             buf.append("\t");
-            //$FALL-THROUGH$
+            index = bytes.readUnsignedShort();
+            buf.append("\t<").append(constantPool.constantToString(index, Const.CONSTANT_Class)).append(">").append(verbose ? " (" + index + ")" : "");
+            break;
         case Const.INSTANCEOF:
             index = bytes.readUnsignedShort();
             buf.append("\t<").append(constantPool.constantToString(index, Const.CONSTANT_Class)).append(">").append(verbose ? " (" + index + ")" : "");
@@ -864,7 +866,7 @@ public static String[] methodSignatureArgumentTypes(final String signature, fina
             // Skip any type arguments to read argument declarations between '(' and ')'
             index = signature.indexOf('(') + 1;
             if (index <= 0) {
-                throw new ClassFormatException("Invalid method signature: " + signature);
+                throw new InvalidMethodSignatureException(signature);
             }
             while (signature.charAt(index) != ')') {
                 vec.add(typeSignatureToString(signature.substring(index), chopit));
@@ -872,7 +874,7 @@ public static String[] methodSignatureArgumentTypes(final String signature, fina
                 index += unwrap(CONSUMER_CHARS); // update position
             }
         } catch (final StringIndexOutOfBoundsException e) { // Should never occur
-            throw new ClassFormatException("Invalid method signature: " + signature, e);
+            throw new InvalidMethodSignatureException(signature, e);
         }
         return vec.toArray(Const.EMPTY_STRING_ARRAY);
     }
@@ -903,11 +905,11 @@ public static String methodSignatureReturnType(final String signature, final boo
             // Read return type after ')'
             index = signature.lastIndexOf(')') + 1;
             if (index <= 0) {
-                throw new ClassFormatException("Invalid method signature: " + signature);
+                throw new InvalidMethodSignatureException(signature);
             }
             type = typeSignatureToString(signature.substring(index), chopit);
         } catch (final StringIndexOutOfBoundsException e) { // Should never occur
-            throw new ClassFormatException("Invalid method signature: " + signature, e);
+            throw new InvalidMethodSignatureException(signature, e);
         }
         return type;
     }
@@ -959,7 +961,7 @@ public static String methodSignatureToString(final String signature, final Strin
             // Skip any type arguments to read argument declarations between '(' and ')'
             index = signature.indexOf('(') + 1;
             if (index <= 0) {
-                throw new ClassFormatException("Invalid method signature: " + signature);
+                throw new InvalidMethodSignatureException(signature);
             }
             while (signature.charAt(index) != ')') {
                 final String paramType = typeSignatureToString(signature.substring(index), chopit);
@@ -985,7 +987,7 @@ public static String methodSignatureToString(final String signature, final Strin
             // Read return type after ')'
             type = typeSignatureToString(signature.substring(index), chopit);
         } catch (final StringIndexOutOfBoundsException e) { // Should never occur
-            throw new ClassFormatException("Invalid method signature: " + signature, e);
+            throw new InvalidMethodSignatureException(signature, e);
         }
         // ignore any throws information in the signature
         if (buf.length() > 1) {
@@ -1172,7 +1174,7 @@ public static String signatureToString(final String signature, final boolean cho
             type = typeParams + typeSignaturesToString(signature.substring(index), chopit, ')');
             index += unwrap(CONSUMER_CHARS); // update position
             // add return type
-            type = type + typeSignatureToString(signature.substring(index), chopit);
+            type += typeSignatureToString(signature.substring(index), chopit);
             index += unwrap(CONSUMER_CHARS); // update position
             // ignore any throws information in the signature
             return type;
@@ -1237,12 +1239,12 @@ public static byte typeOfMethodSignature(final String signature) throws ClassFor
         int index;
         try {
             if (signature.charAt(0) != '(') {
-                throw new ClassFormatException("Invalid method signature: " + signature);
+                throw new InvalidMethodSignatureException(signature);
             }
             index = signature.lastIndexOf(')') + 1;
             return typeOfSignature(signature.substring(index));
         } catch (final StringIndexOutOfBoundsException e) {
-            throw new ClassFormatException("Invalid method signature: " + signature, e);
+            throw new InvalidMethodSignatureException(signature, e);
         }
     }
 
@@ -1286,10 +1288,10 @@ public static byte typeOfSignature(final String signature) throws ClassFormatExc
             case '*':
                 return typeOfSignature(signature.substring(1));
             default:
-                throw new ClassFormatException("Invalid method signature: " + signature);
+                throw new InvalidMethodSignatureException(signature);
             }
         } catch (final StringIndexOutOfBoundsException e) {
-            throw new ClassFormatException("Invalid method signature: " + signature, e);
+            throw new InvalidMethodSignatureException(signature, e);
         }
     }
 
@@ -1469,8 +1471,8 @@ public static String typeSignatureToString(final String signature, final boolean
                 } else {
                     type.append(typeSignatureToString(signature.substring(consumedChars), chopit));
                     // update our consumed count by the number of characters the for type argument
-                    consumedChars = unwrap(Utility.CONSUMER_CHARS) + consumedChars;
-                    wrap(Utility.CONSUMER_CHARS, consumedChars);
+                    consumedChars = unwrap(CONSUMER_CHARS) + consumedChars;
+                    wrap(CONSUMER_CHARS, consumedChars);
                 }
 
                 // are there more TypeArguments?
@@ -1490,8 +1492,8 @@ public static String typeSignatureToString(final String signature, final boolean
                     } else {
                         type.append(typeSignatureToString(signature.substring(consumedChars), chopit));
                         // update our consumed count by the number of characters the for type argument
-                        consumedChars = unwrap(Utility.CONSUMER_CHARS) + consumedChars;
-                        wrap(Utility.CONSUMER_CHARS, consumedChars);
+                        consumedChars = unwrap(CONSUMER_CHARS) + consumedChars;
+                        wrap(CONSUMER_CHARS, consumedChars);
                     }
                 }
 
@@ -1508,14 +1510,14 @@ public static String typeSignatureToString(final String signature, final boolean
                     // update our consumed count by the number of characters the for type argument
                     // note that this count includes the "L" we added, but that is ok
                     // as it accounts for the "." we didn't consume
-                    consumedChars = unwrap(Utility.CONSUMER_CHARS) + consumedChars;
-                    wrap(Utility.CONSUMER_CHARS, consumedChars);
+                    consumedChars = unwrap(CONSUMER_CHARS) + consumedChars;
+                    wrap(CONSUMER_CHARS, consumedChars);
                     return type.toString();
                 }
                 if (signature.charAt(consumedChars) != ';') {
                     throw new ClassFormatException("Invalid signature: " + signature);
                 }
-                wrap(Utility.CONSUMER_CHARS, consumedChars + 1); // remove final ";"
+                wrap(CONSUMER_CHARS, consumedChars + 1); // remove final ";"
                 return type.toString();
             }
             case 'S':
@@ -1536,9 +1538,9 @@ public static String typeSignatureToString(final String signature, final boolean
                 // The rest of the string denotes a ''
                 type = typeSignatureToString(signature.substring(n), chopit);
                 // corrected concurrent private static field acess
-                // Utility.consumed_chars += consumed_chars; is replaced by:
-                final int temp = unwrap(Utility.CONSUMER_CHARS) + consumedChars;
-                wrap(Utility.CONSUMER_CHARS, temp);
+                // consumed_chars += consumed_chars; is replaced by:
+                final int temp = unwrap(CONSUMER_CHARS) + consumedChars;
+                wrap(CONSUMER_CHARS, temp);
                 return type + brackets.toString();
             }
             case 'V':
@@ -1552,11 +1554,11 @@ public static String typeSignatureToString(final String signature, final boolean
     }
 
     private static int unwrap(final ThreadLocal tl) {
-        return tl.get();
+        return tl.get().intValue();
     }
 
     private static void wrap(final ThreadLocal tl, final int value) {
-        tl.set(value);
+        tl.set(Integer.valueOf(value));
     }
 
 }
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Visitor.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Visitor.java
index 74cb8400d3e..1f6fe9c96ee 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Visitor.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Visitor.java
@@ -217,11 +217,32 @@ default void visitNestMembers(final NestMembers obj) {
      */
     void visitParameterAnnotation(ParameterAnnotations obj);
 
+
     /**
      * @since 6.0
      */
     void visitParameterAnnotationEntry(ParameterAnnotationEntry obj);
 
+    /**
+     * Visits a {@link Record} object.
+     *
+     * @param obj Record to visit
+     * @since 6.9.0
+     */
+    default void visitRecord(final Record obj) {
+        // empty
+    }
+
+    /**
+     * Visits a {@link RecordComponentInfo} object.
+     *
+     * @param record component to visit
+     * @since 6.9.0
+     */
+    default void visitRecordComponent(final RecordComponentInfo record) {
+     // noop
+    }
+
     void visitSignature(Signature obj);
 
     void visitSourceFile(SourceFile obj);
@@ -230,7 +251,18 @@ default void visitNestMembers(final NestMembers obj) {
 
     void visitStackMapEntry(StackMapEntry obj);
 
+    /**
+     * Visits a {@link StackMapType} object.
+     *
+     * @param obj object to visit
+     * @since 6.8.0
+     */
+    default void visitStackMapType(final StackMapType obj) {
+      // empty
+    }
+
     void visitSynthetic(Synthetic obj);
 
     void visitUnknown(Unknown obj);
+
 }
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/package-info.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/package-info.java
new file mode 100644
index 00000000000..4e8d383bcab
--- /dev/null
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/package-info.java
@@ -0,0 +1,25 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * Classes that describe the structure of a Java class file and a class file parser.
+ */
+package com.sun.org.apache.bcel.internal.classfile;
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARRAYLENGTH.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARRAYLENGTH.java
index 2d7188e9174..db756700085 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARRAYLENGTH.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARRAYLENGTH.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -28,12 +28,12 @@
  * 
  * Stack: ..., arrayref -> ..., length
  * 
- * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public class ARRAYLENGTH extends Instruction implements ExceptionThrower, StackProducer, StackConsumer /* since 6.0 */ { /** - * Get length of array + * Gets length of array */ public ARRAYLENGTH() { super(com.sun.org.apache.bcel.internal.Const.ARRAYLENGTH, (short) 1); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ATHROW.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ATHROW.java index bb2e953f850..07171fefde1 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ATHROW.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ATHROW.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -28,8 +28,10 @@ *
  * Stack: ..., objectref -> objectref
  * 
+ * + * @LastModified: Sept 2025 */ -public class ATHROW extends Instruction implements UnconditionalBranch, ExceptionThrower { +public class ATHROW extends Instruction implements UnconditionalBranch, ExceptionThrower, StackConsumer { /** * Throw exception @@ -48,6 +50,7 @@ public ATHROW() { public void accept(final Visitor v) { v.visitUnconditionalBranch(this); v.visitExceptionThrower(this); + v.visitStackConsumer(this); v.visitATHROW(this); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationEntryGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationEntryGen.java index ea01a837175..0fad6ea7389 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationEntryGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationEntryGen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -28,6 +28,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import com.sun.org.apache.bcel.internal.classfile.AnnotationEntry; import com.sun.org.apache.bcel.internal.classfile.Attribute; @@ -37,10 +38,11 @@ import com.sun.org.apache.bcel.internal.classfile.RuntimeInvisibleParameterAnnotations; import com.sun.org.apache.bcel.internal.classfile.RuntimeVisibleAnnotations; import com.sun.org.apache.bcel.internal.classfile.RuntimeVisibleParameterAnnotations; +import jdk.xml.internal.Utils; /** * @since 6.0 - * @LastModified: Jan 2020 + * @LastModified: Sept 2025 */ public class AnnotationEntryGen { @@ -53,7 +55,7 @@ public class AnnotationEntryGen { * @param annotationEntryGens An array of AnnotationGen objects */ static Attribute[] getAnnotationAttributes(final ConstantPoolGen cp, final AnnotationEntryGen[] annotationEntryGens) { - if (annotationEntryGens.length == 0) { + if (annotationEntryGens == null && annotationEntryGens.length == 0) { return Attribute.EMPTY_ARRAY; } @@ -255,11 +257,7 @@ public void addElementNameValuePair(final ElementValuePairGen evp) { } private List copyValues(final ElementValuePair[] in, final ConstantPoolGen cpool, final boolean copyPoolEntries) { - final List out = new ArrayList<>(); - for (final ElementValuePair nvp : in) { - out.add(new ElementValuePairGen(nvp, cpool, copyPoolEntries)); - } - return out; + return Utils.streamOfIfNonNull(in).map(nvp -> new ElementValuePairGen(nvp, cpool, copyPoolEntries)).collect(Collectors.toList()); } public void dump(final DataOutputStream dos) throws IOException { @@ -286,18 +284,20 @@ public int getTypeIndex() { } public final String getTypeName() { - return getTypeSignature();// BCELBUG: Should I use this instead? + return getTypeSignature(); // BCELBUG: Should I use this instead? // Utility.signatureToString(getTypeSignature()); } public final String getTypeSignature() { - // ConstantClass c = (ConstantClass)cpool.getConstant(typeIndex); + // ConstantClass c = (ConstantClass) cpool.getConstant(typeIndex); final ConstantUtf8 utf8 = (ConstantUtf8) cpool.getConstant(typeIndex/* c.getNameIndex() */); return utf8.getBytes(); } /** - * Returns list of ElementNameValuePair objects + * Returns list of ElementNameValuePair objects. + * + * @return list of ElementNameValuePair objects. */ public List getValues() { return evs; diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java index 71374877efe..59b774a9afc 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -25,12 +24,15 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import com.sun.org.apache.bcel.internal.classfile.ArrayElementValue; import com.sun.org.apache.bcel.internal.classfile.ElementValue; +import jdk.xml.internal.Utils; /** * @since 6.0 + * @LastModified: Sept 2025 */ public class ArrayElementValueGen extends ElementValueGen { // J5TODO: Should we make this an array or a list? A list would be easier to @@ -46,7 +48,7 @@ public ArrayElementValueGen(final ArrayElementValue value, final ConstantPoolGen evalues = new ArrayList<>(); final ElementValue[] in = value.getElementValuesArray(); for (final ElementValue element : in) { - evalues.add(ElementValueGen.copy(element, cpool, copyPoolEntries)); + evalues.add(copy(element, cpool, copyPoolEntries)); } } @@ -55,15 +57,12 @@ public ArrayElementValueGen(final ConstantPoolGen cp) { evalues = new ArrayList<>(); } - public ArrayElementValueGen(final int type, final ElementValue[] datums, final ConstantPoolGen cpool) { + public ArrayElementValueGen(final int type, final ElementValue[] elementValues, final ConstantPoolGen cpool) { super(type, cpool); if (type != ARRAY) { throw new IllegalArgumentException("Only element values of type array can be built with this ctor - type specified: " + type); } - this.evalues = new ArrayList<>(); - for (final ElementValue datum : datums) { - evalues.add(ElementValueGen.copy(datum, cpool, true)); - } + this.evalues = Utils.streamOfIfNonNull(elementValues).map(e -> copy(e, cpool, true)).collect(Collectors.toList()); } public void addElement(final ElementValueGen gen) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayType.java index 138999ebe90..78a676e875e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayType.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayType.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -24,6 +23,8 @@ /** * Denotes array type, such as int[][] + * + * @LastModified: Sept 2025 */ public final class ArrayType extends ReferenceType { @@ -43,7 +44,7 @@ public ArrayType(final byte type, final int dimensions) { /** * Convenience constructor for reference array type, e.g. Object[] * - * @param className complete name of class (java.lang.String, e.g.) + * @param className complete name of class ({@link String}, for example) * @param dimensions array dimensions */ public ArrayType(final String className, final int dimensions) { @@ -56,6 +57,7 @@ public ArrayType(final String className, final int dimensions) { * @param type type of array (may be an array itself) * @param dimensions array dimensions */ + @SuppressWarnings("deprecation") //signature public ArrayType(final Type type, final int dimensions) { super(Const.T_ARRAY, ""); if (dimensions < 1 || dimensions > Const.MAX_BYTE) { @@ -79,7 +81,7 @@ public ArrayType(final Type type, final int dimensions) { buf.append('['); } buf.append(basicType.getSignature()); - super.setSignature(buf.toString()); + this.signature = buf.toString(); } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchHandle.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchHandle.java index 91ab9ac5463..f489f9a7658 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchHandle.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchHandle.java @@ -63,7 +63,7 @@ public InstructionHandle getTarget() { } /** - * Set new contents. Old instruction is disposed and may not be used anymore. + * Sets new contents. Old instruction is disposed and may not be used anymore. */ @Override // This is only done in order to apply the additional type check; could be merged with super impl. public void setInstruction(final Instruction i) { // TODO could be package-protected? diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CPInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CPInstruction.java index 1dfd244141a..ff45e5cde93 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CPInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CPInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -35,7 +35,7 @@ * @see LDC * @see INVOKEVIRTUAL * - * @LastModified: Jan 2020 + * @LastModified: Sept 2025 */ public abstract class CPInstruction extends Instruction implements TypedInstruction, IndexedInstruction { @@ -104,7 +104,7 @@ protected void initFromFile(final ByteSequence bytes, final boolean wide) throws } /** - * Set the index to constant pool. + * Sets the index to constant pool. * * @param index in constant pool. */ diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassElementValueGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassElementValueGen.java index 1c1c032dbd5..8e024eebaa4 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassElementValueGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassElementValueGen.java @@ -48,12 +48,12 @@ public ClassElementValueGen(final ClassElementValue value, final ConstantPoolGen } protected ClassElementValueGen(final int typeIdx, final ConstantPoolGen cpool) { - super(ElementValueGen.CLASS, cpool); + super(CLASS, cpool); this.idx = typeIdx; } public ClassElementValueGen(final ObjectType t, final ConstantPoolGen cpool) { - super(ElementValueGen.CLASS, cpool); + super(CLASS, cpool); // this.idx = cpool.addClass(t); idx = cpool.addUtf8(t.getSignature()); } @@ -67,9 +67,9 @@ public void dump(final DataOutputStream dos) throws IOException { public String getClassString() { final ConstantUtf8 cu8 = (ConstantUtf8) getConstantPool().getConstant(idx); return cu8.getBytes(); - // ConstantClass c = (ConstantClass)getConstantPool().getConstant(idx); + // ConstantClass c = (ConstantClass) getConstantPool().getConstant(idx); // ConstantUtf8 utf8 = - // (ConstantUtf8)getConstantPool().getConstant(c.getNameIndex()); + // (ConstantUtf8) getConstantPool().getConstant(c.getNameIndex()); // return utf8.getBytes(); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGen.java index acaf4519567..debf930fe90 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -40,40 +40,37 @@ import com.sun.org.apache.bcel.internal.util.BCELComparator; /** - * Template class for building up a java class. May be initialized with an existing java class (file). + * Template class for building up a java class. May be initialized with an existing Java class (file). * * @see JavaClass - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public class ClassGen extends AccessFlags implements Cloneable { - private static BCELComparator bcelComparator = new BCELComparator() { + private static BCELComparator bcelComparator = new BCELComparator() { @Override - public boolean equals(final Object o1, final Object o2) { - final ClassGen THIS = (ClassGen) o1; - final ClassGen THAT = (ClassGen) o2; - return Objects.equals(THIS.getClassName(), THAT.getClassName()); + public boolean equals(final ClassGen a, final ClassGen b) { + return a == b || a != null && b != null && Objects.equals(a.getClassName(), b.getClassName()); } @Override - public int hashCode(final Object o) { - final ClassGen THIS = (ClassGen) o; - return THIS.getClassName().hashCode(); + public int hashCode(final ClassGen o) { + return o != null ? Objects.hashCode(o.getClassName()) : 0; } }; /** * @return Comparison strategy object */ - public static BCELComparator getComparator() { + public static BCELComparator getComparator() { return bcelComparator; } /** * @param comparator Comparison strategy object */ - public static void setComparator(final BCELComparator comparator) { + public static void setComparator(final BCELComparator comparator) { bcelComparator = comparator; } @@ -101,7 +98,7 @@ public static void setComparator(final BCELComparator comparator) { private List observers; /** - * Initialize with existing class. + * Constructs a new instance from an existing class. * * @param clazz JavaClass object (e.g. read from file) */ @@ -118,15 +115,26 @@ public ClassGen(final JavaClass clazz) { final Attribute[] attributes = clazz.getAttributes(); // J5TODO: Could make unpacking lazy, done on first reference final AnnotationEntryGen[] annotations = unpackAnnotations(attributes); - Collections.addAll(interfaceList, clazz.getInterfaceNames()); - for (final Attribute attribute : attributes) { - if (!(attribute instanceof Annotations)) { - addAttribute(attribute); + final String[] interfaceNames = clazz.getInterfaceNames(); + if (interfaceNames != null) { + Collections.addAll(interfaceList, interfaceNames); + } + if (attributes != null) { + for (final Attribute attribute : attributes) { + if (!(attribute instanceof Annotations)) { + addAttribute(attribute); + } } } Collections.addAll(annotationList, annotations); - Collections.addAll(methodList, clazz.getMethods()); - Collections.addAll(fieldList, clazz.getFields()); + final Method[] methods = clazz.getMethods(); + if (methods != null) { + Collections.addAll(methodList, methods); + } + final Field[] fields = clazz.getFields(); + if (fields != null) { + Collections.addAll(fieldList, fields); + } } /** @@ -242,7 +250,7 @@ public Object clone() { try { return super.clone(); } catch (final CloneNotSupportedException e) { - throw new Error("Clone Not Supported"); // never happens + throw new UnsupportedOperationException("Clone Not Supported", e); // never happens } } @@ -282,7 +290,7 @@ public Method containsMethod(final String name, final String signature) { */ @Override public boolean equals(final Object obj) { - return bcelComparator.equals(this, obj); + return obj instanceof ClassGen && bcelComparator.equals(this, (ClassGen) obj); } // J5TODO: Should we make calling unpackAnnotations() lazy and put it in here? @@ -379,7 +387,7 @@ public int getSuperclassNameIndex() { } /** - * Return value as defined by given BCELComparator strategy. By default return the hashcode of the class name. + * Return value as defined by given BCELComparator strategy. By default return the hash code of the class name. * * @see Object#hashCode() */ @@ -478,7 +486,7 @@ public void setConstantPool(final ConstantPoolGen constantPool) { } /** - * Set major version number of class file, default value is 45 (JDK 1.1) + * Sets major version number of class file, default value is 45 (JDK 1.1) * * @param major major version number */ @@ -492,11 +500,13 @@ public void setMethodAt(final Method method, final int pos) { public void setMethods(final Method[] methods) { methodList.clear(); - Collections.addAll(methodList, methods); + if (methods != null) { + Collections.addAll(methodList, methods); + } } /** - * Set minor version number of class file, default value is 3 (JDK 1.1) + * Sets minor version number of class file, default value is 3 (JDK 1.1) * * @param minor minor version number */ @@ -515,17 +525,19 @@ public void setSuperclassNameIndex(final int superclassNameIndex) { } /** - * Look for attributes representing annotations and unpack them. + * Unpacks attributes representing annotations. */ - private AnnotationEntryGen[] unpackAnnotations(final Attribute[] attrs) { + private AnnotationEntryGen[] unpackAnnotations(final Attribute[] attributes) { final List annotationGenObjs = new ArrayList<>(); - for (final Attribute attr : attrs) { - if (attr instanceof RuntimeVisibleAnnotations) { - final RuntimeVisibleAnnotations rva = (RuntimeVisibleAnnotations) attr; - rva.forEach(a -> annotationGenObjs.add(new AnnotationEntryGen(a, getConstantPool(), false))); - } else if (attr instanceof RuntimeInvisibleAnnotations) { - final RuntimeInvisibleAnnotations ria = (RuntimeInvisibleAnnotations) attr; - ria.forEach(a -> annotationGenObjs.add(new AnnotationEntryGen(a, getConstantPool(), false))); + if (attributes != null) { + for (final Attribute attr : attributes) { + if (attr instanceof RuntimeVisibleAnnotations) { + final RuntimeVisibleAnnotations rva = (RuntimeVisibleAnnotations) attr; + rva.forEach(a -> annotationGenObjs.add(new AnnotationEntryGen(a, getConstantPool(), false))); + } else if (attr instanceof RuntimeInvisibleAnnotations) { + final RuntimeInvisibleAnnotations ria = (RuntimeInvisibleAnnotations) attr; + ria.forEach(a -> annotationGenObjs.add(new AnnotationEntryGen(a, getConstantPool(), false))); + } } } return annotationGenObjs.toArray(AnnotationEntryGen.EMPTY_ARRAY); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java index fa660954d15..2518131ccee 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java @@ -63,7 +63,7 @@ public Object clone() { try { return super.clone(); } catch (final CloneNotSupportedException e) { - throw new Error("Clone Not Supported"); // never happens + throw new UnsupportedOperationException("Clone Not Supported", e); // never happens } } @@ -81,7 +81,7 @@ public ObjectType getCatchType() { } /** - * Get CodeException object.
+ * Gets CodeException object.
* * This relies on that the instruction list has already been dumped to byte code or that the 'setPositions' methods * has been called for the instruction list. @@ -120,7 +120,7 @@ public void setCatchType(final ObjectType catchType) { } /* - * Set end of handler + * Sets end of handler * * @param endPc End of handled region (inclusive) */ @@ -130,7 +130,7 @@ public void setEndPC(final InstructionHandle endPc) { // TODO could be package-p } /* - * Set handler code + * Sets handler code * * @param handlerPc Start of handler */ @@ -140,7 +140,7 @@ public void setHandlerPC(final InstructionHandle handlerPc) { // TODO could be p } /* - * Set start of handler + * Sets start of handler * * @param startPc Start of handled region (inclusive) */ diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValuePairGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValuePairGen.java index bdc9c517a86..878f392b6b7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValuePairGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValuePairGen.java @@ -44,7 +44,7 @@ public ElementValuePairGen(final ElementValuePair nvp, final ConstantPoolGen cpo // Could assert nvp.getNameString() points to the same thing as // constantPoolGen.getConstant(nvp.getNameIndex()) // if - // (!nvp.getNameString().equals(((ConstantUtf8)constantPoolGen.getConstant(nvp.getNameIndex())).getBytes())) + // (!nvp.getNameString().equals(((ConstantUtf8) constantPoolGen.getConstant(nvp.getNameIndex())).getBytes())) // { // throw new IllegalArgumentException("envp buggered"); // } @@ -86,7 +86,7 @@ public int getNameIndex() { } public final String getNameString() { - // ConstantString cu8 = (ConstantString)constantPoolGen.getConstant(nameIdx); + // ConstantString cu8 = (ConstantString) constantPoolGen.getConstant(nameIdx); return ((ConstantUtf8) constantPoolGen.getConstant(nameIdx)).getBytes(); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EnumElementValueGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EnumElementValueGen.java index 95ac794f2d7..95c00ed3813 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EnumElementValueGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EnumElementValueGen.java @@ -40,10 +40,8 @@ public class EnumElementValueGen extends ElementValueGen { public EnumElementValueGen(final EnumElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries) { super(ENUM_CONSTANT, cpool); if (copyPoolEntries) { - typeIdx = cpool.addUtf8(value.getEnumTypeString());// was - // addClass(value.getEnumTypeString()); - valueIdx = cpool.addUtf8(value.getEnumValueString()); // was - // addString(value.getEnumValueString()); + typeIdx = cpool.addUtf8(value.getEnumTypeString()); // was addClass(value.getEnumTypeString()); + valueIdx = cpool.addUtf8(value.getEnumValueString()); // was addString(value.getEnumValueString()); } else { typeIdx = value.getTypeIndex(); valueIdx = value.getValueIndex(); @@ -55,7 +53,7 @@ public EnumElementValueGen(final EnumElementValue value, final ConstantPoolGen c * This ctor is used for deserialization */ protected EnumElementValueGen(final int typeIdx, final int valueIdx, final ConstantPoolGen cpool) { - super(ElementValueGen.ENUM_CONSTANT, cpool); + super(ENUM_CONSTANT, cpool); if (super.getElementValueType() != ENUM_CONSTANT) { throw new IllegalArgumentException("Only element values of type enum can be built with this ctor - type specified: " + super.getElementValueType()); } @@ -64,9 +62,9 @@ protected EnumElementValueGen(final int typeIdx, final int valueIdx, final Const } public EnumElementValueGen(final ObjectType t, final String value, final ConstantPoolGen cpool) { - super(ElementValueGen.ENUM_CONSTANT, cpool); - typeIdx = cpool.addUtf8(t.getSignature());// was addClass(t); - valueIdx = cpool.addUtf8(value);// was addString(value); + super(ENUM_CONSTANT, cpool); + typeIdx = cpool.addUtf8(t.getSignature()); // was addClass(t); + valueIdx = cpool.addUtf8(value); // was addString(value); } @Override @@ -90,9 +88,9 @@ public ElementValue getElementValue() { public String getEnumTypeString() { // Constant cc = getConstantPool().getConstant(typeIdx); // ConstantClass cu8 = - // (ConstantClass)getConstantPool().getConstant(typeIdx); + // (ConstantClass) getConstantPool().getConstant(typeIdx); // return - // ((ConstantUtf8)getConstantPool().getConstant(cu8.getNameIndex())).getBytes(); + // ((ConstantUtf8) getConstantPool().getConstant(cu8.getNameIndex())).getBytes(); return ((ConstantUtf8) getConstantPool().getConstant(typeIdx)).getBytes(); // return Utility.signatureToString(cu8.getBytes()); } @@ -100,9 +98,9 @@ public String getEnumTypeString() { public String getEnumValueString() { return ((ConstantUtf8) getConstantPool().getConstant(valueIdx)).getBytes(); // ConstantString cu8 = - // (ConstantString)getConstantPool().getConstant(valueIdx); + // (ConstantString) getConstantPool().getConstant(valueIdx); // return - // ((ConstantUtf8)getConstantPool().getConstant(cu8.getStringIndex())).getBytes(); + // ((ConstantUtf8) getConstantPool().getConstant(cu8.getStringIndex())).getBytes(); } public int getTypeIndex() { @@ -118,8 +116,8 @@ public String stringifyValue() { final ConstantUtf8 cu8 = (ConstantUtf8) getConstantPool().getConstant(valueIdx); return cu8.getBytes(); // ConstantString cu8 = - // (ConstantString)getConstantPool().getConstant(valueIdx); + // (ConstantString) getConstantPool().getConstant(valueIdx); // return - // ((ConstantUtf8)getConstantPool().getConstant(cu8.getStringIndex())).getBytes(); + // ((ConstantUtf8) getConstantPool().getConstant(cu8.getStringIndex())).getBytes(); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ExceptionThrower.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ExceptionThrower.java index 86a0cad256c..2a488c85ede 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ExceptionThrower.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ExceptionThrower.java @@ -23,7 +23,7 @@ /** * Denote an instruction that may throw a run-time or a linking exception (or both) during execution. This is not quite - * the truth as such; because all instructions may throw an java.lang.VirtualMachineError. These exceptions are omitted. + * the truth as such; because all instructions may throw a {@link VirtualMachineError}. These exceptions are omitted. * * The Lava Language Specification specifies exactly which RUN-TIME and which LINKING exceptions each * instruction may throw which is reflected by the implementers. Due to the structure of the JVM specification, it may diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGen.java index 9d1f4d41d93..30786370d29 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -40,37 +40,34 @@ * to a field (which must of course be compatible with to the declared type). * * @see Field - * @LastModified: May 2021 + * @LastModified: Sept 2025 */ public class FieldGen extends FieldGenOrMethodGen { - private static BCELComparator bcelComparator = new BCELComparator() { + private static BCELComparator bcelComparator = new BCELComparator() { @Override - public boolean equals(final Object o1, final Object o2) { - final FieldGen THIS = (FieldGen) o1; - final FieldGen THAT = (FieldGen) o2; - return Objects.equals(THIS.getName(), THAT.getName()) && Objects.equals(THIS.getSignature(), THAT.getSignature()); + public boolean equals(final FieldGen a, final FieldGen b) { + return a == b || a != null && b != null && Objects.equals(a.getName(), b.getName()) && Objects.equals(a.getSignature(), b.getSignature()); } @Override - public int hashCode(final Object o) { - final FieldGen THIS = (FieldGen) o; - return THIS.getSignature().hashCode() ^ THIS.getName().hashCode(); + public int hashCode(final FieldGen o) { + return o != null ? Objects.hash(o.getSignature(), o.getName()) : 0; } }; /** - * @return Comparison strategy object + * @return Comparison strategy object. */ - public static BCELComparator getComparator() { + public static BCELComparator getComparator() { return bcelComparator; } /** - * @param comparator Comparison strategy object + * @param comparator Comparison strategy object. */ - public static void setComparator(final BCELComparator comparator) { + public static void setComparator(final BCELComparator comparator) { bcelComparator = comparator; } @@ -81,8 +78,8 @@ public static void setComparator(final BCELComparator comparator) { /** * Instantiate from existing field. * - * @param field Field object - * @param cp constant pool (must contain the same entries as the field's constant pool) + * @param field Field object. + * @param cp constant pool (must contain the same entries as the field's constant pool). */ public FieldGen(final Field field, final ConstantPoolGen cp) { this(field.getAccessFlags(), Type.getType(field.getSignature()), field.getName(), cp); @@ -187,11 +184,11 @@ public FieldGen copy(final ConstantPoolGen cp) { */ @Override public boolean equals(final Object obj) { - return bcelComparator.equals(this, obj); + return obj instanceof FieldGen && bcelComparator.equals(this, (FieldGen) obj); } /** - * Get field object after having set up all necessary values. + * Gets field object after having set up all necessary values. */ public Field getField() { final String signature = getSignature(); @@ -207,10 +204,7 @@ public Field getField() { } public String getInitValue() { - if (value != null) { - return value.toString(); - } - return null; + return Objects.toString(value, null); } @Override @@ -219,7 +213,7 @@ public String getSignature() { } /** - * Return value as defined by given BCELComparator strategy. By default return the hashcode of the field's name XOR + * Return value as defined by given BCELComparator strategy. By default return the hash code of the field's name XOR * signature. * * @see Object#hashCode() @@ -295,7 +289,7 @@ public void setInitValue(final short s) { } /** - * Set (optional) initial value of field, otherwise it will be set to null/0/false by the JVM automatically. + * Sets (optional) initial value of field, otherwise it will be set to null/0/false by the JVM automatically. */ public void setInitValue(final String str) { checkType(ObjectType.getInstance("java.lang.String")); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGenOrMethodGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGenOrMethodGen.java index 6555392e9d4..bc1fbc8627e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGenOrMethodGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGenOrMethodGen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -30,7 +30,7 @@ /** * Super class for FieldGen and MethodGen objects, since they have some methods in common! * - * @LastModified: May 2021 + * @LastModified: Sept 2025 */ public abstract class FieldGenOrMethodGen extends AccessFlags implements NamedAndTyped, Cloneable { @@ -67,8 +67,10 @@ protected FieldGenOrMethodGen(final int accessFlags) { // TODO could this be pac super(accessFlags); } - protected void addAll(final Attribute[] attrs) { - Collections.addAll(attributeList, attrs); + protected void addAll(final Attribute[] attributes) { + if (attributes != null) { + Collections.addAll(attributeList, attributes); + } } /** @@ -93,7 +95,7 @@ public Object clone() { try { return super.clone(); } catch (final CloneNotSupportedException e) { - throw new Error("Clone Not Supported"); // never happens + throw new UnsupportedOperationException("Clone Not Supported", e); // never happens } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldOrMethod.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldOrMethod.java index 1c646f48292..87ba4cb913e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldOrMethod.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldOrMethod.java @@ -53,7 +53,6 @@ protected FieldOrMethod(final short opcode, final int index) { * generated by Java 1.5, this answer is sometimes wrong (e.g., if the "clone()" method is called on an * array). A better idea is to use the {@link #getReferenceType(ConstantPoolGen)} method, which correctly * distinguishes between class types and array types. - * */ @Deprecated public String getClassName(final ConstantPoolGen cpg) { @@ -89,6 +88,9 @@ public ObjectType getLoadClassType(final ConstantPoolGen cpg) { if (rt instanceof ObjectType) { return (ObjectType) rt; } + if (rt instanceof ArrayType) { + return Type.OBJECT; + } throw new ClassGenException(rt.getClass().getCanonicalName() + " " + rt.getSignature() + " does not represent an ObjectType"); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ICONST.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ICONST.java index 5effd7edcd9..b3eb14a9ddf 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ICONST.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ICONST.java @@ -25,7 +25,6 @@ *
  * Stack: ... -> ...,
  * 
- * */ public class ICONST extends Instruction implements ConstantPushInstruction { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEDYNAMIC.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEDYNAMIC.java index 2865a158de2..998d072e067 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEDYNAMIC.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEDYNAMIC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -37,7 +37,7 @@ * @see The * invokedynamic instruction in The Java Virtual Machine Specification * @since 6.0 - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public class INVOKEDYNAMIC extends InvokeInstruction { @@ -104,11 +104,11 @@ public Class[] getExceptions() { } /** - * Since InvokeDynamic doesn't refer to a reference type, just return java.lang.Object, as that is the only type we can + * Since InvokeDynamic doesn't refer to a reference type, just return {@link Object}, as that is the only type we can * say for sure the reference will be. * * @param cpg the ConstantPoolGen used to create the instruction - * @return an ObjectType for java.lang.Object + * @return an ObjectType for {@link Object} * @since 6.1 */ @Override diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java index 16c8e2444b4..a7124409f12 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -29,7 +29,7 @@ /** * Abstract super class for all Java byte codes. * - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public abstract class Instruction implements Cloneable { @@ -461,7 +461,7 @@ public int consumeStack(final ConstantPoolGen cpg) { public Instruction copy() { Instruction i = null; // "Constant" instruction, no need to duplicate - if (InstructionConst.getInstruction(this.getOpcode()) != null) { + if (InstructionConst.getInstruction(getOpcode()) != null) { i = this; } else { try { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionConst.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionConst.java index 439268e35eb..7b95bfc99b1 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionConst.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionConst.java @@ -170,7 +170,7 @@ public final class InstructionConst { public static final LocalVariableInstruction ISTORE_2 = new ISTORE(2); /** - * Get object via its opcode, for immutable instructions like branch instructions entries are set to null. + * Gets object via its opcode, for immutable instructions like branch instructions entries are set to null. */ static final Instruction[] INSTRUCTIONS = new Instruction[256]; diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java index 5e9220354c3..3c4b3e9f9da 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -30,11 +30,11 @@ * * @see Const * @see InstructionConst - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public class InstructionFactory { - private static class MethodObject { + private static final class MethodObject { final Type[] argTypes; final Type resultType; @@ -53,10 +53,12 @@ private static class MethodObject { private static final String FQCN_STRING_BUFFER = "java.lang.StringBuffer"; - // N.N. These must agree with the order of Constants.T_CHAR through T_LONG - private static final String[] shortNames = {"C", "F", "D", "B", "S", "I", "L"}; + /** + * These must agree with the order of Constants.T_CHAR through T_LONG. + */ + private static final String[] SHORT_NAMES = {"C", "F", "D", "B", "S", "I", "L"}; - private static final MethodObject[] appendMethodObjects = { + private static final MethodObject[] APPEND_METHOD_OBJECTS = { new MethodObject(FQCN_STRING_BUFFER, APPEND, Type.STRINGBUFFER, new Type[] { Type.STRING }), new MethodObject(FQCN_STRING_BUFFER, APPEND, Type.STRINGBUFFER, new Type[] { Type.OBJECT }), null, null, // indices 2, 3 new MethodObject(FQCN_STRING_BUFFER, APPEND, Type.STRINGBUFFER, new Type[] { Type.BOOLEAN }), @@ -484,7 +486,7 @@ public InstructionFactory(final ConstantPoolGen cp) { public Instruction createAppend(final Type type) { final byte t = type.getType(); if (isString(type)) { - return createInvoke(appendMethodObjects[0], Const.INVOKEVIRTUAL); + return createInvoke(APPEND_METHOD_OBJECTS[0], Const.INVOKEVIRTUAL); } switch (t) { case Const.T_BOOLEAN: @@ -495,10 +497,10 @@ public Instruction createAppend(final Type type) { case Const.T_SHORT: case Const.T_INT: case Const.T_LONG: - return createInvoke(appendMethodObjects[t], Const.INVOKEVIRTUAL); + return createInvoke(APPEND_METHOD_OBJECTS[t], Const.INVOKEVIRTUAL); case Const.T_ARRAY: case Const.T_OBJECT: - return createInvoke(appendMethodObjects[1], Const.INVOKEVIRTUAL); + return createInvoke(APPEND_METHOD_OBJECTS[1], Const.INVOKEVIRTUAL); default: throw new IllegalArgumentException("No append for this type? " + type); } @@ -515,7 +517,7 @@ public Instruction createCast(final Type srcType, final Type destType) { if (dest == Const.T_LONG && (src == Const.T_CHAR || src == Const.T_BYTE || src == Const.T_SHORT)) { src = Const.T_INT; } - final String name = "com.sun.org.apache.bcel.internal.generic." + shortNames[src - Const.T_CHAR] + "2" + shortNames[dest - Const.T_CHAR]; + final String name = "com.sun.org.apache.bcel.internal.generic." + SHORT_NAMES[src - Const.T_CHAR] + "2" + SHORT_NAMES[dest - Const.T_CHAR]; Instruction i = null; try { i = (Instruction) Class.forName(name).getDeclaredConstructor().newInstance();; @@ -642,8 +644,10 @@ public InvokeInstruction createInvoke(final String className, final String name, int index; int nargs = 0; final String signature = Type.getMethodSignature(retType, argTypes); - for (final Type argType : argTypes) { - nargs += argType.getSize(); + if (argTypes != null) { + for (final Type argType : argTypes) { + nargs += argType.getSize(); + } } if (useInterface) { index = cp.addInterfaceMethodref(className, name, signature); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionHandle.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionHandle.java index 5e962354d16..2c94b770265 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionHandle.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionHandle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -38,7 +38,7 @@ * @see Instruction * @see BranchHandle * @see InstructionList - * @LastModified: May 2021 + * @LastModified: Sept 2025 */ public class InstructionHandle { @@ -118,7 +118,7 @@ public void addTargeter(final InstructionTargeter t) { if (targeters == null) { targeters = new HashSet<>(); } - // if(!targeters.contains(t)) + // if (!targeters.contains(t)) targeters.add(t); } @@ -135,15 +135,12 @@ void dispose() { } /** - * Get attribute of an instruction handle. + * Gets attribute of an instruction handle. * * @param key the key object to store/retrieve the attribute */ public Object getAttribute(final Object key) { - if (attributes != null) { - return attributes.get(key); - } - return null; + return attributes != null ? attributes.get(key) : null; } /** @@ -247,7 +244,7 @@ final InstructionHandle setNext(final InstructionHandle next) { } /** - * Set the position, i.e., the byte code offset of the contained instruction. + * Sets the position, i.e., the byte code offset of the contained instruction. */ void setPosition(final int pos) { i_position = pos; diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java index 7ffc3a8228e..579efc9fe3b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -33,6 +33,7 @@ import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.classfile.Constant; import com.sun.org.apache.bcel.internal.util.ByteSequence; +import jdk.xml.internal.Utils; /** * This class is a container for a list of Instruction objects. Instructions can be @@ -46,7 +47,7 @@ * @see Instruction * @see InstructionHandle * @see BranchHandle - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public class InstructionList implements Iterable { @@ -60,23 +61,25 @@ public class InstructionList implements Iterable { * @return target position's instruction handle if available */ public static InstructionHandle findHandle(final InstructionHandle[] ihs, final int[] pos, final int count, final int target) { - int l = 0; - int r = count - 1; - /* - * Do a binary search since the pos array is orderd. - */ - do { - final int i = l + r >>> 1; - final int j = pos[i]; - if (j == target) { - return ihs[i]; - } - if (target < j) { - r = i - 1; - } else { - l = i + 1; - } - } while (l <= r); + if (ihs != null && pos != null) { + int l = 0; + int r = count - 1; + /* + * Do a binary search since the pos array is orderd. + */ + do { + final int i = l + r >>> 1; + final int j = pos[i]; + if (j == target) { + return ihs[i]; + } + if (target < j) { + r = i - 1; + } else { + l = i + 1; + } + } while (l <= r); + } return null; } @@ -513,7 +516,7 @@ public void dispose() { } /** - * Get instruction handle for instruction at byte code position pos. This only works properly, if the list is freshly + * Gets instruction handle for instruction at byte code position pos. This only works properly, if the list is freshly * initialized from a byte array or setPositions() has been called before this method. * * @param pos byte code position to search for @@ -605,7 +608,7 @@ public InstructionHandle[] getInstructionHandles() { } /** - * Get positions (offsets) of all instructions in the list. This relies on that the list has been freshly created from + * Gets positions (offsets) of all instructions in the list. This relies on that the list has been freshly created from * an byte code array, or that setPositions() has been called. Otherwise this may be inaccurate. * * @return array containing all instruction's offset in byte code @@ -959,7 +962,7 @@ public void redirectBranches(final InstructionHandle oldTarget, final Instructio * @see MethodGen */ public void redirectExceptionHandlers(final CodeExceptionGen[] exceptions, final InstructionHandle oldTarget, final InstructionHandle newTarget) { - for (final CodeExceptionGen exception : exceptions) { + Utils.streamOfIfNonNull(exceptions).forEach(exception -> { if (exception.getStartPC() == oldTarget) { exception.setStartPC(newTarget); } @@ -969,7 +972,7 @@ public void redirectExceptionHandlers(final CodeExceptionGen[] exceptions, final if (exception.getHandlerPC() == oldTarget) { exception.setHandlerPC(newTarget); } - } + }); } /** @@ -981,16 +984,14 @@ public void redirectExceptionHandlers(final CodeExceptionGen[] exceptions, final * @see MethodGen */ public void redirectLocalVariables(final LocalVariableGen[] lg, final InstructionHandle oldTarget, final InstructionHandle newTarget) { - for (final LocalVariableGen element : lg) { - final InstructionHandle start = element.getStart(); - final InstructionHandle end = element.getEnd(); - if (start == oldTarget) { + Utils.streamOfIfNonNull(lg).forEach(element -> { + if (element.getStart() == oldTarget) { element.setStart(newTarget); } - if (end == oldTarget) { + if (element.getEnd() == oldTarget) { element.setEnd(newTarget); } - } + }); } /** @@ -1120,7 +1121,7 @@ public void setPositions(final boolean check) { // called by code in other packa ih.setPosition(index); pos[count++] = index; /* - * Get an estimate about how many additional bytes may be added, because BranchInstructions may have variable length + * Gets an estimate about how many additional bytes may be added, because BranchInstructions may have variable length * depending on the target offset (short vs. int) or alignment issues (TABLESWITCH and LOOKUPSWITCH). */ switch (i.getOpcode()) { @@ -1132,11 +1133,14 @@ public void setPositions(final boolean check) { // called by code in other packa case Const.LOOKUPSWITCH: maxAdditionalBytes += 3; break; + default: + // TODO should this be an error? + break; } index += i.getLength(); } /* - * Pass 2: Expand the variable-length (Branch)Instructions depending on the target offset (short or int) and ensure that + * Pass 2: Expand the variable-length (Branch) Instructions depending on the target offset (short or int) and ensure that * branch targets are within this list. */ for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) { @@ -1152,8 +1156,7 @@ public void setPositions(final boolean check) { // called by code in other packa pos[count++] = index; index += i.getLength(); } - bytePositions = new int[count]; // Trim to proper size - System.arraycopy(pos, 0, bytePositions, 0, count); + bytePositions = Arrays.copyOfRange(pos, 0, count); // Trim to proper size } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionTargeter.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionTargeter.java index 5146408ef49..0681476b5ee 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionTargeter.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionTargeter.java @@ -22,7 +22,7 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Denote that a class targets InstructionHandles within an InstructionList. Namely the following implementers: + * Denotes that a class targets InstructionHandles within an InstructionList. * * @see BranchHandle * @see LocalVariableGen @@ -33,9 +33,12 @@ public interface InstructionTargeter { // static final InstructionTargeter[] EMPTY_ARRAY = new InstructionTargeter[0]; /** - * Checks whether this targeter targets the specified instruction handle. + * Tests whether this targeter targets the specified instruction handle. + * + * @param instructionHandle the instruction handle to test. + * @return whether this targeter targets the specified instruction handle. */ - boolean containsTarget(InstructionHandle ih); + boolean containsTarget(InstructionHandle instructionHandle); /** * Replaces the target of this targeter from this old handle to the new handle. diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCMP.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCMP.java index c517b492f0a..188ac95f6ef 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCMP.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCMP.java @@ -27,7 +27,6 @@ *
  * Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -> ..., result <= -1, 0, 1>
  * 
- * */ public class LCMP extends Instruction implements TypedInstruction, StackProducer, StackConsumer { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC.java index d95bade23bd..13ca0a84cfa 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC.java @@ -94,6 +94,8 @@ public Type getType(final ConstantPoolGen cpg) { return Type.INT; case com.sun.org.apache.bcel.internal.Const.CONSTANT_Class: return Type.CLASS; + case com.sun.org.apache.bcel.internal.Const.CONSTANT_Dynamic: + return Type.OBJECT; default: // Never reached throw new IllegalArgumentException("Unknown or invalid constant type at " + super.getIndex()); } @@ -113,7 +115,10 @@ public Object getValue(final ConstantPoolGen cpg) { case com.sun.org.apache.bcel.internal.Const.CONSTANT_Class: final int nameIndex = ((com.sun.org.apache.bcel.internal.classfile.ConstantClass) c).getNameIndex(); c = cpg.getConstantPool().getConstant(nameIndex); - return Type.getType(((com.sun.org.apache.bcel.internal.classfile.ConstantUtf8) c).getBytes()); + return Type.getType(Type.internalTypeNameToSignature(((com.sun.org.apache.bcel.internal.classfile.ConstantUtf8) c).getBytes())); + case com.sun.org.apache.bcel.internal.Const.CONSTANT_Dynamic: + // Really not sure what to return here, maybe a BootstrapMethod instance but how do we get it? + return c; default: // Never reached throw new IllegalArgumentException("Unknown or invalid constant type at " + super.getIndex()); } @@ -129,7 +134,7 @@ protected void initFromFile(final ByteSequence bytes, final boolean wide) throws } /** - * Set the index to constant pool and adjust size. + * Sets the index to constant pool and adjust size. */ @Override public final void setIndex(final int index) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java index 3773c21e7b3..68bb2abf513 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java @@ -54,7 +54,7 @@ public Object clone() { try { return super.clone(); } catch (final CloneNotSupportedException e) { - throw new Error("Clone Not Supported"); // never happens + throw new UnsupportedOperationException("Clone Not Supported", e); // never happens } } @@ -71,7 +71,7 @@ public InstructionHandle getInstruction() { } /** - * Get LineNumber attribute. + * Gets LineNumber attribute. * * This relies on that the instruction list has already been dumped to byte code or that the 'setPositions' methods * has been called for the instruction list. diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java index 830564d42c9..71cfa0cf1c2 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java @@ -85,7 +85,7 @@ public Object clone() { try { return super.clone(); } catch (final CloneNotSupportedException e) { - throw new Error("Clone Not Supported"); // never happens + throw new UnsupportedOperationException("Clone Not Supported", e); // never happens } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableInstruction.java index 67184c0b9f1..f952a65880b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -28,7 +28,7 @@ /** * Abstract super class for instructions dealing with local variables. * - * @LastModified: May 2021 + * @LastModified: Sept 2025 */ public abstract class LocalVariableInstruction extends Instruction implements TypedInstruction, IndexedInstruction { @@ -162,7 +162,7 @@ protected void initFromFile(final ByteSequence bytes, final boolean wide) throws } /** - * Set the local variable index. also updates opcode and length TODO Why? + * Sets the local variable index. also updates opcode and length TODO Why? * * @see #setIndexOnly(int) */ diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodGen.java index f6e8333be79..be09b0a5159 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodGen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -27,6 +27,7 @@ import java.util.List; import java.util.Objects; import java.util.Stack; +import java.util.stream.Collectors; import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.classfile.AnnotationEntry; @@ -46,6 +47,7 @@ import com.sun.org.apache.bcel.internal.classfile.RuntimeVisibleParameterAnnotations; import com.sun.org.apache.bcel.internal.classfile.Utility; import com.sun.org.apache.bcel.internal.util.BCELComparator; +import jdk.xml.internal.Utils; /** * Template class for building up a method. This is done by defining exception handlers, adding thrown exceptions, local @@ -57,7 +59,7 @@ * * @see InstructionList * @see Method - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public class MethodGen extends FieldGenOrMethodGen { @@ -102,19 +104,16 @@ static final class BranchTarget { } } - private static BCELComparator bcelComparator = new BCELComparator() { + private static BCELComparator bcelComparator = new BCELComparator() { @Override - public boolean equals(final Object o1, final Object o2) { - final FieldGenOrMethodGen THIS = (FieldGenOrMethodGen) o1; - final FieldGenOrMethodGen THAT = (FieldGenOrMethodGen) o2; - return Objects.equals(THIS.getName(), THAT.getName()) && Objects.equals(THIS.getSignature(), THAT.getSignature()); + public boolean equals(final FieldGenOrMethodGen a, final FieldGenOrMethodGen b) { + return a == b || a != null && b != null && Objects.equals(a.getName(), b.getName()) && Objects.equals(a.getSignature(), b.getSignature()); } @Override - public int hashCode(final Object o) { - final FieldGenOrMethodGen THIS = (FieldGenOrMethodGen) o; - return THIS.getSignature().hashCode() ^ THIS.getName().hashCode(); + public int hashCode(final FieldGenOrMethodGen o) { + return o != null ? Objects.hash(o.getSignature(), o.getName()) : 0; } }; @@ -127,9 +126,9 @@ private static byte[] getByteCodes(final Method method) { } /** - * @return Comparison strategy object + * @return Comparison strategy object. */ - public static BCELComparator getComparator() { + public static BCELComparator getComparator() { return bcelComparator; } @@ -206,9 +205,9 @@ public static int getMaxStack(final ConstantPoolGen cp, final InstructionList il } /** - * @param comparator Comparison strategy object + * @param comparator Comparison strategy object. */ - public static void setComparator(final BCELComparator comparator) { + public static void setComparator(final BCELComparator comparator) { bcelComparator = comparator; } @@ -636,7 +635,7 @@ private void ensureExistingParameterAnnotationsUnpacked() { */ @Override public boolean equals(final Object obj) { - return bcelComparator.equals(this, obj); + return obj instanceof FieldGenOrMethodGen && bcelComparator.equals(this, (FieldGenOrMethodGen) obj); } // J5TODO: Should paramAnnotations be an array of arrays? Rather than an array of lists, this @@ -790,7 +789,7 @@ public int getMaxStack() { } /** - * Get method object. Never forget to call setMaxStack() or setMaxStack(max), respectively, before calling this method + * Gets method object. Never forget to call setMaxStack() or setMaxStack(max), respectively, before calling this method * (the same applies for max locals). * * @return method object @@ -888,7 +887,7 @@ public String getSignature() { } /** - * Return value as defined by given BCELComparator strategy. By default return the hashcode of the method's name XOR + * Return value as defined by given BCELComparator strategy. By default return the hash code of the method's name XOR * signature. * * @see Object#hashCode() @@ -899,11 +898,7 @@ public int hashCode() { } private List makeMutableVersion(final AnnotationEntry[] mutableArray) { - final List result = new ArrayList<>(); - for (final AnnotationEntry element : mutableArray) { - result.add(new AnnotationEntryGen(element, getConstantPool(), false)); - } - return result; + return Utils.streamOfIfNonNull(mutableArray).map(ae -> new AnnotationEntryGen(ae, getConstantPool(), false)).collect(Collectors.toList()); } /** @@ -1027,10 +1022,8 @@ public void removeObserver(final MethodObserver o) { * * @since 6.5.0 */ - public void removeRuntimeAttributes(final Attribute[] attrs) { - for (final Attribute attr : attrs) { - removeAttribute(attr); - } + public void removeRuntimeAttributes(final Attribute[] attributes) { + Utils.streamOfIfNonNull(attributes).forEach(this::removeAttribute); } public void setArgumentName(final int i, final String name) { @@ -1038,7 +1031,7 @@ public void setArgumentName(final int i, final String name) { } public void setArgumentNames(final String[] argNames) { - this.argNames = argNames; + this.argNames = Utils.createEmptyArrayIfNull(argNames, String[].class); } public void setArgumentType(final int i, final Type type) { @@ -1046,7 +1039,7 @@ public void setArgumentType(final int i, final Type type) { } public void setArgumentTypes(final Type[] argTypes) { - this.argTypes = argTypes; + this.argTypes = argTypes != null ? argTypes : Type.NO_ARGS; } public void setClassName(final String className) { // TODO could be package-protected? @@ -1084,7 +1077,7 @@ public void setMaxLocals() { // TODO could be package-protected? (some tests wou } /** - * Set maximum number of local variables. + * Sets maximum number of local variables. */ public void setMaxLocals(final int m) { maxLocals = m; @@ -1102,7 +1095,7 @@ public void setMaxStack() { // TODO could be package-protected? (some tests woul } /** - * Set maximum stack size for this method. + * Sets maximum stack size for this method. */ public void setMaxStack(final int m) { // TODO could be package-protected? maxStack = m; diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ObjectType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ObjectType.java index 46378a1b71e..622a3cdd961 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ObjectType.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ObjectType.java @@ -27,7 +27,7 @@ import com.sun.org.apache.bcel.internal.classfile.Utility; /** - * Denotes reference such as java.lang.String. + * Denotes reference such as {@link String}. */ public class ObjectType extends ReferenceType { @@ -47,7 +47,7 @@ public static ObjectType getInstance(final String className) { /** * Constructs a new instance. * - * @param className fully qualified class name, e.g. java.lang.String + * @param className fully qualified class name, e.g. {@link String} */ public ObjectType(final String className) { super(Const.T_REFERENCE, "L" + Utility.packageToPath(className) + ";"); @@ -151,7 +151,7 @@ public boolean referencesInterfaceExact() throws ClassNotFoundException { * @throws ClassNotFoundException if any of this class's superclasses can't be found */ public boolean subclassOf(final ObjectType superclass) throws ClassNotFoundException { - if (this.referencesInterfaceExact() || superclass.referencesInterfaceExact()) { + if (referencesInterfaceExact() || superclass.referencesInterfaceExact()) { return false; } return Repository.instanceOf(this.className, superclass.className); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RET.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RET.java index a7cacc7c165..99a1efbed16 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RET.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RET.java @@ -110,7 +110,7 @@ protected void initFromFile(final ByteSequence bytes, final boolean wide) throws } /** - * Set index of local variable containg the return address + * Sets index of local variable containg the return address */ @Override public final void setIndex(final int n) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReferenceType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReferenceType.java index fe75792e213..9b94a1dcf2d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReferenceType.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReferenceType.java @@ -42,10 +42,10 @@ protected ReferenceType(final byte t, final String s) { /** * This commutative operation returns the first common superclass (narrowest ReferenceType referencing a class, not an - * interface). If one of the types is a superclass of the other, the former is returned. If "this" is Type.NULL, then t - * is returned. If t is Type.NULL, then "this" is returned. If "this" equals t ['this.equals(t)'] "this" is returned. If - * "this" or t is an ArrayType, then Type.OBJECT is returned. If "this" or t is a ReferenceType referencing an - * interface, then Type.OBJECT is returned. If not all of the two classes' superclasses cannot be found, "null" is + * interface). If one of the types is a superclass of the other, the former is returned. If "this" is NULL, then t + * is returned. If t is NULL, then "this" is returned. If "this" equals t ['this.equals(t)'] "this" is returned. If + * "this" or t is an ArrayType, then {@link #OBJECT} is returned. If "this" or t is a ReferenceType referencing an + * interface, then {@link #OBJECT} is returned. If not all of the two classes' superclasses cannot be found, "null" is * returned. See the JVM specification edition 2, "4.9.2 The Bytecode Verifier". * * @deprecated use getFirstCommonSuperclass(ReferenceType t) which has slightly changed semantics. @@ -53,46 +53,46 @@ protected ReferenceType(final byte t, final String s) { */ @Deprecated public ReferenceType firstCommonSuperclass(final ReferenceType t) throws ClassNotFoundException { - if (this.equals(Type.NULL)) { + if (equals(NULL)) { return t; } - if (t.equals(Type.NULL) || this.equals(t)) { + if (t.equals(NULL) || equals(t)) { return this; /* - * TODO: Above sounds a little arbitrary. On the other hand, there is no object referenced by Type.NULL so we can also - * say all the objects referenced by Type.NULL were derived from java.lang.Object. However, the Java Language's - * "instanceof" operator proves us wrong: "null" is not referring to an instance of java.lang.Object :) + * TODO: Above sounds a little arbitrary. On the other hand, there is no object referenced by {@link #NULL} so we can also + * say all the objects referenced by {@link #NULL} were derived from {@link Object}. However, the Java Language's + * "instanceof" operator proves us wrong: "null" is not referring to an instance of {@link Object} :) */ } if (this instanceof ArrayType || t instanceof ArrayType) { - return Type.OBJECT; - // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType? + return OBJECT; + // TODO: Is there a proof of {@link #OBJECT} being the direct ancestor of every ArrayType? } return getFirstCommonSuperclassInternal(t); } /** * This commutative operation returns the first common superclass (narrowest ReferenceType referencing a class, not an - * interface). If one of the types is a superclass of the other, the former is returned. If "this" is Type.NULL, then t - * is returned. If t is Type.NULL, then "this" is returned. If "this" equals t ['this.equals(t)'] "this" is returned. If - * "this" or t is an ArrayType, then Type.OBJECT is returned; unless their dimensions match. Then an ArrayType of the + * interface). If one of the types is a superclass of the other, the former is returned. If "this" is NULL, then t + * is returned. If t is NULL, then "this" is returned. If "this" equals t ['this.equals(t)'] "this" is returned. If + * "this" or t is an ArrayType, then {@link #OBJECT} is returned; unless their dimensions match. Then an ArrayType of the * same number of dimensions is returned, with its basic type being the first common super class of the basic types of - * "this" and t. If "this" or t is a ReferenceType referencing an interface, then Type.OBJECT is returned. If not all of + * "this" and t. If "this" or t is a ReferenceType referencing an interface, then {@link #OBJECT} is returned. If not all of * the two classes' superclasses cannot be found, "null" is returned. See the JVM specification edition 2, "4.9.2 The * Bytecode Verifier". * * @throws ClassNotFoundException on failure to find superclasses of this type, or the type passed as a parameter */ public ReferenceType getFirstCommonSuperclass(final ReferenceType t) throws ClassNotFoundException { - if (this.equals(Type.NULL)) { + if (equals(NULL)) { return t; } - if (t.equals(Type.NULL) || this.equals(t)) { + if (t.equals(NULL) || equals(t)) { return this; /* - * TODO: Above sounds a little arbitrary. On the other hand, there is no object referenced by Type.NULL so we can also - * say all the objects referenced by Type.NULL were derived from java.lang.Object. However, the Java Language's - * "instanceof" operator proves us wrong: "null" is not referring to an instance of java.lang.Object :) + * TODO: Above sounds a little arbitrary. On the other hand, there is no object referenced by {@link #NULL} so we can also + * say all the objects referenced by {@link #NULL} were derived from {@link Object}. However, the Java Language's + * "instanceof" operator proves us wrong: "null" is not referring to an instance of {@link Object} :) */ } /* This code is from a bug report by Konstantin Shagin */ @@ -106,8 +106,8 @@ public ReferenceType getFirstCommonSuperclass(final ReferenceType t) throws Clas } } if (this instanceof ArrayType || t instanceof ArrayType) { - return Type.OBJECT; - // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType? + return OBJECT; + // TODO: Is there a proof of {@link #OBJECT} being the direct ancestor of every ArrayType? } return getFirstCommonSuperclassInternal(t); } @@ -115,7 +115,7 @@ public ReferenceType getFirstCommonSuperclass(final ReferenceType t) throws Clas private ReferenceType getFirstCommonSuperclassInternal(final ReferenceType t) throws ClassNotFoundException { if (this instanceof ObjectType && ((ObjectType) this).referencesInterfaceExact() || t instanceof ObjectType && ((ObjectType) t).referencesInterfaceExact()) { - return Type.OBJECT; + return OBJECT; // TODO: The above line is correct comparing to the vmspec2. But one could // make class file verification a bit stronger here by using the notion of // superinterfaces or even castability or assignment compatibility. @@ -142,7 +142,7 @@ private ReferenceType getFirstCommonSuperclassInternal(final ReferenceType t) th } } } - // Huh? Did you ask for Type.OBJECT's superclass?? + // Huh? Did you ask for OBJECT's superclass?? return null; } @@ -158,7 +158,7 @@ public boolean isAssignmentCompatibleWith(final Type t) throws ClassNotFoundExce return false; } final ReferenceType T = (ReferenceType) t; - if (this.equals(Type.NULL)) { + if (equals(NULL)) { return true; // This is not explicitly stated, but clear. Isn't it? } /* @@ -169,7 +169,7 @@ public boolean isAssignmentCompatibleWith(final Type t) throws ClassNotFoundExce * If T is a class type, then this must be the same class as T, or this must be a subclass of T; */ if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact() - && (this.equals(T) || Repository.instanceOf(((ObjectType) this).getClassName(), ((ObjectType) T).getClassName()))) { + && (equals(T) || Repository.instanceOf(((ObjectType) this).getClassName(), ((ObjectType) T).getClassName()))) { return true; } /* @@ -187,14 +187,14 @@ public boolean isAssignmentCompatibleWith(final Type t) throws ClassNotFoundExce /* * If T is a class type, then T must be Object (2.4.7). */ - if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact() && T.equals(Type.OBJECT)) { + if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact() && T.equals(OBJECT)) { return true; } /* * If T is an interface type, then T must be the same interface as this or a superinterface of this (2.13.2). */ if (T instanceof ObjectType && ((ObjectType) T).referencesInterfaceExact() - && (this.equals(T) || Repository.implementationOf(((ObjectType) this).getClassName(), ((ObjectType) T).getClassName()))) { + && (equals(T) || Repository.implementationOf(((ObjectType) this).getClassName(), ((ObjectType) T).getClassName()))) { return true; } } @@ -205,7 +205,7 @@ public boolean isAssignmentCompatibleWith(final Type t) throws ClassNotFoundExce /* * If T is a class type, then T must be Object (2.4.7). */ - if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact() && T.equals(Type.OBJECT)) { + if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact() && T.equals(OBJECT)) { return true; } /* @@ -246,14 +246,14 @@ public boolean isAssignmentCompatibleWith(final Type t) throws ClassNotFoundExce /** * Return true iff this type is castable to another type t as defined in the JVM specification. The case where this is - * Type.NULL is not defined (see the CHECKCAST definition in the JVM specification). However, because e.g. CHECKCAST + * {@link #NULL} is not defined (see the CHECKCAST definition in the JVM specification). However, because e.g. CHECKCAST * doesn't throw a ClassCastException when casting a null reference to any Object, true is returned in this case. * * @throws ClassNotFoundException if any classes or interfaces required to determine assignment compatibility can't be * found */ public boolean isCastableTo(final Type t) throws ClassNotFoundException { - if (this.equals(Type.NULL)) { + if (equals(NULL)) { return t instanceof ReferenceType; // If this is ever changed in isAssignmentCompatible() } return isAssignmentCompatibleWith(t); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWITCH.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWITCH.java index aed1626ec0d..f929176c174 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWITCH.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWITCH.java @@ -95,7 +95,7 @@ public SWITCH(final int[] match, final InstructionHandle[] targets, final Instru * @param maxGap maximum gap that may between case branches */ public SWITCH(final int[] match, final InstructionHandle[] targets, final InstructionHandle target, final int maxGap) { - int[] matchClone = match.clone(); + final int[] matchClone = match.clone(); final InstructionHandle[] targetsClone = targets.clone(); final int matchLength = match.length; if (matchLength < 2) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Select.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Select.java index a90e795e99f..a3086ac1664 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Select.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Select.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -33,7 +33,7 @@ * @see LOOKUPSWITCH * @see TABLESWITCH * @see InstructionList - * @LastModified: May 2021 + * @LastModified: Sept 2025 */ public abstract class Select extends BranchInstruction implements VariableLengthInstruction, StackConsumer /* @since 6.0 */, StackProducer { @@ -87,7 +87,7 @@ public abstract class Select extends BranchInstruction implements VariableLength * @param defaultTarget default instruction target */ Select(final short opcode, final int[] match, final InstructionHandle[] targets, final InstructionHandle defaultTarget) { - // don't set default target before instuction is built + // don't set default target before instruction is built super(opcode, null); this.match = match; this.targets = targets; @@ -288,7 +288,7 @@ final int setMatchLength(final int matchLength) { } /** - * Set branch target for 'i'th case + * Sets branch target for 'i'th case */ public void setTarget(final int i, final InstructionHandle target) { // TODO could be package-protected? notifyTarget(targets[i], target, this); @@ -314,7 +314,11 @@ public String toString(final boolean verbose) { for (int i = 0; i < match_length; i++) { String s = "null"; if (targets[i] != null) { - s = targets[i].getInstruction().toString(); + if (targets[i].getInstruction() == this) { + s = ""; + } else { + s = targets[i].getInstruction().toString(); + } } buf.append("(").append(match[i]).append(", ").append(s).append(" = {").append(indices[i]).append("})"); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SimpleElementValueGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SimpleElementValueGen.java index a4de20315d7..363b3237632 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SimpleElementValueGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SimpleElementValueGen.java @@ -166,7 +166,7 @@ public void dump(final DataOutputStream dos) throws IOException { dos.writeShort(idx); break; default: - throw new IllegalStateException("SimpleElementValueGen doesnt know how to write out type " + super.getElementValueType()); + throw new IllegalStateException("SimpleElementValueGen doesn't know how to write out type " + super.getElementValueType()); } } @@ -184,7 +184,7 @@ public int getIndex() { public int getValueInt() { if (super.getElementValueType() != PRIMITIVE_INT) { - throw new IllegalStateException("Dont call getValueString() on a non STRING ElementValue"); + throw new IllegalStateException("Don't call getValueString() on a non STRING ElementValue"); } final ConstantInteger c = (ConstantInteger) getConstantPool().getConstant(idx); return c.getBytes(); @@ -192,7 +192,7 @@ public int getValueInt() { public String getValueString() { if (super.getElementValueType() != STRING) { - throw new IllegalStateException("Dont call getValueString() on a non STRING ElementValue"); + throw new IllegalStateException("Don't call getValueString() on a non STRING ElementValue"); } final ConstantUtf8 c = (ConstantUtf8) getConstantPool().getConstant(idx); return c.getBytes(); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TargetLostException.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TargetLostException.java index 40ed6ff4c38..038bbe63148 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TargetLostException.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TargetLostException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -21,32 +21,32 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Thrown by InstructionList.remove() when one or multiple disposed instructions are still being referenced by an - * InstructionTargeter object. I.e. the InstructionTargeter has to be notified that (one of) the InstructionHandle it is - * referencing is being removed from the InstructionList and thus not valid anymore. + * Thrown by {@link InstructionList} when one or multiple disposed instructions are still being referenced by an {@link InstructionTargeter} object. I.e. the + * {@link InstructionTargeter} has to be notified that (one of) the {@link InstructionHandle} it is referencing is being removed from the + * {@link InstructionList} and thus not valid anymore. * *

- * Making this an exception instead of a return value forces the user to handle these case explicitly in a try { ... } - * catch. The following code illustrates how this may be done: + * Making this an exception instead of a return value forces the user to handle these case explicitly in a try { ... } catch. The following code illustrates how + * this may be done: *

* - *
+ * 
  *     ...
  *     try {
  *         il.delete(start_ih, end_ih);
- *     } catch(TargetLostException e) {
+ *     } catch (TargetLostException e) {
  *         for (InstructionHandle target : e.getTargets()) {
  *             for (InstructionTargeter targeter : target.getTargeters()) {
  *                 targeter.updateTarget(target, new_target);
  *             }
  *         }
  *     }
- * 
+ *
* * @see InstructionHandle * @see InstructionList * @see InstructionTargeter - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public final class TargetLostException extends Exception { @@ -54,12 +54,14 @@ public final class TargetLostException extends Exception { @SuppressWarnings("serial") // Array component type is not Serializable private final InstructionHandle[] targets; - TargetLostException(final InstructionHandle[] t, final String mesg) { - super(mesg); - targets = t; + TargetLostException(final InstructionHandle[] targets, final String message) { + super(message); + this.targets = targets; } /** + * Gets the list of instructions still being targeted. + * * @return list of instructions still being targeted. */ public InstructionHandle[] getTargets() { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Type.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Type.java index ea20710af2e..b58645b402e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Type.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Type.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -26,12 +26,14 @@ import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.classfile.ClassFormatException; +import com.sun.org.apache.bcel.internal.classfile.InvalidMethodSignatureException; import com.sun.org.apache.bcel.internal.classfile.Utility; +import jdk.xml.internal.Utils; /** - * Abstract super class for all possible java types, namely basic types such as int, object types like String and array + * Abstract super class for all possible Java types, namely basic types such as int, object types like String and array * types, e.g. int[] - * @LastModified: May 2021 + * @LastModified: Sept 2025 */ public abstract class Type { @@ -88,15 +90,15 @@ public static Type[] getArgumentTypes(final String signature) { // Skip any type arguments to read argument declarations between '(' and ')' index = signature.indexOf('(') + 1; if (index <= 0) { - throw new ClassFormatException("Invalid method signature: " + signature); + throw new InvalidMethodSignatureException(signature); } while (signature.charAt(index) != ')') { vec.add(getType(signature.substring(index))); - // corrected concurrent private static field acess + // corrected concurrent private static field access index += unwrap(CONSUMED_CHARS); // update position } } catch (final StringIndexOutOfBoundsException e) { // Should never occur - throw new ClassFormatException("Invalid method signature: " + signature, e); + throw new InvalidMethodSignatureException(signature, e); } final Type[] types = new Type[vec.size()]; vec.toArray(types); @@ -110,7 +112,7 @@ static int getArgumentTypesSize(final String signature) { // Skip any type arguments to read argument declarations between '(' and ')' index = signature.indexOf('(') + 1; if (index <= 0) { - throw new ClassFormatException("Invalid method signature: " + signature); + throw new InvalidMethodSignatureException(signature); } while (signature.charAt(index) != ')') { final int coded = getTypeSize(signature.substring(index)); @@ -118,7 +120,7 @@ static int getArgumentTypesSize(final String signature) { index += consumed(coded); } } catch (final StringIndexOutOfBoundsException e) { // Should never occur - throw new ClassFormatException("Invalid method signature: " + signature, e); + throw new InvalidMethodSignatureException(signature, e); } return res; } @@ -154,13 +156,13 @@ public static Type getReturnType(final String signature) { final int index = signature.lastIndexOf(')') + 1; return getType(signature.substring(index)); } catch (final StringIndexOutOfBoundsException e) { // Should never occur - throw new ClassFormatException("Invalid method signature: " + signature, e); + throw new InvalidMethodSignatureException(signature, e); } } static int getReturnTypeSize(final String signature) { final int index = signature.lastIndexOf(')') + 1; - return Type.size(getTypeSize(signature.substring(index))); + return size(getTypeSize(signature.substring(index))); } public static String getSignature(final java.lang.reflect.Method meth) { @@ -175,7 +177,7 @@ public static String getSignature(final java.lang.reflect.Method meth) { } /** - * Convert runtime java.lang.Class to BCEL Type object. + * Convert runtime {@link Class} to BCEL Type object. * * @param cls Java class * @return corresponding Type object @@ -183,7 +185,7 @@ public static String getSignature(final java.lang.reflect.Method meth) { public static Type getType(final Class cls) { Objects.requireNonNull(cls, "cls"); /* - * That's an amzingly easy case, because getName() returns the signature. That's what we would have liked anyway. + * That's an amazingly easy case, because getName() returns the signature. That's what we would have liked anyway. */ if (cls.isArray()) { return getType(cls.getName()); @@ -230,7 +232,7 @@ public static Type getType(final Class cls) { public static Type getType(final String signature) throws StringIndexOutOfBoundsException { final byte type = Utility.typeOfSignature(signature); if (type <= Const.T_VOID) { - // corrected concurrent private static field acess + // corrected concurrent private static field access wrap(CONSUMED_CHARS, 1); return BasicType.getType(type); } @@ -246,7 +248,7 @@ public static Type getType(final String signature) throws StringIndexOutOfBounds } while (signature.charAt(dim) == '['); // Recurse, but just once, if the signature is ok final Type t = getType(signature.substring(dim)); - // corrected concurrent private static field acess + // corrected concurrent private static field access // consumed_chars += dim; // update counter - is replaced by final int temp = unwrap(CONSUMED_CHARS) + dim; wrap(CONSUMED_CHARS, temp); @@ -254,7 +256,7 @@ public static Type getType(final String signature) throws StringIndexOutOfBounds } /** - * Convert runtime java.lang.Class[] to BCEL Type objects. + * Convert runtime {@code java.lang.Class[]} to BCEL Type objects. * * @param classes an array of runtime class objects * @return array of corresponding Type objects @@ -286,6 +288,24 @@ static int getTypeSize(final String signature) throws StringIndexOutOfBoundsExce return encode(1, index + 1); } + static String internalTypeNameToSignature(final String internalTypeName) { + if (Utils.isEmpty(internalTypeName) || Arrays.asList(Const.SHORT_TYPE_NAMES).contains(internalTypeName)) { + return internalTypeName; + } + switch (internalTypeName.charAt(0)) { + case '[': + return internalTypeName; + case 'L': + case 'T': + if (internalTypeName.charAt(internalTypeName.length() - 1) == ';') { + return internalTypeName; + } + return 'L' + internalTypeName + ';'; + default: + return 'L' + internalTypeName + ';'; + } + } + static int size(final int coded) { return coded & 3; } @@ -361,7 +381,7 @@ public byte getType() { } /** - * @return hashcode of Type + * @return hash code of Type */ @Override public int hashCode() { @@ -369,31 +389,23 @@ public int hashCode() { } /** - * boolean, short and char variable are considered as int in the stack or local variable area. Returns {@link Type#INT} - * for {@link Type#BOOLEAN}, {@link Type#SHORT} or {@link Type#CHAR}, otherwise returns the given type. + * boolean, short and char variable are considered as int in the stack or local variable area. Returns {@link #INT} + * for {@link #BOOLEAN}, {@link #SHORT} or {@link #CHAR}, otherwise returns the given type. * * @since 6.0 */ public Type normalizeForStackOrLocal() { - if (this == Type.BOOLEAN || this == Type.BYTE || this == Type.SHORT || this == Type.CHAR) { - return Type.INT; + if (this == BOOLEAN || this == BYTE || this == SHORT || this == CHAR) { + return INT; } return this; } - /* - * Currently only used by the ArrayType constructor. The signature has a complicated dependency on other parameter so - * it's tricky to do it in a call to the super ctor. - */ - void setSignature(final String signature) { - this.signature = signature; - } - /** * @return Type string, e.g. 'int[]' */ @Override public String toString() { - return this.equals(Type.NULL) || type >= Const.T_UNKNOWN ? signature : Utility.signatureToString(signature, false); + return equals(NULL) || type >= Const.T_UNKNOWN ? signature : Utility.signatureToString(signature, false); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TypedInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TypedInstruction.java index 5a22942a6a7..27b952f3996 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TypedInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TypedInstruction.java @@ -22,7 +22,7 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Get the type associated with an instruction, int for ILOAD, or the type of the field of a PUTFIELD instruction, e.g.. + * Gets the type associated with an instruction, int for ILOAD, or the type of the field of a PUTFIELD instruction, e.g.. */ public interface TypedInstruction { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/package-info.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/package-info.java new file mode 100644 index 00000000000..63d4dc876ce --- /dev/null +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/package-info.java @@ -0,0 +1,26 @@ +/* + * reserved comment block + * DO NOT REMOVE OR ALTER! + */ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Generic part of the Apache Byte Code Engineering Library (BCEL), classes to dynamically modify class objects + * and byte code instructions. + */ +package com.sun.org.apache.bcel.internal.generic; diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/package-info.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/package-info.java new file mode 100644 index 00000000000..581037d7981 --- /dev/null +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/package-info.java @@ -0,0 +1,26 @@ +/* + * reserved comment block + * DO NOT REMOVE OR ALTER! + */ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Basic classes for the Apache Byte Code Engineering Library (BCEL) and constants defined by the + * JVM specification. + */ +package com.sun.org.apache.bcel.internal; diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELComparator.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELComparator.java index 2e663bfdaa1..fb32dc35e0b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELComparator.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELComparator.java @@ -22,26 +22,27 @@ package com.sun.org.apache.bcel.internal.util; /** - * Used for BCEL comparison strategy + * Used for BCEL comparison strategy. * + * @param What type we are comparing. * @since 5.2 */ -public interface BCELComparator { +public interface BCELComparator { /** - * Compare two objects and return what THIS.equals(THAT) should return + * Compares two objects and return what a.equals(b) should return. * - * @param THIS - * @param THAT - * @return true if and only if THIS equals THAT + * @param a an object. + * @param b an object to be compared with {@code a} for equality. + * @return {@code true} if the arguments are equal to each other and {@code false} otherwise. */ - boolean equals(Object THIS, Object THAT); + boolean equals(T a, T b); /** - * Return hashcode for THIS.hashCode() + * Gets the hash code for o.hashCode() * - * @param THIS - * @return hashcode for THIS.hashCode() + * @param o + * @return hash code for o.hashCode() */ - int hashCode(Object THIS); + int hashCode(T o); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELFactory.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELFactory.java index c931fb1e422..93f22e7d0ad 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELFactory.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -63,9 +63,9 @@ * Factory creates il.append() statements, and sets instruction targets. A helper class for BCELifier. * * @see BCELifier - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ -class BCELFactory extends EmptyVisitor { +final class BCELFactory extends EmptyVisitor { private static final String CONSTANT_PREFIX = Const.class.getSimpleName() + "."; private final MethodGen methodGen; @@ -88,7 +88,7 @@ private void createConstant(final Object value) { if (value instanceof String) { embed = '"' + Utility.convertString(embed) + '"'; } else if (value instanceof Character) { - embed = "(char)0x" + Integer.toHexString(((Character) value).charValue()); + embed = "(char) 0x" + Integer.toHexString(((Character) value).charValue()); } else if (value instanceof Float) { final Float f = (Float) value; if (Float.isNaN(f)) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELifier.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELifier.java index 151083ea71b..0eb9bfb4ee1 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELifier.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -30,11 +30,15 @@ import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.Repository; import com.sun.org.apache.bcel.internal.classfile.ClassParser; +import com.sun.org.apache.bcel.internal.classfile.Code; import com.sun.org.apache.bcel.internal.classfile.ConstantValue; import com.sun.org.apache.bcel.internal.classfile.ExceptionTable; import com.sun.org.apache.bcel.internal.classfile.Field; import com.sun.org.apache.bcel.internal.classfile.JavaClass; import com.sun.org.apache.bcel.internal.classfile.Method; +import com.sun.org.apache.bcel.internal.classfile.StackMap; +import com.sun.org.apache.bcel.internal.classfile.StackMapEntry; +import com.sun.org.apache.bcel.internal.classfile.StackMapType; import com.sun.org.apache.bcel.internal.classfile.Utility; import com.sun.org.apache.bcel.internal.generic.ArrayType; import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; @@ -46,7 +50,7 @@ * This gives new users of BCEL a useful example showing how things are done with BCEL. It does not cover all features * of BCEL, but tries to mimic hand-written code as close as possible. * - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public class BCELifier extends com.sun.org.apache.bcel.internal.classfile.EmptyVisitor { @@ -74,7 +78,7 @@ static JavaClass getJavaClass(final String name) throws ClassNotFoundException, /** * Default main method */ - public static void _main(final String[] argv) throws Exception { + public static void main(final String[] argv) throws Exception { if (argv.length != 1) { System.out.println("Usage: BCELifier className"); System.out.println("\tThe class must exist on the classpath"); @@ -311,6 +315,13 @@ public void visitMethod(final Method method) { printWriter.println("\");"); } } + final Code code = method.getCode(); + if (code != null) { + final StackMap stackMap = code.getStackMap(); + if (stackMap != null) { + stackMap.accept(this); + } + } printWriter.println(); final BCELFactory factory = new BCELFactory(mg, printWriter); factory.start(); @@ -319,4 +330,78 @@ public void visitMethod(final Method method) { printWriter.println(" _cg.addMethod(method.getMethod());"); printWriter.println(" il.dispose();"); } + + @Override + public void visitStackMap(final StackMap stackMap) { + super.visitStackMap(stackMap); + printWriter.print(" method.addCodeAttribute("); + printWriter.print("new StackMap(_cp.addUtf8(\""); + printWriter.print(stackMap.getName()); + printWriter.print("\"), "); + printWriter.print(stackMap.getLength()); + printWriter.print(", "); + printWriter.print("new StackMapEntry[] {"); + final StackMapEntry[] table = stackMap.getStackMap(); + for (int i = 0; i < table.length; i++) { + table[i].accept(this); + if (i < table.length - 1) { + printWriter.print(", "); + } else { + printWriter.print(" }"); + } + } + printWriter.print(", _cp.getConstantPool())"); + printWriter.println(");"); + } + + @Override + public void visitStackMapEntry(final StackMapEntry stackMapEntry) { + super.visitStackMapEntry(stackMapEntry); + printWriter.print("new StackMapEntry("); + printWriter.print(stackMapEntry.getFrameType()); + printWriter.print(", "); + printWriter.print(stackMapEntry.getByteCodeOffset()); + printWriter.print(", "); + visitStackMapTypeArray(stackMapEntry.getTypesOfLocals()); + printWriter.print(", "); + visitStackMapTypeArray(stackMapEntry.getTypesOfStackItems()); + printWriter.print(", _cp.getConstantPool())"); + } + + /** + * Visits a {@link StackMapType} object. + * @param stackMapType object to visit + * @since 6.7.1 + */ + @Override + public void visitStackMapType(final StackMapType stackMapType) { + super.visitStackMapType(stackMapType); + printWriter.print("new StackMapType((byte)"); + printWriter.print(stackMapType.getType()); + printWriter.print(", "); + if (stackMapType.hasIndex()) { + printWriter.print("_cp.addClass(\""); + printWriter.print(stackMapType.getClassName()); + printWriter.print("\")"); + } else { + printWriter.print("-1"); + } + printWriter.print(", _cp.getConstantPool())"); + } + + private void visitStackMapTypeArray(final StackMapType[] types) { + if (types == null || types.length == 0) { + printWriter.print("null"); // null translates to StackMapType.EMPTY_ARRAY + } else { + printWriter.print("new StackMapType[] {"); + for (int i = 0; i < types.length; i++) { + types[i].accept(this); + if (i < types.length - 1) { + printWriter.print(", "); + } else { + printWriter.print(" }"); + } + } + } + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Class2HTML.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Class2HTML.java index f644c698b72..10d31974d47 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Class2HTML.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Class2HTML.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -53,7 +53,7 @@ * All subfiles reference each other appropriately, e.g. clicking on a method in the Method's frame will jump to the * appropriate method in the Code frame. * - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public class Class2HTML { @@ -73,7 +73,7 @@ public class Class2HTML { basicTypes.add("float"); } - public static void _main(final String[] argv) throws IOException { + public static void main(final String[] argv) throws IOException { final String[] fileName = new String[argv.length]; int files = 0; ClassParser parser = null; @@ -89,7 +89,7 @@ public static void _main(final String[] argv) throws IOException { if (argv[i].equals("-d")) { // Specify target directory, default '.' dir = argv[++i]; if (!dir.endsWith("" + sep)) { - dir = dir + sep; + dir += sep; } final File store = new File(dir); if (!store.isDirectory()) { @@ -115,7 +115,7 @@ public static void _main(final String[] argv) throws IOException { if (zipFile == null) { parser = new ClassParser(fileName[i]); // Create parser object from file } else { - parser = new ClassParser(zipFile, fileName[i]); // Create parser object from zip file + parser = new ClassParser(zipFile, fileName[i]); // Create parser object from ZIP file } javaClass = parser.parse(); new Class2HTML(javaClass, dir); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassSet.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassSet.java index 178ccc786b1..e95e8fbd0a0 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassSet.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -30,7 +30,7 @@ * Utility class implementing a (type-safe) set of JavaClass objects. Since JavaClass has no equals() method, the name of the class is used for comparison. * * @see ClassStack - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public class ClassSet { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/CodeHTML.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/CodeHTML.java index 723fc07509b..1935d724b3b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/CodeHTML.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/CodeHTML.java @@ -542,7 +542,7 @@ private void writeMethod(final Method method, final int methodNumber) throws IOE final String str = codeToHTML(stream, methodNumber); String anchor = ""; /* - * Set an anchor mark if this line is targetted by a goto, jsr, etc. Defining an anchor for every line is very + * Sets an anchor mark if this line is targetted by a goto, jsr, etc. Defining an anchor for every line is very * inefficient! */ if (gotoSet.get(offset)) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java index 5b045bf08cc..510fe4a03a6 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -63,14 +63,13 @@ * * @see com.sun.org.apache.bcel.internal.generic.Instruction * @see InstructionList - * @LastModified: May 2021 + * @LastModified: Sept 2025 */ public class InstructionFinder { /** * Code patterns found may be checked using an additional user-defined constraint object whether they really match the * needed criterion. I.e., check constraints that can not expressed with regular expressions. - * */ public interface CodeConstraint { @@ -374,7 +373,7 @@ public final Iterator search(final String pattern, final In // } // private static final String pattern2string( String pattern, boolean make_string ) { -// StringBuffer buf = new StringBuffer(); +// StringBuilder buf = new StringBuilder(); // for (int i = 0; i < pattern.length(); i++) { // char ch = pattern.charAt(i); // if (ch >= OFFSET) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Repository.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Repository.java index 8d1ddf493cd..c44e36d0a81 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Repository.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Repository.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -25,8 +25,8 @@ * Abstract definition of a class repository. Instances may be used to load classes from different sources and may be * used in the Repository.setRepository method. * - * @see org.apache.bcel.Repository - * @LastModified: Feb 2023 + * @see com.sun.org.apache.bcel.internal.Repository + * @LastModified: Sept 2025 */ public interface Repository { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/package-info.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/package-info.java new file mode 100644 index 00000000000..2bd92f155bc --- /dev/null +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/package-info.java @@ -0,0 +1,32 @@ +/* + * reserved comment block + * DO NOT REMOVE OR ALTER! + */ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Utility classes for the Apache Byte Code Engineering Library (BCEL), namely: + *
    + *
  • Collection classes for JavaClass objects
  • + *
  • A converter for class files to HTML
  • + *
  • A tool to find instructions patterns via regular expressions
  • + *
  • A class to find classes as defined in the CLASSPATH
  • + *
  • A class loader that allows to create classes at run time
  • + *
+ */ +package com.sun.org.apache.bcel.internal.util; diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderFactoryImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderFactoryImpl.java index 385b8e29439..bc8e93b4f0b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderFactoryImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderFactoryImpl.java @@ -41,7 +41,7 @@ /** * @author Rajiv Mordani * @author Edwin Goei - * @LastModified: May 2025 + * @LastModified: June 2025 */ public class DocumentBuilderFactoryImpl extends DocumentBuilderFactory { /** These are DocumentBuilderFactory attributes not DOM attributes */ @@ -59,11 +59,24 @@ public class DocumentBuilderFactoryImpl extends DocumentBuilderFactory { XMLSecurityManager fSecurityManager; XMLSecurityPropertyManager fSecurityPropertyMgr; + /** + * Creates a new {@code DocumentBuilderFactory} instance. + */ public DocumentBuilderFactoryImpl() { + this(null, null); + } + + /** + * Creates a new {@code DocumentBuilderFactory} instance with a {@code XMLSecurityManager} + * and {@code XMLSecurityPropertyManager}. + * @param xsm the {@code XMLSecurityManager} + * @param xspm the {@code XMLSecurityPropertyManager} + */ + public DocumentBuilderFactoryImpl(XMLSecurityManager xsm, XMLSecurityPropertyManager xspm) { JdkXmlConfig config = JdkXmlConfig.getInstance(false); // security (property) managers updated with current system properties - fSecurityManager = config.getXMLSecurityManager(true); - fSecurityPropertyMgr = config.getXMLSecurityPropertyManager(true); + fSecurityManager = (xsm == null) ? config.getXMLSecurityManager(true) : xsm; + fSecurityPropertyMgr = (xspm == null) ? config.getXMLSecurityPropertyManager(true) : xspm; } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java index 1288f1dbac3..2f4d2ade545 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java @@ -35,7 +35,7 @@ * * @author Ramesh Mandava * - * @LastModified: May 2025 + * @LastModified: June 2025 */ public class XPathFactoryImpl extends XPathFactory { @@ -72,6 +72,7 @@ public class XPathFactoryImpl extends XPathFactory { * The XML security manager */ private XMLSecurityManager _xmlSecMgr; + private XMLSecurityPropertyManager _xmlSecPropMgr; /** * javax.xml.xpath.XPathFactory implementation. @@ -80,6 +81,7 @@ public XPathFactoryImpl() { JdkXmlConfig config = JdkXmlConfig.getInstance(false); _xmlSecMgr = config.getXMLSecurityManager(true); _featureManager = config.getXMLFeatures(true); + _xmlSecPropMgr = config.getXMLSecurityPropertyManager(true); } /** @@ -129,7 +131,7 @@ public boolean isObjectModelSupported(String objectModel) { */ public javax.xml.xpath.XPath newXPath() { return new XPathImpl(xPathVariableResolver, xPathFunctionResolver, - !_isNotSecureProcessing, _featureManager, _xmlSecMgr); + !_isNotSecureProcessing, _featureManager, _xmlSecMgr, _xmlSecPropMgr); } /** @@ -183,6 +185,7 @@ public void setFeature(String name, boolean value) if (value && _featureManager != null) { _featureManager.setFeature(JdkXmlFeatures.XmlFeature.ENABLE_EXTENSION_FUNCTION, JdkProperty.State.FSP, false); + _xmlSecMgr.setSecureProcessing(value); } // all done processing feature @@ -338,8 +341,7 @@ public void setProperty(String name, String value) { throw new NullPointerException(fmsg); } - if (_xmlSecMgr != null && - _xmlSecMgr.setLimit(name, JdkProperty.State.APIPROPERTY, value)) { + if (JdkXmlUtils.setProperty(_xmlSecMgr, _xmlSecPropMgr, name, value)) { return; } diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java index 53099ad078e..c2faf90ce2e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java @@ -36,6 +36,7 @@ import jdk.xml.internal.JdkXmlConfig; import jdk.xml.internal.JdkXmlFeatures; import jdk.xml.internal.XMLSecurityManager; +import jdk.xml.internal.XMLSecurityPropertyManager; import org.w3c.dom.Document; import org.xml.sax.InputSource; @@ -50,7 +51,7 @@ * New methods: evaluateExpression * Refactored to share code with XPathExpressionImpl. * - * @LastModified: May 2025 + * @LastModified: June 2025 */ public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath { @@ -62,12 +63,13 @@ public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath { XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr) { this(vr, fr, false, JdkXmlConfig.getInstance(false).getXMLFeatures(false), - JdkXmlConfig.getInstance(false).getXMLSecurityManager(false)); + JdkXmlConfig.getInstance(false).getXMLSecurityManager(false), + JdkXmlConfig.getInstance(false).getXMLSecurityPropertyManager(false)); } XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr, boolean featureSecureProcessing, JdkXmlFeatures featureManager, - XMLSecurityManager xmlSecMgr) { + XMLSecurityManager xmlSecMgr, XMLSecurityPropertyManager xmlSecPropMgr) { this.origVariableResolver = this.variableResolver = vr; this.origFunctionResolver = this.functionResolver = fr; this.featureSecureProcessing = featureSecureProcessing; @@ -75,6 +77,7 @@ public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath { overrideDefaultParser = featureManager.getFeature( JdkXmlFeatures.XmlFeature.JDK_OVERRIDE_PARSER); this.xmlSecMgr = xmlSecMgr; + this.xmlSecPropMgr = xmlSecPropMgr; } diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java index a92090900fa..3de72f3f68b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java @@ -31,6 +31,7 @@ import com.sun.org.apache.xpath.internal.objects.XObject; import com.sun.org.apache.xpath.internal.res.XPATHErrorResources; import java.io.IOException; +import javax.xml.XMLConstants; import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -44,6 +45,7 @@ import jdk.xml.internal.JdkXmlFeatures; import jdk.xml.internal.JdkXmlUtils; import jdk.xml.internal.XMLSecurityManager; +import jdk.xml.internal.XMLSecurityPropertyManager; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.traversal.NodeIterator; @@ -54,7 +56,7 @@ * This class contains several utility methods used by XPathImpl and * XPathExpressionImpl * - * @LastModified: Apr 2025 + * @LastModified: June 2025 */ class XPathImplUtil { XPathFunctionResolver functionResolver; @@ -67,6 +69,7 @@ class XPathImplUtil { boolean featureSecureProcessing = false; JdkXmlFeatures featureManager; XMLSecurityManager xmlSecMgr; + XMLSecurityPropertyManager xmlSecPropMgr; /** * Evaluate an XPath context using the internal XPath engine @@ -128,7 +131,12 @@ Document getDocument(InputSource source) // // so we really have to create a fresh DocumentBuilder every time we need one // - KK - DocumentBuilderFactory dbf = JdkXmlUtils.getDOMFactory(overrideDefaultParser); + DocumentBuilderFactory dbf = JdkXmlUtils.getDOMFactory( + overrideDefaultParser, xmlSecMgr, xmlSecPropMgr); + if (xmlSecMgr != null && xmlSecMgr.isSecureProcessingSet()) { + dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, + xmlSecMgr.isSecureProcessing()); + } return dbf.newDocumentBuilder().parse(source); } catch (ParserConfigurationException | SAXException | IOException e) { throw new XPathExpressionException (e); diff --git a/src/java.xml/share/classes/jdk/xml/internal/JdkXmlUtils.java b/src/java.xml/share/classes/jdk/xml/internal/JdkXmlUtils.java index 93b63a746f1..9e718b264e4 100644 --- a/src/java.xml/share/classes/jdk/xml/internal/JdkXmlUtils.java +++ b/src/java.xml/share/classes/jdk/xml/internal/JdkXmlUtils.java @@ -445,6 +445,20 @@ public static Document getDOMDocument() { * @return a DocumentBuilderFactory instance. */ public static DocumentBuilderFactory getDOMFactory(boolean overrideDefaultParser) { + return getDOMFactory(overrideDefaultParser, null, null); + } + + /** + * {@return a DocumentBuilderFactory instance} + * + * @param overrideDefaultParser a flag indicating whether the system-default + * implementation may be overridden. If the system property of the + * DOM factory ID is set, override is always allowed. + * @param xsm XMLSecurityManager + * @param xspm XMLSecurityPropertyManager + */ + public static DocumentBuilderFactory getDOMFactory(boolean overrideDefaultParser, + XMLSecurityManager xsm, XMLSecurityPropertyManager xspm) { boolean override = overrideDefaultParser; String spDOMFactory = SecuritySupport.getJAXPSystemProperty(DOM_FACTORY_ID); @@ -453,7 +467,7 @@ public static DocumentBuilderFactory getDOMFactory(boolean overrideDefaultParser } DocumentBuilderFactory dbf = !override - ? new DocumentBuilderFactoryImpl() + ? new DocumentBuilderFactoryImpl(xsm, xspm) : DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); // false is the default setting. This step here is for compatibility diff --git a/src/java.xml/share/classes/jdk/xml/internal/Utils.java b/src/java.xml/share/classes/jdk/xml/internal/Utils.java index f55ab95a58f..96d9b1b9521 100644 --- a/src/java.xml/share/classes/jdk/xml/internal/Utils.java +++ b/src/java.xml/share/classes/jdk/xml/internal/Utils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,11 @@ package jdk.xml.internal; +import java.lang.reflect.Array; import java.util.Arrays; +import java.util.Objects; import java.util.function.Supplier; +import java.util.stream.Stream; /** * General utility. Use JdkXmlUtils for XML processing related functions. @@ -76,4 +79,59 @@ public static Class[] arraysAppend(final Class[] original, final Class. System.arraycopy(items, 0, result, original.length, items.length); return result; } + + /** + * Returns the original array, or an empty array if it is {@code null}. + * @param array the specified array + * @return the original array, or an empty array if it is {@code null} + */ + public static byte[] createEmptyArrayIfNull(byte[] array) { + return (array != null) ? array : new byte[0]; + } + + /** + * Returns the original array, or an empty array if it is {@code null}. + * @param array the specified array + * @return the original array, or an empty array if it is {@code null} + */ + public static int[] createEmptyArrayIfNull(int[] array) { + return (array != null) ? array : new int[0]; + } + + /** + * Returns the original array, or an empty array if it is {@code null}. + * @param the class type + * @param array the specified array + * @param type the type of the array + * @return the original array, or an empty array if it is {@code null} + */ + public static T[] createEmptyArrayIfNull(final T[] array, final Class type) { + Objects.requireNonNull(type, "The type argument should not be null."); + + return (array != null) ? array : type.cast(Array.newInstance(type.getComponentType(), 0)); + } + + /** + * Returns the new stream created by {@code Stream.of(values)} or an empty + * sequential stream created by {@code Stream.empty()} if values is null. + * + * @param the type of stream elements + * @param values the elements of the new stream + * @return the new stream created by {@code Stream.of(values)} or an empty + * sequential stream created by {@code Stream.empty()} if values is null. + */ + @SafeVarargs + @SuppressWarnings("varargs") // Creating a stream from an array is safe + public static Stream streamOfIfNonNull(final T... values) { + return values == null ? Stream.empty() : Stream.of(values); + } + + /** + * Checks if a CharSequence is empty ("") or null. + * @param cs the CharSequence to check, may be null + * @return {@code true} if the CharSequence is empty or null + */ + public static boolean isEmpty(final CharSequence cs) { + return cs == null || cs.length() == 0; + } } diff --git a/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java b/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java index 5ca4073e20f..a1687c420c3 100644 --- a/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java +++ b/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java @@ -244,6 +244,12 @@ public static enum Processor { */ boolean secureProcessing; + /** + * Flag indicating the secure processing is set explicitly through factories' + * setFeature method and then the setSecureProcessing method + */ + boolean secureProcessingSet; + /** * States that determine if properties are set explicitly */ @@ -340,6 +346,7 @@ private NotFoundAction toActionType(String resolve) { * Setting FEATURE_SECURE_PROCESSING explicitly */ public void setSecureProcessing(boolean secure) { + secureProcessingSet = true; secureProcessing = secure; for (Limit limit : Limit.values()) { if (secure) { @@ -358,6 +365,15 @@ public boolean isSecureProcessing() { return secureProcessing; } + /** + * Returns the state indicating whether the Secure Processing is set explicitly, + * via factories' setFeature and then this class' setSecureProcessing method. + * @return the state indicating whether the Secure Processing is set explicitly + */ + public boolean isSecureProcessingSet() { + return secureProcessingSet; + } + /** * Finds a limit's new name with the given property name. * @param propertyName the property name specified diff --git a/src/java.xml/share/legal/bcel.md b/src/java.xml/share/legal/bcel.md index 2c673d6b1af..b64fc3640d4 100644 --- a/src/java.xml/share/legal/bcel.md +++ b/src/java.xml/share/legal/bcel.md @@ -1,4 +1,4 @@ -## Apache Commons Byte Code Engineering Library (BCEL) Version 6.7.0 +## Apache Commons Byte Code Engineering Library (BCEL) Version 6.10.0 ### Apache Commons BCEL Notice
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
index 725c7f8063b..e916466998e 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
@@ -756,6 +756,11 @@ public CondItem genCond(JCTree _tree, boolean markBranches) {
             }
             CondItem result = genCond(tree.expr, markBranches);
             code.endScopes(limit);
+            //make sure variables defined in the let expression are not included
+            //in the defined variables for jumps that go outside of this let
+            //expression:
+            undefineVariablesInChain(result.falseJumps, limit);
+            undefineVariablesInChain(result.trueJumps, limit);
             return result;
         } else {
             CondItem result = genExpr(_tree, syms.booleanType).mkCond();
@@ -763,6 +768,13 @@ public CondItem genCond(JCTree _tree, boolean markBranches) {
             return result;
         }
     }
+        //where:
+        private void undefineVariablesInChain(Chain toClear, int limit) {
+            while (toClear != null) {
+                toClear.state.defined.excludeFrom(limit);
+                toClear = toClear.next;
+            }
+        }
 
     public Code getCode() {
         return code;
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/RSACipherAdaptor.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/RSACipherAdaptor.java
new file mode 100644
index 00000000000..183a71ee806
--- /dev/null
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/RSACipherAdaptor.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.pkcs11;
+
+import java.io.ByteArrayOutputStream;
+import java.security.MessageDigest;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.SignatureSpi;
+import java.security.InvalidKeyException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidParameterException;
+import java.security.ProviderException;
+import java.security.SignatureException;
+import java.security.spec.AlgorithmParameterSpec;
+import javax.crypto.Cipher;
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import sun.security.pkcs11.wrapper.PKCS11Exception;
+
+/**
+ * NONEwithRSA Signature implementation using the RSA/ECB/PKCS1Padding Cipher
+ * implementation from SunPKCS11.
+ */
+public final class RSACipherAdaptor extends SignatureSpi {
+
+    private final P11RSACipher c;
+    private ByteArrayOutputStream verifyBuf;
+
+    public RSACipherAdaptor(Token token, long mechanism) {
+        try {
+            c = new P11RSACipher(token, "", mechanism);
+            c.engineSetPadding("pkcs1padding");
+        } catch (PKCS11Exception | NoSuchPaddingException e) {
+            // should not happen, but wrap and re-throw if it were to happen
+            throw new ProviderException(e);
+        }
+    }
+
+    @Override
+    protected void engineInitVerify(PublicKey publicKey)
+            throws InvalidKeyException {
+        c.engineInit(Cipher.DECRYPT_MODE, publicKey, null);
+        if (verifyBuf == null) {
+            verifyBuf = new ByteArrayOutputStream(128);
+        } else {
+            verifyBuf.reset();
+        }
+    }
+
+    @Override
+    protected void engineInitSign(PrivateKey privateKey)
+            throws InvalidKeyException {
+        c.engineInit(Cipher.ENCRYPT_MODE, privateKey, null);
+        verifyBuf = null;
+    }
+
+    @Override
+    protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
+            throws InvalidKeyException {
+        c.engineInit(Cipher.ENCRYPT_MODE, privateKey, random);
+        verifyBuf = null;
+    }
+
+    @Override
+    protected void engineUpdate(byte b) throws SignatureException {
+        engineUpdate(new byte[] {b}, 0, 1);
+    }
+
+    @Override
+    protected void engineUpdate(byte[] b, int off, int len)
+            throws SignatureException {
+        if (verifyBuf != null) {
+            verifyBuf.write(b, off, len);
+        } else {
+            byte[] out = c.engineUpdate(b, off, len);
+            if ((out != null) && (out.length != 0)) {
+                throw new SignatureException
+                       ("Cipher unexpectedly returned data");
+            }
+        }
+    }
+
+    @Override
+    protected byte[] engineSign() throws SignatureException {
+        try {
+            return c.engineDoFinal(null, 0, 0);
+        } catch (IllegalBlockSizeException | BadPaddingException e) {
+           throw new SignatureException("doFinal() failed", e);
+        }
+    }
+
+    @Override
+    protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
+        try {
+            byte[] out = c.engineDoFinal(sigBytes, 0, sigBytes.length);
+            byte[] data = verifyBuf.toByteArray();
+            verifyBuf.reset();
+            return MessageDigest.isEqual(out, data);
+        } catch (BadPaddingException e) {
+            // e.g. wrong public key used
+            // return false rather than throwing exception
+            return false;
+        } catch (IllegalBlockSizeException e) {
+            throw new SignatureException("doFinal() failed", e);
+        }
+    }
+
+    @Override
+    protected void engineSetParameter(AlgorithmParameterSpec params)
+            throws InvalidAlgorithmParameterException {
+        if (params != null) {
+            throw new InvalidParameterException("Parameters not supported");
+        }
+    }
+
+    @Override
+    @SuppressWarnings("deprecation")
+    protected void engineSetParameter(String param, Object value)
+            throws InvalidParameterException {
+        throw new InvalidParameterException("Parameters not supported");
+    }
+
+    @Override
+    @SuppressWarnings("deprecation")
+    protected Object engineGetParameter(String param)
+            throws InvalidParameterException {
+        throw new InvalidParameterException("Parameters not supported");
+    }
+}
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
index eb0569ec0d4..00d8559e696 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
@@ -974,6 +974,8 @@ private static void register(Descriptor d) {
         d(SIG, "SHA3-512withECDSAinP1363Format", P11Signature,
                 m(CKM_ECDSA_SHA3_512, CKM_ECDSA));
 
+        d(SIG, "NONEwithRSA",    "sun.security.pkcs11.RSACipherAdaptor",
+                m(CKM_RSA_PKCS));
         dA(SIG, "MD2withRSA",    P11Signature,
                 m(CKM_MD2_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
         dA(SIG, "MD5withRSA",    P11Signature,
@@ -1425,6 +1427,8 @@ public Object newInstance0(Object param) throws
             } else if (type == SIG) {
                 if (algorithm.contains("RSASSA-PSS")) {
                     return new P11PSSSignature(token, algorithm, mechanism);
+                } else if (algorithm.equals("NONEwithRSA")) {
+                    return new RSACipherAdaptor(token, mechanism);
                 } else {
                     return new P11Signature(token, algorithm, mechanism);
                 }
diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c
index f88477681b7..37404db1024 100644
--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c
+++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c
@@ -1461,8 +1461,7 @@ jobject ckAttributeValueToJObject(JNIEnv *env, const CK_ATTRIBUTE_PTR ckpAttribu
         case CKA_OWNER:
         case CKA_AC_ISSUER:
         case CKA_ATTR_TYPES:
-        case CKA_ECDSA_PARAMS:
-            /* CKA_EC_PARAMS is the same, these two are equivalent */
+        case CKA_EC_PARAMS:
         case CKA_EC_POINT:
         case CKA_PRIVATE_EXPONENT:
         case CKA_PRIME_1:
diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_crypt.c b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_crypt.c
index d969fabffd0..052c7011860 100644
--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_crypt.c
+++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_crypt.c
@@ -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.
  */
 
 /* Copyright  (c) 2002 Graz University of Technology. All rights reserved.
@@ -184,9 +184,12 @@ Java_sun_security_pkcs11_wrapper_PKCS11_C_1Encrypt
 
     if (directIn != 0) {
       inBufP = (CK_BYTE_PTR) jlong_to_ptr(directIn);
-    } else {
+    } else if (jIn != NULL) {
       inBufP = (*env)->GetPrimitiveArrayCritical(env, jIn, NULL);
+      // may happen if out of memory
       if (inBufP == NULL) { return 0; }
+    } else {
+      inBufP = NULL;
     }
 
     if (directOut != 0) {
@@ -194,7 +197,7 @@ Java_sun_security_pkcs11_wrapper_PKCS11_C_1Encrypt
     } else {
       outBufP = (*env)->GetPrimitiveArrayCritical(env, jOut, NULL);
       if (outBufP == NULL) {
-        if (directIn == 0) {
+        if (directIn == 0 && inBufP != NULL) {
           (*env)->ReleasePrimitiveArrayCritical(env, jIn, inBufP, JNI_ABORT);
         }
         return 0;
@@ -208,7 +211,7 @@ Java_sun_security_pkcs11_wrapper_PKCS11_C_1Encrypt
                                     (CK_BYTE_PTR)(outBufP + jOutOfs),
                                     &ckEncryptedLen);
 
-    if (directIn == 0) {
+    if (directIn == 0 && inBufP != NULL) {
         (*env)->ReleasePrimitiveArrayCritical(env, jIn, inBufP, JNI_ABORT);
     }
     if (directOut == 0) {
@@ -251,9 +254,12 @@ Java_sun_security_pkcs11_wrapper_PKCS11_C_1EncryptUpdate
 
     if (directIn != 0) {
       inBufP = (CK_BYTE_PTR) jlong_to_ptr(directIn);
-    } else {
+    } else if (jIn != NULL) {
       inBufP = (*env)->GetPrimitiveArrayCritical(env, jIn, NULL);
+      // may happen if out of memory
       if (inBufP == NULL) { return 0; }
+    } else {
+      inBufP = NULL;
     }
 
     if (directOut != 0) {
@@ -261,7 +267,7 @@ Java_sun_security_pkcs11_wrapper_PKCS11_C_1EncryptUpdate
     } else {
       outBufP = (*env)->GetPrimitiveArrayCritical(env, jOut, NULL);
       if (outBufP == NULL) {
-        if (directIn == 0) {
+        if (directIn == 0 && inBufP != NULL) {
           (*env)->ReleasePrimitiveArrayCritical(env, jIn, inBufP, JNI_ABORT);
         }
         return 0;
@@ -275,7 +281,7 @@ Java_sun_security_pkcs11_wrapper_PKCS11_C_1EncryptUpdate
                                           (CK_BYTE_PTR)(outBufP + jOutOfs),
                                           &ckEncryptedPartLen);
 
-    if (directIn == 0) {
+    if (directIn == 0 && inBufP != NULL) {
         (*env)->ReleasePrimitiveArrayCritical(env, jIn, inBufP, JNI_ABORT);
     }
     if (directOut == 0) {
@@ -462,9 +468,12 @@ Java_sun_security_pkcs11_wrapper_PKCS11_C_1Decrypt
 
     if (directIn != 0) {
       inBufP = (CK_BYTE_PTR) jlong_to_ptr(directIn);
-    } else {
+    } else if (jIn != NULL) {
       inBufP = (*env)->GetPrimitiveArrayCritical(env, jIn, NULL);
+      // may happen if out of memory
       if (inBufP == NULL) { return 0; }
+    } else {
+      inBufP = NULL;
     }
 
     if (directOut != 0) {
@@ -472,7 +481,7 @@ Java_sun_security_pkcs11_wrapper_PKCS11_C_1Decrypt
     } else {
       outBufP = (*env)->GetPrimitiveArrayCritical(env, jOut, NULL);
       if (outBufP == NULL) {
-        if (directIn == 0) {
+        if (directIn == 0 && inBufP != NULL) {
           (*env)->ReleasePrimitiveArrayCritical(env, jIn, inBufP, JNI_ABORT);
         }
         return 0;
@@ -485,7 +494,7 @@ Java_sun_security_pkcs11_wrapper_PKCS11_C_1Decrypt
                                     (CK_BYTE_PTR)(outBufP + jOutOfs),
                                     &ckOutLen);
 
-    if (directIn == 0) {
+    if (directIn == 0 && inBufP != NULL) {
         (*env)->ReleasePrimitiveArrayCritical(env, jIn, inBufP, JNI_ABORT);
     }
     if (directOut == 0) {
@@ -528,9 +537,12 @@ Java_sun_security_pkcs11_wrapper_PKCS11_C_1DecryptUpdate
 
     if (directIn != 0) {
       inBufP = (CK_BYTE_PTR) jlong_to_ptr(directIn);
-    } else {
+    } else if (jIn != NULL) {
       inBufP = (*env)->GetPrimitiveArrayCritical(env, jIn, NULL);
+      // may happen if out of memory
       if (inBufP == NULL) { return 0; }
+    } else {
+      inBufP = NULL;
     }
 
     if (directOut != 0) {
@@ -538,7 +550,7 @@ Java_sun_security_pkcs11_wrapper_PKCS11_C_1DecryptUpdate
     } else {
       outBufP = (*env)->GetPrimitiveArrayCritical(env, jOut, NULL);
       if (outBufP == NULL) {
-        if (directIn == 0) {
+        if (directIn == 0 && inBufP != NULL) {
           (*env)->ReleasePrimitiveArrayCritical(env, jIn, inBufP, JNI_ABORT);
         }
         return 0;
@@ -551,7 +563,7 @@ Java_sun_security_pkcs11_wrapper_PKCS11_C_1DecryptUpdate
                                           (CK_BYTE_PTR)(outBufP + jOutOfs),
                                           &ckDecryptedPartLen);
 
-    if (directIn == 0) {
+    if (directIn == 0 && inBufP != NULL) {
         (*env)->ReleasePrimitiveArrayCritical(env, jIn, inBufP, JNI_ABORT);
     }
     if (directOut == 0) {
diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_keymgmt.c b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_keymgmt.c
index d522c4864ba..f2e1a46565d 100644
--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_keymgmt.c
+++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_keymgmt.c
@@ -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.
  */
 
 /* Copyright  (c) 2002 Graz University of Technology. All rights reserved.
@@ -56,69 +56,78 @@
 
 #ifdef P11_ENABLE_GETNATIVEKEYINFO
 
-#define CK_ATTRIBUTES_TEMPLATE_LENGTH (CK_ULONG)61U
+#define CK_ATTRIBUTES_TEMPLATE_LENGTH (CK_ULONG)60U
 
+// Group attributes based on their value types; put attributes whose values
+// requiring address alignments, e.g. CK_ULONG, first
 static CK_ATTRIBUTE ckpAttributesTemplate[CK_ATTRIBUTES_TEMPLATE_LENGTH] = {
-        {CKA_CLASS, 0, 0},
-        {CKA_TOKEN, 0, 0},
-        {CKA_PRIVATE, 0, 0},
-        {CKA_LABEL, 0, 0},
-        {CKA_APPLICATION, 0, 0},
-        {CKA_VALUE, 0, 0},
-        {CKA_OBJECT_ID, 0, 0},
+        // CK_ULONG
         {CKA_CERTIFICATE_TYPE, 0, 0},
-        {CKA_ISSUER, 0, 0},
-        {CKA_SERIAL_NUMBER, 0, 0},
-        {CKA_AC_ISSUER, 0, 0},
-        {CKA_OWNER, 0, 0},
-        {CKA_ATTR_TYPES, 0, 0},
-        {CKA_TRUSTED, 0, 0},
+        {CKA_CLASS, 0, 0},
+        {CKA_HW_FEATURE_TYPE, 0, 0},
+        {CKA_KEY_GEN_MECHANISM, 0, 0},
         {CKA_KEY_TYPE, 0, 0},
-        {CKA_SUBJECT, 0, 0},
-        {CKA_ID, 0, 0},
-        {CKA_SENSITIVE, 0, 0},
-        {CKA_ENCRYPT, 0, 0},
-        {CKA_DECRYPT, 0, 0},
-        {CKA_WRAP, 0, 0},
-        {CKA_UNWRAP, 0, 0},
-        {CKA_SIGN, 0, 0},
-        {CKA_SIGN_RECOVER, 0, 0},
-        {CKA_VERIFY, 0, 0},
-        {CKA_VERIFY_RECOVER, 0, 0},
-        {CKA_DERIVE, 0, 0},
-        {CKA_START_DATE, 0, 0},
-        {CKA_END_DATE, 0, 0},
-        {CKA_MODULUS, 0, 0},
         {CKA_MODULUS_BITS, 0, 0},
-        {CKA_PUBLIC_EXPONENT, 0, 0},
-        {CKA_PRIVATE_EXPONENT, 0, 0},
-        {CKA_PRIME_1, 0, 0},
-        {CKA_PRIME_2, 0, 0},
-        {CKA_EXPONENT_1, 0, 0},
-        {CKA_EXPONENT_2, 0, 0},
-        {CKA_COEFFICIENT, 0, 0},
-        {CKA_PRIME, 0, 0},
-        {CKA_SUBPRIME, 0, 0},
-        {CKA_BASE, 0, 0},
         {CKA_PRIME_BITS, 0, 0},
         {CKA_SUB_PRIME_BITS, 0, 0},
         {CKA_VALUE_BITS, 0, 0},
         {CKA_VALUE_LEN, 0, 0},
+        // CK_BBOOL
+        {CKA_ALWAYS_SENSITIVE, 0, 0},
+        {CKA_DECRYPT, 0, 0},
+        {CKA_DERIVE, 0, 0},
+        {CKA_ENCRYPT, 0, 0},
         {CKA_EXTRACTABLE, 0, 0},
+        {CKA_HAS_RESET, 0, 0},
         {CKA_LOCAL, 0, 0},
-        {CKA_NEVER_EXTRACTABLE, 0, 0},
-        {CKA_ALWAYS_SENSITIVE, 0, 0},
-        {CKA_KEY_GEN_MECHANISM, 0, 0},
         {CKA_MODIFIABLE, 0, 0},
-        {CKA_ECDSA_PARAMS, 0, 0},
+        {CKA_NEVER_EXTRACTABLE, 0, 0},
+        {CKA_PRIVATE, 0, 0},
+        {CKA_RESET_ON_INIT, 0, 0},
+        {CKA_SENSITIVE, 0, 0},
+        {CKA_SIGN, 0, 0},
+        {CKA_SIGN_RECOVER, 0, 0},
+        {CKA_TOKEN, 0, 0},
+        {CKA_TRUSTED, 0, 0},
+        {CKA_UNWRAP, 0, 0},
+        {CKA_VERIFY, 0, 0},
+        {CKA_VERIFY_RECOVER, 0, 0},
+        {CKA_WRAP, 0, 0},
+        // PTR: byte[]
+        {CKA_AC_ISSUER, 0, 0},
+        {CKA_ATTR_TYPES, 0, 0},
+        {CKA_BASE, 0, 0},
+        {CKA_COEFFICIENT, 0, 0},
         {CKA_EC_PARAMS, 0, 0},
         {CKA_EC_POINT, 0, 0},
+        {CKA_EXPONENT_1, 0, 0},
+        {CKA_EXPONENT_2, 0, 0},
+        {CKA_ID, 0, 0},
+        {CKA_ISSUER, 0, 0},
+        {CKA_MODULUS, 0, 0},
+        {CKA_OBJECT_ID, 0, 0},
+        {CKA_OWNER, 0, 0},
+        {CKA_PRIME, 0, 0},
+        {CKA_PRIME_1, 0, 0},
+        {CKA_PRIME_2, 0, 0},
+        {CKA_PRIVATE_EXPONENT, 0, 0},
+        {CKA_PUBLIC_EXPONENT, 0, 0},
+        {CKA_SERIAL_NUMBER, 0, 0},
+        {CKA_SUBJECT, 0, 0},
+        {CKA_SUBPRIME, 0, 0},
+        {CKA_VALUE, 0, 0},
+        // PTR: CK_UTF8CHAR[]
+        {CKA_APPLICATION, 0, 0},
+        {CKA_LABEL, 0, 0},
+        // PTR: CK_DATE
+        {CKA_START_DATE, 0, 0},
+        {CKA_END_DATE, 0, 0},
+        // deprecated
         {CKA_SECONDARY_AUTH, 0, 0},
         {CKA_AUTH_PIN_FLAGS, 0, 0},
-        {CKA_HW_FEATURE_TYPE, 0, 0},
-        {CKA_RESET_ON_INIT, 0, 0},
-        {CKA_HAS_RESET, 0, 0},
+        // misc
         {CKA_VENDOR_DEFINED, 0, 0},
+        // keep this at the end to match the impl in getNativeKeyInfo(...)
         {CKA_NETSCAPE_DB, 0, 0},
 };
 
diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c
index 9c854e09141..463818626dd 100644
--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c
+++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c
@@ -481,6 +481,10 @@ CK_MECHANISM_PTR updateGCMParams(JNIEnv *env, CK_MECHANISM_PTR mechPtr) {
             // CK_GCM_PARAMS => CK_GCM_PARAMS_NO_IVBITS
             pParams = (CK_GCM_PARAMS*) mechPtr->pParameter;
             pParamsNoIvBits = calloc(1, sizeof(CK_GCM_PARAMS_NO_IVBITS));
+            if (pParamsNoIvBits == NULL) {
+                p11ThrowOutOfMemoryError(env, 0);
+                return NULL;
+            }
             pParamsNoIvBits->pIv = pParams->pIv;
             pParamsNoIvBits->ulIvLen = pParams->ulIvLen;
             pParamsNoIvBits->pAAD = pParams->pAAD;
@@ -495,6 +499,10 @@ CK_MECHANISM_PTR updateGCMParams(JNIEnv *env, CK_MECHANISM_PTR mechPtr) {
             // CK_GCM_PARAMS_NO_IVBITS => CK_GCM_PARAMS
             pParamsNoIvBits = (CK_GCM_PARAMS_NO_IVBITS*) mechPtr->pParameter;
             pParams = calloc(1, sizeof(CK_GCM_PARAMS));
+            if (pParams == NULL) {
+                p11ThrowOutOfMemoryError(env, 0);
+                return NULL;
+            }
             pParams->pIv = pParamsNoIvBits->pIv;
             pParams->ulIvLen = pParamsNoIvBits->ulIvLen;
             pParams->ulIvBits = pParamsNoIvBits->ulIvLen << 3;
@@ -1201,7 +1209,7 @@ CK_VOID_PTR jObjectToPrimitiveCKObjectPtr(JNIEnv *env, jobject jObject, CK_ULONG
     jclass jBooleanArrayClass, jIntArrayClass, jLongArrayClass;
     jclass jStringClass;
     jclass jObjectClass, jClassClass;
-    CK_VOID_PTR ckpObject;
+    CK_VOID_PTR ckpObject = NULL;
     jmethodID jMethod;
     jobject jClassObject;
     jstring jClassNameString;
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java
index 20c5fabf8bc..f93728103e3 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java
@@ -180,6 +180,11 @@ public ImmutableOopMapSet getOopMaps() {
 
   public boolean isUpcallStub()         { return getKind() == UpcallKind; }
 
+  public boolean isContinuationStub()   {
+    // NOTE: In newer versions this is renamed to "continuation stubs" by JDK-8360707.
+    return getName().equals("StubRoutines (continuationstubs)");
+  }
+
   public boolean isJavaMethod()         { return false; }
 
   public boolean isNativeMethod()       { return false; }
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ContinuationEntry.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ContinuationEntry.java
new file mode 100644
index 00000000000..73152bdee84
--- /dev/null
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ContinuationEntry.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2025, NTT DATA.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.runtime;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.types.*;
+
+
+public class ContinuationEntry extends VMObject {
+    private static long size;
+    private static Address returnPC;
+
+    static {
+        VM.registerVMInitializedObserver((o, d) -> initialize(VM.getVM().getTypeDataBase()));
+    }
+
+    private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
+        Type type = db.lookupType("ContinuationEntry");
+        size = type.getSize();
+        returnPC = type.getAddressField("_return_pc").getValue();
+    }
+
+    public ContinuationEntry(Address addr) {
+        super(addr);
+    }
+
+    public Address getEntryPC() {
+        return returnPC;
+    }
+
+    public Address getEntrySP(){
+        return this.getAddress();
+    }
+
+    public Address getEntryFP(){
+        return this.getAddress().addOffsetTo(size);
+    }
+
+}
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java
index d92f464f0d2..826b5cecfd5 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java
@@ -47,6 +47,7 @@ public class JavaThread extends Thread {
   private static AddressField  stackBaseField;
   private static CIntegerField stackSizeField;
   private static CIntegerField terminatedField;
+  private static AddressField  contEntryField;
   private static AddressField activeHandlesField;
   private static CIntegerField monitorOwnerIDField;
   private static long oopPtrSize;
@@ -95,6 +96,7 @@ private static synchronized void initialize(TypeDataBase db) {
     stackBaseField    = type.getAddressField("_stack_base");
     stackSizeField    = type.getCIntegerField("_stack_size");
     terminatedField   = type.getCIntegerField("_terminated");
+    contEntryField    = type.getAddressField("_cont_entry");
     activeHandlesField = type.getAddressField("_active_handles");
     monitorOwnerIDField = type.getCIntegerField("_monitor_owner_id");
 
@@ -340,6 +342,10 @@ public int getTerminated() {
       return (int) terminatedField.getValue(addr);
   }
 
+  public ContinuationEntry getContEntry() {
+      return VMObjectFactory.newObject(ContinuationEntry.class, contEntryField.getValue(addr));
+  }
+
   /** Gets the Java-side thread object for this JavaThread */
   public Oop getThreadObj() {
     Oop obj = null;
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64Frame.java
index dca5f2efa3b..3746f676c11 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64Frame.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64Frame.java
@@ -292,7 +292,13 @@ public Frame sender(RegisterMap regMap, CodeBlob cb) {
     }
 
     if (cb != null) {
-      return cb.isUpcallStub() ? senderForUpcallStub(map, (UpcallStub)cb) : senderForCompiledFrame(map, cb);
+      if (cb.isUpcallStub()) {
+        return senderForUpcallStub(map, (UpcallStub)cb);
+      } else if (cb.isContinuationStub()) {
+        return senderForContinuationStub(map, cb);
+      } else {
+        return senderForCompiledFrame(map, cb);
+      }
     }
 
     // Must be native-compiled frame, i.e. the marshaling code for native
@@ -396,6 +402,16 @@ private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) {
     map.setLocation(fp, savedFPAddr);
   }
 
+  private Frame senderForContinuationStub(AARCH64RegisterMap map, CodeBlob cb) {
+    var contEntry = map.getThread().getContEntry();
+
+    Address senderSP = contEntry.getEntrySP();
+    Address senderPC = contEntry.getEntryPC();
+    Address senderFP = contEntry.getEntryFP();
+
+    return new AARCH64Frame(senderSP, senderFP, senderPC);
+  }
+
   private Frame senderForCompiledFrame(AARCH64RegisterMap map, CodeBlob cb) {
     if (DEBUG) {
       System.out.println("senderForCompiledFrame");
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java
index a47a632c286..c3cefc861e9 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java
@@ -279,7 +279,13 @@ public Frame sender(RegisterMap regMap, CodeBlob cb) {
     }
 
     if (cb != null) {
-      return cb.isUpcallStub() ? senderForUpcallStub(map, (UpcallStub)cb) : senderForCompiledFrame(map, cb);
+      if (cb.isUpcallStub()) {
+        return senderForUpcallStub(map, (UpcallStub)cb);
+      } else if (cb.isContinuationStub()) {
+        return senderForContinuationStub(map, cb);
+      } else {
+        return senderForCompiledFrame(map, cb);
+      }
     }
 
     // Must be native-compiled frame, i.e. the marshaling code for native
@@ -358,6 +364,15 @@ private Frame senderForInterpreterFrame(PPC64RegisterMap map) {
     return new PPC64Frame(sp, unextendedSP, getLink(), getSenderPC());
   }
 
+  private Frame senderForContinuationStub(PPC64RegisterMap map, CodeBlob cb) {
+    var contEntry = map.getThread().getContEntry();
+
+    Address sp = contEntry.getEntrySP();
+    Address pc = contEntry.getEntryPC();
+    Address fp = contEntry.getEntryFP();
+
+    return new PPC64Frame(sp, fp, pc);
+  }
 
   private Frame senderForCompiledFrame(PPC64RegisterMap map, CodeBlob cb) {
     if (DEBUG) {
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java
index 948a3008016..f9b09a94dd4 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java
@@ -284,7 +284,13 @@ public Frame sender(RegisterMap regMap, CodeBlob cb) {
     }
 
     if (cb != null) {
-      return cb.isUpcallStub() ? senderForUpcallStub(map, (UpcallStub)cb) : senderForCompiledFrame(map, cb);
+      if (cb.isUpcallStub()) {
+        return senderForUpcallStub(map, (UpcallStub)cb);
+      } else if (cb.isContinuationStub()) {
+        return senderForContinuationStub(map, cb);
+      } else {
+        return senderForCompiledFrame(map, cb);
+      }
     }
 
     // Must be native-compiled frame, i.e. the marshaling code for native
@@ -388,6 +394,16 @@ private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) {
     map.setLocation(fp, savedFPAddr);
   }
 
+  private Frame senderForContinuationStub(RISCV64RegisterMap map, CodeBlob cb) {
+    var contEntry = map.getThread().getContEntry();
+
+    Address senderSP = contEntry.getEntrySP();
+    Address senderPC = contEntry.getEntryPC();
+    Address senderFP = contEntry.getEntryFP();
+
+    return new RISCV64Frame(senderSP, senderFP, senderPC);
+  }
+
   private Frame senderForCompiledFrame(RISCV64RegisterMap map, CodeBlob cb) {
     if (DEBUG) {
       System.out.println("senderForCompiledFrame");
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java
index 169ecea1565..8ac68e6c7ca 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java
@@ -289,7 +289,13 @@ public Frame sender(RegisterMap regMap, CodeBlob cb) {
     }
 
     if (cb != null) {
-      return cb.isUpcallStub() ? senderForUpcallStub(map, (UpcallStub)cb) : senderForCompiledFrame(map, cb);
+      if (cb.isUpcallStub()) {
+        return senderForUpcallStub(map, (UpcallStub)cb);
+      } else if (cb.isContinuationStub()) {
+        return senderForContinuationStub(map, cb);
+      } else {
+        return senderForCompiledFrame(map, cb);
+      }
     }
 
     // Must be native-compiled frame, i.e. the marshaling code for native
@@ -393,6 +399,16 @@ private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) {
     map.setLocation(rbp, savedFPAddr);
   }
 
+  private Frame senderForContinuationStub(X86RegisterMap map, CodeBlob cb) {
+    var contEntry = map.getThread().getContEntry();
+
+    Address senderSP = contEntry.getEntrySP();
+    Address senderPC = contEntry.getEntryPC();
+    Address senderFP = contEntry.getEntryFP();
+
+    return new X86Frame(senderSP, senderFP, senderPC);
+  }
+
   private Frame senderForCompiledFrame(X86RegisterMap map, CodeBlob cb) {
     if (DEBUG) {
       System.out.println("senderForCompiledFrame");
diff --git a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/Headers.java b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/Headers.java
index 84535027eb4..279203d1d5b 100644
--- a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/Headers.java
+++ b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/Headers.java
@@ -36,6 +36,7 @@
 import java.util.function.BiFunction;
 import java.util.stream.Collectors;
 import sun.net.httpserver.UnmodifiableHeaders;
+import sun.net.httpserver.Utils;
 
 /**
  * HTTP request and response headers are represented by this class which
@@ -176,8 +177,13 @@ public String getFirst(String key) {
 
     @Override
     public List put(String key, List value) {
+        // checkHeader is called in this class to fail fast
+        // It also must be called in sendResponseHeaders because
+        // Headers instances internal state can be modified
+        // external to these methods.
+        Utils.checkHeader(key, false);
         for (String v : value)
-            checkValue(v);
+            Utils.checkHeader(v, true);
         return map.put(normalize(key), value);
     }
 
@@ -189,7 +195,8 @@ public List put(String key, List value) {
      * @param value the value to add to the header
      */
     public void add(String key, String value) {
-        checkValue(value);
+        Utils.checkHeader(key, false);
+        Utils.checkHeader(value, true);
         String k = normalize(key);
         List l = map.get(k);
         if (l == null) {
@@ -199,30 +206,6 @@ public void add(String key, String value) {
         l.add(value);
     }
 
-    private static void checkValue(String value) {
-        int len = value.length();
-        for (int i=0; i= len - 2) {
-                    throw new IllegalArgumentException("Illegal CR found in header");
-                }
-                char c1 = value.charAt(i+1);
-                char c2 = value.charAt(i+2);
-                if (c1 != '\n') {
-                    throw new IllegalArgumentException("Illegal char found after CR in header");
-                }
-                if (c2 != ' ' && c2 != '\t') {
-                    throw new IllegalArgumentException("No whitespace found after CRLF in header");
-                }
-                i+=2;
-            } else if (c == '\n') {
-                throw new IllegalArgumentException("Illegal LF found in header");
-            }
-        }
-    }
-
     /**
      * Sets the given {@code value} as the sole header value for the given
      * {@code key}. If the mapping does not already exist, then it is created.
@@ -264,7 +247,7 @@ public Set>> entrySet() {
     public void replaceAll(BiFunction, ? extends List> function) {
         var f = function.andThen(values -> {
             Objects.requireNonNull(values);
-            values.forEach(Headers::checkValue);
+            values.forEach(value -> Utils.checkHeader(value, true));
             return values;
         });
         Map.super.replaceAll(f);
diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java
index 1119d1e386b..818849a791e 100644
--- a/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java
+++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java
@@ -198,6 +198,8 @@ PlaceholderOutputStream getPlaceholderResponseBody () {
         return uos_orig;
     }
 
+    private static final byte[] CRLF = new byte[] {0x0D, 0x0A};
+
     public void sendResponseHeaders (int rCode, long contentLen)
     throws IOException
     {
@@ -206,10 +208,11 @@ public void sendResponseHeaders (int rCode, long contentLen)
             throw new IOException ("headers already sent");
         }
         this.rcode = rCode;
-        String statusLine = "HTTP/1.1 "+rCode+Code.msg(rCode)+"\r\n";
+        String statusLine = "HTTP/1.1 "+rCode+Code.msg(rCode);
         ByteArrayOutputStream tmpout = new ByteArrayOutputStream();
         PlaceholderOutputStream o = getPlaceholderResponseBody();
-        tmpout.write (bytes(statusLine, 0), 0, statusLine.length());
+        tmpout.write (bytes(statusLine, false, 0), 0, statusLine.length());
+        tmpout.write (CRLF);
         boolean noContentToSend = false; // assume there is content
         boolean noContentLengthHeader = false; // must not send Content-length is set
         rspHdrs.set("Date", FORMATTER.format(Instant.now()));
@@ -296,11 +299,11 @@ void write (Headers map, OutputStream os) throws IOException {
             List values = entry.getValue();
             for (String val : values) {
                 int i = key.length();
-                buf = bytes (key, 2);
+                buf = bytes (key, true, 2);
                 buf[i++] = ':';
                 buf[i++] = ' ';
                 os.write (buf, 0, i);
-                buf = bytes (val, 2);
+                buf = bytes (val, false, 2);
                 i = val.length();
                 buf[i++] = '\r';
                 buf[i++] = '\n';
@@ -318,8 +321,14 @@ void write (Headers map, OutputStream os) throws IOException {
      * Make sure that at least "extra" bytes are free at end
      * of rspbuf. Reallocate rspbuf if not big enough.
      * caller must check return value to see if rspbuf moved
+     *
+     * Header values are supposed to be limited to 7-bit ASCII
+     * but 8-bit has to be allowed (for ISO_8859_1). For efficiency
+     * we just down cast 16 bit Java chars to byte. We don't allow
+     * any character that can't be encoded in 8 bits.
      */
-    private byte[] bytes (String s, int extra) {
+    private byte[] bytes (String s, boolean isKey, int extra) throws IOException {
+        Utils.checkHeader(s, !isKey);
         int slen = s.length();
         if (slen+extra > rspbuf.length) {
             int diff = slen + extra - rspbuf.length;
diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/Utils.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/Utils.java
index 43dadb84a90..41834172f27 100644
--- a/src/jdk.httpserver/share/classes/sun/net/httpserver/Utils.java
+++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/Utils.java
@@ -88,4 +88,37 @@ public static boolean isQuotedStringContent(String token) {
         }
         return true;
     }
+
+    /* Throw IAE if illegal character found.  isValue is true if String is
+     * a value. Otherwise it is header name
+     */
+    public static void checkHeader(String str, boolean isValue) {
+        int len = str.length();
+        for (int i=0; i= len - 2) {
+                    throw new IllegalArgumentException("Illegal CR found in header");
+                }
+                char c1 = str.charAt(i+1);
+                char c2 = str.charAt(i+2);
+                if (c1 != '\n') {
+                    throw new IllegalArgumentException("Illegal char found after CR in header");
+                }
+                if (c2 != ' ' && c2 != '\t') {
+                    throw new IllegalArgumentException("No whitespace found after CRLF in header");
+                }
+                i+=2;
+            } else if (c == '\n') {
+                throw new IllegalArgumentException("Illegal LF found in header");
+            } else if (c > 255) {
+                throw new IllegalArgumentException("Illegal character found in header");
+            }
+        }
+    }
+
 }
diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java
index 365f6d1e68a..4e4751b264e 100644
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java
@@ -50,7 +50,7 @@ public class JdkConsoleProviderImpl implements JdkConsoleProvider {
      */
     @Override
     public JdkConsole console(boolean isTTY, Charset inCharset, Charset outCharset) {
-        return new LazyDelegatingJdkConsoleImpl(inCharset, outCharset);
+        return isTTY ? new LazyDelegatingJdkConsoleImpl(inCharset, outCharset) : null;
     }
 
     private static class LazyDelegatingJdkConsoleImpl implements JdkConsole {
diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java
index 0cb56354498..b25f7a09256 100644
--- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java
+++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java
@@ -654,6 +654,8 @@ native int installCode0(long compiledCodeBuffer,
                     long failedSpeculationsAddress,
                     byte[] speculations);
 
+    native String getInvalidationReasonDescription(int invalidationReason);
+
     /**
      * Gets flags specifying optional parts of code info. Only if a flag is set, will the
      * corresponding code info being included in the {@linkplain HotSpotCompiledCodeStream
@@ -842,7 +844,7 @@ void reprofile(HotSpotResolvedJavaMethodImpl method) {
      * {@code nmethod} associated with {@code nmethodMirror} is also made non-entrant and if
      * {@code deoptimize == true} any current activations of the {@code nmethod} are deoptimized.
      */
-    native void invalidateHotSpotNmethod(HotSpotNmethod nmethodMirror, boolean deoptimize);
+    native void invalidateHotSpotNmethod(HotSpotNmethod nmethodMirror, boolean deoptimize, int invalidationReason);
 
     /**
      * Collects the current values of all JVMCI benchmark counters, summed up over all threads.
diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java
index a0130d1bda9..9545c9aa9ec 100644
--- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java
+++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java
@@ -154,16 +154,20 @@ public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compile
         return logOrDump(resultInstalledCode, compiledCode);
     }
 
-    @Override
-    public void invalidateInstalledCode(InstalledCode installedCode) {
+    public void invalidateInstalledCode(InstalledCode installedCode, int invalidationReason) {
         if (installedCode instanceof HotSpotNmethod) {
             HotSpotNmethod nmethod = (HotSpotNmethod) installedCode;
-            nmethod.invalidate(true);
+            nmethod.invalidate(true, invalidationReason);
         } else {
             throw new IllegalArgumentException("Cannot invalidate a " + Objects.requireNonNull(installedCode).getClass().getName());
         }
     }
 
+    @Override
+    public void invalidateInstalledCode(InstalledCode installedCode) {
+        invalidateInstalledCode(installedCode, jvmciInvalidationReason());
+    }
+
     @Override
     public TargetDescription getTarget() {
         return target;
@@ -201,4 +205,8 @@ public int interpreterFrameSize(BytecodeFrame pos) {
     public void resetCompilationStatistics() {
         runtime.getCompilerToVM().resetCompilationStatistics();
     }
+
+    private static int jvmciInvalidationReason() {
+        return HotSpotJVMCIRuntime.runtime().config.getConstant("nmethod::InvalidationReason::JVMCI_INVALIDATE", Integer.class);
+    }
 }
diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java
index ebe2778ca3c..02e181347e9 100644
--- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java
+++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java
@@ -186,7 +186,10 @@ public static HotSpotJVMCIRuntime runtime() {
                         // Can only do eager initialization of the JVMCI compiler
                         // once the singleton instance is available.
                         if (result.config.getFlag("EagerJVMCI", Boolean.class)) {
-                            result.getCompiler();
+                            // EagerJVMCI only applies to JVMCI when used by the CompileBroker.
+                            if (result.getCompilerToVM().isCompilerThread()) {
+                                result.getCompiler();
+                            }
                         }
                     }
                     // Ensures JVMCIRuntime::_HotSpotJVMCIRuntime_instance is
diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl.java
index 55d5492c2f8..641dd4676ae 100644
--- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl.java
+++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2024, 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
@@ -43,9 +43,6 @@ static MetaspaceObject getMetaspaceObject(Constant constant) {
     private HotSpotMetaspaceConstantImpl(MetaspaceObject metaspaceObject, boolean compressed) {
         this.metaspaceObject = metaspaceObject;
         this.compressed = compressed;
-        if (compressed && !canBeStoredInCompressibleMetaSpace()) {
-            throw new IllegalArgumentException("constant cannot be compressed: " + metaspaceObject);
-        }
     }
 
     @Override
@@ -88,19 +85,7 @@ public boolean isCompressed() {
 
     @Override
     public boolean isCompressible() {
-        if (compressed) {
-            return false;
-        }
-        return canBeStoredInCompressibleMetaSpace();
-    }
-
-    private boolean canBeStoredInCompressibleMetaSpace() {
-        if (metaspaceObject instanceof HotSpotResolvedJavaType t && !t.isArray()) {
-            // As of JDK-8338526, interface and abstract types are not stored
-            // in compressible metaspace.
-            return !t.isInterface() && !t.isAbstract();
-        }
-        return true;
+        return !compressed;
     }
 
     @Override
diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotNmethod.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotNmethod.java
index 9ed03f9749e..5c7089da6cb 100644
--- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotNmethod.java
+++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotNmethod.java
@@ -27,6 +27,7 @@
 
 import jdk.vm.ci.code.InstalledCode;
 import jdk.vm.ci.code.InvalidInstalledCodeException;
+import jdk.vm.ci.common.JVMCIError;
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.JavaType;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -76,12 +77,19 @@ boolean inOopsTable() {
      */
     private final long compileIdSnapshot;
 
+    /**
+     * Identify the reason that caused this nmethod to be invalidated.
+     * A value of -1 means that the nmethod was not invalidated.
+     */
+    private int invalidationReason;
+
     HotSpotNmethod(HotSpotResolvedJavaMethodImpl method, String name, boolean isDefault, long compileId) {
         super(name);
         this.method = method;
         this.isDefault = isDefault;
         boolean inOopsTable = !IS_IN_NATIVE_IMAGE && !isDefault;
         this.compileIdSnapshot = inOopsTable ? 0L : compileId;
+        this.invalidationReason = -1;
         assert inOopsTable || compileId != 0L : this;
     }
 
@@ -122,9 +130,19 @@ public ResolvedJavaMethod getMethod() {
         return method;
     }
 
+    /**
+     * Invalidate this nmethod using the reason specified in {@code invalidationReason} and
+     * optionally deoptimize the method if {@code deoptimize} is set.
+     * @param deoptimize whether or not to deoptimize the method.
+     * @param invalidationReason invalidation reason code.
+     */
+    public void invalidate(boolean deoptimize, int invalidationReason) {
+        compilerToVM().invalidateHotSpotNmethod(this, deoptimize, invalidationReason);
+    }
+
     @Override
     public void invalidate(boolean deoptimize) {
-        compilerToVM().invalidateHotSpotNmethod(this, deoptimize);
+        invalidate(deoptimize, jvmciInvalidationReason());
     }
 
     @Override
@@ -188,4 +206,22 @@ public Object executeVarargs(Object... args) throws InvalidInstalledCodeExceptio
     public long getStart() {
         return isValid() ? super.getStart() : 0;
     }
+
+    /**
+     * @return an integer representing the reason why this nmethod was invalidated.
+     */
+    public int getInvalidationReason() {
+        return invalidationReason;
+    }
+
+    /**
+     * @return a String describing the reason why this nmethod was invalidated.
+     */
+    public String getInvalidationReasonDescription() {
+        return compilerToVM().getInvalidationReasonDescription(this.getInvalidationReason());
+    }
+
+    private static int jvmciInvalidationReason() {
+        return HotSpotJVMCIRuntime.runtime().config.getConstant("nmethod::InvalidationReason::JVMCI_INVALIDATE", Integer.class);
+    }
 }
diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java
index bc2e121fe90..e4e23c6d8b8 100644
--- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java
+++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/Main.java b/src/jdk.jartool/share/classes/sun/tools/jar/Main.java
index 60fb85baca8..38b0ba84c8a 100644
--- a/src/jdk.jartool/share/classes/sun/tools/jar/Main.java
+++ b/src/jdk.jartool/share/classes/sun/tools/jar/Main.java
@@ -420,7 +420,8 @@ public synchronized boolean run(String[] args) {
                 if (fname != null) {
                     file = new File(fname);
                 } else {
-                    file = createTemporaryFile("tmpJar", ".jar");
+                    tmpFile = createTemporaryFile("tmpJar", ".jar");
+                    file = tmpFile;
                     try (InputStream in = new FileInputStream(FileDescriptor.in);
                          OutputStream os = Files.newOutputStream(file.toPath())) {
                         in.transferTo(os);
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SearchWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SearchWriter.java
index 778e2625f32..433a641530d 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SearchWriter.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SearchWriter.java
@@ -108,6 +108,7 @@ private Content createModuleSelector() {
 
         var select = HtmlTree.of(HtmlTag.SELECT)
                 .setId(HtmlId.of("search-modules"))
+                .put(HtmlAttr.ARIA_LABEL, resources.getText("doclet.selectModule"))
                 .add(HtmlTree.of(HtmlTag.OPTION)
                         .put(HtmlAttr.VALUE, "")
                         .add(contents.getContent("doclet.search.all_modules")));
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties
index 9b111cb5edf..d469ef66534 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties
@@ -783,3 +783,6 @@ doclet.NoFrames_specified=\
 doclet.footer_specified=\
     The -footer option is no longer supported and will be ignored.\n\
     It may be removed in a future release.
+
+doclet.selectModule=\
+    Select the module to search in.
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/html/HtmlTree.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/html/HtmlTree.java
index 2d81a2914e6..f53a71a6999 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/html/HtmlTree.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/html/HtmlTree.java
@@ -586,8 +586,7 @@ public static HtmlTree EM(String body) {
      * @return the element
      */
     public static HtmlTree FOOTER() {
-        return new HtmlTree(HtmlTag.FOOTER)
-                .setRole(HtmlAttr.Role.CONTENTINFO);
+        return new HtmlTree(HtmlTag.FOOTER);
     }
 
     /**
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/MethodTraceEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/MethodTraceEvent.java
index a56de3e6fca..fa9d1345cd6 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/events/MethodTraceEvent.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/events/MethodTraceEvent.java
@@ -49,7 +49,7 @@ public static long timestamp() {
         return 0;
     }
 
-    public static boolean enabled() {
+    public static boolean shouldCommit(long duration) {
         // Generated by JFR
         return false;
     }
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java
index e574ab47992..22d55e6e99f 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java
@@ -291,7 +291,7 @@ private byte[] getBinaryRepresentation() {
         }
     }
 
-    synchronized boolean isEnabled(String eventName) {
+    boolean isEnabled(String eventName) {
         return settingsManager.isEnabled(eventName);
     }
 
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java
index 40876fae4e1..9b988139d44 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java
@@ -49,6 +49,7 @@ public final class PlatformEventType extends Type {
     private final boolean isJDK;
     private final boolean isMethodSampling;
     private final boolean isCPUTimeMethodSampling;
+    private final boolean isBackToBackSensitive;
     private final List settings = new ArrayList<>(5);
     private final boolean dynamicSettings;
     private final int stackTraceOffset;
@@ -82,10 +83,25 @@ public final class PlatformEventType extends Type {
         this.isJVM = Type.isDefinedByJVM(id);
         this.isMethodSampling = determineMethodSampling();
         this.isCPUTimeMethodSampling = isJVM && name.equals(Type.EVENT_NAME_PREFIX + "CPUTimeSample");
+        this.isBackToBackSensitive = determineBackToBackSensitive();
         this.isJDK = isJDK;
         this.stackTraceOffset = determineStackTraceOffset();
     }
 
+    private boolean determineBackToBackSensitive() {
+        if (getName().equals(Type.EVENT_NAME_PREFIX + "ThreadDump")) {
+            return true;
+        }
+        if (getName().equals(Type.EVENT_NAME_PREFIX + "ClassLoaderStatistics")) {
+            return true;
+        }
+        return false;
+    }
+
+    public boolean isBackToBackSensitive() {
+        return isBackToBackSensitive;
+    }
+
     private boolean isExceptionEvent() {
         switch (getName()) {
             case Type.EVENT_NAME_PREFIX + "JavaErrorThrow" :
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java
index 2184d85cf34..cf46c05b804 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java
@@ -263,7 +263,7 @@ synchronized long start(PlatformRecording recording) {
         if (toDisk) {
             PeriodicEvents.setFlushInterval(streamInterval);
         }
-        PeriodicEvents.doChunkBegin();
+        PeriodicEvents.doChunkBegin(true);
         Duration duration = recording.getDuration();
         if (duration != null) {
             recording.setStopTime(startTime.plus(duration));
@@ -335,7 +335,7 @@ synchronized void stop(PlatformRecording recording) {
                 finishChunk(currentChunk, stopTime, null);
             }
             currentChunk = newChunk;
-            PeriodicEvents.doChunkBegin();
+            PeriodicEvents.doChunkBegin(false);
         }
 
         if (toDisk) {
@@ -390,7 +390,7 @@ synchronized void rotateDisk() {
             finishChunk(currentChunk, timestamp, null);
         }
         currentChunk = newChunk;
-        PeriodicEvents.doChunkBegin();
+        PeriodicEvents.doChunkBegin(false);
     }
 
     private List getRunningRecordings() {
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/SettingsManager.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/SettingsManager.java
index 8521cd4303f..bd8fa078dc8 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/SettingsManager.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/SettingsManager.java
@@ -129,7 +129,7 @@ public void finish() {
         }
     }
 
-   private Map availableSettings = new LinkedHashMap<>();
+    private volatile Map availableSettings = new LinkedHashMap<>();
 
     void setSettings(List> activeSettings, boolean writeSettingEvents) {
         // store settings so they are available if a new event class is loaded
@@ -194,7 +194,7 @@ private Collection makeInternalSettings(Map rec
             String key = entry.getKey();
             String value = entry.getValue();
             int index = key.indexOf("#");
-            if (index > 1 && index < key.length() - 2) {
+            if (index > 0 && index < key.length() - 1) {
                 String eventName = key.substring(0, index);
                 eventName = Utils.upgradeLegacyJDKEvent(eventName);
                 InternalSetting s = internals.get(eventName);
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java
index 46dab564ac0..c8db9aef169 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java
@@ -257,6 +257,11 @@ private void processOrdered(Dispatcher c) throws IOException {
         }
         for (int i = 0; i < index; i++) {
             c.dispatch(sortedCache[i]);
+            sortedCache[i] = null;
+        }
+        // Shrink array
+        if (index > 100_000 && 4 * index < sortedCache.length) {
+            sortedCache = new RecordedEvent[2 * index];
         }
         onFlush();
         return;
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java
index 56d9fe01d79..82712fcbedc 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java
@@ -127,6 +127,10 @@ private void processOrdered(Dispatcher c) throws IOException {
                 cacheSorted[index++] = event;
             }
             dispatchOrdered(c, index);
+            if (index > 100_000 && 4 * index < cacheSorted.length) {
+                cacheSorted = new RecordedEvent[2 * index];
+            }
+            onFlush();
             index = 0;
         }
     }
@@ -136,8 +140,8 @@ private void dispatchOrdered(Dispatcher c, int index) {
         Arrays.sort(cacheSorted, 0, index, EVENT_COMPARATOR);
         for (int i = 0; i < index; i++) {
             c.dispatch(cacheSorted[i]);
+            cacheSorted[i] = null;
         }
-        onFlush();
     }
 
     private void processUnordered(Dispatcher c) throws IOException {
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/PeriodicEvents.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/PeriodicEvents.java
index 8cbf6334e64..92033dcce70 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/PeriodicEvents.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/PeriodicEvents.java
@@ -69,12 +69,14 @@ public static boolean removeEvent(Runnable runnable) {
         return taskRepository.removeTask(runnable);
     }
 
-    public static void doChunkBegin() {
+    public static void doChunkBegin(boolean startRecording) {
         long timestamp = JVM.counterTime();
         for (EventTask task : taskRepository.getTasks()) {
             var eventType = task.getEventType();
             if (eventType.isEnabled() && eventType.isBeginChunk()) {
-                task.run(timestamp, PeriodicType.BEGIN_CHUNK);
+                if (!eventType.isBackToBackSensitive() || startRecording) {
+                    task.run(timestamp, PeriodicType.BEGIN_CHUNK);
+                }
             }
         }
     }
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/tracing/MethodTracer.java b/src/jdk.jfr/share/classes/jdk/jfr/tracing/MethodTracer.java
index 0d7b8072194..c4cb0e4fa2c 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/tracing/MethodTracer.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/tracing/MethodTracer.java
@@ -50,7 +50,7 @@ public static long timestamp() {
     public static void traceObjectInit(long startTime, long methodId) {
         long endTime = JVM.counterTime();
         long duration = endTime - startTime;
-        if (MethodTraceEvent.enabled() && JVM.getEventWriter() != null) {
+        if (MethodTraceEvent.shouldCommit(duration) && JVM.getEventWriter() != null) {
             MethodTraceEvent.commit(startTime, duration, methodId);
         }
     }
@@ -66,7 +66,7 @@ public static void timingObjectInit(long startTime, long methodId) {
     public static void traceTimingObjectInit(long startTime, long methodId) {
         long endTime = JVM.counterTime();
         long duration = endTime - startTime;
-        if (MethodTraceEvent.enabled() && JVM.getEventWriter() != null) {
+        if (MethodTraceEvent.shouldCommit(duration) && JVM.getEventWriter() != null) {
             MethodTraceEvent.commit(startTime, duration, methodId);
         }
         if (MethodTimingEvent.enabled()) {
@@ -77,7 +77,7 @@ public static void traceTimingObjectInit(long startTime, long methodId) {
     public static void trace(long startTime, long methodId) {
         long endTime = JVM.counterTime();
         long duration = endTime - startTime;
-        if (MethodTraceEvent.enabled()) {
+        if (MethodTraceEvent.shouldCommit(duration)) {
             MethodTraceEvent.commit(startTime, duration, methodId);
         }
     }
@@ -96,7 +96,7 @@ public static void traceTiming(long startTime, long methodId) {
         if (MethodTimingEvent.enabled()) {
             PlatformTracer.addTiming(methodId, duration);
         }
-        if (MethodTraceEvent.enabled()) {
+        if (MethodTraceEvent.shouldCommit(duration)) {
             MethodTraceEvent.commit(startTime, duration, methodId);
         }
     }
diff --git a/src/jdk.jfr/share/conf/jfr/default.jfc b/src/jdk.jfr/share/conf/jfr/default.jfc
index 20051864895..eb3b8626722 100644
--- a/src/jdk.jfr/share/conf/jfr/default.jfc
+++ b/src/jdk.jfr/share/conf/jfr/default.jfc
@@ -33,12 +33,12 @@
     
 
     
-      true
+      false
       10 s
     
 
     
-      true
+      false
       10 s
     
 
@@ -762,7 +762,7 @@
     
 
     
-      true
+      false
       endChunk
     
 
diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/AppImageSigner.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/AppImageSigner.java
index d7b2431c1d3..a9ca374f295 100644
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/AppImageSigner.java
+++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/AppImageSigner.java
@@ -229,7 +229,7 @@ static Codesigners create(CodesignConfig signingCfg) {
 
             final var codesignExecutableFile = Codesign.build(signingCfg::toCodesignArgs).quiet(true).create().asConsumer();
             final var codesignFile = Codesign.build(signingCfgWithoutEntitlements::toCodesignArgs).quiet(true).create().asConsumer();
-            final var codesignDir = Codesign.build(signingCfgWithoutEntitlements::toCodesignArgs).force(true).create().asConsumer();
+            final var codesignDir = Codesign.build(signingCfg::toCodesignArgs).force(true).create().asConsumer();
 
             return new Codesigners(codesignFile, codesignExecutableFile, codesignDir);
         }
diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/SigningIdentityBuilder.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/SigningIdentityBuilder.java
index 119d7797453..bf8f1519fe1 100644
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/SigningIdentityBuilder.java
+++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/SigningIdentityBuilder.java
@@ -113,14 +113,16 @@ private SigningIdentity validatedSigningIdentity() throws ConfigException {
 
         final var signingIdentityNames = certificateSelector.signingIdentities();
 
+        // Look up for the exact match.
         var matchingCertificates = mappedCertficates.stream().filter(e -> {
             return signingIdentityNames.contains(e.getKey());
         }).map(Map.Entry::getValue).toList();
 
         if (matchingCertificates.isEmpty()) {
+            // No exact matches found, look up for substrings.
             matchingCertificates = mappedCertficates.stream().filter(e -> {
                 return signingIdentityNames.stream().anyMatch(filter -> {
-                    return filter.startsWith(e.getKey());
+                    return e.getKey().startsWith(filter);
                 });
             }).map(Map.Entry::getValue).toList();
         }
diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/FromParams.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/FromParams.java
index 92059b87590..201483c3a1f 100644
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/FromParams.java
+++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/FromParams.java
@@ -52,6 +52,7 @@
 
 import java.io.IOException;
 import java.nio.file.Path;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -194,8 +195,14 @@ private static ApplicationLaunchers createLaunchers(
 //                    mainParams), APP_NAME.fetchFrom(launcherParams)));
             launcherParams.put(DESCRIPTION.getID(), DESCRIPTION.fetchFrom(mainParams));
         }
-        return AddLauncherArguments.merge(mainParams, launcherParams, ICON.getID(), ADD_LAUNCHERS
-                .getID(), FILE_ASSOCIATIONS.getID());
+
+        var excludes = new ArrayList(List.of(ICON.getID(), ADD_LAUNCHERS.getID()));
+        if (!NAME.findIn(mainParams).equals(NAME.findIn(launcherParams))) {
+            // This is the additional launcher. It shouldn't have FA.
+            excludes.add(FILE_ASSOCIATIONS.getID());
+        }
+
+        return AddLauncherArguments.merge(mainParams, launcherParams, excludes.toArray(String[]::new));
     }
 
     static final BundlerParamInfo APPLICATION = createApplicationBundlerParam(null);
diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/PListReader.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/PListReader.java
index 211a55897d0..6d7532bbd74 100644
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/PListReader.java
+++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/PListReader.java
@@ -24,21 +24,141 @@
  */
 package jdk.jpackage.internal.util;
 
+import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier;
+
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.stream.Stream;
 import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPath;
 import javax.xml.xpath.XPathConstants;
 import javax.xml.xpath.XPathFactory;
-import jdk.jpackage.internal.util.function.ThrowingSupplier;
+import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.xml.sax.SAXException;
 
+/**
+ * Property list (plist) file reader.
+ */
 public final class PListReader {
 
+    public record Raw(String value, Type type) {
+
+        public enum Type {
+            STRING,
+            BOOLEAN,
+            REAL,
+            INTEGER,
+            DATE,
+            DATA;
+
+            private static Optional fromElementName(String name) {
+                switch (name) {
+                    case "string" -> {
+                        return Optional.of(STRING);
+                    }
+                    case "true" -> {
+                        return Optional.of(BOOLEAN);
+                    }
+                    case "false" -> {
+                        return Optional.of(BOOLEAN);
+                    }
+                    case "real" -> {
+                        return Optional.of(REAL);
+                    }
+                    case "integer" -> {
+                        return Optional.of(INTEGER);
+                    }
+                    case "date" -> {
+                        return Optional.of(DATE);
+                    }
+                    case "data" -> {
+                        return Optional.of(DATA);
+                    }
+                    default -> {
+                        return Optional.empty();
+                    }
+                }
+            }
+        }
+
+        public Raw {
+            Objects.requireNonNull(value);
+            Objects.requireNonNull(type);
+        }
+
+        private static Optional tryCreate(Element e) {
+            return Type.fromElementName(e.getNodeName()).map(type -> {
+                if (type == Type.BOOLEAN) {
+                    if ("true".equals(e.getNodeName())) {
+                        return new Raw(Boolean.TRUE.toString(), type);
+                    } else {
+                        return new Raw(Boolean.FALSE.toString(), type);
+                    }
+                } else {
+                    return new Raw(e.getTextContent(), type);
+                }
+            });
+        }
+    }
+
+    /**
+     * Returns the contents of the the underlying "dict" element as a Map.
+     * 

+ * The keys in the returned map are names of the properties. + *

+ * Values of nested "dict" properties are stored as {@code Map} + * or {@code PListReader} objects depending on the value of the + * {@code fetchDictionaries} parameter. + *

+ * Values of "array" properties are stored as {@code List} objects. + *

+ * Values of other properties are stored as {@code Raw} objects. + * + * @param fetchDictionaries controls the type of objects of nested "dict" + * elements. If the value is {@code true}, + * {@code Map} type is used, and + * {@code PListReader} type otherwise. + * @return the contents of the the underlying "dict" element as a Map + */ + public Map toMap(boolean fetchDictionaries) { + Map reply = new HashMap<>(); + var nodes = root.getChildNodes(); + for (int i = 0; i != nodes.getLength(); i++) { + if (nodes.item(i) instanceof Element e) { + tryCreateValue(e, fetchDictionaries).ifPresent(value -> { + final var query = "preceding-sibling::*[1]"; + Optional.ofNullable(toSupplier(() -> { + return (Node) XPathSingleton.INSTANCE.evaluate(query, e, XPathConstants.NODE); + }).get()).ifPresent(n -> { + if ("key".equals(n.getNodeName())) { + var keyName = n.getTextContent(); + reply.putIfAbsent(keyName, value); + } + }); + }); + } + } + + return reply; + } + + /** + * Returns the value of the given string property in the underlying "dict" + * element. + * + * @param keyName the name of a string property whose value to query + * @return the value of the string property with the specified name in the + * underlying "dict" element + * @throws NoSuchElementException if there is no string property with the given + * name in the underlying "dict" element + */ public String queryValue(String keyName) { final var node = getNode(keyName); switch (node.getNodeName()) { @@ -51,6 +171,38 @@ public String queryValue(String keyName) { } } + /** + * Returns the value of the given "dict" property in the underlying "dict" + * element. + * + * @param keyName the name of a "dict" property whose value to query + * @return the value of the "dict" property with the specified name in the + * underlying "dict" element + * @throws NoSuchElementException if there is no "dict" property with the given + * name in the underlying "dict" element + */ + public PListReader queryDictValue(String keyName) { + final var node = getNode(keyName); + switch (node.getNodeName()) { + case "dict" -> { + return new PListReader(node); + } + default -> { + throw new NoSuchElementException(); + } + } + } + + /** + * Returns the value of the given boolean property in the underlying "dict" + * element. + * + * @param keyName the name of a boolean property whose value to query + * @return the value of the boolean property with the specified name in the + * underlying "dict" element + * @throws NoSuchElementException if there is no string property with the given + * name in the underlying "dict" element + */ public boolean queryBoolValue(String keyName) { final var node = getNode(keyName); switch (node.getNodeName()) { @@ -66,13 +218,58 @@ public boolean queryBoolValue(String keyName) { } } - public List queryArrayValue(String keyName) { + /** + * Returns the value of the given array property in the underlying "dict" + * element as a list of strings. + *

+ * Processes the result of calling {@link #queryArrayValue(String)} on the + * specified property name by filtering {@link Raw} instances of type + * {@link Raw.Type#STRING}. + * + * @param keyName the name of an array property whose value to query + * @return the value of the array property with the specified name in the + * underlying "dict" element + * @throws NoSuchElementException if there is no array property with the given + * name in the underlying "dict" element + */ + public List queryStringArrayValue(String keyName) { + return queryArrayValue(keyName, false).map(v -> { + if (v instanceof Raw r) { + if (r.type() == Raw.Type.STRING) { + return r.value(); + } + } + return (String)null; + }).filter(Objects::nonNull).toList(); + } + + /** + * Returns the value of the given array property in the underlying "dict" + * element as a stream of {@link Object}-s. + *

+ * Values of "dict" array items are stored as {@code Map} or + * {@code PListReader} objects depending on the value of the + * {@code fetchDictionaries} parameter. + *

+ * Values of "array" array items are stored as {@code List} objects. + *

+ * Values of other types are stored as {@code Raw} objects. + * + * @param keyName the name of an array property whose value to query + * @param fetchDictionaries controls the type of objects of "dict" elements. If + * the value is {@code true}, + * {@code Map} type is used, and + * {@code PListReader} type otherwise. + * @return the value of the array property with the specified name in the + * underlying "dict" element + * @throws NoSuchElementException if there is no array key with the given name + * in the underlying "dict" element + */ + public Stream queryArrayValue(String keyName, boolean fetchDictionaries) { final var node = getNode(keyName); switch (node.getNodeName()) { case "array" -> { - return XmlUtils.toStream(node.getChildNodes()).filter(n -> { - return n.getNodeName().equals("string"); - }).map(Node::getTextContent).toList(); + return readArray(node, fetchDictionaries); } default -> { throw new NoSuchElementException(); @@ -80,21 +277,75 @@ public List queryArrayValue(String keyName) { } } - public PListReader(Node doc) { - this.root = Objects.requireNonNull(doc); + /** + * Creates plist reader from the given node. + *

+ * If the specified node is an element with the name "dict", the reader is bound + * to the specified node; otherwise, it is bound to the {@code /plist/dict} + * element in the document. + * + * @param node the node + * @throws NoSuchElementException if the specified node is not an element with + * name "dict" and there is no + * {@code /plist/dict} node in the document + */ + public PListReader(Node node) { + Objects.requireNonNull(node); + if (node.getNodeName().equals("dict")) { + this.root = node; + } else { + this.root = Optional.ofNullable(toSupplier(() -> { + return (Node) XPathSingleton.INSTANCE.evaluate("/plist[1]/dict[1]", node, XPathConstants.NODE); + }).get()).orElseThrow(NoSuchElementException::new); + } } public PListReader(byte[] xmlData) throws ParserConfigurationException, SAXException, IOException { this(XmlUtils.initDocumentBuilder().parse(new ByteArrayInputStream(xmlData))); } + private Optional tryCreateValue(Element e, boolean fetchDictionaries) { + switch (e.getNodeName()) { + case "dict" -> { + var plistReader = new PListReader(e); + if (fetchDictionaries) { + return Optional.of(plistReader.toMap(fetchDictionaries)); + } else { + return Optional.of(plistReader); + } + } + case "array" -> { + return Optional.of(readArray(e, fetchDictionaries).toList()); + } + default -> { + return Raw.tryCreate(e); + } + } + } + + private Stream readArray(Node node, boolean fetchDictionaries) { + return XmlUtils.toStream(node.getChildNodes()).map(n -> { + if (n instanceof Element e) { + return tryCreateValue(e, fetchDictionaries); + } else { + return Optional.empty(); + } + }).filter(Optional::isPresent).map(Optional::get); + } + private Node getNode(String keyName) { - final var xPath = XPathFactory.newInstance().newXPath(); - final var query = String.format("//*[preceding-sibling::key = \"%s\"][1]", keyName); - return Optional.ofNullable(ThrowingSupplier.toSupplier(() -> { - return (Node) xPath.evaluate(query, root, XPathConstants.NODE); + Objects.requireNonNull(keyName); + final var query = String.format("*[preceding-sibling::key = \"%s\"][1]", keyName); + return Optional.ofNullable(toSupplier(() -> { + return (Node) XPathSingleton.INSTANCE.evaluate(query, root, XPathConstants.NODE); }).get()).orElseThrow(NoSuchElementException::new); } + + private static final class XPathSingleton { + private static final XPath INSTANCE = XPathFactory.newInstance().newXPath(); + } + + private final Node root; } diff --git a/src/jdk.jpackage/windows/native/applauncher/WinLauncher.cpp b/src/jdk.jpackage/windows/native/applauncher/WinLauncher.cpp index fe59cd94b84..8b3c3bb6aef 100644 --- a/src/jdk.jpackage/windows/native/applauncher/WinLauncher.cpp +++ b/src/jdk.jpackage/windows/native/applauncher/WinLauncher.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -256,6 +256,16 @@ bool needRestartLauncher(AppLauncher& appLauncher, CfgFile& cfgFile) { } +void enableConsoleCtrlHandler(bool enable) { + if (!SetConsoleCtrlHandler(NULL, enable ? FALSE : TRUE)) { + JP_THROW(SysError(tstrings::any() << "SetConsoleCtrlHandler(NULL, " + << (enable ? "FALSE" : "TRUE") + << ") failed", + SetConsoleCtrlHandler)); + } +} + + void launchApp() { // [RT-31061] otherwise UI can be left in back of other windows. ::AllowSetForegroundWindow(ASFW_ANY); @@ -310,6 +320,19 @@ void launchApp() { exec.arg(arg); }); + exec.afterProcessCreated([&](HANDLE pid) { + // + // Ignore Ctrl+C in the current process. + // This will prevent child process termination without allowing + // it to handle Ctrl+C events. + // + // Disable the default Ctrl+C handler *after* the child process + // has been created as it is inheritable and we want the child + // process to have the default handler. + // + enableConsoleCtrlHandler(false); + }); + DWORD exitCode = RunExecutorWithMsgLoop::apply(exec); exit(exitCode); diff --git a/src/jdk.jpackage/windows/native/common/Executor.cpp b/src/jdk.jpackage/windows/native/common/Executor.cpp index edb850afdbb..dfb6b299e5d 100644 --- a/src/jdk.jpackage/windows/native/common/Executor.cpp +++ b/src/jdk.jpackage/windows/native/common/Executor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -161,6 +161,10 @@ UniqueHandle Executor::startProcess(UniqueHandle* threadHandle) const { } } + if (afterProcessCreatedCallback) { + afterProcessCreatedCallback(processInfo.hProcess); + } + // Return process handle. return UniqueHandle(processInfo.hProcess); } diff --git a/src/jdk.jpackage/windows/native/common/Executor.h b/src/jdk.jpackage/windows/native/common/Executor.h index a6edcbd4f76..09c9f85bac6 100644 --- a/src/jdk.jpackage/windows/native/common/Executor.h +++ b/src/jdk.jpackage/windows/native/common/Executor.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,8 @@ #ifndef EXECUTOR_H #define EXECUTOR_H +#include + #include "tstrings.h" #include "UniqueHandle.h" @@ -97,6 +99,14 @@ class Executor { */ int execAndWaitForExit() const; + /** + * Call provided function after the process hass been created. + */ + Executor& afterProcessCreated(const std::function& v) { + afterProcessCreatedCallback = v; + return *this; + } + private: UniqueHandle startProcess(UniqueHandle* threadHandle=0) const; @@ -106,6 +116,7 @@ class Executor { HANDLE jobHandle; tstring_array argsArray; std::wstring appPath; + std::function afterProcessCreatedCallback; }; #endif // #ifndef EXECUTOR_H diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/RemoteRecordingStream.java b/src/jdk.management.jfr/share/classes/jdk/management/jfr/RemoteRecordingStream.java index 862781802fc..a8752e159ad 100644 --- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/RemoteRecordingStream.java +++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/RemoteRecordingStream.java @@ -98,10 +98,12 @@ static final class RemoteSettings implements EventSettingsModifier { private final FlightRecorderMXBean mbean; private final long recordingId; + private final String identifier; - RemoteSettings(FlightRecorderMXBean mbean, long recordingId) { + RemoteSettings(FlightRecorderMXBean mbean, long recordingId, String identifier) { this.mbean = mbean; this.recordingId = recordingId; + this.identifier = identifier; } @Override @@ -111,7 +113,7 @@ public void with(String name, String value) { // FlightRecorderMXBean implementation always returns // new instance of Map so no need to create new here. Map newSettings = getEventSettings(); - newSettings.put(name, value); + newSettings.put(identifier + "#" + name, value); mbean.setRecordingSettings(recordingId, newSettings); } @@ -340,9 +342,9 @@ public void setSettings(Map settings) { */ public EventSettings disable(String name) { Objects.requireNonNull(name, "name"); - EventSettings s = ManagementSupport.newEventSettings(new RemoteSettings(mbean, recordingId)); + EventSettings s = ManagementSupport.newEventSettings(new RemoteSettings(mbean, recordingId, name)); try { - return s.with(name + "#" + ENABLED, "false"); + return s.with(ENABLED, "false"); } catch (Exception e) { ManagementSupport.logDebug(e.getMessage()); close(); @@ -364,9 +366,9 @@ public EventSettings disable(String name) { */ public EventSettings enable(String name) { Objects.requireNonNull(name, "name"); - EventSettings s = ManagementSupport.newEventSettings(new RemoteSettings(mbean, recordingId)); + EventSettings s = ManagementSupport.newEventSettings(new RemoteSettings(mbean, recordingId, name)); try { - return s.with(name + "#" + ENABLED, "true"); + return s.with(ENABLED, "true"); } catch (Exception e) { ManagementSupport.logDebug(e.getMessage()); close(); diff --git a/src/jdk.management/aix/native/libmanagement_ext/UnixOperatingSystem.c b/src/jdk.management/aix/native/libmanagement_ext/UnixOperatingSystem.c index 228c5eb5c14..ec738c6c1ce 100644 --- a/src/jdk.management/aix/native/libmanagement_ext/UnixOperatingSystem.c +++ b/src/jdk.management/aix/native/libmanagement_ext/UnixOperatingSystem.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2015, 2020 SAP SE. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,20 +28,111 @@ /* Implement and update https://bugs.openjdk.org/browse/JDK-8030957 */ #include +#include +#include +#include +#include #include "com_sun_management_internal_OperatingSystemImpl.h" +static struct perfMetrics{ + unsigned long long timebase; + perfstat_process_t stats; + perfstat_cpu_total_t cpu_total; +} counters; + +static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + +int perfInit() { + static int initialized = 0; + if (!initialized) { + + perfstat_id_t id; + counters.stats = (perfstat_process_t){0}; + counters.timebase = 0; + int rc = perfstat_cpu_total(NULL, &counters.cpu_total, sizeof(perfstat_cpu_total_t), 1); + if (rc < 0) { + return -1; + } + rc = perfstat_process(&id, &counters.stats, sizeof(perfstat_process_t), 1); + if (rc < 0) { + return -1; + } + counters.timebase = counters.stats.last_timebase; + initialized = 1; + } + return initialized ? 0 : -1; +} + JNIEXPORT jdouble JNICALL Java_com_sun_management_internal_OperatingSystemImpl_getCpuLoad0 (JNIEnv *env, jobject dummy) { - return -1.0; + double load = -1.0; + pthread_mutex_lock(&lock); + if (perfInit() == 0) { + int ret; + perfstat_cpu_total_t cpu_total; + ret = perfstat_cpu_total(NULL, &cpu_total, sizeof(perfstat_cpu_total_t), 1); + if (ret < 0) { + return -1.0; + } + long long user_diff = cpu_total.user - counters.cpu_total.user; + long long sys_diff = cpu_total.sys - counters.cpu_total.sys; + long long idle_diff = cpu_total.idle - counters.cpu_total.idle; + long long wait_diff = cpu_total.wait - counters.cpu_total.wait; + long long total = user_diff + sys_diff + idle_diff + wait_diff; + if (total < (user_diff + sys_diff)) { + total = user_diff + sys_diff; + } + if (total == 0) { + load = 0.0; + } else { + load = (double)(user_diff + sys_diff) / total; + load = MAX(load, 0.0); + load = MIN(load, 1.0); + } + counters.cpu_total = cpu_total; + } + pthread_mutex_unlock(&lock); + return load; } JNIEXPORT jdouble JNICALL Java_com_sun_management_internal_OperatingSystemImpl_getProcessCpuLoad0 (JNIEnv *env, jobject dummy) { - return -1.0; + perfstat_process_t curr_stats; + perfstat_id_t id; + unsigned long long curr_timebase, timebase_diff; + double user_diff, sys_diff, delta_time; + double cpu_load = -1.0; + pthread_mutex_lock(&lock); + if (perfInit() == 0) { + int ret; + ret = perfstat_process(&id, &curr_stats, sizeof(perfstat_process_t), 1); + if (ret < 0) { + return -1.0; + } + curr_timebase = curr_stats.last_timebase; + timebase_diff = curr_timebase - counters.timebase; + if ((long long)timebase_diff < 0 || XINTFRAC == 0) { + return -1.0; + } + delta_time = HTIC2NANOSEC(timebase_diff) / 1000000000.0; + user_diff = (double)(curr_stats.ucpu_time - counters.stats.ucpu_time); + sys_diff = (double)(curr_stats.scpu_time - counters.stats.scpu_time); + counters.stats = curr_stats; + counters.timebase = curr_timebase; + if (delta_time == 0) { + cpu_load = 0.0; + } else { + cpu_load = (user_diff + sys_diff) / delta_time; + cpu_load = MAX(cpu_load, 0.0); + cpu_load = MIN(cpu_load, 1.0); + } + } + pthread_mutex_unlock(&lock); + return (jdouble)cpu_load; } JNIEXPORT jdouble JNICALL diff --git a/src/jdk.management/linux/native/libmanagement_ext/UnixOperatingSystem.c b/src/jdk.management/linux/native/libmanagement_ext/UnixOperatingSystem.c index af7d52424b7..326dd916f7e 100644 --- a/src/jdk.management/linux/native/libmanagement_ext/UnixOperatingSystem.c +++ b/src/jdk.management/linux/native/libmanagement_ext/UnixOperatingSystem.c @@ -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 @@ -195,7 +195,7 @@ static int get_jvmticks(ticks *pticks) { uint64_t userTicks; uint64_t systemTicks; - if (read_ticks("/proc/self/stat", &userTicks, &systemTicks) < 0) { + if (read_ticks("/proc/self/stat", &userTicks, &systemTicks) != 2) { return -1; } diff --git a/test/docs/TEST.ROOT b/test/docs/TEST.ROOT index 9be915dd4ff..bcbfd717dc0 100644 --- a/test/docs/TEST.ROOT +++ b/test/docs/TEST.ROOT @@ -38,7 +38,7 @@ groups=TEST.groups # Minimum jtreg version -requiredVersion=7.5.1+1 +requiredVersion=8+2 # Use new module options useNewOptions=true diff --git a/test/hotspot/gtest/gc/shenandoah/test_shenandoahAgeCensus.cpp b/test/hotspot/gtest/gc/shenandoah/test_shenandoahAgeCensus.cpp new file mode 100644 index 00000000000..c53d0a15554 --- /dev/null +++ b/test/hotspot/gtest/gc/shenandoah/test_shenandoahAgeCensus.cpp @@ -0,0 +1,159 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "gc/shenandoah/shenandoahAgeCensus.hpp" +#include "unittest.hpp" + +class ShenandoahAgeCensusTest : public ::testing::Test { +protected: + static constexpr size_t MinimumPopulationSize = 4*K; + static constexpr size_t InitialPopulationSize = MinimumPopulationSize * 1000; + + size_t _cohorts_count = ShenandoahAgeCensus::MAX_COHORTS; + double _mortality_rates[ShenandoahAgeCensus::MAX_COHORTS]; + size_t _cohort_populations[ShenandoahAgeCensus::MAX_COHORTS]; + + ShenandoahAgeCensusTest() + : _mortality_rates{0.9, 0.7, 0.5, 0.3, 0.09, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0} + { + build_cohort_populations(_mortality_rates, _cohort_populations, _cohorts_count); + } + + static void add_population(ShenandoahAgeCensus& census, const uint age, const size_t population_words) { + CENSUS_NOISE(census.add(age, 0, 0, population_words, 0)); + NO_CENSUS_NOISE(census.add(age, 0, population_words, 0)); + } + + void update(ShenandoahAgeCensus& census, size_t cohorts) const { + for (uint i = 1; i < cohorts; i++) { + add_population(census, i, _cohort_populations[i]); + } + census.update_census(_cohort_populations[0]); + } + + void update(ShenandoahAgeCensus& census) const { + update(census, _cohorts_count); + } + + size_t get_total_population_older_than(const size_t min_cohort_age) const { + size_t total = 0; + for (size_t i = 0; i < _cohorts_count; i++) { + if (i >= min_cohort_age) { + total += _cohort_populations[i]; + } + } + return total; + } + + void promote_all_tenurable(const size_t tenuring_threshold) { + for (size_t i = 0; i < _cohorts_count; i++) { + if (i > tenuring_threshold) { + _cohort_populations[i] = 0; + } + } + } + + static void build_cohort_populations(const double mortality_rates[], size_t cohort_populations[], const size_t cohorts) { + cohort_populations[0] = InitialPopulationSize; + for (size_t i = 1; i < cohorts; i++) { + cohort_populations[i] = cohort_populations[i - 1] * (1.0 - mortality_rates[i - 1]); + } + } +}; + +TEST_F(ShenandoahAgeCensusTest, initialize) { + const ShenandoahAgeCensus census(1); + EXPECT_EQ(census.tenuring_threshold(), ShenandoahAgeCensus::MAX_COHORTS); +} + +TEST_F(ShenandoahAgeCensusTest, ignore_small_populations) { + // Small populations are ignored so we do not return early before reaching the youngest cohort. + ShenandoahAgeCensus census(1); + add_population(census,1, 32); + add_population(census,1, 32); + census.update_census(64); + EXPECT_EQ(1u, census.tenuring_threshold()); +} + +TEST_F(ShenandoahAgeCensusTest, find_high_mortality_rate) { + ShenandoahAgeCensus census(1); + + // Initial threshold, no data + EXPECT_EQ(16u, census.tenuring_threshold()); + + // Provide population data for 1st cohort. Previous epoch has no population data so our + // algorithm skips over all cohorts, leaving tenuring threshold at 1. + update(census, 1); + EXPECT_EQ(1u, census.tenuring_threshold()); + + // Mortality rate of 1st cohort at age 1 is 0.9, we don't want to promote here. Move threshold to 2. + update(census, 2); + EXPECT_EQ(2u, census.tenuring_threshold()); + + // Mortality rate of 1st cohort at age 2 is 0.7, we don't want to promote here. Move threshold to 3. + update(census, 3); + EXPECT_EQ(3u, census.tenuring_threshold()); + + // Mortality rate of 1st cohort at age 3 is 0.5, we don't want to promote here. Move threshold to 4. + update(census, 4); + EXPECT_EQ(4u, census.tenuring_threshold()); + + // Mortality rate of 1st cohort at age 4 is 0.3, we don't want to promote here. Move threshold to 5. + update(census, 5); + EXPECT_EQ(5u, census.tenuring_threshold()); + + // Mortality rate of 1st cohort at age 5 is 0.09, this is less than the mortality rate threshold. It + // is okay to tenure objects older than 5 now. Keep threshold at 5. + update(census, 6); + EXPECT_EQ(5u, census.tenuring_threshold()); + + // Mortality rate at this age is 0. Keep tenuring threshold at 5. + update(census, 7); + EXPECT_EQ(5u, census.tenuring_threshold()); +} + +TEST_F(ShenandoahAgeCensusTest, ignore_mortality_caused_by_promotions) { + ShenandoahAgeCensus census(1); + + // Simulate a sequence of censuses with the same mortality rate. Each one will see a + // mortality rate above the tenuring threshold and raise the tenuring threshold by one. + update(census, 1); + update(census, 2); + update(census, 3); + update(census, 4); + update(census, 5); + + EXPECT_EQ(5u, census.tenuring_threshold()); + + // Simulate the effect of promoting all objects above the tenuring threshold + // out of the young generation. This will look like a very high (100%) mortality + // rate for these cohorts. However, we do _not_ want to raise the threshold in + // this case because these objects haven't really "died", they have just been + // tenured. + promote_all_tenurable(census.tenuring_threshold()); + update(census); + + // We want this to stay at 5 - the mortality in 1st cohort at age 6 was caused by expected promotions. + EXPECT_EQ(5u, census.tenuring_threshold()); +} diff --git a/test/hotspot/gtest/gc/shenandoah/test_shenandoahCollectorPolicy.cpp b/test/hotspot/gtest/gc/shenandoah/test_shenandoahCollectorPolicy.cpp new file mode 100644 index 00000000000..b5c974f65ad --- /dev/null +++ b/test/hotspot/gtest/gc/shenandoah/test_shenandoahCollectorPolicy.cpp @@ -0,0 +1,72 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "gc/shenandoah/shenandoahCollectorPolicy.hpp" +#include "unittest.hpp" + +TEST(ShenandoahCollectorPolicyTest, track_degen_cycles_sanity) { + ShenandoahCollectorPolicy policy; + EXPECT_EQ(policy.consecutive_degenerated_gc_count(), 0UL); + EXPECT_EQ(policy.generational_should_upgrade_degenerated_gc(), false); +} + +TEST(ShenandoahCollectorPolicyTest, track_degen_cycles_no_upgrade) { + ShenandoahCollectorPolicy policy; + policy.record_degenerated(true, true, true); + policy.record_degenerated(true, true, true); + EXPECT_EQ(policy.consecutive_degenerated_gc_count(), 2UL); + EXPECT_EQ(policy.generational_should_upgrade_degenerated_gc(), false); +} + +TEST(ShenandoahCollectorPolicyTest, track_degen_cycles_upgrade) { + ShenandoahCollectorPolicy policy; + policy.record_degenerated(true, true, false); + policy.record_degenerated(true, true, false); + EXPECT_EQ(policy.consecutive_degenerated_gc_count(), 2UL); + EXPECT_EQ(policy.generational_should_upgrade_degenerated_gc(), true); +} + +TEST(ShenandoahCollectorPolicyTest, track_degen_cycles_reset_progress) { + ShenandoahCollectorPolicy policy; + policy.record_degenerated(true, true, false); + policy.record_degenerated(true, true, true); + EXPECT_EQ(policy.consecutive_degenerated_gc_count(), 2UL); + EXPECT_EQ(policy.generational_should_upgrade_degenerated_gc(), false); +} + +TEST(ShenandoahCollectorPolicyTest, track_degen_cycles_full_reset) { + ShenandoahCollectorPolicy policy; + policy.record_degenerated(true, true, false); + policy.record_success_full(); + EXPECT_EQ(policy.consecutive_degenerated_gc_count(), 0UL); + EXPECT_EQ(policy.generational_should_upgrade_degenerated_gc(), false); +} + +TEST(ShenandoahCollectorPolicyTest, track_degen_cycles_reset) { + ShenandoahCollectorPolicy policy; + policy.record_degenerated(true, true, false); + policy.record_success_concurrent(true, true); + EXPECT_EQ(policy.consecutive_degenerated_gc_count(), 0UL); + EXPECT_EQ(policy.generational_should_upgrade_degenerated_gc(), false); +} diff --git a/test/hotspot/gtest/gc/shenandoah/test_shenandoahMarkBitMap.cpp b/test/hotspot/gtest/gc/shenandoah/test_shenandoahMarkBitMap.cpp new file mode 100644 index 00000000000..3dbb7c62122 --- /dev/null +++ b/test/hotspot/gtest/gc/shenandoah/test_shenandoahMarkBitMap.cpp @@ -0,0 +1,571 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +#include "gc/shenandoah/shenandoahHeap.inline.hpp" +#include "gc/shenandoah/shenandoahMarkBitMap.hpp" +#include "gc/shenandoah/shenandoahMarkBitMap.inline.hpp" + +BEGIN_ALLOW_FORBIDDEN_FUNCTIONS +#include +END_ALLOW_FORBIDDEN_FUNCTIONS + +#include "memory/memRegion.hpp" +#include "unittest.hpp" + +#include "utilities/ostream.hpp" +#include "utilities/vmassert_reinstall.hpp" +#include "utilities/vmassert_uninstall.hpp" + +// These tests will all be skipped (unless Shenandoah becomes the default +// collector). To execute these tests, you must enable Shenandoah, which +// is done with: +// +// % make exploded-test TEST="gtest:ShenandoahOld*" CONF=release TEST_OPTS="JAVA_OPTIONS=-XX:+UseShenandoahGC -XX:+UnlockExperimentalVMOptions -XX:ShenandoahGCMode=generational" +// +// Please note that these 'unit' tests are really integration tests and rely +// on the JVM being initialized. These tests manipulate the state of the +// collector in ways that are not compatible with a normal collection run. +// If these tests take longer than the minimum time between gc intervals - +// or, more likely, if you have them paused in a debugger longer than this +// interval - you can expect trouble. These tests will also not run in a build +// with asserts enabled because they use APIs that expect to run on a safepoint. + +#ifdef ASSERT +#define SKIP_IF_NOT_SHENANDOAH() \ + std::cout << "skipped (debug build)\n"; \ + return; +#else +#define SKIP_IF_NOT_SHENANDOAH() \ + if (!UseShenandoahGC) { \ + std::cout << "skipped\n"; \ + return; \ + } +#endif + +static bool _success; +static size_t _assertion_failures; + +#define MarkBitMapAssertEqual(a, b) EXPECT_EQ((a), (b)); if ((a) != (b)) { _assertion_failures++; } +#define MarkBitMapAssertTrue(a) EXPECT_TRUE((a)); if ((a) == 0) { _assertion_failures++; } + + +class ShenandoahMarkBitMapTest: public ::testing::Test { +protected: + + static void verify_bitmap_is_empty(HeapWord *start, size_t words_in_heap, ShenandoahMarkBitMap* mbm) { + MarkBitMapAssertTrue(mbm->is_bitmap_clear_range(start, start + words_in_heap)); + while (words_in_heap-- > 0) { + MarkBitMapAssertTrue(!mbm->is_marked(start)); + MarkBitMapAssertTrue(!mbm->is_marked_weak(start)); + MarkBitMapAssertTrue(!mbm->is_marked_strong(start)); + start++; + } + } + + static void verify_bitmap_is_weakly_marked(ShenandoahMarkBitMap* mbm, + HeapWord* weakly_marked_addresses[], size_t weakly_marked_objects) { + for (size_t i = 0; i < weakly_marked_objects; i++) { + HeapWord* obj_addr = weakly_marked_addresses[i]; + MarkBitMapAssertTrue(mbm->is_marked(obj_addr)); + MarkBitMapAssertTrue(mbm->is_marked_weak(obj_addr)); + } + } + + static void verify_bitmap_is_strongly_marked(ShenandoahMarkBitMap* mbm, + HeapWord* strongly_marked_addresses[], size_t strongly_marked_objects) { + for (size_t i = 0; i < strongly_marked_objects; i++) { + HeapWord* obj_addr = strongly_marked_addresses[i]; + MarkBitMapAssertTrue(mbm->is_marked(obj_addr)); + MarkBitMapAssertTrue(mbm->is_marked_strong(obj_addr)); + } + } + + static void verify_bitmap_all(ShenandoahMarkBitMap* mbm, HeapWord* all_marked_addresses[], + bool is_weakly_marked_object[], bool is_strongly_marked_object[], size_t all_marked_objects, + HeapWord* heap_memory, HeapWord* end_of_heap_memory) { + HeapWord* last_marked_addr = &heap_memory[-1]; + for (size_t i = 0; i < all_marked_objects; i++) { + HeapWord* obj_addr = all_marked_addresses[i]; + if (is_strongly_marked_object[i]) { + MarkBitMapAssertTrue(mbm->is_marked(obj_addr)); + MarkBitMapAssertTrue(mbm->is_marked_strong(obj_addr)); + } + if (is_weakly_marked_object[i]) { + MarkBitMapAssertTrue(mbm->is_marked(obj_addr)); + MarkBitMapAssertTrue(mbm->is_marked_weak(obj_addr)); + } + while (++last_marked_addr < obj_addr) { + MarkBitMapAssertTrue(!mbm->is_marked(last_marked_addr)); + MarkBitMapAssertTrue(!mbm->is_marked_strong(last_marked_addr)); + MarkBitMapAssertTrue(!mbm->is_marked_weak(last_marked_addr)); + } + last_marked_addr = obj_addr; + } + while (++last_marked_addr < end_of_heap_memory) { + MarkBitMapAssertTrue(!mbm->is_marked(last_marked_addr)); + MarkBitMapAssertTrue(!mbm->is_marked_strong(last_marked_addr)); + MarkBitMapAssertTrue(!mbm->is_marked_weak(last_marked_addr)); + } + + HeapWord* next_marked = (HeapWord*) &heap_memory[0] - 1; + for (size_t i = 0; i < all_marked_objects; i++) { + next_marked = mbm->get_next_marked_addr(next_marked + 1, end_of_heap_memory); + MarkBitMapAssertTrue(mbm->is_marked(next_marked)); + MarkBitMapAssertEqual(next_marked, all_marked_addresses[i]); + if (is_strongly_marked_object[i]) { + MarkBitMapAssertTrue(mbm->is_marked_strong(next_marked)); + } + if (is_weakly_marked_object[i]) { + MarkBitMapAssertTrue(mbm->is_marked_weak(next_marked)); + } + } + // We expect no more marked addresses to be found. Should return limit. + HeapWord* sentinel = mbm->get_next_marked_addr(next_marked + 1, end_of_heap_memory); + MarkBitMapAssertEqual(sentinel, end_of_heap_memory); + + HeapWord* prev_marked = end_of_heap_memory + 1; + for (int i = (int) all_marked_objects - 1; i >= 0; i--) { + prev_marked = mbm->get_prev_marked_addr(&heap_memory[0], prev_marked - 1); + MarkBitMapAssertEqual(prev_marked, all_marked_addresses[i]); + MarkBitMapAssertTrue(mbm->is_marked(prev_marked)); + if (is_strongly_marked_object[i]) { + MarkBitMapAssertTrue(mbm->is_marked_strong(prev_marked)); + } + if (is_weakly_marked_object[i]) { + MarkBitMapAssertTrue(mbm->is_marked_weak(prev_marked)); + } + } + // We expect no more marked addresses to be found. should return prev_marked. + sentinel = mbm->get_prev_marked_addr(&heap_memory[0], prev_marked - 1); + MarkBitMapAssertEqual(sentinel, prev_marked); + } + +public: + + static bool run_test() { + ShenandoahHeap* heap = ShenandoahHeap::heap(); + size_t heap_size = heap->max_capacity(); + size_t heap_size_words = heap_size / HeapWordSize; + HeapWord* my_heap_memory = heap->base(); + HeapWord* end_of_my_heap = my_heap_memory + heap_size_words; + MemRegion heap_descriptor(my_heap_memory, heap_size_words); + + _success = false; + _assertion_failures = 0; + + size_t bitmap_page_size = UseLargePages ? os::large_page_size() : os::vm_page_size(); + size_t bitmap_size_orig = ShenandoahMarkBitMap::compute_size(heap_size); + size_t bitmap_size = align_up(bitmap_size_orig, bitmap_page_size); + size_t bitmap_word_size = (bitmap_size + HeapWordSize - 1) / HeapWordSize; + + HeapWord* my_bitmap_memory = NEW_C_HEAP_ARRAY(HeapWord, bitmap_word_size, mtGC); + + MarkBitMapAssertTrue(my_bitmap_memory != nullptr); + if (my_bitmap_memory == nullptr) { + std::cout <<"Cannot run test because failed to allocate bitmap memory\n" << std::flush; + return false; + } + MemRegion bitmap_descriptor(my_bitmap_memory, bitmap_size / HeapWordSize); + ShenandoahMarkBitMap mbm(heap_descriptor, bitmap_descriptor); + + mbm.clear_range_large(heap_descriptor); + verify_bitmap_is_empty((HeapWord*) my_heap_memory, heap_size_words, &mbm); + + HeapWord* weakly_marked_addresses[] = { + (HeapWord*) &my_heap_memory[13], + (HeapWord*) &my_heap_memory[14], + (HeapWord*) &my_heap_memory[15], + (HeapWord*) &my_heap_memory[16], + (HeapWord*) &my_heap_memory[176], + (HeapWord*) &my_heap_memory[240], + (HeapWord*) &my_heap_memory[480], + (HeapWord*) &my_heap_memory[1360], + (HeapWord*) &my_heap_memory[1488], + (HeapWord*) &my_heap_memory[2416], + (HeapWord*) &my_heap_memory[5968], + (HeapWord*) &my_heap_memory[8191], + (HeapWord*) &my_heap_memory[8192], + (HeapWord*) &my_heap_memory[8193] + }; + size_t weakly_marked_objects = sizeof(weakly_marked_addresses) / sizeof(HeapWord*); + for (size_t i = 0; i < weakly_marked_objects; i++) { + mbm.mark_weak(weakly_marked_addresses[i]); + } + HeapWord* next_marked = (HeapWord*) &my_heap_memory[0] - 1; + for (size_t i = 0; i < weakly_marked_objects; i++) { + next_marked = mbm.get_next_marked_addr(next_marked + 1, end_of_my_heap); + MarkBitMapAssertEqual(next_marked, weakly_marked_addresses[i]); + MarkBitMapAssertTrue(mbm.is_marked(next_marked)); + MarkBitMapAssertTrue(mbm.is_marked_weak(next_marked)); + MarkBitMapAssertTrue(!mbm.is_marked_strong(next_marked)); + } + // We expect no more marked addresses to be found. Should return limit. + HeapWord* sentinel = mbm.get_next_marked_addr(next_marked + 1, end_of_my_heap); + HeapWord* heap_limit = end_of_my_heap; + MarkBitMapAssertEqual(sentinel, heap_limit); + HeapWord* prev_marked = end_of_my_heap + 1;; + for (int i = (int) weakly_marked_objects - 1; i >= 0; i--) { + // to be renamed get_prev_marked_addr() + prev_marked = mbm.get_prev_marked_addr(&my_heap_memory[0], prev_marked - 1); + MarkBitMapAssertEqual(prev_marked, weakly_marked_addresses[i]); + MarkBitMapAssertTrue(mbm.is_marked(prev_marked)); + MarkBitMapAssertTrue(mbm.is_marked_weak(prev_marked)); + MarkBitMapAssertTrue(!mbm.is_marked_strong(prev_marked)); + } + // We expect no more marked addresses to be found. should return prev_marked. + sentinel = mbm.get_prev_marked_addr(&my_heap_memory[0], prev_marked - 1); + // MarkBitMapAssertEqual(sentinel, prev_marked); + MarkBitMapAssertEqual(sentinel, prev_marked); + verify_bitmap_is_weakly_marked(&mbm, weakly_marked_addresses, weakly_marked_objects); + + HeapWord* strongly_marked_addresses[] = { + (HeapWord*) &my_heap_memory[8], + (HeapWord*) &my_heap_memory[24], + (HeapWord*) &my_heap_memory[32], + (HeapWord*) &my_heap_memory[56], + (HeapWord*) &my_heap_memory[64], + (HeapWord*) &my_heap_memory[168], + (HeapWord*) &my_heap_memory[232], + (HeapWord*) &my_heap_memory[248], + (HeapWord*) &my_heap_memory[256], + (HeapWord*) &my_heap_memory[257], + (HeapWord*) &my_heap_memory[258], + (HeapWord*) &my_heap_memory[259], + (HeapWord*) &my_heap_memory[488], + (HeapWord*) &my_heap_memory[1352], + (HeapWord*) &my_heap_memory[1496], + (HeapWord*) &my_heap_memory[2432], + (HeapWord*) &my_heap_memory[5960] + }; + size_t strongly_marked_objects = sizeof(strongly_marked_addresses) / sizeof(HeapWord*); + for (size_t i = 0; i < strongly_marked_objects; i++) { + bool upgraded = false; + mbm.mark_strong(strongly_marked_addresses[i], upgraded); + MarkBitMapAssertTrue(!upgraded); + } + verify_bitmap_is_strongly_marked(&mbm, strongly_marked_addresses, strongly_marked_objects); + HeapWord* upgraded_weakly_marked_addresses[] = { + (HeapWord*) &my_heap_memory[240], + (HeapWord*) &my_heap_memory[1360], + }; + size_t upgraded_weakly_marked_objects = sizeof(upgraded_weakly_marked_addresses) / sizeof(HeapWord *); + for (size_t i = 0; i < upgraded_weakly_marked_objects; i++) { + bool upgraded = false; + mbm.mark_strong(upgraded_weakly_marked_addresses[i], upgraded); + MarkBitMapAssertTrue(upgraded); + } + verify_bitmap_is_strongly_marked(&mbm, upgraded_weakly_marked_addresses, upgraded_weakly_marked_objects); + + HeapWord* all_marked_addresses[] = { + (HeapWord*) &my_heap_memory[8], /* strongly marked */ + (HeapWord*) &my_heap_memory[13], /* weakly marked */ + (HeapWord*) &my_heap_memory[14], /* weakly marked */ + (HeapWord*) &my_heap_memory[15], /* weakly marked */ + (HeapWord*) &my_heap_memory[16], /* weakly marked */ + (HeapWord*) &my_heap_memory[24], /* strongly marked */ + (HeapWord*) &my_heap_memory[32], /* strongly marked */ + (HeapWord*) &my_heap_memory[56], /* strongly marked */ + (HeapWord*) &my_heap_memory[64], /* strongly marked */ + (HeapWord*) &my_heap_memory[168], /* strongly marked */ + (HeapWord*) &my_heap_memory[176], /* weakly marked */ + (HeapWord*) &my_heap_memory[232], /* strongly marked */ + (HeapWord*) &my_heap_memory[240], /* weakly marked upgraded to strongly marked */ + (HeapWord*) &my_heap_memory[248], /* strongly marked */ + (HeapWord*) &my_heap_memory[256], /* strongly marked */ + (HeapWord*) &my_heap_memory[257], /* strongly marked */ + (HeapWord*) &my_heap_memory[258], /* strongly marked */ + (HeapWord*) &my_heap_memory[259], /* strongly marked */ + (HeapWord*) &my_heap_memory[480], /* weakly marked */ + (HeapWord*) &my_heap_memory[488], /* strongly marked */ + (HeapWord*) &my_heap_memory[1352], /* strongly marked */ + (HeapWord*) &my_heap_memory[1360], /* weakly marked upgraded to strongly marked */ + (HeapWord*) &my_heap_memory[1488], /* weakly marked */ + (HeapWord*) &my_heap_memory[1496], /* strongly marked */ + (HeapWord*) &my_heap_memory[2416], /* weakly marked */ + (HeapWord*) &my_heap_memory[2432], /* strongly marked */ + (HeapWord*) &my_heap_memory[5960], /* strongly marked */ + (HeapWord*) &my_heap_memory[5968], /* weakly marked */ + (HeapWord*) &my_heap_memory[8191], /* weakly marked */ + (HeapWord*) &my_heap_memory[8192], /* weakly marked */ + (HeapWord*) &my_heap_memory[8193] /* weakly marked */ + }; + size_t all_marked_objects = sizeof(all_marked_addresses) / sizeof(HeapWord*); + bool is_weakly_marked_object[] = { + false, + true, + true, + true, + true, + false, + false, + false, + false, + false, + true, + false, + true, + false, + false, + false, + false, + false, + true, + false, + false, + true, + true, + false, + true, + false, + false, + true, + true, + true, + true + }; + bool is_strongly_marked_object[] = { + true, + false, + false, + false, + false, + true, + true, + true, + true, + true, + false, + true, + true, + true, + true, + true, + true, + true, + false, + true, + true, + true, + false, + true, + false, + true, + true, + false, + false, + false, + false + }; + verify_bitmap_all(&mbm, all_marked_addresses, is_weakly_marked_object, is_strongly_marked_object, all_marked_objects, + my_heap_memory, end_of_my_heap); + + MemRegion first_clear_region(&my_heap_memory[168], &my_heap_memory[256]); + mbm.clear_range_large(first_clear_region); + // Five objects are no longer marked + HeapWord* all_marked_addresses_after_first_clear[] = { + (HeapWord*) &my_heap_memory[8], /* strongly marked */ + (HeapWord*) &my_heap_memory[13], /* weakly marked */ + (HeapWord*) &my_heap_memory[14], /* weakly marked */ + (HeapWord*) &my_heap_memory[15], /* weakly marked */ + (HeapWord*) &my_heap_memory[16], /* weakly marked */ + (HeapWord*) &my_heap_memory[24], /* strongly marked */ + (HeapWord*) &my_heap_memory[32], /* strongly marked */ + (HeapWord*) &my_heap_memory[56], /* strongly marked */ + (HeapWord*) &my_heap_memory[64], /* strongly marked */ + (HeapWord*) &my_heap_memory[256], /* strongly marked */ + (HeapWord*) &my_heap_memory[257], /* strongly marked */ + (HeapWord*) &my_heap_memory[258], /* strongly marked */ + (HeapWord*) &my_heap_memory[259], /* strongly marked */ + (HeapWord*) &my_heap_memory[480], /* weakly marked */ + (HeapWord*) &my_heap_memory[488], /* strongly marked */ + (HeapWord*) &my_heap_memory[1352], /* strongly marked */ + (HeapWord*) &my_heap_memory[1360], /* weakly marked upgraded to strongly marked */ + (HeapWord*) &my_heap_memory[1488], /* weakly marked */ + (HeapWord*) &my_heap_memory[1496], /* strongly marked */ + (HeapWord*) &my_heap_memory[2416], /* weakly marked */ + (HeapWord*) &my_heap_memory[2432], /* strongly marked */ + (HeapWord*) &my_heap_memory[5960], /* strongly marked */ + (HeapWord*) &my_heap_memory[5968], /* weakly marked */ + (HeapWord*) &my_heap_memory[8191], /* weakly marked */ + (HeapWord*) &my_heap_memory[8192], /* weakly marked */ + (HeapWord*) &my_heap_memory[8193] /* weakly marked */ + }; + size_t all_marked_objects_after_first_clear = sizeof(all_marked_addresses_after_first_clear) / sizeof(HeapWord*); + bool is_weakly_marked_object_after_first_clear[] = { + false, + true, + true, + true, + true, + false, + false, + false, + false, + false, + false, + false, + false, + true, + false, + false, + true, + true, + false, + true, + false, + false, + true, + true, + true, + true + }; + bool is_strongly_marked_object_after_first_clear[] = { + true, + false, + false, + false, + false, + true, + true, + true, + true, + true, + true, + true, + true, + false, + true, + true, + true, + false, + true, + false, + true, + true, + false, + false, + false, + false + }; + verify_bitmap_all(&mbm, all_marked_addresses_after_first_clear, + is_weakly_marked_object_after_first_clear, is_strongly_marked_object_after_first_clear, + all_marked_objects_after_first_clear, my_heap_memory, end_of_my_heap); + + MemRegion second_clear_region(&my_heap_memory[1360], &my_heap_memory[2416]); + mbm.clear_range_large(second_clear_region); + // Five objects are no longer marked + HeapWord* all_marked_addresses_after_2nd_clear[] = { + (HeapWord*) &my_heap_memory[8], /* strongly marked */ + (HeapWord*) &my_heap_memory[13], /* weakly marked */ + (HeapWord*) &my_heap_memory[14], /* weakly marked */ + (HeapWord*) &my_heap_memory[15], /* weakly marked */ + (HeapWord*) &my_heap_memory[16], /* weakly marked */ + (HeapWord*) &my_heap_memory[24], /* strongly marked */ + (HeapWord*) &my_heap_memory[32], /* strongly marked */ + (HeapWord*) &my_heap_memory[56], /* strongly marked */ + (HeapWord*) &my_heap_memory[64], /* strongly marked */ + (HeapWord*) &my_heap_memory[256], /* strongly marked */ + (HeapWord*) &my_heap_memory[257], /* strongly marked */ + (HeapWord*) &my_heap_memory[258], /* strongly marked */ + (HeapWord*) &my_heap_memory[259], /* strongly marked */ + (HeapWord*) &my_heap_memory[480], /* weakly marked */ + (HeapWord*) &my_heap_memory[488], /* strongly marked */ + (HeapWord*) &my_heap_memory[1352], /* strongly marked */ + (HeapWord*) &my_heap_memory[2416], /* weakly marked */ + (HeapWord*) &my_heap_memory[2432], /* strongly marked */ + (HeapWord*) &my_heap_memory[5960], /* strongly marked */ + (HeapWord*) &my_heap_memory[5968], /* weakly marked */ + (HeapWord*) &my_heap_memory[8191], /* weakly marked */ + (HeapWord*) &my_heap_memory[8192], /* weakly marked */ + (HeapWord*) &my_heap_memory[8193] /* weakly marked */ + }; + size_t all_marked_objects_after_2nd_clear = sizeof(all_marked_addresses_after_2nd_clear) / sizeof(HeapWord*); + bool is_weakly_marked_object_after_2nd_clear[] = { + false, + true, + true, + true, + true, + false, + false, + false, + false, + false, + false, + false, + false, + true, + false, + false, + true, + false, + false, + true, + true, + true, + true + }; + bool is_strongly_marked_object_after_2nd_clear[] = { + true, + false, + false, + false, + false, + true, + true, + true, + true, + true, + true, + true, + true, + false, + true, + true, + false, + true, + true, + false, + false, + false, + false + }; + verify_bitmap_all(&mbm, all_marked_addresses_after_2nd_clear, + is_weakly_marked_object_after_2nd_clear, is_strongly_marked_object_after_2nd_clear, + all_marked_objects_after_2nd_clear, my_heap_memory, end_of_my_heap); + + FREE_C_HEAP_ARRAY(HeapWord, my_bitmap_memory); + _success = true; + return true; + } +}; + +TEST_VM_F(ShenandoahMarkBitMapTest, minimum_test) { + SKIP_IF_NOT_SHENANDOAH(); + + bool result = ShenandoahMarkBitMapTest::run_test(); + ASSERT_EQ(result, true); + ASSERT_EQ(_success, true); + ASSERT_EQ(_assertion_failures, (size_t) 0); +} diff --git a/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldGeneration.cpp b/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldGeneration.cpp index 3a5e0662b0c..2fd87b48dc2 100644 --- a/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldGeneration.cpp +++ b/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldGeneration.cpp @@ -52,7 +52,7 @@ class ShenandoahOldGenerationTest : public ::testing::Test { ShenandoahHeap::heap()->lock()->lock(false); - old = new ShenandoahOldGeneration(8, 1024 * 1024, 1024); + old = new ShenandoahOldGeneration(8, 1024 * 1024); old->set_promoted_reserve(512 * HeapWordSize); old->expend_promoted(256 * HeapWordSize); old->set_evacuation_reserve(512 * HeapWordSize); diff --git a/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldHeuristic.cpp b/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldHeuristic.cpp index d08cfd7618b..7b633338c1f 100644 --- a/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldHeuristic.cpp +++ b/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldHeuristic.cpp @@ -49,7 +49,7 @@ #else #define SKIP_IF_NOT_SHENANDOAH() \ if (!UseShenandoahGC) { \ - tty->print_cr("skipped"); \ + std::cout << "skipped\n"; \ return; \ } #endif diff --git a/test/hotspot/gtest/nmt/test_nmt_buffer_overflow_detection.cpp b/test/hotspot/gtest/nmt/test_nmt_buffer_overflow_detection.cpp index f987d83755c..ae3f4e74516 100644 --- a/test/hotspot/gtest/nmt/test_nmt_buffer_overflow_detection.cpp +++ b/test/hotspot/gtest/nmt/test_nmt_buffer_overflow_detection.cpp @@ -35,7 +35,7 @@ // This prefix shows up on any c heap corruption NMT detects. If unsure which assert will // come, just use this one. -#define COMMON_NMT_HEAP_CORRUPTION_MESSAGE_PREFIX "NMT corruption" +#define COMMON_NMT_HEAP_CORRUPTION_MESSAGE_PREFIX "NMT has detected a memory corruption bug." #define DEFINE_TEST(test_function, expected_assertion_message) \ TEST_VM_FATAL_ERROR_MSG(NMT, test_function, ".*" expected_assertion_message ".*") { \ diff --git a/test/hotspot/gtest/runtime/test_arguments.cpp b/test/hotspot/gtest/runtime/test_arguments.cpp index 132157c98b6..074636fea0d 100644 --- a/test/hotspot/gtest/runtime/test_arguments.cpp +++ b/test/hotspot/gtest/runtime/test_arguments.cpp @@ -22,7 +22,6 @@ */ #include "jvm.h" -#include "unittest.hpp" #include "runtime/arguments.hpp" #include "runtime/flags/jvmFlag.hpp" #include "utilities/align.hpp" @@ -30,6 +29,8 @@ #include +#include "unittest.hpp" + class ArgumentsTest : public ::testing::Test { public: static intx parse_xss_inner_annotated(const char* str, jint expected_err, const char* file, int line_number); @@ -57,7 +58,7 @@ class ArgumentsTest : public ::testing::Test { TEST_F(ArgumentsTest, atojulong) { char ullong_max[32]; - int ret = jio_snprintf(ullong_max, sizeof(ullong_max), JULONG_FORMAT, ULLONG_MAX); + int ret = jio_snprintf(ullong_max, sizeof(ullong_max), "%llu", ULLONG_MAX); ASSERT_NE(-1, ret); julong value; diff --git a/test/hotspot/gtest/runtime/test_cgroupSubsystem_linux.cpp b/test/hotspot/gtest/runtime/test_cgroupSubsystem_linux.cpp index c090aa28e9a..b33d6454477 100644 --- a/test/hotspot/gtest/runtime/test_cgroupSubsystem_linux.cpp +++ b/test/hotspot/gtest/runtime/test_cgroupSubsystem_linux.cpp @@ -341,7 +341,6 @@ TEST(cgroupTest, read_string_tests) { ok = controller->read_string(base_with_slash, result, 1024); EXPECT_FALSE(ok) << "Empty file should have failed"; EXPECT_STREQ("", result) << "Expected untouched result"; - delete_file(test_file); // File contents larger than 1K // We only read in the first 1K - 1 bytes @@ -358,6 +357,8 @@ TEST(cgroupTest, read_string_tests) { EXPECT_TRUE(1023 == strlen(result)) << "Expected only the first 1023 chars to be read in"; EXPECT_EQ(0, strncmp(too_large, result, 1023)); EXPECT_EQ(result[1023], '\0') << "The last character must be the null character"; + + delete_file(test_file); } TEST(cgroupTest, read_number_tuple_test) { @@ -393,6 +394,8 @@ TEST(cgroupTest, read_number_tuple_test) { ok = controller->read_numerical_tuple_value(base_with_slash, true /* use_first */, &result); EXPECT_FALSE(ok) << "Empty file should be an error"; EXPECT_EQ((jlong)-10, result) << "result value should be unchanged"; + + delete_file(test_file); } TEST(cgroupTest, read_numerical_key_beyond_max_path) { diff --git a/test/hotspot/gtest/runtime/test_os.cpp b/test/hotspot/gtest/runtime/test_os.cpp index c52f7a692c7..71c9dae8cd7 100644 --- a/test/hotspot/gtest/runtime/test_os.cpp +++ b/test/hotspot/gtest/runtime/test_os.cpp @@ -935,7 +935,7 @@ TEST_VM(os, dll_address_to_function_and_library_name) { LOG("shorten_paths=%d, demangle=%d, strip_arguments=%d, provide_scratch_buffer=%d", shorten_paths, demangle, strip_arguments, provide_scratch_buffer); - // Should show os::min_page_size in libjvm + // Should show Threads::create_vm in libjvm addr = CAST_FROM_FN_PTR(address, Threads::create_vm); st.reset(); EXPECT_TRUE(os::print_function_and_library_name(&st, addr, @@ -943,8 +943,16 @@ TEST_VM(os, dll_address_to_function_and_library_name) { sizeof(tmp), shorten_paths, demangle, strip_arguments)); + +#ifdef _WINDOWS + // On Windows, if no full .pdb file is available, the output can be something like "0x... in ..." + if (strncmp(output, "0x", 2) != 0) { +#endif EXPECT_CONTAINS(output, "Threads"); EXPECT_CONTAINS(output, "create_vm"); +#ifdef _WINDOWS + } +#endif EXPECT_CONTAINS(output, "jvm"); // "jvm.dll" or "libjvm.so" or similar LOG("%s", output); diff --git a/test/hotspot/gtest/x86/asmtest.out.h b/test/hotspot/gtest/x86/asmtest.out.h index a2071bafc20..1f5aae4f636 100644 --- a/test/hotspot/gtest/x86/asmtest.out.h +++ b/test/hotspot/gtest/x86/asmtest.out.h @@ -289,667 +289,751 @@ __ exorl(rdx, Address(r10, r16, (Address::ScaleFactor)2, -0x161e1d47), 16777216, false); // {EVEX}xor edx, dword ptr [r10+r16*4-0x161e1d47], 16777216 IID265 __ exorl(rdx, Address(r29, r23, (Address::ScaleFactor)1, +0x1b34e2f8), 16777216, true); // {NF}xor edx, dword ptr [r29+r23*2+0x1b34e2f8], 16777216 IID266 __ eaddl(r19, Address(r27, r31, (Address::ScaleFactor)0, +0x1f3ce7d8), r29, false); // {EVEX}add r19d, dword ptr [r27+r31*1+0x1f3ce7d8], r29d IID267 - __ eaddl(r28, Address(r24, rcx, (Address::ScaleFactor)3, -0x6053edc2), r28, false); // {EVEX}add r28d, dword ptr [r24+rcx*8-0x6053edc2], r28d IID268 + __ eaddl(r28, Address(r24, rcx, (Address::ScaleFactor)3, -0x6053edc2), r28, false); // add r28d, dword ptr [r24+rcx*8-0x6053edc2] IID268 __ eaddl(r17, Address(r18, r24, (Address::ScaleFactor)3, -0x1bf71f78), r29, true); // {NF}add r17d, dword ptr [r18+r24*8-0x1bf71f78], r29d IID269 __ eaddl(rcx, Address(r15, r28, (Address::ScaleFactor)1, +0x15b8216), rcx, true); // {NF}add ecx, dword ptr [r15+r28*2+0x15b8216], ecx IID270 - __ eorl(r30, Address(rbx, rdx, (Address::ScaleFactor)3, -0x463540b4), r28, false); // {EVEX}or r30d, dword ptr [rbx+rdx*8-0x463540b4], r28d IID271 - __ eorl(r18, Address(r28, r10, (Address::ScaleFactor)3, +0x3523a73b), r18, false); // {EVEX}or r18d, dword ptr [r28+r10*8+0x3523a73b], r18d IID272 - __ eorl(r9, Address(r15, r15, (Address::ScaleFactor)1, -0x2a0bdd56), r21, true); // {NF}or r9d, dword ptr [r15+r15*2-0x2a0bdd56], r21d IID273 - __ eorl(r16, Address(r23, -0x165064ff), r16, true); // {NF}or r16d, dword ptr [r23-0x165064ff], r16d IID274 - __ eorb(r28, Address(r30, r11, (Address::ScaleFactor)0, +0x17281e3a), r20, false); // {EVEX}or r28b, byte ptr [r30+r11*1+0x17281e3a], r20b IID275 - __ eorb(rdx, Address(rbx, r31, (Address::ScaleFactor)2, +0x2477b5bb), rdx, false); // {EVEX}or dl, byte ptr [rbx+r31*4+0x2477b5bb], dl IID276 - __ eorb(r16, Address(r11, rcx, (Address::ScaleFactor)1, -0x3175d1af), r24, true); // {NF}or r16b, byte ptr [r11+rcx*2-0x3175d1af], r24b IID277 - __ eorb(rbx, Address(r11, r20, (Address::ScaleFactor)3, -0x22d67bd3), rbx, true); // {NF}or bl, byte ptr [r11+r20*8-0x22d67bd3], bl IID278 - __ esubl(r26, Address(r27, r30, (Address::ScaleFactor)1, -0x3d9bce2e), rdx, false); // {EVEX}sub r26d, dword ptr [r27+r30*2-0x3d9bce2e], edx IID279 - __ esubl(r31, Address(r22, r29, (Address::ScaleFactor)1, +0x14218519), r31, false); // {EVEX}sub r31d, dword ptr [r22+r29*2+0x14218519], r31d IID280 - __ esubl(r21, Address(r9, -0x1050127a), r13, true); // {NF}sub r21d, dword ptr [r9-0x1050127a], r13d IID281 - __ esubl(r31, Address(r9, r8, (Address::ScaleFactor)0, -0xae18961), r31, true); // {NF}sub r31d, dword ptr [r9+r8*1-0xae18961], r31d IID282 - __ exorl(r15, Address(r18, +0x5c2bbce5), r12, false); // {EVEX}xor r15d, dword ptr [r18+0x5c2bbce5], r12d IID283 - __ exorl(r27, Address(r25, r23, (Address::ScaleFactor)0, +0x5c6078b3), r27, false); // {EVEX}xor r27d, dword ptr [r25+r23*1+0x5c6078b3], r27d IID284 - __ exorl(r18, Address(r8, rdx, (Address::ScaleFactor)3, -0x9ed3881), r14, true); // {NF}xor r18d, dword ptr [r8+rdx*8-0x9ed3881], r14d IID285 - __ exorl(r9, Address(r15, +0x775acdad), r9, true); // {NF}xor r9d, dword ptr [r15+0x775acdad], r9d IID286 - __ exorb(r21, Address(r18, r26, (Address::ScaleFactor)1, +0x2fe31fd5), r23, false); // {EVEX}xor r21b, byte ptr [r18+r26*2+0x2fe31fd5], r23b IID287 - __ exorb(r10, Address(r27, +0xa3150de), r10, false); // {EVEX}xor r10b, byte ptr [r27+0xa3150de], r10b IID288 - __ exorb(r18, Address(r22, r30, (Address::ScaleFactor)3, +0x1ad4e897), r24, true); // {NF}xor r18b, byte ptr [r22+r30*8+0x1ad4e897], r24b IID289 - __ exorb(r8, Address(r16, r20, (Address::ScaleFactor)0, +0x626eae82), r8, true); // {NF}xor r8b, byte ptr [r16+r20*1+0x626eae82], r8b IID290 - __ eaddl(r21, r15, 1048576, false); // {EVEX}add r21d, r15d, 1048576 IID291 - __ eaddl(rax, r18, 1048576, false); // {EVEX}add eax, r18d, 1048576 IID292 - __ eaddl(r18, r18, 256, false); // add r18d, 256 IID293 - __ eaddl(r13, r19, 16, true); // {NF}add r13d, r19d, 16 IID294 - __ eaddl(rax, r23, 16, true); // {NF}add eax, r23d, 16 IID295 - __ eaddl(r25, r25, 16777216, true); // {NF}add r25d, r25d, 16777216 IID296 - __ eandl(r29, r18, 1048576, false); // {EVEX}and r29d, r18d, 1048576 IID297 - __ eandl(rax, r14, 1048576, false); // {EVEX}and eax, r14d, 1048576 IID298 - __ eandl(r19, r19, 65536, false); // and r19d, 65536 IID299 - __ eandl(r27, r25, 1048576, true); // {NF}and r27d, r25d, 1048576 IID300 - __ eandl(rax, r20, 1048576, true); // {NF}and eax, r20d, 1048576 IID301 - __ eandl(r28, r28, 16, true); // {NF}and r28d, r28d, 16 IID302 - __ eimull(r31, r22, 4096, false); // {EVEX}imul r31d, r22d, 4096 IID303 + __ eandl(r30, Address(rbx, rdx, (Address::ScaleFactor)3, -0x463540b4), r28, false); // {EVEX}and r30d, dword ptr [rbx+rdx*8-0x463540b4], r28d IID271 + __ eandl(r18, Address(r28, r10, (Address::ScaleFactor)3, +0x3523a73b), r18, false); // and r18d, dword ptr [r28+r10*8+0x3523a73b] IID272 + __ eandl(r9, Address(r15, r15, (Address::ScaleFactor)1, -0x2a0bdd56), r21, true); // {NF}and r9d, dword ptr [r15+r15*2-0x2a0bdd56], r21d IID273 + __ eandl(r16, Address(r23, -0x165064ff), r16, true); // {NF}and r16d, dword ptr [r23-0x165064ff], r16d IID274 + __ eorl(r28, Address(r30, r11, (Address::ScaleFactor)0, +0x17281e3a), r20, false); // {EVEX}or r28d, dword ptr [r30+r11*1+0x17281e3a], r20d IID275 + __ eorl(rdx, Address(rbx, r31, (Address::ScaleFactor)2, +0x2477b5bb), rdx, false); // or edx, dword ptr [rbx+r31*4+0x2477b5bb] IID276 + __ eorl(r16, Address(r11, rcx, (Address::ScaleFactor)1, -0x3175d1af), r24, true); // {NF}or r16d, dword ptr [r11+rcx*2-0x3175d1af], r24d IID277 + __ eorl(rbx, Address(r11, r20, (Address::ScaleFactor)3, -0x22d67bd3), rbx, true); // {NF}or ebx, dword ptr [r11+r20*8-0x22d67bd3], ebx IID278 + __ eorb(r26, Address(r27, r30, (Address::ScaleFactor)1, -0x3d9bce2e), rdx, false); // {EVEX}or r26b, byte ptr [r27+r30*2-0x3d9bce2e], dl IID279 + __ eorb(r31, Address(r22, r29, (Address::ScaleFactor)1, +0x14218519), r31, false); // or r31b, byte ptr [r22+r29*2+0x14218519] IID280 + __ eorb(r21, Address(r9, -0x1050127a), r13, true); // {NF}or r21b, byte ptr [r9-0x1050127a], r13b IID281 + __ eorb(r31, Address(r9, r8, (Address::ScaleFactor)0, -0xae18961), r31, true); // {NF}or r31b, byte ptr [r9+r8*1-0xae18961], r31b IID282 + __ esubl(r15, Address(r18, +0x5c2bbce5), r12, false); // {EVEX}sub r15d, dword ptr [r18+0x5c2bbce5], r12d IID283 + __ esubl(r27, Address(r25, r23, (Address::ScaleFactor)0, +0x5c6078b3), r27, false); // {EVEX}sub r27d, dword ptr [r25+r23*1+0x5c6078b3], r27d IID284 + __ esubl(r18, Address(r8, rdx, (Address::ScaleFactor)3, -0x9ed3881), r14, true); // {NF}sub r18d, dword ptr [r8+rdx*8-0x9ed3881], r14d IID285 + __ esubl(r9, Address(r15, +0x775acdad), r9, true); // {NF}sub r9d, dword ptr [r15+0x775acdad], r9d IID286 + __ exorl(r21, Address(r18, r26, (Address::ScaleFactor)1, +0x2fe31fd5), r23, false); // {EVEX}xor r21d, dword ptr [r18+r26*2+0x2fe31fd5], r23d IID287 + __ exorl(r10, Address(r27, +0xa3150de), r10, false); // xor r10d, dword ptr [r27+0xa3150de] IID288 + __ exorl(r18, Address(r22, r30, (Address::ScaleFactor)3, +0x1ad4e897), r24, true); // {NF}xor r18d, dword ptr [r22+r30*8+0x1ad4e897], r24d IID289 + __ exorl(r8, Address(r16, r20, (Address::ScaleFactor)0, +0x626eae82), r8, true); // {NF}xor r8d, dword ptr [r16+r20*1+0x626eae82], r8d IID290 + __ exorb(r16, Address(r21, r15, (Address::ScaleFactor)0, -0x1403b60d), r18, false); // {EVEX}xor r16b, byte ptr [r21+r15*1-0x1403b60d], r18b IID291 + __ exorb(r13, Address(r19, r23, (Address::ScaleFactor)2, +0x237ef1e1), r13, false); // xor r13b, byte ptr [r19+r23*4+0x237ef1e1] IID292 + __ exorb(r29, Address(r18, r14, (Address::ScaleFactor)2, +0x5cc0095b), r14, true); // {NF}xor r29b, byte ptr [r18+r14*4+0x5cc0095b], r14b IID293 + __ exorb(r27, Address(r25, r20, (Address::ScaleFactor)3, +0x1cf7b958), r27, true); // {NF}xor r27b, byte ptr [r25+r20*8+0x1cf7b958], r27b IID294 + __ eaddl(r16, r24, 16, false); // {EVEX}add r16d, r24d, 16 IID295 + __ eaddl(rax, r24, 16, false); // {EVEX}add eax, r24d, 16 IID296 + __ eaddl(r21, r21, 65536, false); // add r21d, 65536 IID297 + __ eaddl(r24, r8, 1048576, true); // {NF}add r24d, r8d, 1048576 IID298 + __ eaddl(rax, r13, 1048576, true); // {NF}add eax, r13d, 1048576 IID299 + __ eaddl(r29, r29, 16777216, true); // {NF}add r29d, r29d, 16777216 IID300 + __ eandl(r12, r12, 16, false); // and r12d, 16 IID301 + __ eandl(rax, r30, 16, false); // {EVEX}and eax, r30d, 16 IID302 + __ eandl(r24, r24, 16, false); // and r24d, 16 IID303 + __ eandl(r8, r12, 1, true); // {NF}and r8d, r12d, 1 IID304 + __ eandl(rax, r13, 1, true); // {NF}and eax, r13d, 1 IID305 + __ eandl(r25, r25, 16, true); // {NF}and r25d, r25d, 16 IID306 + __ eimull(r18, r23, 65536, false); // {EVEX}imul r18d, r23d, 65536 IID307 + __ eimull(rax, r9, 65536, false); // {EVEX}imul eax, r9d, 65536 IID308 + __ eimull(r26, r26, 268435456, false); // {EVEX}imul r26d, r26d, 268435456 IID309 + __ eimull(r25, r21, 1, true); // {NF}imul r25d, r21d, 1 IID310 + __ eimull(rax, r24, 1, true); // {NF}imul eax, r24d, 1 IID311 + __ eimull(r24, r24, 16777216, true); // {NF}imul r24d, r24d, 16777216 IID312 + __ eorl(r30, r26, 1, false); // {EVEX}or r30d, r26d, 1 IID313 + __ eorl(rax, r22, 1, false); // {EVEX}or eax, r22d, 1 IID314 + __ eorl(r17, r17, 1048576, false); // or r17d, 1048576 IID315 + __ eorl(r24, r8, 1, true); // {NF}or r24d, r8d, 1 IID316 + __ eorl(rax, r27, 1, true); // {NF}or eax, r27d, 1 IID317 #endif // _LP64 - __ eimull(rax, rbx, 4096, false); // {EVEX}imul eax, ebx, 4096 IID304 + __ eorl(rdx, rdx, 268435456, true); // {NF}or edx, edx, 268435456 IID318 #ifdef _LP64 - __ eimull(r24, r24, 1048576, false); // {EVEX}imul r24d, r24d, 1048576 IID305 - __ eimull(r21, r16, 65536, true); // {NF}imul r21d, r16d, 65536 IID306 - __ eimull(rax, r24, 65536, true); // {NF}imul eax, r24d, 65536 IID307 - __ eimull(r13, r13, 16, true); // {NF}imul r13d, r13d, 16 IID308 - __ eorl(r29, r8, 16777216, false); // {EVEX}or r29d, r8d, 16777216 IID309 - __ eorl(rax, r12, 16777216, false); // {EVEX}or eax, r12d, 16777216 IID310 - __ eorl(r30, r30, 4096, false); // or r30d, 4096 IID311 - __ eorl(r24, rdx, 16, true); // {NF}or r24d, edx, 16 IID312 - __ eorl(rax, r8, 16, true); // {NF}or eax, r8d, 16 IID313 - __ eorl(r13, r13, 4096, true); // {NF}or r13d, r13d, 4096 IID314 - __ ercll(r25, r13, 1); // {EVEX}rcl r25d, r13d, 1 IID315 - __ ercll(rax, r18, 1); // {EVEX}rcl eax, r18d, 1 IID316 - __ ercll(r9, r9, 16); // rcl r9d, 16 IID317 - __ eroll(r26, r25, 8, false); // {EVEX}rol r26d, r25d, 8 IID318 + __ ercll(r22, r22, 8); // rcl r22d, 8 IID319 + __ ercll(rax, r23, 8); // {EVEX}rcl eax, r23d, 8 IID320 + __ ercll(r19, r19, 4); // rcl r19d, 4 IID321 + __ eroll(r30, r24, 2, false); // {EVEX}rol r30d, r24d, 2 IID322 + __ eroll(rax, r29, 2, false); // {EVEX}rol eax, r29d, 2 IID323 + __ eroll(r8, r8, 2, false); // rol r8d, 2 IID324 + __ eroll(r18, r24, 16, true); // {NF}rol r18d, r24d, 16 IID325 + __ eroll(rax, r13, 16, true); // {NF}rol eax, r13d, 16 IID326 + __ eroll(r24, r24, 1, true); // {NF}rol r24d, r24d, 1 IID327 + __ erorl(r28, r17, 16, false); // {EVEX}ror r28d, r17d, 16 IID328 + __ erorl(rax, r24, 16, false); // {EVEX}ror eax, r24d, 16 IID329 + __ erorl(r17, r17, 4, false); // ror r17d, 4 IID330 + __ erorl(r24, rcx, 4, true); // {NF}ror r24d, ecx, 4 IID331 + __ erorl(rax, r16, 4, true); // {NF}ror eax, r16d, 4 IID332 + __ erorl(r15, r15, 2, true); // {NF}ror r15d, r15d, 2 IID333 + __ esall(r14, r27, 4, false); // {EVEX}sal r14d, r27d, 4 IID334 + __ esall(rax, r23, 4, false); // {EVEX}sal eax, r23d, 4 IID335 + __ esall(r30, r30, 4, false); // sal r30d, 4 IID336 + __ esall(r27, rdx, 2, true); // {NF}sal r27d, edx, 2 IID337 + __ esall(rax, r19, 2, true); // {NF}sal eax, r19d, 2 IID338 + __ esall(r20, r20, 2, true); // {NF}sal r20d, r20d, 2 IID339 + __ esarl(r21, r23, 1, false); // {EVEX}sar r21d, r23d, 1 IID340 + __ esarl(rax, r30, 1, false); // {EVEX}sar eax, r30d, 1 IID341 + __ esarl(r25, r25, 2, false); // sar r25d, 2 IID342 + __ esarl(r24, r19, 4, true); // {NF}sar r24d, r19d, 4 IID343 + __ esarl(rax, r14, 4, true); // {NF}sar eax, r14d, 4 IID344 + __ esarl(r26, r26, 16, true); // {NF}sar r26d, r26d, 16 IID345 + __ eshll(r22, r13, 8, false); // {EVEX}shl r22d, r13d, 8 IID346 + __ eshll(rax, r24, 8, false); // {EVEX}shl eax, r24d, 8 IID347 + __ eshll(r14, r14, 16, false); // shl r14d, 16 IID348 + __ eshll(r28, r25, 8, true); // {NF}shl r28d, r25d, 8 IID349 + __ eshll(rax, r10, 8, true); // {NF}shl eax, r10d, 8 IID350 + __ eshll(r20, r20, 1, true); // {NF}shl r20d, r20d, 1 IID351 + __ eshrl(r12, rbx, 4, false); // {EVEX}shr r12d, ebx, 4 IID352 + __ eshrl(rax, r23, 4, false); // {EVEX}shr eax, r23d, 4 IID353 + __ eshrl(r28, r28, 16, false); // shr r28d, 16 IID354 + __ eshrl(r24, r30, 4, true); // {NF}shr r24d, r30d, 4 IID355 + __ eshrl(rax, r31, 4, true); // {NF}shr eax, r31d, 4 IID356 + __ eshrl(r31, r31, 2, true); // {NF}shr r31d, r31d, 2 IID357 + __ esubl(r20, r10, 256, false); // {EVEX}sub r20d, r10d, 256 IID358 + __ esubl(rax, r13, 256, false); // {EVEX}sub eax, r13d, 256 IID359 + __ esubl(r25, r25, 256, false); // sub r25d, 256 IID360 + __ esubl(r23, r12, 268435456, true); // {NF}sub r23d, r12d, 268435456 IID361 + __ esubl(rax, r16, 268435456, true); // {NF}sub eax, r16d, 268435456 IID362 + __ esubl(r31, r31, 1, true); // {NF}sub r31d, r31d, 1 IID363 + __ exorl(r9, r15, 16777216, false); // {EVEX}xor r9d, r15d, 16777216 IID364 + __ exorl(rax, r13, 16777216, false); // {EVEX}xor eax, r13d, 16777216 IID365 + __ exorl(r28, r28, 16, false); // xor r28d, 16 IID366 + __ exorl(r29, r22, 16, true); // {NF}xor r29d, r22d, 16 IID367 #endif // _LP64 - __ eroll(rax, rdx, 8, false); // {EVEX}rol eax, edx, 8 IID319 + __ exorl(rax, rbx, 16, true); // {NF}xor eax, ebx, 16 IID368 #ifdef _LP64 - __ eroll(r24, r24, 16, false); // rol r24d, 16 IID320 - __ eroll(r24, rcx, 8, true); // {NF}rol r24d, ecx, 8 IID321 - __ eroll(rax, r30, 8, true); // {NF}rol eax, r30d, 8 IID322 - __ eroll(r28, r28, 16, true); // {NF}rol r28d, r28d, 16 IID323 - __ erorl(r17, r28, 4, false); // {EVEX}ror r17d, r28d, 4 IID324 + __ exorl(r8, r8, 16, true); // {NF}xor r8d, r8d, 16 IID369 + __ esubl_imm32(r16, r13, 4194304, false); // {EVEX}sub r16d, r13d, 4194304 IID370 + __ esubl_imm32(rax, r12, 4194304, false); // {EVEX}sub eax, r12d, 4194304 IID371 + __ esubl_imm32(r17, r17, 67108864, false); // sub r17d, 67108864 IID372 + __ esubl_imm32(r22, r26, 1073741824, true); // {NF}sub r22d, r26d, 1073741824 IID373 + __ esubl_imm32(rax, r10, 1073741824, true); // {NF}sub eax, r10d, 1073741824 IID374 + __ esubl_imm32(r11, r11, 1073741824, true); // {NF}sub r11d, r11d, 1073741824 IID375 + __ eaddl(r19, r12, Address(r30, r8, (Address::ScaleFactor)0, +0x6a1a0a73), false); // {EVEX}add r19d, r12d, dword ptr [r30+r8*1+0x6a1a0a73] IID376 + __ eaddl(r30, r30, Address(r18, r19, (Address::ScaleFactor)2, +0x25f990cf), false); // add r30d, dword ptr [r18+r19*4+0x25f990cf] IID377 + __ eaddl(rcx, r25, Address(r19, r16, (Address::ScaleFactor)0, +0x482d5dbc), true); // {NF}add ecx, r25d, dword ptr [r19+r16*1+0x482d5dbc] IID378 + __ eaddl(r9, r9, Address(r11, +0x43d5ee01), true); // {NF}add r9d, r9d, dword ptr [r11+0x43d5ee01] IID379 + __ eandl(rcx, r23, Address(r21, r15, (Address::ScaleFactor)2, +0x2825c2bc), false); // {EVEX}and ecx, r23d, dword ptr [r21+r15*4+0x2825c2bc] IID380 + __ eandl(r27, r27, Address(r13, r15, (Address::ScaleFactor)3, -0x1268b895), false); // and r27d, dword ptr [r13+r15*8-0x1268b895] IID381 + __ eandl(r9, r23, Address(r22, r30, (Address::ScaleFactor)0, -0x715acbb), true); // {NF}and r9d, r23d, dword ptr [r22+r30*1-0x715acbb] IID382 + __ eandl(rbx, rbx, Address(r28, r16, (Address::ScaleFactor)2, +0xb0223ee), true); // {NF}and ebx, ebx, dword ptr [r28+r16*4+0xb0223ee] IID383 + __ eimull(r15, r29, Address(r15, r28, (Address::ScaleFactor)1, -0x1f297a69), false); // {EVEX}imul r15d, r29d, dword ptr [r15+r28*2-0x1f297a69] IID384 + __ eimull(r17, r17, Address(r23, rbx, (Address::ScaleFactor)1, +0xadc7545), false); // imul r17d, dword ptr [r23+rbx*2+0xadc7545] IID385 + __ eimull(r27, r9, Address(rdx, r22, (Address::ScaleFactor)2, -0x43d90f61), true); // {NF}imul r27d, r9d, dword ptr [rdx+r22*4-0x43d90f61] IID386 + __ eimull(rbx, rbx, Address(r28, r22, (Address::ScaleFactor)3, -0x519d9a27), true); // {NF}imul ebx, ebx, dword ptr [r28+r22*8-0x519d9a27] IID387 + __ eorl(r17, rcx, Address(r14, +0x10642223), false); // {EVEX}or r17d, ecx, dword ptr [r14+0x10642223] IID388 + __ eorl(r26, r26, Address(r31, -0x7a9a83ba), false); // or r26d, dword ptr [r31-0x7a9a83ba] IID389 + __ eorl(r15, r22, Address(r12, r12, (Address::ScaleFactor)2, +0x743b6997), true); // {NF}or r15d, r22d, dword ptr [r12+r12*4+0x743b6997] IID390 + __ eorl(r8, r8, Address(rdx, r22, (Address::ScaleFactor)3, -0x588414dc), true); // {NF}or r8d, r8d, dword ptr [rdx+r22*8-0x588414dc] IID391 + __ esubl(rcx, r28, Address(r30, r13, (Address::ScaleFactor)2, +0xe9310e5), false); // {EVEX}sub ecx, r28d, dword ptr [r30+r13*4+0xe9310e5] IID392 + __ esubl(rcx, rcx, Address(r30, r10, (Address::ScaleFactor)1, -0x1b076ed1), false); // sub ecx, dword ptr [r30+r10*2-0x1b076ed1] IID393 + __ esubl(r9, r21, Address(r30, +0x2f79ffd3), true); // {NF}sub r9d, r21d, dword ptr [r30+0x2f79ffd3] IID394 + __ esubl(r16, r16, Address(rdx, r14, (Address::ScaleFactor)2, +0x675d71c1), true); // {NF}sub r16d, r16d, dword ptr [rdx+r14*4+0x675d71c1] IID395 + __ exorl(r27, r28, Address(rbx, r26, (Address::ScaleFactor)2, -0x78c20b81), false); // {EVEX}xor r27d, r28d, dword ptr [rbx+r26*4-0x78c20b81] IID396 + __ exorl(r14, r14, Address(r31, r19, (Address::ScaleFactor)1, -0x4ff251cc), false); // xor r14d, dword ptr [r31+r19*2-0x4ff251cc] IID397 + __ exorl(r20, r18, Address(r13, r16, (Address::ScaleFactor)2, -0x19efc6e2), true); // {NF}xor r20d, r18d, dword ptr [r13+r16*4-0x19efc6e2] IID398 + __ exorl(r19, r19, Address(r13, r23, (Address::ScaleFactor)1, -0x2d1bd8aa), true); // {NF}xor r19d, r19d, dword ptr [r13+r23*2-0x2d1bd8aa] IID399 + __ exorb(r29, r17, Address(rdx, r29, (Address::ScaleFactor)2, +0x66573e84), false); // {EVEX}xor r29b, r17b, byte ptr [rdx+r29*4+0x66573e84] IID400 + __ exorb(r22, r22, Address(r24, r25, (Address::ScaleFactor)3, +0x3a94a93f), false); // xor r22b, byte ptr [r24+r25*8+0x3a94a93f] IID401 + __ exorb(r13, r29, Address(r15, r23, (Address::ScaleFactor)1, +0x76d43532), true); // {NF}xor r13b, r29b, byte ptr [r15+r23*2+0x76d43532] IID402 + __ exorb(r15, r15, Address(r13, r9, (Address::ScaleFactor)0, -0x474e6d1a), true); // {NF}xor r15b, r15b, byte ptr [r13+r9*1-0x474e6d1a] IID403 + __ exorw(r17, r16, Address(r23, rdx, (Address::ScaleFactor)0, +0x562a291), false); // {EVEX}xor r17w, r16w, word ptr [r23+rdx*1+0x562a291] IID404 + __ exorw(r29, r29, Address(r18, r28, (Address::ScaleFactor)3, -0x541967f2), false); // xor r29w, word ptr [r18+r28*8-0x541967f2] IID405 + __ exorw(r27, r11, Address(r10, +0xa911c5a), true); // {NF}xor r27w, r11w, word ptr [r10+0xa911c5a] IID406 + __ exorw(r31, r31, Address(r30, r19, (Address::ScaleFactor)2, -0xf6a3da), true); // {NF}xor r31w, r31w, word ptr [r30+r19*4-0xf6a3da] IID407 + __ eaddl(r12, r13, r23, false); // {load}{EVEX}add r12d, r13d, r23d IID408 + __ eaddl(r28, r28, r20, false); // {load}add r28d, r20d IID409 + __ eaddl(r20, r24, r20, false); // {load}add r20d, r24d IID410 + __ eaddl(r11, r10, r15, true); // {load}{NF}add r11d, r10d, r15d IID411 + __ eaddl(r19, r19, r20, true); // {load}{NF}add r19d, r19d, r20d IID412 + __ eaddl(r23, r15, r23, true); // {load}{NF}add r23d, r15d, r23d IID413 + __ eandl(r26, r19, r24, false); // {load}{EVEX}and r26d, r19d, r24d IID414 + __ eandl(r23, r23, r28, false); // {load}and r23d, r28d IID415 + __ eandl(r11, r13, r11, false); // {load}and r11d, r13d IID416 + __ eandl(r13, rdx, r31, true); // {load}{NF}and r13d, edx, r31d IID417 + __ eandl(r23, r23, r23, true); // {load}{NF}and r23d, r23d, r23d IID418 + __ eandl(r9, r27, r9, true); // {load}{NF}and r9d, r27d, r9d IID419 + __ eimull(r21, r20, r24, false); // {load}{EVEX}imul r21d, r20d, r24d IID420 + __ eimull(r21, r21, r29, false); // {load}imul r21d, r29d IID421 + __ eimull(rbx, r11, rbx, false); // {load}imul ebx, r11d IID422 + __ eimull(r21, rbx, rcx, true); // {load}{NF}imul r21d, ebx, ecx IID423 + __ eimull(r31, r31, r21, true); // {load}{NF}imul r31d, r31d, r21d IID424 + __ eimull(r15, r25, r15, true); // {load}{NF}imul r15d, r25d, r15d IID425 + __ eorw(r30, r23, r25, false); // {load}{EVEX}or r30w, r23w, r25w IID426 + __ eorw(r18, r18, rcx, false); // {load}or r18w, cx IID427 + __ eorw(r10, rcx, r10, false); // {load}or r10w, cx IID428 + __ eorw(r31, r21, r26, true); // {load}{NF}or r31w, r21w, r26w IID429 + __ eorw(r21, r21, r19, true); // {load}{NF}or r21w, r21w, r19w IID430 #endif // _LP64 - __ erorl(rax, rdx, 4, false); // {EVEX}ror eax, edx, 4 IID325 + __ eorw(rdx, rbx, rdx, true); // {load}{NF}or dx, bx, dx IID431 #ifdef _LP64 - __ erorl(r8, r8, 16, false); // ror r8d, 16 IID326 - __ erorl(r19, rdx, 16, true); // {NF}ror r19d, edx, 16 IID327 - __ erorl(rax, r31, 16, true); // {NF}ror eax, r31d, 16 IID328 - __ erorl(r22, r22, 8, true); // {NF}ror r22d, r22d, 8 IID329 - __ esall(r23, r25, 16, false); // {EVEX}sal r23d, r25d, 16 IID330 - __ esall(rax, r14, 16, false); // {EVEX}sal eax, r14d, 16 IID331 - __ esall(r31, r31, 8, false); // sal r31d, 8 IID332 - __ esall(r30, r24, 2, true); // {NF}sal r30d, r24d, 2 IID333 - __ esall(rax, r29, 2, true); // {NF}sal eax, r29d, 2 IID334 - __ esall(r8, r8, 2, true); // {NF}sal r8d, r8d, 2 IID335 - __ esarl(r18, r24, 16, false); // {EVEX}sar r18d, r24d, 16 IID336 - __ esarl(rax, r13, 16, false); // {EVEX}sar eax, r13d, 16 IID337 - __ esarl(r24, r24, 1, false); // sar r24d, 1 IID338 - __ esarl(r28, r17, 16, true); // {NF}sar r28d, r17d, 16 IID339 - __ esarl(rax, r24, 16, true); // {NF}sar eax, r24d, 16 IID340 - __ esarl(r17, r17, 4, true); // {NF}sar r17d, r17d, 4 IID341 - __ eshll(r24, rcx, 4, false); // {EVEX}shl r24d, ecx, 4 IID342 - __ eshll(rax, r16, 4, false); // {EVEX}shl eax, r16d, 4 IID343 - __ eshll(r15, r15, 2, false); // shl r15d, 2 IID344 - __ eshll(r14, r27, 4, true); // {NF}shl r14d, r27d, 4 IID345 - __ eshll(rax, r23, 4, true); // {NF}shl eax, r23d, 4 IID346 - __ eshll(r30, r30, 4, true); // {NF}shl r30d, r30d, 4 IID347 - __ eshrl(r27, rdx, 2, false); // {EVEX}shr r27d, edx, 2 IID348 - __ eshrl(rax, r19, 2, false); // {EVEX}shr eax, r19d, 2 IID349 - __ eshrl(r20, r20, 2, false); // shr r20d, 2 IID350 - __ eshrl(r21, r23, 1, true); // {NF}shr r21d, r23d, 1 IID351 - __ eshrl(rax, r30, 1, true); // {NF}shr eax, r30d, 1 IID352 - __ eshrl(r25, r25, 2, true); // {NF}shr r25d, r25d, 2 IID353 - __ esubl(r24, r19, 1048576, false); // {EVEX}sub r24d, r19d, 1048576 IID354 - __ esubl(rax, r14, 1048576, false); // {EVEX}sub eax, r14d, 1048576 IID355 - __ esubl(r22, r22, 268435456, false); // sub r22d, 268435456 IID356 - __ esubl(r24, r24, 65536, true); // {NF}sub r24d, r24d, 65536 IID357 - __ esubl(rax, r14, 65536, true); // {NF}sub eax, r14d, 65536 IID358 - __ esubl(r28, r28, 268435456, true); // {NF}sub r28d, r28d, 268435456 IID359 - __ exorl(rbx, r20, 256, false); // {EVEX}xor ebx, r20d, 256 IID360 - __ exorl(rax, r15, 256, false); // {EVEX}xor eax, r15d, 256 IID361 + __ eorl(rcx, r24, r22, false); // {load}{EVEX}or ecx, r24d, r22d IID432 + __ eorl(rcx, rcx, r19, false); // {load}or ecx, r19d IID433 + __ eorl(r27, r27, r27, false); // {load}or r27d, r27d IID434 + __ eorl(r31, r9, r13, true); // {load}{NF}or r31d, r9d, r13d IID435 + __ eorl(r31, r31, r23, true); // {load}{NF}or r31d, r31d, r23d IID436 + __ eorl(r19, r17, r19, true); // {load}{NF}or r19d, r17d, r19d IID437 + __ eshldl(r20, r16, r24, false); // {load}{EVEX}shld r20d, r16d, r24d, cl IID438 + __ eshldl(rdx, rdx, r12, false); // {load}shld edx, r12d IID439 + __ eshldl(r29, r9, r31, true); // {load}{NF}shld r29d, r9d, r31d, cl IID440 + __ eshldl(r17, r17, r20, true); // {load}{NF}shld r17d, r17d, r20d, cl IID441 + __ eshrdl(r20, r15, r18, false); // {load}{EVEX}shrd r20d, r15d, r18d, cl IID442 + __ eshrdl(rcx, rcx, r12, false); // {load}shrd ecx, r12d IID443 + __ eshrdl(r14, r9, r23, true); // {load}{NF}shrd r14d, r9d, r23d, cl IID444 + __ eshrdl(r19, r19, r13, true); // {load}{NF}shrd r19d, r19d, r13d, cl IID445 + __ esubl(r30, r27, r27, false); // {load}{EVEX}sub r30d, r27d, r27d IID446 + __ esubl(rdx, rdx, r11, false); // {load}sub edx, r11d IID447 + __ esubl(r15, r11, r24, true); // {load}{NF}sub r15d, r11d, r24d IID448 + __ esubl(r14, r14, r25, true); // {load}{NF}sub r14d, r14d, r25d IID449 + __ exorl(r31, r16, r12, false); // {load}{EVEX}xor r31d, r16d, r12d IID450 + __ exorl(r20, r20, r14, false); // {load}xor r20d, r14d IID451 + __ exorl(r30, r13, r30, false); // {load}xor r30d, r13d IID452 + __ exorl(r24, r17, r17, true); // {load}{NF}xor r24d, r17d, r17d IID453 + __ exorl(r26, r26, r21, true); // {load}{NF}xor r26d, r26d, r21d IID454 + __ exorl(r11, r13, r11, true); // {load}{NF}xor r11d, r13d, r11d IID455 + __ eshldl(r27, r25, r21, 4, false); // {EVEX}shld r27d, r25d, r21d, 4 IID456 + __ eshldl(r22, r22, r10, 4, false); // shld r22d, r10d, 4 IID457 + __ eshldl(r21, r15, r24, 16, true); // {NF}shld r21d, r15d, r24d, 16 IID458 + __ eshldl(rdx, rdx, r19, 1, true); // {NF}shld edx, edx, r19d, 1 IID459 + __ eshrdl(r23, r13, r8, 16, false); // {EVEX}shrd r23d, r13d, r8d, 16 IID460 + __ eshrdl(r26, r26, r22, 1, false); // shrd r26d, r22d, 1 IID461 + __ eshrdl(r24, r9, r30, 16, true); // {NF}shrd r24d, r9d, r30d, 16 IID462 + __ eshrdl(r19, r19, r8, 4, true); // {NF}shrd r19d, r19d, r8d, 4 IID463 + __ ecmovl (Assembler::Condition::overflow, r30, r26, r17); // cmovo r30d, r26d, r17d IID464 + __ ecmovl (Assembler::Condition::overflow, r14, r14, r26); // cmovo r14d, r26d IID465 + __ ecmovl (Assembler::Condition::noOverflow, r24, r19, r29); // cmovno r24d, r19d, r29d IID466 + __ ecmovl (Assembler::Condition::noOverflow, r25, r25, r20); // cmovno r25d, r20d IID467 + __ ecmovl (Assembler::Condition::below, r11, r10, r14); // cmovb r11d, r10d, r14d IID468 + __ ecmovl (Assembler::Condition::below, r30, r30, r25); // cmovb r30d, r25d IID469 + __ ecmovl (Assembler::Condition::aboveEqual, r13, r22, r27); // cmovae r13d, r22d, r27d IID470 + __ ecmovl (Assembler::Condition::aboveEqual, r16, r16, r24); // cmovae r16d, r24d IID471 + __ ecmovl (Assembler::Condition::zero, r28, r13, r30); // cmovz r28d, r13d, r30d IID472 + __ ecmovl (Assembler::Condition::zero, r30, r30, r24); // cmovz r30d, r24d IID473 + __ ecmovl (Assembler::Condition::notZero, r21, r20, r31); // cmovnz r21d, r20d, r31d IID474 + __ ecmovl (Assembler::Condition::notZero, r8, r8, r16); // cmovnz r8d, r16d IID475 + __ ecmovl (Assembler::Condition::belowEqual, r15, r26, r22); // cmovbe r15d, r26d, r22d IID476 + __ ecmovl (Assembler::Condition::belowEqual, r31, r31, rdx); // cmovbe r31d, edx IID477 + __ ecmovl (Assembler::Condition::above, r27, r8, r10); // cmova r27d, r8d, r10d IID478 + __ ecmovl (Assembler::Condition::above, r18, r18, r11); // cmova r18d, r11d IID479 + __ ecmovl (Assembler::Condition::negative, r27, rbx, r21); // cmovs r27d, ebx, r21d IID480 + __ ecmovl (Assembler::Condition::negative, r12, r12, r31); // cmovs r12d, r31d IID481 + __ ecmovl (Assembler::Condition::positive, r12, rdx, r18); // cmovns r12d, edx, r18d IID482 + __ ecmovl (Assembler::Condition::positive, r18, r18, r19); // cmovns r18d, r19d IID483 + __ ecmovl (Assembler::Condition::parity, r16, r20, r23); // cmovp r16d, r20d, r23d IID484 + __ ecmovl (Assembler::Condition::parity, r18, r18, r16); // cmovp r18d, r16d IID485 + __ ecmovl (Assembler::Condition::noParity, rbx, r31, r30); // cmovnp ebx, r31d, r30d IID486 + __ ecmovl (Assembler::Condition::noParity, r31, r31, r29); // cmovnp r31d, r29d IID487 + __ ecmovl (Assembler::Condition::less, r28, r25, r10); // cmovl r28d, r25d, r10d IID488 + __ ecmovl (Assembler::Condition::less, r24, r24, r20); // cmovl r24d, r20d IID489 + __ ecmovl (Assembler::Condition::greaterEqual, r16, rdx, r26); // cmovge r16d, edx, r26d IID490 + __ ecmovl (Assembler::Condition::greaterEqual, r28, r28, r28); // cmovge r28d, r28d IID491 + __ ecmovl (Assembler::Condition::lessEqual, r9, r20, r24); // cmovle r9d, r20d, r24d IID492 + __ ecmovl (Assembler::Condition::lessEqual, r24, r24, r29); // cmovle r24d, r29d IID493 + __ ecmovl (Assembler::Condition::greater, r23, r27, r15); // cmovg r23d, r27d, r15d IID494 + __ ecmovl (Assembler::Condition::greater, r12, r12, r18); // cmovg r12d, r18d IID495 + __ ecmovl (Assembler::Condition::overflow, r19, r9, Address(r31, rcx, (Address::ScaleFactor)1, -0x2be98bd)); // cmovo r19d, r9d, dword ptr [r31+rcx*2-0x2be98bd] IID496 + __ ecmovl (Assembler::Condition::overflow, r8, r8, Address(r21, r24, (Address::ScaleFactor)1, +0x41e6a0cb)); // cmovo r8d, dword ptr [r21+r24*2+0x41e6a0cb] IID497 + __ ecmovl (Assembler::Condition::noOverflow, r23, r15, Address(r19, r30, (Address::ScaleFactor)3, -0x55adfe2d)); // cmovno r23d, r15d, dword ptr [r19+r30*8-0x55adfe2d] IID498 + __ ecmovl (Assembler::Condition::noOverflow, rdx, rdx, Address(r27, rdx, (Address::ScaleFactor)0, -0x1aa12735)); // cmovno edx, dword ptr [r27+rdx*1-0x1aa12735] IID499 + __ ecmovl (Assembler::Condition::below, rbx, r29, Address(r31, r12, (Address::ScaleFactor)0, +0xbd42246)); // cmovb ebx, r29d, dword ptr [r31+r12*1+0xbd42246] IID500 + __ ecmovl (Assembler::Condition::below, r21, r21, Address(r19, r21, (Address::ScaleFactor)1, -0x41518818)); // cmovb r21d, dword ptr [r19+r21*2-0x41518818] IID501 + __ ecmovl (Assembler::Condition::aboveEqual, r23, r29, Address(r22, r9, (Address::ScaleFactor)2, -0x35addbd8)); // cmovae r23d, r29d, dword ptr [r22+r9*4-0x35addbd8] IID502 + __ ecmovl (Assembler::Condition::aboveEqual, r18, r18, Address(r25, +0x632184c3)); // cmovae r18d, dword ptr [r25+0x632184c3] IID503 + __ ecmovl (Assembler::Condition::zero, r29, r13, Address(r18, r13, (Address::ScaleFactor)0, -0x3972eac6)); // cmovz r29d, r13d, dword ptr [r18+r13*1-0x3972eac6] IID504 + __ ecmovl (Assembler::Condition::zero, r29, r29, Address(r12, r9, (Address::ScaleFactor)3, -0x668cdfd2)); // cmovz r29d, dword ptr [r12+r9*8-0x668cdfd2] IID505 + __ ecmovl (Assembler::Condition::notZero, r25, r18, Address(r9, r22, (Address::ScaleFactor)2, +0x7f6ac91f)); // cmovnz r25d, r18d, dword ptr [r9+r22*4+0x7f6ac91f] IID506 + __ ecmovl (Assembler::Condition::notZero, r28, r28, Address(r30, +0x562e6594)); // cmovnz r28d, dword ptr [r30+0x562e6594] IID507 + __ ecmovl (Assembler::Condition::belowEqual, r27, r24, Address(r15, r20, (Address::ScaleFactor)2, -0x466538b7)); // cmovbe r27d, r24d, dword ptr [r15+r20*4-0x466538b7] IID508 + __ ecmovl (Assembler::Condition::belowEqual, r25, r25, Address(r26, r11, (Address::ScaleFactor)3, -0x593812a9)); // cmovbe r25d, dword ptr [r26+r11*8-0x593812a9] IID509 + __ ecmovl (Assembler::Condition::above, rcx, r20, Address(r16, -0x1389a3eb)); // cmova ecx, r20d, dword ptr [r16-0x1389a3eb] IID510 + __ ecmovl (Assembler::Condition::above, rbx, rbx, Address(r29, r8, (Address::ScaleFactor)0, +0x1d022615)); // cmova ebx, dword ptr [r29+r8*1+0x1d022615] IID511 + __ ecmovl (Assembler::Condition::negative, rdx, r14, Address(r12, r28, (Address::ScaleFactor)1, -0x51725a91)); // cmovs edx, r14d, dword ptr [r12+r28*2-0x51725a91] IID512 + __ ecmovl (Assembler::Condition::negative, r24, r24, Address(r17, r18, (Address::ScaleFactor)1, -0x1725c4e4)); // cmovs r24d, dword ptr [r17+r18*2-0x1725c4e4] IID513 + __ ecmovl (Assembler::Condition::positive, rcx, rcx, Address(r15, r23, (Address::ScaleFactor)2, -0x6bd22ccf)); // cmovns ecx, dword ptr [r15+r23*4-0x6bd22ccf] IID514 + __ ecmovl (Assembler::Condition::positive, r24, r24, Address(r15, r10, (Address::ScaleFactor)1, -0x7ffb3d09)); // cmovns r24d, dword ptr [r15+r10*2-0x7ffb3d09] IID515 + __ ecmovl (Assembler::Condition::parity, r23, rcx, Address(r11, r23, (Address::ScaleFactor)0, +0x3738c585)); // cmovp r23d, ecx, dword ptr [r11+r23*1+0x3738c585] IID516 + __ ecmovl (Assembler::Condition::parity, r24, r24, Address(r30, r10, (Address::ScaleFactor)0, +0xfcc15a8)); // cmovp r24d, dword ptr [r30+r10*1+0xfcc15a8] IID517 + __ ecmovl (Assembler::Condition::noParity, r14, r26, Address(r14, r21, (Address::ScaleFactor)1, -0x4430ce9f)); // cmovnp r14d, r26d, dword ptr [r14+r21*2-0x4430ce9f] IID518 + __ ecmovl (Assembler::Condition::noParity, r10, r10, Address(r28, +0x3d7c59f)); // cmovnp r10d, dword ptr [r28+0x3d7c59f] IID519 + __ ecmovl (Assembler::Condition::less, r10, r21, Address(r8, r8, (Address::ScaleFactor)3, +0x4a6584b4)); // cmovl r10d, r21d, dword ptr [r8+r8*8+0x4a6584b4] IID520 + __ ecmovl (Assembler::Condition::less, r26, r26, Address(r19, r20, (Address::ScaleFactor)3, +0x47c660ef)); // cmovl r26d, dword ptr [r19+r20*8+0x47c660ef] IID521 + __ ecmovl (Assembler::Condition::greaterEqual, r26, r10, Address(rcx, +0x61977a97)); // cmovge r26d, r10d, dword ptr [rcx+0x61977a97] IID522 + __ ecmovl (Assembler::Condition::greaterEqual, r30, r30, Address(r15, r19, (Address::ScaleFactor)3, +0x53c601cb)); // cmovge r30d, dword ptr [r15+r19*8+0x53c601cb] IID523 + __ ecmovl (Assembler::Condition::lessEqual, r14, r9, Address(r17, -0x566ceee2)); // cmovle r14d, r9d, dword ptr [r17-0x566ceee2] IID524 + __ ecmovl (Assembler::Condition::lessEqual, r15, r15, Address(r27, r20, (Address::ScaleFactor)0, +0x76164792)); // cmovle r15d, dword ptr [r27+r20*1+0x76164792] IID525 + __ ecmovl (Assembler::Condition::greater, r27, r14, Address(r9, r13, (Address::ScaleFactor)2, +0xf5752d7)); // cmovg r27d, r14d, dword ptr [r9+r13*4+0xf5752d7] IID526 + __ ecmovl (Assembler::Condition::greater, r12, r12, Address(rbx, rcx, (Address::ScaleFactor)3, -0x5501b4c6)); // cmovg r12d, dword ptr [rbx+rcx*8-0x5501b4c6] IID527 #endif // _LP64 - __ exorl(rbx, rbx, 4096, false); // xor ebx, 4096 IID362 #ifdef _LP64 - __ exorl(r24, r30, 65536, true); // {NF}xor r24d, r30d, 65536 IID363 - __ exorl(rax, r31, 65536, true); // {NF}xor eax, r31d, 65536 IID364 - __ exorl(r31, r31, 4096, true); // {NF}xor r31d, r31d, 4096 IID365 - __ esubl_imm32(r20, r10, 1048576, false); // {EVEX}sub r20d, r10d, 1048576 IID366 - __ esubl_imm32(rax, r13, 1048576, false); // {EVEX}sub eax, r13d, 1048576 IID367 - __ esubl_imm32(r25, r25, 1048576, false); // sub r25d, 1048576 IID368 - __ esubl_imm32(r23, r12, 1073741824, true); // {NF}sub r23d, r12d, 1073741824 IID369 - __ esubl_imm32(rax, r16, 1073741824, true); // {NF}sub eax, r16d, 1073741824 IID370 - __ esubl_imm32(r31, r31, 65536, true); // {NF}sub r31d, r31d, 65536 IID371 - __ eaddl(r17, r13, Address(r9, +0x7fef2f98), false); // {EVEX}add r17d, r13d, dword ptr [r9+0x7fef2f98] IID372 - __ eaddl(r29, r8, Address(r22, -0x4df70aac), true); // {NF}add r29d, r8d, dword ptr [r22-0x4df70aac] IID373 - __ eandl(r13, r17, Address(r12, r15, (Address::ScaleFactor)3, +0x50a8a902), false); // {EVEX}and r13d, r17d, dword ptr [r12+r15*8+0x50a8a902] IID374 - __ eandl(r22, r25, Address(r26, r10, (Address::ScaleFactor)2, +0x70ea2754), true); // {NF}and r22d, r25d, dword ptr [r26+r10*4+0x70ea2754] IID375 - __ eimull(r19, r12, Address(r30, r8, (Address::ScaleFactor)0, +0x6a1a0a73), false); // {EVEX}imul r19d, r12d, dword ptr [r30+r8*1+0x6a1a0a73] IID376 - __ eimull(r30, r18, Address(r18, r19, (Address::ScaleFactor)2, -0x7fcd28c7), true); // {NF}imul r30d, r18d, dword ptr [r18+r19*4-0x7fcd28c7] IID377 - __ eorl(r16, r31, Address(r25, r11, (Address::ScaleFactor)3, +0x482d5dbc), false); // {EVEX}or r16d, r31d, dword ptr [r25+r11*8+0x482d5dbc] IID378 - __ eorl(r9, r27, Address(r11, +0x43d5ee01), true); // {NF}or r9d, r27d, dword ptr [r11+0x43d5ee01] IID379 - __ esubl(rcx, r23, Address(r21, r15, (Address::ScaleFactor)2, +0x2825c2bc), false); // {EVEX}sub ecx, r23d, dword ptr [r21+r15*4+0x2825c2bc] IID380 - __ esubl(r27, r22, Address(r13, r15, (Address::ScaleFactor)1, +0x771f0da7), true); // {NF}sub r27d, r22d, dword ptr [r13+r15*2+0x771f0da7] IID381 - __ exorl(r9, r30, Address(r9, r22, (Address::ScaleFactor)3, -0x4ad6c88e), false); // {EVEX}xor r9d, r30d, dword ptr [r9+r22*8-0x4ad6c88e] IID382 - __ exorl(r11, r16, Address(rbx, r28, (Address::ScaleFactor)2, +0xb0223ee), true); // {NF}xor r11d, r16d, dword ptr [rbx+r28*4+0xb0223ee] IID383 - __ exorb(r15, r29, Address(r15, r28, (Address::ScaleFactor)1, -0x1f297a69), false); // {EVEX}xor r15b, r29b, byte ptr [r15+r28*2-0x1f297a69] IID384 - __ exorb(r17, r30, Address(r23, rbx, (Address::ScaleFactor)1, +0xadc7545), true); // {NF}xor r17b, r30b, byte ptr [r23+rbx*2+0xadc7545] IID385 - __ exorw(r27, r9, Address(rdx, r22, (Address::ScaleFactor)2, -0x43d90f61), false); // {EVEX}xor r27w, r9w, word ptr [rdx+r22*4-0x43d90f61] IID386 - __ exorw(rbx, r22, Address(r28, r22, (Address::ScaleFactor)0, -0x7d30a0b1), true); // {NF}xor bx, r22w, word ptr [r28+r22*1-0x7d30a0b1] IID387 - __ eaddl(r14, r24, rcx, false); // {load}{EVEX}add r14d, r24d, ecx IID388 - __ eaddl(r8, r8, r17, false); // {load}add r8d, r17d IID389 - __ eaddl(r26, r24, r12, true); // {load}{NF}add r26d, r24d, r12d IID390 - __ eaddl(r24, r24, r23, true); // {load}{NF}add r24d, r24d, r23d IID391 - __ eandl(r13, r26, r31, false); // {load}{EVEX}and r13d, r26d, r31d IID392 - __ eandl(r11, r11, r8, false); // {load}and r11d, r8d IID393 - __ eandl(rcx, r19, r15, true); // {load}{NF}and ecx, r19d, r15d IID394 - __ eandl(r12, r12, r12, true); // {load}{NF}and r12d, r12d, r12d IID395 - __ eimull(r22, r20, r19, false); // {load}{EVEX}imul r22d, r20d, r19d IID396 - __ eimull(r8, r8, rdx, false); // {load}imul r8d, edx IID397 - __ eimull(r22, r27, r23, true); // {load}{NF}imul r22d, r27d, r23d IID398 - __ eimull(r9, r9, r18, true); // {load}{NF}imul r9d, r9d, r18d IID399 - __ eorw(rcx, r30, r13, false); // {load}{EVEX}or cx, r30w, r13w IID400 - __ eorw(r28, r28, r19, false); // {load}or r28w, r19w IID401 - __ eorw(r12, r30, r27, true); // {load}{NF}or r12w, r30w, r27w IID402 - __ eorw(r8, r8, r22, true); // {load}{NF}or r8w, r8w, r22w IID403 - __ eorl(r16, rcx, r30, false); // {load}{EVEX}or r16d, ecx, r30d IID404 - __ eorl(r10, r10, r25, false); // {load}or r10d, r25d IID405 - __ eorl(r15, r17, r17, true); // {load}{NF}or r15d, r17d, r17d IID406 - __ eorl(r9, r9, r30, true); // {load}{NF}or r9d, r9d, r30d IID407 - __ eshldl(r20, r21, r8, false); // {load}{EVEX}shld r20d, r21d, r8d, cl IID408 - __ eshldl(r26, r26, r14, false); // {load}shld r26d, r14d IID409 - __ eshldl(r16, rdx, r14, true); // {load}{NF}shld r16d, edx, r14d, cl IID410 - __ eshldl(r19, r19, r8, true); // {load}{NF}shld r19d, r19d, r8d, cl IID411 - __ eshrdl(r27, rbx, r26, false); // {load}{EVEX}shrd r27d, ebx, r26d, cl IID412 - __ eshrdl(r28, r28, r19, false); // {load}shrd r28d, r19d IID413 - __ eshrdl(rcx, r11, r14, true); // {load}{NF}shrd ecx, r11d, r14d, cl IID414 - __ eshrdl(r31, r31, r19, true); // {load}{NF}shrd r31d, r31d, r19d, cl IID415 - __ esubl(r26, r13, r25, false); // {load}{EVEX}sub r26d, r13d, r25d IID416 - __ esubl(r24, r24, r11, false); // {load}sub r24d, r11d IID417 - __ esubl(r18, r20, r13, true); // {load}{NF}sub r18d, r20d, r13d IID418 - __ esubl(r16, r16, r18, true); // {load}{NF}sub r16d, r16d, r18d IID419 - __ exorl(r19, r17, r8, false); // {load}{EVEX}xor r19d, r17d, r8d IID420 - __ exorl(r19, r19, r13, false); // {load}xor r19d, r13d IID421 - __ exorl(r23, r13, r15, true); // {load}{NF}xor r23d, r13d, r15d IID422 - __ exorl(r11, r11, r29, true); // {load}{NF}xor r11d, r11d, r29d IID423 - __ eshldl(r29, r17, r17, 1, false); // {EVEX}shld r29d, r17d, r17d, 1 IID424 - __ eshldl(r22, r22, r24, 4, false); // shld r22d, r24d, 4 IID425 - __ eshldl(r8, r28, r11, 16, true); // {NF}shld r8d, r28d, r11d, 16 IID426 - __ eshldl(r15, r15, r23, 4, true); // {NF}shld r15d, r15d, r23d, 4 IID427 - __ eshrdl(r29, r22, r16, 4, false); // {EVEX}shrd r29d, r22d, r16d, 4 IID428 - __ eshrdl(r13, r13, r9, 4, false); // shrd r13d, r9d, 4 IID429 - __ eshrdl(r15, r21, r12, 2, true); // {NF}shrd r15d, r21d, r12d, 2 IID430 - __ eshrdl(r17, r17, r23, 2, true); // {NF}shrd r17d, r17d, r23d, 2 IID431 - __ ecmovl (Assembler::Condition::overflow, rdx, r16, r29); // cmovo edx, r16d, r29d IID432 - __ ecmovl (Assembler::Condition::overflow, r10, r10, r21); // cmovo r10d, r21d IID433 - __ ecmovl (Assembler::Condition::noOverflow, r17, r29, r18); // cmovno r17d, r29d, r18d IID434 - __ ecmovl (Assembler::Condition::noOverflow, r28, r28, r24); // cmovno r28d, r24d IID435 - __ ecmovl (Assembler::Condition::below, r10, r20, r27); // cmovb r10d, r20d, r27d IID436 - __ ecmovl (Assembler::Condition::below, r10, r10, r14); // cmovb r10d, r14d IID437 - __ ecmovl (Assembler::Condition::aboveEqual, r11, r27, rcx); // cmovae r11d, r27d, ecx IID438 - __ ecmovl (Assembler::Condition::aboveEqual, r22, r22, r15); // cmovae r22d, r15d IID439 - __ ecmovl (Assembler::Condition::zero, r31, r30, r19); // cmovz r31d, r30d, r19d IID440 - __ ecmovl (Assembler::Condition::zero, r19, r19, r26); // cmovz r19d, r26d IID441 - __ ecmovl (Assembler::Condition::notZero, r21, r14, r26); // cmovnz r21d, r14d, r26d IID442 - __ ecmovl (Assembler::Condition::notZero, r20, r20, r15); // cmovnz r20d, r15d IID443 - __ ecmovl (Assembler::Condition::belowEqual, r12, r13, r23); // cmovbe r12d, r13d, r23d IID444 - __ ecmovl (Assembler::Condition::belowEqual, r28, r28, r20); // cmovbe r28d, r20d IID445 - __ ecmovl (Assembler::Condition::above, r20, r24, r11); // cmova r20d, r24d, r11d IID446 - __ ecmovl (Assembler::Condition::above, r10, r10, r15); // cmova r10d, r15d IID447 - __ ecmovl (Assembler::Condition::negative, r19, r20, r23); // cmovs r19d, r20d, r23d IID448 - __ ecmovl (Assembler::Condition::negative, r15, r15, r26); // cmovs r15d, r26d IID449 - __ ecmovl (Assembler::Condition::positive, r19, r24, r23); // cmovns r19d, r24d, r23d IID450 - __ ecmovl (Assembler::Condition::positive, r28, r28, r11); // cmovns r28d, r11d IID451 - __ ecmovl (Assembler::Condition::parity, r13, r13, rdx); // cmovp r13d, edx IID452 - __ ecmovl (Assembler::Condition::parity, r31, r31, r23); // cmovp r31d, r23d IID453 - __ ecmovl (Assembler::Condition::noParity, r23, r9, r27); // cmovnp r23d, r9d, r27d IID454 - __ ecmovl (Assembler::Condition::noParity, r21, r21, r20); // cmovnp r21d, r20d IID455 - __ ecmovl (Assembler::Condition::less, r24, r21, r29); // cmovl r24d, r21d, r29d IID456 - __ ecmovl (Assembler::Condition::less, rbx, rbx, r11); // cmovl ebx, r11d IID457 - __ ecmovl (Assembler::Condition::greaterEqual, r21, rbx, rcx); // cmovge r21d, ebx, ecx IID458 - __ ecmovl (Assembler::Condition::greaterEqual, r31, r31, r21); // cmovge r31d, r21d IID459 - __ ecmovl (Assembler::Condition::lessEqual, r15, r25, r30); // cmovle r15d, r25d, r30d IID460 - __ ecmovl (Assembler::Condition::lessEqual, r23, r23, r25); // cmovle r23d, r25d IID461 - __ ecmovl (Assembler::Condition::greater, r18, rcx, r10); // cmovg r18d, ecx, r10d IID462 - __ ecmovl (Assembler::Condition::greater, rcx, rcx, r31); // cmovg ecx, r31d IID463 - __ ecmovl (Assembler::Condition::overflow, r21, r19, Address(r26, -0x6e290873)); // cmovo r21d, r19d, dword ptr [r26-0x6e290873] IID464 - __ ecmovl (Assembler::Condition::noOverflow, r24, r19, Address(r22, rcx, (Address::ScaleFactor)0, +0x11f85f9a)); // cmovno r24d, r19d, dword ptr [r22+rcx*1+0x11f85f9a] IID465 - __ ecmovl (Assembler::Condition::below, r17, r24, Address(r20, +0x534d775e)); // cmovb r17d, r24d, dword ptr [r20+0x534d775e] IID466 - __ ecmovl (Assembler::Condition::aboveEqual, r20, r18, Address(r20, -0x47c94ecd)); // cmovae r20d, r18d, dword ptr [r20-0x47c94ecd] IID467 - __ ecmovl (Assembler::Condition::zero, r9, r13, Address(r23, -0x4b83c563)); // cmovz r9d, r13d, dword ptr [r23-0x4b83c563] IID468 - __ ecmovl (Assembler::Condition::notZero, r11, r25, Address(r24, r14, (Address::ScaleFactor)1, -0x446507af)); // cmovnz r11d, r25d, dword ptr [r24+r14*2-0x446507af] IID469 - __ ecmovl (Assembler::Condition::belowEqual, r14, r24, Address(r30, r13, (Address::ScaleFactor)2, +0xd0661d)); // cmovbe r14d, r24d, dword ptr [r30+r13*4+0xd0661d] IID470 - __ ecmovl (Assembler::Condition::above, r13, r25, Address(r14, r27, (Address::ScaleFactor)3, +0x47e1403)); // cmova r13d, r25d, dword ptr [r14+r27*8+0x47e1403] IID471 - __ ecmovl (Assembler::Condition::negative, r24, r19, Address(rcx, rdx, (Address::ScaleFactor)3, -0x644a5318)); // cmovs r24d, r19d, dword ptr [rcx+rdx*8-0x644a5318] IID472 - __ ecmovl (Assembler::Condition::positive, r26, r24, Address(r22, r22, (Address::ScaleFactor)0, +0x70352446)); // cmovns r26d, r24d, dword ptr [r22+r22*1+0x70352446] IID473 - __ ecmovl (Assembler::Condition::parity, r19, r26, Address(r8, r30, (Address::ScaleFactor)2, +0x78a12f5c)); // cmovp r19d, r26d, dword ptr [r8+r30*4+0x78a12f5c] IID474 - __ ecmovl (Assembler::Condition::noParity, r29, r11, Address(r25, r20, (Address::ScaleFactor)0, +0x27a8303a)); // cmovnp r29d, r11d, dword ptr [r25+r20*1+0x27a8303a] IID475 - __ ecmovl (Assembler::Condition::less, r22, r24, Address(r27, r16, (Address::ScaleFactor)1, +0x2541a10)); // cmovl r22d, r24d, dword ptr [r27+r16*2+0x2541a10] IID476 - __ ecmovl (Assembler::Condition::greaterEqual, r31, r15, Address(r8, r16, (Address::ScaleFactor)3, +0x558e3251)); // cmovge r31d, r15d, dword ptr [r8+r16*8+0x558e3251] IID477 - __ ecmovl (Assembler::Condition::lessEqual, r27, r18, Address(r8, r10, (Address::ScaleFactor)0, -0x471987b7)); // cmovle r27d, r18d, dword ptr [r8+r10*1-0x471987b7] IID478 - __ ecmovl (Assembler::Condition::greater, r18, r16, Address(r18, r19, (Address::ScaleFactor)2, -0x120ae81e)); // cmovg r18d, r16d, dword ptr [r18+r19*4-0x120ae81e] IID479 -#endif // _LP64 -#ifdef _LP64 - __ adcq(rbx, r31); // {load}adc rbx, r31 IID480 - __ cmpq(r30, r31); // {load}cmp r30, r31 IID481 - __ imulq(r29, r28); // {load}imul r29, r28 IID482 - __ popcntq(r25, r10); // {load}popcnt r25, r10 IID483 - __ sbbq(r24, r20); // {load}sbb r24, r20 IID484 - __ subq(r16, rdx); // {load}sub r16, rdx IID485 - __ tzcntq(r26, r28); // {load}tzcnt r26, r28 IID486 - __ lzcntq(r28, r9); // {load}lzcnt r28, r9 IID487 - __ addq(r20, r24); // {load}add r20, r24 IID488 - __ andq(r24, r29); // {load}and r24, r29 IID489 - __ orq(r23, r27); // {load}or r23, r27 IID490 - __ xorq(r15, r12); // {load}xor r15, r12 IID491 - __ movq(r18, r19); // {load}mov r18, r19 IID492 - __ bsfq(r31, rcx); // {load}bsf r31, rcx IID493 - __ bsrq(r9, r13); // {load}bsr r9, r13 IID494 - __ btq(r20, rcx); // {load}bt r20, rcx IID495 - __ xchgq(r8, r21); // {load}xchg r8, r21 IID496 - __ testq(r24, r14); // {load}test r24, r14 IID497 - __ addq(Address(rcx, r23, (Address::ScaleFactor)2, +0x4ff06c4d), r29); // add qword ptr [rcx+r23*4+0x4ff06c4d], r29 IID498 - __ andq(Address(r24, r10, (Address::ScaleFactor)1, -0x75d9a189), r26); // and qword ptr [r24+r10*2-0x75d9a189], r26 IID499 - __ cmpq(Address(rbx, rbx, (Address::ScaleFactor)0, +0x4033d59c), r17); // cmp qword ptr [rbx+rbx*1+0x4033d59c], r17 IID500 - __ orq(Address(r22, r12, (Address::ScaleFactor)3, -0x3893347d), r18); // or qword ptr [r22+r12*8-0x3893347d], r18 IID501 - __ xorq(Address(r20, r23, (Address::ScaleFactor)3, +0x4b311560), r12); // xor qword ptr [r20+r23*8+0x4b311560], r12 IID502 - __ subq(Address(r10, r28, (Address::ScaleFactor)2, +0x5c3a2657), r29); // sub qword ptr [r10+r28*4+0x5c3a2657], r29 IID503 - __ movq(Address(r13, r25, (Address::ScaleFactor)3, +0x1a3d6f3f), r22); // mov qword ptr [r13+r25*8+0x1a3d6f3f], r22 IID504 - __ xaddq(Address(r17, r24, (Address::ScaleFactor)3, -0x35addbd8), r25); // xadd qword ptr [r17+r24*8-0x35addbd8], r25 IID505 - __ andq(Address(r25, +0x632184c3), 16777216); // and qword ptr [r25+0x632184c3], 16777216 IID506 - __ addq(Address(r13, r13, (Address::ScaleFactor)0, -0x3972eac6), 16777216); // add qword ptr [r13+r13*1-0x3972eac6], 16777216 IID507 - __ cmpq(Address(r9, -0x13b4c806), 4096); // cmp qword ptr [r9-0x13b4c806], 4096 IID508 - __ sarq(Address(r31, +0x4fa7f551), 1); // sar qword ptr [r31+0x4fa7f551], 1 IID509 - __ salq(Address(r21, r31, (Address::ScaleFactor)2, +0x31aa8232), 1); // sal qword ptr [r21+r31*4+0x31aa8232], 1 IID510 - __ sbbq(Address(r24, r31, (Address::ScaleFactor)2, -0x466538b7), 268435456); // sbb qword ptr [r24+r31*4-0x466538b7], 268435456 IID511 - __ shrq(Address(r28, r22, (Address::ScaleFactor)0, -0x3efe85b1), 2); // shr qword ptr [r28+r22*1-0x3efe85b1], 2 IID512 - __ subq(Address(r16, -0x1389a3eb), 1048576); // sub qword ptr [r16-0x1389a3eb], 1048576 IID513 - __ xorq(Address(r29, r8, (Address::ScaleFactor)0, +0x1d022615), 16); // xor qword ptr [r29+r8*1+0x1d022615], 16 IID514 - __ orq(Address(r12, r28, (Address::ScaleFactor)1, -0x34c898e2), 1); // or qword ptr [r12+r28*2-0x34c898e2], 1 IID515 - __ movq(Address(rcx, r24, (Address::ScaleFactor)2, -0x1644eb08), 256); // mov qword ptr [rcx+r24*4-0x1644eb08], 256 IID516 - __ testq(Address(r29, -0x7d23890b), -65536); // test qword ptr [r29-0x7d23890b], -65536 IID517 - __ addq(r23, Address(rcx, r19, (Address::ScaleFactor)2, +0x70eac654)); // add r23, qword ptr [rcx+r19*4+0x70eac654] IID518 - __ andq(rdx, Address(r24, r15, (Address::ScaleFactor)0, -0x204ddaa9)); // and rdx, qword ptr [r24+r15*1-0x204ddaa9] IID519 - __ cmpq(rdx, Address(r23, r11, (Address::ScaleFactor)3, +0x32c930bd)); // cmp rdx, qword ptr [r23+r11*8+0x32c930bd] IID520 - __ lzcntq(r28, Address(rdx, -0x5433c28f)); // lzcnt r28, qword ptr [rdx-0x5433c28f] IID521 - __ orq(r22, Address(r19, r14, (Address::ScaleFactor)1, -0x2cc67d38)); // or r22, qword ptr [r19+r14*2-0x2cc67d38] IID522 - __ adcq(r10, Address(r10, +0x3d7c59f)); // adc r10, qword ptr [r10+0x3d7c59f] IID523 - __ imulq(r10, Address(r8, r8, (Address::ScaleFactor)3, -0xe61862d)); // imul r10, qword ptr [r8+r8*8-0xe61862d] IID524 - __ popcntq(r23, Address(r29, -0x777ed96d)); // popcnt r23, qword ptr [r29-0x777ed96d] IID525 - __ sbbq(rcx, Address(rbx, r19, (Address::ScaleFactor)1, +0x53c601cb)); // sbb rcx, qword ptr [rbx+r19*2+0x53c601cb] IID526 - __ subq(r14, Address(r17, rbx, (Address::ScaleFactor)0, -0x768bf073)); // sub r14, qword ptr [r17+rbx*1-0x768bf073] IID527 - __ tzcntq(r29, Address(r10, r19, (Address::ScaleFactor)1, +0x30c98d3c)); // tzcnt r29, qword ptr [r10+r19*2+0x30c98d3c] IID528 - __ xorq(r10, Address(r16, r27, (Address::ScaleFactor)0, -0x3d08d602)); // xor r10, qword ptr [r16+r27*1-0x3d08d602] IID529 - __ movq(r18, Address(r28, r28, (Address::ScaleFactor)3, -0x62fbac91)); // mov r18, qword ptr [r28+r28*8-0x62fbac91] IID530 - __ leaq(rbx, Address(rcx, +0x450602a5)); // lea rbx, qword ptr [rcx+0x450602a5] IID531 - __ cvttsd2siq(r12, Address(r30, r31, (Address::ScaleFactor)0, -0x6798a630)); // cvttsd2si r12, qword ptr [r30+r31*1-0x6798a630] IID532 - __ xchgq(r31, Address(r24, r10, (Address::ScaleFactor)1, -0x706712ed)); // xchg r31, qword ptr [r24+r10*2-0x706712ed] IID533 - __ testq(r14, Address(r13, r20, (Address::ScaleFactor)3, +0x171081f2)); // test r14, qword ptr [r13+r20*8+0x171081f2] IID534 - __ addq(r31, 16); // add r31, 16 IID535 - __ andq(r25, 16); // and r25, 16 IID536 - __ adcq(r23, 256); // adc r23, 256 IID537 - __ cmpq(r19, 268435456); // cmp r19, 268435456 IID538 - __ rclq(r31, 1); // rcl r31, 1 IID539 - __ rcrq(r17, 1); // rcr r17, 1 IID540 - __ rolq(r25, 2); // rol r25, 2 IID541 - __ rorq(r17, 4); // ror r17, 4 IID542 - __ sarq(r28, 1); // sar r28, 1 IID543 - __ salq(r15, 4); // sal r15, 4 IID544 - __ sbbq(rbx, 65536); // sbb rbx, 65536 IID545 - __ shlq(r21, 1); // shl r21, 1 IID546 - __ shrq(r10, 1); // shr r10, 1 IID547 - __ subq(r14, 16); // sub r14, 16 IID548 - __ xorq(r18, 268435456); // xor r18, 268435456 IID549 - __ movq(r23, 16); // mov r23, 16 IID550 - __ mov64(r12, 1099511627776); // mov r12, 1099511627776 IID551 - __ btq(r14, 4); // bt r14, 4 IID552 - __ testq(r24, -4096); // test r24, -4096 IID553 - __ orq_imm32(r19, 1048576); // or r19, 1048576 IID554 - __ subq_imm32(rcx, 268435456); // sub rcx, 268435456 IID555 - __ cmovq(Assembler::Condition::overflow, rdx, Address(r19, rbx, (Address::ScaleFactor)3, +0x211c8c4)); // cmovo rdx, qword ptr [r19+rbx*8+0x211c8c4] IID556 - __ cmovq(Assembler::Condition::noOverflow, rbx, Address(r21, +0x49267743)); // cmovno rbx, qword ptr [r21+0x49267743] IID557 - __ cmovq(Assembler::Condition::below, r21, Address(r8, r28, (Address::ScaleFactor)1, -0x4c8c2946)); // cmovb r21, qword ptr [r8+r28*2-0x4c8c2946] IID558 - __ cmovq(Assembler::Condition::aboveEqual, r12, Address(r26, r20, (Address::ScaleFactor)0, -0x264df89c)); // cmovae r12, qword ptr [r26+r20*1-0x264df89c] IID559 - __ cmovq(Assembler::Condition::zero, r17, Address(r28, r9, (Address::ScaleFactor)2, +0x3497196b)); // cmovz r17, qword ptr [r28+r9*4+0x3497196b] IID560 - __ cmovq(Assembler::Condition::notZero, r13, Address(r15, r23, (Address::ScaleFactor)1, -0x27a30999)); // cmovnz r13, qword ptr [r15+r23*2-0x27a30999] IID561 - __ cmovq(Assembler::Condition::belowEqual, r22, Address(r22, +0xf39ab05)); // cmovbe r22, qword ptr [r22+0xf39ab05] IID562 - __ cmovq(Assembler::Condition::above, rcx, Address(r22, r26, (Address::ScaleFactor)3, -0x48c954c)); // cmova rcx, qword ptr [r22+r26*8-0x48c954c] IID563 - __ cmovq(Assembler::Condition::negative, r25, Address(r19, r21, (Address::ScaleFactor)0, +0xe405b0b)); // cmovs r25, qword ptr [r19+r21*1+0xe405b0b] IID564 - __ cmovq(Assembler::Condition::positive, r12, Address(r19, r29, (Address::ScaleFactor)3, -0x7762044b)); // cmovns r12, qword ptr [r19+r29*8-0x7762044b] IID565 - __ cmovq(Assembler::Condition::parity, rbx, Address(r30, r10, (Address::ScaleFactor)1, -0x19798323)); // cmovp rbx, qword ptr [r30+r10*2-0x19798323] IID566 - __ cmovq(Assembler::Condition::noParity, r21, Address(r24, r31, (Address::ScaleFactor)0, -0x5731652b)); // cmovnp r21, qword ptr [r24+r31*1-0x5731652b] IID567 - __ cmovq(Assembler::Condition::less, r18, Address(r8, r10, (Address::ScaleFactor)1, -0x5613be89)); // cmovl r18, qword ptr [r8+r10*2-0x5613be89] IID568 - __ cmovq(Assembler::Condition::greaterEqual, r28, Address(r21, r21, (Address::ScaleFactor)3, +0x65a0fdc4)); // cmovge r28, qword ptr [r21+r21*8+0x65a0fdc4] IID569 - __ cmovq(Assembler::Condition::lessEqual, r23, Address(r11, r18, (Address::ScaleFactor)0, -0x1d1af10c)); // cmovle r23, qword ptr [r11+r18*1-0x1d1af10c] IID570 - __ cmovq(Assembler::Condition::greater, r22, Address(r18, r12, (Address::ScaleFactor)1, +0x1a5f1c38)); // cmovg r22, qword ptr [r18+r12*2+0x1a5f1c38] IID571 - __ call(r23); // call r23 IID572 - __ divq(r30); // div r30 IID573 - __ idivq(r19); // idiv r19 IID574 - __ imulq(r9); // imul r9 IID575 - __ mulq(r13); // mul r13 IID576 - __ negq(r16); // neg r16 IID577 - __ notq(r29); // not r29 IID578 - __ rolq(rcx); // rol rcx, cl IID579 - __ rorq(r25); // ror r25, cl IID580 - __ sarq(r8); // sar r8, cl IID581 - __ salq(r27); // sal r27, cl IID582 - __ shlq(r30); // shl r30, cl IID583 - __ shrq(r23); // shr r23, cl IID584 - __ incrementq(rbx); // inc rbx IID585 - __ decrementq(r14); // dec r14 IID586 - __ pushp(r21); // pushp r21 IID587 - __ popp(r21); // popp r21 IID588 - __ call(Address(r20, r21, (Address::ScaleFactor)1, +0x56c6af2f)); // call qword ptr [r20+r21*2+0x56c6af2f] IID589 - __ mulq(Address(r31, r19, (Address::ScaleFactor)3, -0x1b4eb23)); // mul qword ptr [r31+r19*8-0x1b4eb23] IID590 - __ negq(Address(r27, r27, (Address::ScaleFactor)0, -0x58dbfc1f)); // neg qword ptr [r27+r27*1-0x58dbfc1f] IID591 - __ sarq(Address(rbx, r22, (Address::ScaleFactor)2, -0x606349d1)); // sar qword ptr [rbx+r22*4-0x606349d1], cl IID592 - __ salq(Address(r26, r23, (Address::ScaleFactor)3, +0xb95a079)); // sal qword ptr [r26+r23*8+0xb95a079], cl IID593 - __ shrq(Address(r14, r26, (Address::ScaleFactor)0, +0x3544e09)); // shr qword ptr [r14+r26*1+0x3544e09], cl IID594 - __ incrementq(Address(r27, rdx, (Address::ScaleFactor)0, +0x120b3250)); // inc qword ptr [r27+rdx*1+0x120b3250] IID595 - __ decrementq(Address(r9, r25, (Address::ScaleFactor)2, -0x34aaeccb)); // dec qword ptr [r9+r25*4-0x34aaeccb] IID596 - __ imulq(r20, Address(r16, r28, (Address::ScaleFactor)1, -0x59de05a5), 1048576); // imul r20, qword ptr [r16+r28*2-0x59de05a5], 1048576 IID597 - __ imulq(r17, r23, 256); // imul r17, r23, 256 IID598 - __ shldq(r19, r11, 8); // shld r19, r11, 8 IID599 - __ shrdq(r28, r10, 8); // shrd r28, r10, 8 IID600 - __ pop2(r29, r26); // {load}pop2 r26, r29 IID601 - __ pop2p(r22, r10); // {load}pop2p r10, r22 IID602 - __ push2(r25, r30); // {load}push2 r30, r25 IID603 - __ push2p(r28, r15); // {load}push2p r15, r28 IID604 - __ movzbq(r11, Address(r29, r19, (Address::ScaleFactor)2, -0x12368d34)); // movzx r11, byte ptr [r29+r19*4-0x12368d34] IID605 - __ movzwq(r14, Address(r8, r30, (Address::ScaleFactor)2, -0x4a9392de)); // movzx r14, word ptr [r8+r30*4-0x4a9392de] IID606 - __ movsbq(r28, Address(r23, r15, (Address::ScaleFactor)0, +0x6189cb54)); // movsx r28, byte ptr [r23+r15*1+0x6189cb54] IID607 - __ movswq(r28, Address(rbx, r23, (Address::ScaleFactor)3, -0x2de86561)); // movsx r28, word ptr [rbx+r23*8-0x2de86561] IID608 - __ movzbq(r11, rcx); // movzx r11, cl IID609 - __ movzwq(r30, r15); // movzx r30, r15w IID610 - __ movsbq(r14, rcx); // movsx r14, cl IID611 - __ movswq(r23, r9); // movsx r23, r9w IID612 - __ cmpxchgq(r12, Address(r13, r10, (Address::ScaleFactor)1, -0x7c62c3a)); // cmpxchg qword ptr [r13+r10*2-0x7c62c3a], r12 IID613 - __ eidivq(rcx, false); // {EVEX}idiv rcx IID614 - __ eidivq(r15, true); // {NF}idiv r15 IID615 - __ edivq(r23, false); // {EVEX}div r23 IID616 - __ edivq(r24, true); // {NF}div r24 IID617 - __ eimulq(r27, false); // {EVEX}imul r27 IID618 - __ eimulq(r30, true); // {NF}imul r30 IID619 - __ emulq(r12, false); // {EVEX}mul r12 IID620 - __ emulq(rcx, true); // {NF}mul rcx IID621 - __ emulq(Address(r13, r9, (Address::ScaleFactor)3, -0x226aab94), false); // {EVEX}mul qword ptr [r13+r9*8-0x226aab94] IID622 - __ emulq(Address(r13, r24, (Address::ScaleFactor)3, -0x286c7605), true); // {NF}mul qword ptr [r13+r24*8-0x286c7605] IID623 - __ eimulq(r21, r30, false); // {EVEX}imul r21, r30 IID624 - __ eimulq(r17, r17, false); // imul r17 IID625 - __ eimulq(r29, r12, true); // {NF}imul r29, r12 IID626 - __ eimulq(r30, r30, true); // {NF}imul r30, r30 IID627 - __ elzcntq(r24, r15, false); // {EVEX}lzcnt r24, r15 IID628 - __ elzcntq(r25, r25, false); // {EVEX}lzcnt r25, r25 IID629 - __ elzcntq(r25, r21, true); // {NF}lzcnt r25, r21 IID630 - __ elzcntq(r22, r22, true); // {NF}lzcnt r22, r22 IID631 - __ enegq(r17, r30, false); // {EVEX}neg r17, r30 IID632 - __ enegq(r17, r17, false); // neg r17 IID633 - __ enegq(r31, r17, true); // {NF}neg r31, r17 IID634 - __ enegq(r29, r29, true); // {NF}neg r29, r29 IID635 - __ enotq(r10, r9); // {EVEX}not r10, r9 IID636 - __ enotq(r24, r24); // not r24 IID637 - __ epopcntq(r28, r15, false); // {EVEX}popcnt r28, r15 IID638 - __ epopcntq(r10, r10, false); // {EVEX}popcnt r10, r10 IID639 - __ epopcntq(r27, r30, true); // {NF}popcnt r27, r30 IID640 - __ epopcntq(r28, r28, true); // {NF}popcnt r28, r28 IID641 - __ erolq(r28, r14, false); // {EVEX}rol r28, r14, cl IID642 - __ erolq(r23, r23, false); // rol r23, cl IID643 - __ erolq(r23, r24, true); // {NF}rol r23, r24, cl IID644 - __ erolq(r21, r21, true); // {NF}rol r21, r21, cl IID645 - __ erorq(r31, r22, false); // {EVEX}ror r31, r22, cl IID646 - __ erorq(r28, r28, false); // ror r28, cl IID647 - __ erorq(r17, r10, true); // {NF}ror r17, r10, cl IID648 - __ erorq(r9, r9, true); // {NF}ror r9, r9, cl IID649 - __ esalq(r29, r30, false); // {EVEX}sal r29, r30, cl IID650 - __ esalq(r11, r11, false); // sal r11, cl IID651 - __ esalq(r26, r11, true); // {NF}sal r26, r11, cl IID652 - __ esalq(r16, r16, true); // {NF}sal r16, r16, cl IID653 - __ esarq(rbx, r15, false); // {EVEX}sar rbx, r15, cl IID654 - __ esarq(r14, r14, false); // sar r14, cl IID655 - __ esarq(r25, r16, true); // {NF}sar r25, r16, cl IID656 - __ esarq(r8, r8, true); // {NF}sar r8, r8, cl IID657 - __ edecq(r11, r13, false); // {EVEX}dec r11, r13 IID658 - __ edecq(rcx, rcx, false); // dec rcx IID659 - __ edecq(r21, r18, true); // {NF}dec r21, r18 IID660 - __ edecq(r28, r28, true); // {NF}dec r28, r28 IID661 - __ eincq(r16, r16, false); // inc r16 IID662 - __ eincq(r29, r29, false); // inc r29 IID663 - __ eincq(r18, r9, true); // {NF}inc r18, r9 IID664 - __ eincq(r19, r19, true); // {NF}inc r19, r19 IID665 - __ eshlq(r19, r18, false); // {EVEX}shl r19, r18, cl IID666 - __ eshlq(r8, r8, false); // shl r8, cl IID667 - __ eshlq(r12, r15, true); // {NF}shl r12, r15, cl IID668 - __ eshlq(r29, r29, true); // {NF}shl r29, r29, cl IID669 - __ eshrq(r28, r24, false); // {EVEX}shr r28, r24, cl IID670 - __ eshrq(r19, r19, false); // shr r19, cl IID671 - __ eshrq(r8, r28, true); // {NF}shr r8, r28, cl IID672 - __ eshrq(r17, r17, true); // {NF}shr r17, r17, cl IID673 - __ etzcntq(r28, r16, false); // {EVEX}tzcnt r28, r16 IID674 - __ etzcntq(r14, r14, false); // {EVEX}tzcnt r14, r14 IID675 - __ etzcntq(r12, r31, true); // {NF}tzcnt r12, r31 IID676 - __ etzcntq(r14, r14, true); // {NF}tzcnt r14, r14 IID677 - __ eimulq(r31, Address(r13, -0x69c4b352), false); // {EVEX}imul r31, qword ptr [r13-0x69c4b352] IID678 - __ eimulq(r17, Address(r18, -0x60ab1105), true); // {NF}imul r17, qword ptr [r18-0x60ab1105] IID679 - __ elzcntq(r27, Address(r14, r25, (Address::ScaleFactor)2, +0x2798bf83), false); // {EVEX}lzcnt r27, qword ptr [r14+r25*4+0x2798bf83] IID680 - __ elzcntq(r23, Address(r10, r11, (Address::ScaleFactor)0, -0x378e635d), true); // {NF}lzcnt r23, qword ptr [r10+r11*1-0x378e635d] IID681 - __ enegq(rcx, Address(r19, r9, (Address::ScaleFactor)3, -0x6847d440), false); // {EVEX}neg rcx, qword ptr [r19+r9*8-0x6847d440] IID682 - __ enegq(rcx, Address(rbx, rcx, (Address::ScaleFactor)0, +0x6f92d38d), true); // {NF}neg rcx, qword ptr [rbx+rcx*1+0x6f92d38d] IID683 - __ epopcntq(r20, Address(r12, -0x2a8b27d6), false); // {EVEX}popcnt r20, qword ptr [r12-0x2a8b27d6] IID684 - __ epopcntq(r31, Address(r30, +0x4603f6d0), true); // {NF}popcnt r31, qword ptr [r30+0x4603f6d0] IID685 - __ esalq(rbx, Address(r24, +0x567d06f9), false); // {EVEX}sal rbx, qword ptr [r24+0x567d06f9], cl IID686 - __ esalq(r12, Address(r24, r28, (Address::ScaleFactor)0, -0x1c4c584e), true); // {NF}sal r12, qword ptr [r24+r28*1-0x1c4c584e], cl IID687 - __ esarq(r12, Address(r23, r24, (Address::ScaleFactor)2, -0x3157bcba), false); // {EVEX}sar r12, qword ptr [r23+r24*4-0x3157bcba], cl IID688 - __ esarq(r8, Address(r14, r24, (Address::ScaleFactor)2, -0x714290a5), true); // {NF}sar r8, qword ptr [r14+r24*4-0x714290a5], cl IID689 - __ edecq(r23, Address(r8, r15, (Address::ScaleFactor)1, -0x5ae272dd), false); // {EVEX}dec r23, qword ptr [r8+r15*2-0x5ae272dd] IID690 - __ edecq(r13, Address(r29, r9, (Address::ScaleFactor)3, -0x5b5174a9), true); // {NF}dec r13, qword ptr [r29+r9*8-0x5b5174a9] IID691 - __ eincq(r11, Address(r21, r31, (Address::ScaleFactor)3, -0x2176b4dc), false); // {EVEX}inc r11, qword ptr [r21+r31*8-0x2176b4dc] IID692 - __ eincq(r13, Address(rcx, r16, (Address::ScaleFactor)0, -0x36b448c9), true); // {NF}inc r13, qword ptr [rcx+r16*1-0x36b448c9] IID693 - __ eshrq(r26, Address(r25, rcx, (Address::ScaleFactor)2, -0x5f894993), false); // {EVEX}shr r26, qword ptr [r25+rcx*4-0x5f894993], cl IID694 - __ eshrq(r25, Address(r9, +0x51798d21), true); // {NF}shr r25, qword ptr [r9+0x51798d21], cl IID695 - __ etzcntq(r28, Address(r13, r26, (Address::ScaleFactor)2, +0x207196f6), false); // {EVEX}tzcnt r28, qword ptr [r13+r26*4+0x207196f6] IID696 - __ etzcntq(rbx, Address(r19, r13, (Address::ScaleFactor)0, -0x24d937d5), true); // {NF}tzcnt rbx, qword ptr [r19+r13*1-0x24d937d5] IID697 - __ eaddq(r17, Address(r30, +0x3935ccff), r31, false); // {EVEX}add r17, qword ptr [r30+0x3935ccff], r31 IID698 - __ eaddq(r14, Address(r27, r10, (Address::ScaleFactor)2, -0x34ad9bab), r14, false); // {EVEX}add r14, qword ptr [r27+r10*4-0x34ad9bab], r14 IID699 - __ eaddq(r18, Address(r20, r23, (Address::ScaleFactor)0, +0x5ad3ed4b), r30, true); // {NF}add r18, qword ptr [r20+r23*1+0x5ad3ed4b], r30 IID700 - __ eaddq(r20, Address(rdx, -0x322a99e5), r20, true); // {NF}add r20, qword ptr [rdx-0x322a99e5], r20 IID701 - __ eandq(r31, Address(rbx, r27, (Address::ScaleFactor)3, +0x4ce247d2), r17, false); // {EVEX}and r31, qword ptr [rbx+r27*8+0x4ce247d2], r17 IID702 - __ eandq(r30, Address(r18, r19, (Address::ScaleFactor)1, -0x4ee3d14), r30, false); // {EVEX}and r30, qword ptr [r18+r19*2-0x4ee3d14], r30 IID703 - __ eandq(r28, Address(r11, rbx, (Address::ScaleFactor)3, -0x28994bbf), r24, true); // {NF}and r28, qword ptr [r11+rbx*8-0x28994bbf], r24 IID704 - __ eandq(r30, Address(r22, +0x7d21c24), r30, true); // {NF}and r30, qword ptr [r22+0x7d21c24], r30 IID705 - __ eorq(r26, Address(r15, r19, (Address::ScaleFactor)3, +0x58c21792), r20, false); // {EVEX}or r26, qword ptr [r15+r19*8+0x58c21792], r20 IID706 - __ eorq(r13, Address(r10, r27, (Address::ScaleFactor)2, -0x2c70d333), r13, false); // {EVEX}or r13, qword ptr [r10+r27*4-0x2c70d333], r13 IID707 - __ eorq(rbx, Address(r12, rbx, (Address::ScaleFactor)0, -0x1fb0f1bc), r26, true); // {NF}or rbx, qword ptr [r12+rbx*1-0x1fb0f1bc], r26 IID708 - __ eorq(r31, Address(r27, r31, (Address::ScaleFactor)1, +0x28d1756), r31, true); // {NF}or r31, qword ptr [r27+r31*2+0x28d1756], r31 IID709 - __ esubq(r24, Address(r28, r23, (Address::ScaleFactor)1, +0x6980f610), r27, false); // {EVEX}sub r24, qword ptr [r28+r23*2+0x6980f610], r27 IID710 - __ esubq(r15, Address(r11, r30, (Address::ScaleFactor)3, -0x49777e7), r15, false); // {EVEX}sub r15, qword ptr [r11+r30*8-0x49777e7], r15 IID711 - __ esubq(r17, Address(r25, r13, (Address::ScaleFactor)2, +0x31619e46), r31, true); // {NF}sub r17, qword ptr [r25+r13*4+0x31619e46], r31 IID712 - __ esubq(r18, Address(r11, r10, (Address::ScaleFactor)2, +0x1922861a), r18, true); // {NF}sub r18, qword ptr [r11+r10*4+0x1922861a], r18 IID713 - __ exorq(rbx, Address(r11, -0x4716d420), r21, false); // {EVEX}xor rbx, qword ptr [r11-0x4716d420], r21 IID714 - __ exorq(r8, Address(rdx, r9, (Address::ScaleFactor)2, -0x4cfe39c), r8, false); // {EVEX}xor r8, qword ptr [rdx+r9*4-0x4cfe39c], r8 IID715 - __ exorq(r16, Address(r14, r27, (Address::ScaleFactor)0, +0x7c6654d9), r25, true); // {NF}xor r16, qword ptr [r14+r27*1+0x7c6654d9], r25 IID716 - __ exorq(r29, Address(r15, -0x5efab479), r29, true); // {NF}xor r29, qword ptr [r15-0x5efab479], r29 IID717 - __ eaddq(r19, Address(r13, r22, (Address::ScaleFactor)2, +0x68b64559), 16777216, false); // {EVEX}add r19, qword ptr [r13+r22*4+0x68b64559], 16777216 IID718 - __ eaddq(r16, Address(r13, r31, (Address::ScaleFactor)3, -0x65143af5), 1, true); // {NF}add r16, qword ptr [r13+r31*8-0x65143af5], 1 IID719 - __ eandq(r31, Address(r24, r13, (Address::ScaleFactor)1, -0x25b16a0e), 1, false); // {EVEX}and r31, qword ptr [r24+r13*2-0x25b16a0e], 1 IID720 - __ eandq(r11, Address(r28, -0xf6d4b26), 65536, true); // {NF}and r11, qword ptr [r28-0xf6d4b26], 65536 IID721 - __ eimulq(rcx, Address(r18, r10, (Address::ScaleFactor)0, +0x46ec6da1), 16777216, false); // {EVEX}imul rcx, qword ptr [r18+r10*1+0x46ec6da1], 16777216 IID722 - __ eimulq(r15, Address(r9, r10, (Address::ScaleFactor)3, -0x7fc36af3), 16, true); // {NF}imul r15, qword ptr [r9+r10*8-0x7fc36af3], 16 IID723 - __ eorq(r17, Address(r27, r30, (Address::ScaleFactor)0, +0x1b4cda2c), 1, false); // {EVEX}or r17, qword ptr [r27+r30*1+0x1b4cda2c], 1 IID724 - __ eorq(rdx, Address(r25, r14, (Address::ScaleFactor)2, -0x59aa6b85), 4096, true); // {NF}or rdx, qword ptr [r25+r14*4-0x59aa6b85], 4096 IID725 - __ esalq(r17, Address(r26, r21, (Address::ScaleFactor)1, -0x6ab1f15f), 8, false); // {EVEX}sal r17, qword ptr [r26+r21*2-0x6ab1f15f], 8 IID726 - __ esalq(r12, Address(r22, r17, (Address::ScaleFactor)0, -0x43ac14ab), 2, true); // {NF}sal r12, qword ptr [r22+r17*1-0x43ac14ab], 2 IID727 - __ esarq(r29, Address(r18, r16, (Address::ScaleFactor)0, -0x59dc0c61), 4, false); // {EVEX}sar r29, qword ptr [r18+r16*1-0x59dc0c61], 4 IID728 - __ esarq(r16, Address(r11, -0x7bdd314), 4, true); // {NF}sar r16, qword ptr [r11-0x7bdd314], 4 IID729 - __ eshrq(r26, Address(r23, r27, (Address::ScaleFactor)3, -0x55b92314), 16, false); // {EVEX}shr r26, qword ptr [r23+r27*8-0x55b92314], 16 IID730 - __ eshrq(r23, Address(r16, r29, (Address::ScaleFactor)1, +0x71311a1d), 2, true); // {NF}shr r23, qword ptr [r16+r29*2+0x71311a1d], 2 IID731 - __ esubq(r25, Address(r9, -0x9532bac), 1048576, false); // {EVEX}sub r25, qword ptr [r9-0x9532bac], 1048576 IID732 - __ esubq(r17, Address(r8, r23, (Address::ScaleFactor)0, +0x55d06ca2), 1048576, true); // {NF}sub r17, qword ptr [r8+r23*1+0x55d06ca2], 1048576 IID733 - __ exorq(r29, Address(r9, r24, (Address::ScaleFactor)0, -0x2c141c1), 1048576, false); // {EVEX}xor r29, qword ptr [r9+r24*1-0x2c141c1], 1048576 IID734 - __ exorq(r28, Address(r22, r19, (Address::ScaleFactor)1, -0x2d9d9abd), 16, true); // {NF}xor r28, qword ptr [r22+r19*2-0x2d9d9abd], 16 IID735 - __ eaddq(r22, r14, 16, false); // {EVEX}add r22, r14, 16 IID736 - __ eaddq(rax, r12, 16, false); // {EVEX}add rax, r12, 16 IID737 - __ eaddq(r24, r24, 65536, false); // add r24, 65536 IID738 - __ eaddq(r21, rbx, 65536, true); // {NF}add r21, rbx, 65536 IID739 - __ eaddq(rax, rbx, 65536, true); // {NF}add rax, rbx, 65536 IID740 - __ eaddq(r24, r24, 65536, true); // {NF}add r24, r24, 65536 IID741 - __ eandq(r21, r27, 16777216, false); // {EVEX}and r21, r27, 16777216 IID742 - __ eandq(rax, r27, 16777216, false); // {EVEX}and rax, r27, 16777216 IID743 - __ eandq(r24, r24, 65536, false); // and r24, 65536 IID744 - __ eandq(r13, r31, 1048576, true); // {NF}and r13, r31, 1048576 IID745 - __ eandq(rax, r21, 1048576, true); // {NF}and rax, r21, 1048576 IID746 - __ eandq(r30, r30, 1048576, true); // {NF}and r30, r30, 1048576 IID747 - __ eimulq(r8, r13, 268435456, false); // {EVEX}imul r8, r13, 268435456 IID748 - __ eimulq(rax, r31, 268435456, false); // {EVEX}imul rax, r31, 268435456 IID749 - __ eimulq(r13, r13, 65536, false); // {EVEX}imul r13, r13, 65536 IID750 - __ eimulq(r14, r29, 1048576, true); // {NF}imul r14, r29, 1048576 IID751 - __ eimulq(rax, r22, 1048576, true); // {NF}imul rax, r22, 1048576 IID752 - __ eimulq(r8, r8, 268435456, true); // {NF}imul r8, r8, 268435456 IID753 - __ eorq(r30, r15, 4096, false); // {EVEX}or r30, r15, 4096 IID754 - __ eorq(rax, r28, 4096, false); // {EVEX}or rax, r28, 4096 IID755 - __ eorq(r26, r26, 1048576, false); // or r26, 1048576 IID756 - __ eorq(r16, r12, 268435456, true); // {NF}or r16, r12, 268435456 IID757 - __ eorq(rax, r9, 268435456, true); // {NF}or rax, r9, 268435456 IID758 - __ eorq(r23, r23, 256, true); // {NF}or r23, r23, 256 IID759 - __ erclq(r15, r9, 16); // {EVEX}rcl r15, r9, 16 IID760 - __ erclq(rax, r8, 16); // {EVEX}rcl rax, r8, 16 IID761 - __ erclq(r25, r25, 1); // rcl r25, 1 IID762 - __ erolq(r9, r17, 16, false); // {EVEX}rol r9, r17, 16 IID763 - __ erolq(rax, r20, 16, false); // {EVEX}rol rax, r20, 16 IID764 - __ erolq(r27, r27, 1, false); // rol r27, 1 IID765 - __ erolq(r20, r31, 1, true); // {NF}rol r20, r31, 1 IID766 - __ erolq(rax, r18, 1, true); // {NF}rol rax, r18, 1 IID767 - __ erolq(r28, r28, 16, true); // {NF}rol r28, r28, 16 IID768 - __ erorq(r26, r18, 16, false); // {EVEX}ror r26, r18, 16 IID769 - __ erorq(rax, r24, 16, false); // {EVEX}ror rax, r24, 16 IID770 - __ erorq(r22, r22, 16, false); // ror r22, 16 IID771 - __ erorq(r27, r29, 1, true); // {NF}ror r27, r29, 1 IID772 - __ erorq(rax, r18, 1, true); // {NF}ror rax, r18, 1 IID773 - __ erorq(r21, r21, 1, true); // {NF}ror r21, r21, 1 IID774 - __ esalq(r12, rcx, 2, false); // {EVEX}sal r12, rcx, 2 IID775 - __ esalq(rax, r24, 2, false); // {EVEX}sal rax, r24, 2 IID776 - __ esalq(r22, r22, 8, false); // sal r22, 8 IID777 - __ esalq(r17, r23, 8, true); // {NF}sal r17, r23, 8 IID778 - __ esalq(rax, r27, 8, true); // {NF}sal rax, r27, 8 IID779 - __ esalq(r23, r23, 1, true); // {NF}sal r23, r23, 1 IID780 - __ esarq(r8, r25, 16, false); // {EVEX}sar r8, r25, 16 IID781 - __ esarq(rax, r23, 16, false); // {EVEX}sar rax, r23, 16 IID782 - __ esarq(r9, r9, 4, false); // sar r9, 4 IID783 - __ esarq(r22, r13, 1, true); // {NF}sar r22, r13, 1 IID784 - __ esarq(rax, r11, 1, true); // {NF}sar rax, r11, 1 IID785 - __ esarq(r12, r12, 2, true); // {NF}sar r12, r12, 2 IID786 - __ eshlq(rcx, r30, 8, false); // {EVEX}shl rcx, r30, 8 IID787 - __ eshlq(rax, r19, 8, false); // {EVEX}shl rax, r19, 8 IID788 - __ eshlq(r13, r13, 2, false); // shl r13, 2 IID789 - __ eshlq(r18, r11, 8, true); // {NF}shl r18, r11, 8 IID790 - __ eshlq(rax, r9, 8, true); // {NF}shl rax, r9, 8 IID791 - __ eshlq(rcx, rcx, 16, true); // {NF}shl rcx, rcx, 16 IID792 - __ eshrq(r10, r22, 4, false); // {EVEX}shr r10, r22, 4 IID793 - __ eshrq(rax, r9, 4, false); // {EVEX}shr rax, r9, 4 IID794 - __ eshrq(r12, r12, 2, false); // shr r12, 2 IID795 - __ eshrq(r26, r31, 8, true); // {NF}shr r26, r31, 8 IID796 - __ eshrq(rax, r12, 8, true); // {NF}shr rax, r12, 8 IID797 - __ eshrq(r28, r28, 1, true); // {NF}shr r28, r28, 1 IID798 - __ esubq(r15, r30, 65536, false); // {EVEX}sub r15, r30, 65536 IID799 - __ esubq(rax, rcx, 65536, false); // {EVEX}sub rax, rcx, 65536 IID800 - __ esubq(r26, r26, 16, false); // sub r26, 16 IID801 - __ esubq(r12, r14, 1, true); // {NF}sub r12, r14, 1 IID802 - __ esubq(rax, r21, 1, true); // {NF}sub rax, r21, 1 IID803 - __ esubq(r20, r20, 1048576, true); // {NF}sub r20, r20, 1048576 IID804 - __ exorq(r11, rbx, 16777216, false); // {EVEX}xor r11, rbx, 16777216 IID805 - __ exorq(rax, r23, 16777216, false); // {EVEX}xor rax, r23, 16777216 IID806 - __ exorq(r31, r31, 268435456, false); // xor r31, 268435456 IID807 - __ exorq(r29, r28, 4096, true); // {NF}xor r29, r28, 4096 IID808 - __ exorq(rax, r19, 4096, true); // {NF}xor rax, r19, 4096 IID809 - __ exorq(rdx, rdx, 268435456, true); // {NF}xor rdx, rdx, 268435456 IID810 - __ eorq_imm32(rdx, rdx, 1048576, false); // or rdx, 1048576 IID811 - __ eorq_imm32(rax, r22, 1048576, false); // {EVEX}or rax, r22, 1048576 IID812 - __ eorq_imm32(r29, r29, 1048576, false); // or r29, 1048576 IID813 - __ eorq_imm32(r17, rcx, 4194304, false); // {EVEX}or r17, rcx, 4194304 IID814 - __ eorq_imm32(rax, r25, 4194304, false); // {EVEX}or rax, r25, 4194304 IID815 - __ eorq_imm32(r27, r27, 1073741824, false); // or r27, 1073741824 IID816 - __ esubq_imm32(r16, r19, 4194304, false); // {EVEX}sub r16, r19, 4194304 IID817 - __ esubq_imm32(rax, r31, 4194304, false); // {EVEX}sub rax, r31, 4194304 IID818 - __ esubq_imm32(r26, r26, 262144, false); // sub r26, 262144 IID819 - __ esubq_imm32(r17, r22, 1073741824, true); // {NF}sub r17, r22, 1073741824 IID820 - __ esubq_imm32(rax, r18, 1073741824, true); // {NF}sub rax, r18, 1073741824 IID821 - __ esubq_imm32(r23, r23, 268435456, true); // {NF}sub r23, r23, 268435456 IID822 - __ eaddq(r13, r30, Address(r24, r19, (Address::ScaleFactor)1, +0x56ea3a3b), false); // {EVEX}add r13, r30, qword ptr [r24+r19*2+0x56ea3a3b] IID823 - __ eaddq(r29, r15, Address(r26, r27, (Address::ScaleFactor)3, -0x4b113958), true); // {NF}add r29, r15, qword ptr [r26+r27*8-0x4b113958] IID824 - __ eandq(r12, r30, Address(r31, -0x46103c74), false); // {EVEX}and r12, r30, qword ptr [r31-0x46103c74] IID825 - __ eandq(r27, r10, Address(r22, r25, (Address::ScaleFactor)1, +0x6a1ebee5), true); // {NF}and r27, r10, qword ptr [r22+r25*2+0x6a1ebee5] IID826 - __ eorq(r30, r26, Address(r11, r18, (Address::ScaleFactor)2, -0x2b9fff29), false); // {EVEX}or r30, r26, qword ptr [r11+r18*4-0x2b9fff29] IID827 - __ eorq(r9, r12, Address(r18, r17, (Address::ScaleFactor)0, +0xb4859f6), true); // {NF}or r9, r12, qword ptr [r18+r17*1+0xb4859f6] IID828 - __ eimulq(rdx, r17, Address(r24, rdx, (Address::ScaleFactor)2, +0x3d284cd8), false); // {EVEX}imul rdx, r17, qword ptr [r24+rdx*4+0x3d284cd8] IID829 - __ eimulq(r29, r26, Address(r30, r12, (Address::ScaleFactor)1, +0x6e813124), true); // {NF}imul r29, r26, qword ptr [r30+r12*2+0x6e813124] IID830 - __ esubq(rbx, r13, Address(r22, -0x702a289e), false); // {EVEX}sub rbx, r13, qword ptr [r22-0x702a289e] IID831 - __ esubq(r23, r29, Address(r25, rdx, (Address::ScaleFactor)0, -0x6252a7ed), true); // {NF}sub r23, r29, qword ptr [r25+rdx*1-0x6252a7ed] IID832 - __ exorq(r8, r18, Address(r19, r14, (Address::ScaleFactor)2, -0xebfa697), false); // {EVEX}xor r8, r18, qword ptr [r19+r14*4-0xebfa697] IID833 - __ exorq(r10, r28, Address(r26, +0x168381ca), true); // {NF}xor r10, r28, qword ptr [r26+0x168381ca] IID834 - __ eaddq(rcx, r18, r8, false); // {load}{EVEX}add rcx, r18, r8 IID835 - __ eaddq(rcx, rcx, r14, false); // {load}add rcx, r14 IID836 - __ eaddq(r23, r10, r16, true); // {load}{NF}add r23, r10, r16 IID837 - __ eaddq(r11, r11, r24, true); // {load}{NF}add r11, r11, r24 IID838 - __ eadcxq(r9, r18, rdx); // {load}{EVEX}adcx r9, r18, rdx IID839 - __ eadcxq(r8, r8, r15); // {load}adcx r8, r15 IID840 - __ eadoxq(r15, r22, r26); // {load}{EVEX}adox r15, r22, r26 IID841 - __ eadoxq(r11, r11, rdx); // {load}adox r11, rdx IID842 - __ eandq(r19, rdx, r22, false); // {load}{EVEX}and r19, rdx, r22 IID843 - __ eandq(r29, r29, r17, false); // {load}and r29, r17 IID844 - __ eandq(r23, r27, r15, true); // {load}{NF}and r23, r27, r15 IID845 - __ eandq(r9, r9, r13, true); // {load}{NF}and r9, r9, r13 IID846 - __ eimulq(r18, r15, r16, false); // {load}{EVEX}imul r18, r15, r16 IID847 - __ eimulq(rcx, rcx, r17, false); // {load}imul rcx, r17 IID848 - __ eimulq(r23, r12, r20, true); // {load}{NF}imul r23, r12, r20 IID849 - __ eimulq(r10, r10, r9, true); // {load}{NF}imul r10, r10, r9 IID850 - __ eorq(rdx, r19, r14, false); // {load}{EVEX}or rdx, r19, r14 IID851 - __ eorq(rcx, rcx, r13, false); // {load}or rcx, r13 IID852 - __ eorq(r9, r25, r29, true); // {load}{NF}or r9, r25, r29 IID853 - __ eorq(rdx, rdx, r25, true); // {load}{NF}or rdx, rdx, r25 IID854 - __ esubq(r23, r8, r16, false); // {load}{EVEX}sub r23, r8, r16 IID855 - __ esubq(r13, r13, r13, false); // {load}sub r13, r13 IID856 - __ esubq(r19, r12, r15, true); // {load}{NF}sub r19, r12, r15 IID857 - __ esubq(r9, r9, rdx, true); // {load}{NF}sub r9, r9, rdx IID858 - __ exorq(r13, r16, r31, false); // {load}{EVEX}xor r13, r16, r31 IID859 - __ exorq(r17, r17, r30, false); // {load}xor r17, r30 IID860 - __ exorq(r19, r30, r20, true); // {load}{NF}xor r19, r30, r20 IID861 - __ exorq(r31, r31, r13, true); // {load}{NF}xor r31, r31, r13 IID862 - __ eshldq(r22, r10, r13, 4, false); // {EVEX}shld r22, r10, r13, 4 IID863 - __ eshldq(r24, r24, r21, 16, false); // shld r24, r21, 16 IID864 - __ eshldq(r20, r13, r27, 16, true); // {NF}shld r20, r13, r27, 16 IID865 - __ eshldq(r31, r31, r19, 2, true); // {NF}shld r31, r31, r19, 2 IID866 - __ eshrdq(r30, r20, r11, 8, false); // {EVEX}shrd r30, r20, r11, 8 IID867 - __ eshrdq(rdx, rdx, r15, 1, false); // shrd rdx, r15, 1 IID868 - __ eshrdq(r28, r30, r14, 2, true); // {NF}shrd r28, r30, r14, 2 IID869 - __ eshrdq(r20, r20, r16, 1, true); // {NF}shrd r20, r20, r16, 1 IID870 - __ ecmovq (Assembler::Condition::overflow, r21, r17, r28); // cmovo r21, r17, r28 IID871 - __ ecmovq (Assembler::Condition::overflow, r15, r15, r30); // cmovo r15, r30 IID872 - __ ecmovq (Assembler::Condition::noOverflow, rcx, r15, r15); // cmovno rcx, r15, r15 IID873 - __ ecmovq (Assembler::Condition::noOverflow, rcx, rcx, r13); // cmovno rcx, r13 IID874 - __ ecmovq (Assembler::Condition::below, rdx, r26, r26); // cmovb rdx, r26, r26 IID875 - __ ecmovq (Assembler::Condition::below, r28, r28, r15); // cmovb r28, r15 IID876 - __ ecmovq (Assembler::Condition::aboveEqual, r8, rdx, rcx); // cmovae r8, rdx, rcx IID877 - __ ecmovq (Assembler::Condition::aboveEqual, rcx, rcx, rcx); // cmovae rcx, rcx IID878 - __ ecmovq (Assembler::Condition::zero, r10, r13, r9); // cmovz r10, r13, r9 IID879 - __ ecmovq (Assembler::Condition::zero, r14, r14, r27); // cmovz r14, r27 IID880 - __ ecmovq (Assembler::Condition::notZero, r11, r23, r9); // cmovnz r11, r23, r9 IID881 - __ ecmovq (Assembler::Condition::notZero, r11, r11, rdx); // cmovnz r11, rdx IID882 - __ ecmovq (Assembler::Condition::belowEqual, r31, r14, r25); // cmovbe r31, r14, r25 IID883 - __ ecmovq (Assembler::Condition::belowEqual, r20, r20, r12); // cmovbe r20, r12 IID884 - __ ecmovq (Assembler::Condition::above, rdx, r10, r28); // cmova rdx, r10, r28 IID885 - __ ecmovq (Assembler::Condition::above, r8, r8, r17); // cmova r8, r17 IID886 - __ ecmovq (Assembler::Condition::negative, rcx, r30, r23); // cmovs rcx, r30, r23 IID887 - __ ecmovq (Assembler::Condition::negative, r26, r26, r18); // cmovs r26, r18 IID888 - __ ecmovq (Assembler::Condition::positive, rdx, rbx, r18); // cmovns rdx, rbx, r18 IID889 - __ ecmovq (Assembler::Condition::positive, r21, r21, r13); // cmovns r21, r13 IID890 - __ ecmovq (Assembler::Condition::parity, r27, r28, r27); // cmovp r27, r28, r27 IID891 - __ ecmovq (Assembler::Condition::parity, r11, r11, r30); // cmovp r11, r30 IID892 - __ ecmovq (Assembler::Condition::noParity, rcx, r21, r18); // cmovnp rcx, r21, r18 IID893 - __ ecmovq (Assembler::Condition::noParity, rcx, rcx, r29); // cmovnp rcx, r29 IID894 - __ ecmovq (Assembler::Condition::less, rdx, r21, r12); // cmovl rdx, r21, r12 IID895 - __ ecmovq (Assembler::Condition::less, rdx, rdx, r26); // cmovl rdx, r26 IID896 - __ ecmovq (Assembler::Condition::greaterEqual, r17, rbx, r22); // cmovge r17, rbx, r22 IID897 - __ ecmovq (Assembler::Condition::greaterEqual, rdx, rdx, r11); // cmovge rdx, r11 IID898 - __ ecmovq (Assembler::Condition::lessEqual, rdx, r14, r8); // cmovle rdx, r14, r8 IID899 - __ ecmovq (Assembler::Condition::lessEqual, r14, r14, r8); // cmovle r14, r8 IID900 - __ ecmovq (Assembler::Condition::greater, r25, r29, r21); // cmovg r25, r29, r21 IID901 - __ ecmovq (Assembler::Condition::greater, r26, r26, r30); // cmovg r26, r30 IID902 - __ ecmovq (Assembler::Condition::overflow, r24, r21, Address(r13, r11, (Address::ScaleFactor)1, +0x439c521e)); // cmovo r24, r21, qword ptr [r13+r11*2+0x439c521e] IID903 - __ ecmovq (Assembler::Condition::noOverflow, r11, r18, Address(r29, r16, (Address::ScaleFactor)0, +0x632127f)); // cmovno r11, r18, qword ptr [r29+r16*1+0x632127f] IID904 - __ ecmovq (Assembler::Condition::below, r16, r8, Address(r8, r26, (Address::ScaleFactor)1, +0x10633def)); // cmovb r16, r8, qword ptr [r8+r26*2+0x10633def] IID905 - __ ecmovq (Assembler::Condition::aboveEqual, r13, r14, Address(r18, -0x54f69e38)); // cmovae r13, r14, qword ptr [r18-0x54f69e38] IID906 - __ ecmovq (Assembler::Condition::zero, r12, r8, Address(r31, r26, (Address::ScaleFactor)1, -0x7a1e447a)); // cmovz r12, r8, qword ptr [r31+r26*2-0x7a1e447a] IID907 - __ ecmovq (Assembler::Condition::notZero, r29, r29, Address(r19, r11, (Address::ScaleFactor)2, -0x35d82dd2)); // cmovnz r29, qword ptr [r19+r11*4-0x35d82dd2] IID908 - __ ecmovq (Assembler::Condition::belowEqual, rcx, r18, Address(r25, r28, (Address::ScaleFactor)0, +0x30be64a0)); // cmovbe rcx, r18, qword ptr [r25+r28*1+0x30be64a0] IID909 - __ ecmovq (Assembler::Condition::above, r28, r12, Address(r10, r16, (Address::ScaleFactor)1, -0x22b8fefa)); // cmova r28, r12, qword ptr [r10+r16*2-0x22b8fefa] IID910 - __ ecmovq (Assembler::Condition::negative, r11, r8, Address(rbx, r11, (Address::ScaleFactor)3, +0x25cc9e96)); // cmovs r11, r8, qword ptr [rbx+r11*8+0x25cc9e96] IID911 - __ ecmovq (Assembler::Condition::positive, r12, r27, Address(r11, -0xc2d70fe)); // cmovns r12, r27, qword ptr [r11-0xc2d70fe] IID912 - __ ecmovq (Assembler::Condition::parity, r8, r26, Address(r19, rbx, (Address::ScaleFactor)1, -0x486db7ea)); // cmovp r8, r26, qword ptr [r19+rbx*2-0x486db7ea] IID913 - __ ecmovq (Assembler::Condition::noParity, r30, r10, Address(r14, r18, (Address::ScaleFactor)3, +0x14884884)); // cmovnp r30, r10, qword ptr [r14+r18*8+0x14884884] IID914 - __ ecmovq (Assembler::Condition::less, r27, r8, Address(r29, r14, (Address::ScaleFactor)2, +0x92b7a8)); // cmovl r27, r8, qword ptr [r29+r14*4+0x92b7a8] IID915 - __ ecmovq (Assembler::Condition::greaterEqual, r14, r28, Address(r19, rdx, (Address::ScaleFactor)0, +0x9c2d45)); // cmovge r14, r28, qword ptr [r19+rdx*1+0x9c2d45] IID916 - __ ecmovq (Assembler::Condition::lessEqual, r25, r8, Address(rcx, r18, (Address::ScaleFactor)2, +0x6655c86b)); // cmovle r25, r8, qword ptr [rcx+r18*4+0x6655c86b] IID917 - __ ecmovq (Assembler::Condition::greater, r19, r21, Address(r10, r25, (Address::ScaleFactor)0, -0x1005430b)); // cmovg r19, r21, qword ptr [r10+r25*1-0x1005430b] IID918 + __ adcq(r30, r31); // {load}adc r30, r31 IID528 + __ cmpq(r12, rdx); // {load}cmp r12, rdx IID529 + __ imulq(r21, r24); // {load}imul r21, r24 IID530 + __ popcntq(r9, r25); // {load}popcnt r9, r25 IID531 + __ sbbq(r8, r12); // {load}sbb r8, r12 IID532 + __ subq(r31, r24); // {load}sub r31, r24 IID533 + __ tzcntq(r10, r16); // {load}tzcnt r10, r16 IID534 + __ lzcntq(r20, r21); // {load}lzcnt r20, r21 IID535 + __ addq(rdx, r17); // {load}add rdx, r17 IID536 + __ andq(r14, r13); // {load}and r14, r13 IID537 + __ orq(r20, r24); // {load}or r20, r24 IID538 + __ xorq(r21, r22); // {load}xor r21, r22 IID539 + __ movq(r12, r27); // {load}mov r12, r27 IID540 + __ bsfq(r23, rdx); // {load}bsf r23, rdx IID541 + __ bsrq(r31, r28); // {load}bsr r31, r28 IID542 + __ btq(r8, r25); // {load}bt r8, r25 IID543 + __ xchgq(r21, rbx); // {load}xchg r21, rbx IID544 + __ testq(r23, r23); // {load}test r23, r23 IID545 + __ addq(Address(r19, -0x180d3ea1), r10); // add qword ptr [r19-0x180d3ea1], r10 IID546 + __ andq(Address(r11, r17, (Address::ScaleFactor)1, -0x78976be8), r25); // and qword ptr [r11+r17*2-0x78976be8], r25 IID547 + __ cmpq(Address(rbx, r28, (Address::ScaleFactor)3, +0x35f72102), r13); // cmp qword ptr [rbx+r28*8+0x35f72102], r13 IID548 + __ orq(Address(r8, -0x34465011), r21); // or qword ptr [r8-0x34465011], r21 IID549 + __ xorq(Address(r19, -0x404b22dd), r18); // xor qword ptr [r19-0x404b22dd], r18 IID550 + __ subq(Address(r23, r27, (Address::ScaleFactor)3, -0x428d2646), r14); // sub qword ptr [r23+r27*8-0x428d2646], r14 IID551 + __ movq(Address(r9, rcx, (Address::ScaleFactor)2, -0x72611661), r28); // mov qword ptr [r9+rcx*4-0x72611661], r28 IID552 + __ xaddq(Address(r24, r21, (Address::ScaleFactor)2, +0x3a6be990), rbx); // xadd qword ptr [r24+r21*4+0x3a6be990], rbx IID553 + __ andq(Address(r22, r10, (Address::ScaleFactor)0, +0x7ef8bdd), 1048576); // and qword ptr [r22+r10*1+0x7ef8bdd], 1048576 IID554 + __ addq(Address(r13, r28, (Address::ScaleFactor)0, -0x754789b1), 65536); // add qword ptr [r13+r28*1-0x754789b1], 65536 IID555 + __ cmpq(Address(r10, -0xbd2a8da), 268435456); // cmp qword ptr [r10-0xbd2a8da], 268435456 IID556 + __ sarq(Address(r23, r14, (Address::ScaleFactor)1, +0x6a16d9f5), 4); // sar qword ptr [r23+r14*2+0x6a16d9f5], 4 IID557 + __ salq(Address(rcx, r21, (Address::ScaleFactor)1, +0x5f66ac1e), 8); // sal qword ptr [rcx+r21*2+0x5f66ac1e], 8 IID558 + __ sbbq(Address(rcx, r22, (Address::ScaleFactor)3, -0x48c954c), 268435456); // sbb qword ptr [rcx+r22*8-0x48c954c], 268435456 IID559 + __ shrq(Address(r21, r30, (Address::ScaleFactor)0, +0xe405b0b), 8); // shr qword ptr [r21+r30*1+0xe405b0b], 8 IID560 + __ subq(Address(r19, r29, (Address::ScaleFactor)3, -0x7762044b), 4096); // sub qword ptr [r19+r29*8-0x7762044b], 4096 IID561 + __ xorq(Address(r30, r10, (Address::ScaleFactor)1, -0x19798323), 16); // xor qword ptr [r30+r10*2-0x19798323], 16 IID562 + __ orq(Address(rdx, r24, (Address::ScaleFactor)3, +0x18d9b316), 4096); // or qword ptr [rdx+r24*8+0x18d9b316], 4096 IID563 + __ movq(Address(rbx, -0x3058074d), 256); // mov qword ptr [rbx-0x3058074d], 256 IID564 + __ testq(Address(r28, r21, (Address::ScaleFactor)3, +0x65a0fdc4), -268435456); // test qword ptr [r28+r21*8+0x65a0fdc4], -268435456 IID565 + __ addq(r23, Address(r11, r18, (Address::ScaleFactor)0, -0x1d1af10c)); // add r23, qword ptr [r11+r18*1-0x1d1af10c] IID566 + __ andq(r22, Address(r18, r12, (Address::ScaleFactor)1, +0x1a5f1c38)); // and r22, qword ptr [r18+r12*2+0x1a5f1c38] IID567 + __ cmpq(r23, Address(r30, r19, (Address::ScaleFactor)0, -0x3e912f7f)); // cmp r23, qword ptr [r30+r19*1-0x3e912f7f] IID568 + __ lzcntq(r29, Address(rcx, +0x12e3fbe4)); // lzcnt r29, qword ptr [rcx+0x12e3fbe4] IID569 + __ orq(r14, Address(r21, r21, (Address::ScaleFactor)2, +0xd73042)); // or r14, qword ptr [r21+r21*4+0xd73042] IID570 + __ adcq(r31, Address(r17, r31, (Address::ScaleFactor)2, +0xabde912)); // adc r31, qword ptr [r17+r31*4+0xabde912] IID571 + __ imulq(r20, Address(r13, r27, (Address::ScaleFactor)0, -0x58dbfc1f)); // imul r20, qword ptr [r13+r27*1-0x58dbfc1f] IID572 + __ popcntq(rbx, Address(r22, -0x72c66c23)); // popcnt rbx, qword ptr [r22-0x72c66c23] IID573 + __ sbbq(r26, Address(r9, +0x334aba09)); // sbb r26, qword ptr [r9+0x334aba09] IID574 + __ subq(r9, Address(r9, r30, (Address::ScaleFactor)3, -0x219a6102)); // sub r9, qword ptr [r9+r30*8-0x219a6102] IID575 + __ tzcntq(r25, Address(r20, -0x2131bab1)); // tzcnt r25, qword ptr [r20-0x2131bab1] IID576 + __ xorq(r16, Address(r28, r16, (Address::ScaleFactor)1, +0x48c483b9)); // xor r16, qword ptr [r28+r16*2+0x48c483b9] IID577 + __ movq(r30, Address(r9, r16, (Address::ScaleFactor)0, -0x88ce84f)); // mov r30, qword ptr [r9+r16*1-0x88ce84f] IID578 + __ leaq(r11, Address(r30, r29, (Address::ScaleFactor)2, +0x3eeb8fd0)); // lea r11, qword ptr [r30+r29*4+0x3eeb8fd0] IID579 + __ cvttsd2siq(r26, Address(r29, r10, (Address::ScaleFactor)3, +0x3ef4822e)); // cvttsd2si r26, qword ptr [r29+r10*8+0x3ef4822e] IID580 + __ xchgq(r29, Address(r19, r20, (Address::ScaleFactor)2, -0x3f0f3db9)); // xchg r29, qword ptr [r19+r20*4-0x3f0f3db9] IID581 + __ testq(r8, Address(r30, r20, (Address::ScaleFactor)0, +0x15b56a17)); // test r8, qword ptr [r30+r20*1+0x15b56a17] IID582 + __ addq(r26, 4096); // add r26, 4096 IID583 + __ andq(r20, 16); // and r20, 16 IID584 + __ adcq(r23, 1048576); // adc r23, 1048576 IID585 + __ cmpq(r12, 4096); // cmp r12, 4096 IID586 + __ rclq(rcx, 4); // rcl rcx, 4 IID587 + __ rcrq(r14, 1); // rcr r14, 1 IID588 + __ rolq(r23, 2); // rol r23, 2 IID589 + __ rorq(r12, 4); // ror r12, 4 IID590 + __ sarq(r10, 4); // sar r10, 4 IID591 + __ salq(r20, 4); // sal r20, 4 IID592 + __ sbbq(rcx, 1048576); // sbb rcx, 1048576 IID593 + __ shlq(r23, 16); // shl r23, 16 IID594 + __ shrq(r27, 2); // shr r27, 2 IID595 + __ subq(rcx, 65536); // sub rcx, 65536 IID596 + __ xorq(r9, 1048576); // xor r9, 1048576 IID597 + __ movq(r16, 65536); // mov r16, 65536 IID598 + __ mov64(r24, 4503599627370496); // mov r24, 4503599627370496 IID599 + __ btq(r18, 64); // bt r18, 64 IID600 + __ testq(r29, -4096); // test r29, -4096 IID601 + __ orq_imm32(r30, 67108864); // or r30, 67108864 IID602 + __ subq_imm32(r25, 268435456); // sub r25, 268435456 IID603 + __ cmovq(Assembler::Condition::overflow, r30, Address(r17, r31, (Address::ScaleFactor)2, +0x47ff92f0)); // cmovo r30, qword ptr [r17+r31*4+0x47ff92f0] IID604 + __ cmovq(Assembler::Condition::noOverflow, r9, Address(r24, r28, (Address::ScaleFactor)1, +0x384904c0)); // cmovno r9, qword ptr [r24+r28*2+0x384904c0] IID605 + __ cmovq(Assembler::Condition::below, r23, Address(r23, r24, (Address::ScaleFactor)3, -0x197f1266)); // cmovb r23, qword ptr [r23+r24*8-0x197f1266] IID606 + __ cmovq(Assembler::Condition::aboveEqual, r9, Address(r29, r30, (Address::ScaleFactor)0, +0x2b5d49c8)); // cmovae r9, qword ptr [r29+r30*1+0x2b5d49c8] IID607 + __ cmovq(Assembler::Condition::zero, r16, Address(rbx, r15, (Address::ScaleFactor)1, +0x22379381)); // cmovz r16, qword ptr [rbx+r15*2+0x22379381] IID608 + __ cmovq(Assembler::Condition::notZero, r8, Address(r11, +0x49d67a0)); // cmovnz r8, qword ptr [r11+0x49d67a0] IID609 + __ cmovq(Assembler::Condition::belowEqual, r28, Address(r16, r16, (Address::ScaleFactor)2, -0x5e941da9)); // cmovbe r28, qword ptr [r16+r16*4-0x5e941da9] IID610 + __ cmovq(Assembler::Condition::above, r19, Address(r18, r8, (Address::ScaleFactor)0, -0xa5e55ec)); // cmova r19, qword ptr [r18+r8*1-0xa5e55ec] IID611 + __ cmovq(Assembler::Condition::negative, r28, Address(r17, r28, (Address::ScaleFactor)1, -0x3264220c)); // cmovs r28, qword ptr [r17+r28*2-0x3264220c] IID612 + __ cmovq(Assembler::Condition::positive, r31, Address(r14, r31, (Address::ScaleFactor)1, +0x5001bc5a)); // cmovns r31, qword ptr [r14+r31*2+0x5001bc5a] IID613 + __ cmovq(Assembler::Condition::parity, rbx, Address(r18, r17, (Address::ScaleFactor)2, -0x286f2379)); // cmovp rbx, qword ptr [r18+r17*4-0x286f2379] IID614 + __ cmovq(Assembler::Condition::noParity, r17, Address(r20, -0x5549f838)); // cmovnp r17, qword ptr [r20-0x5549f838] IID615 + __ cmovq(Assembler::Condition::less, r30, Address(r9, r28, (Address::ScaleFactor)1, -0x25b00cf3)); // cmovl r30, qword ptr [r9+r28*2-0x25b00cf3] IID616 + __ cmovq(Assembler::Condition::greaterEqual, r19, Address(r9, -0x2aabf22c)); // cmovge r19, qword ptr [r9-0x2aabf22c] IID617 + __ cmovq(Assembler::Condition::lessEqual, rbx, Address(rcx, r12, (Address::ScaleFactor)1, -0x432d68cc)); // cmovle rbx, qword ptr [rcx+r12*2-0x432d68cc] IID618 + __ cmovq(Assembler::Condition::greater, rbx, Address(r15, r17, (Address::ScaleFactor)3, -0x2b97565e)); // cmovg rbx, qword ptr [r15+r17*8-0x2b97565e] IID619 + __ call(r24); // call r24 IID620 + __ divq(r9); // div r9 IID621 + __ idivq(r28); // idiv r28 IID622 + __ imulq(rdx); // imul rdx IID623 + __ mulq(r31); // mul r31 IID624 + __ negq(r12); // neg r12 IID625 + __ notq(r12); // not r12 IID626 + __ rolq(r24); // rol r24, cl IID627 + __ rorq(r28); // ror r28, cl IID628 + __ sarq(r11); // sar r11, cl IID629 + __ salq(r27); // sal r27, cl IID630 + __ shlq(r23); // shl r23, cl IID631 + __ shrq(r17); // shr r17, cl IID632 + __ incrementq(r16); // inc r16 IID633 + __ decrementq(r12); // dec r12 IID634 + __ pushp(r23); // pushp r23 IID635 + __ popp(r24); // popp r24 IID636 + __ call(Address(r18, r14, (Address::ScaleFactor)0, -0x66639d32)); // call qword ptr [r18+r14*1-0x66639d32] IID637 + __ mulq(Address(r24, -0x660a2421)); // mul qword ptr [r24-0x660a2421] IID638 + __ negq(Address(r14, r18, (Address::ScaleFactor)0, +0x40f3936e)); // neg qword ptr [r14+r18*1+0x40f3936e] IID639 + __ sarq(Address(r10, r13, (Address::ScaleFactor)0, +0x7d04cb72)); // sar qword ptr [r10+r13*1+0x7d04cb72], cl IID640 + __ salq(Address(r18, r11, (Address::ScaleFactor)3, -0x2176b4dc)); // sal qword ptr [r18+r11*8-0x2176b4dc], cl IID641 + __ shrq(Address(r13, rcx, (Address::ScaleFactor)1, +0x7996aa80)); // shr qword ptr [r13+rcx*2+0x7996aa80], cl IID642 + __ incrementq(Address(r14, +0x67c2d02a)); // inc qword ptr [r14+0x67c2d02a] IID643 + __ decrementq(Address(r22, r26, (Address::ScaleFactor)0, +0x224f62c0)); // dec qword ptr [r22+r26*1+0x224f62c0] IID644 + __ imulq(rdx, Address(r31, rbx, (Address::ScaleFactor)1, +0x2b00bb10), 16777216); // imul rdx, qword ptr [r31+rbx*2+0x2b00bb10], 16777216 IID645 + __ imulq(r21, r31, 4096); // imul r21, r31, 4096 IID646 + __ shldq(rbx, r19, 1); // shld rbx, r19, 1 IID647 + __ shrdq(r11, r23, 4); // shrd r11, r23, 4 IID648 + __ pop2(r16, r30); // {load}pop2 r30, r16 IID649 + __ pop2p(r17, rbx); // {load}pop2p rbx, r17 IID650 + __ push2(r20, r30); // {load}push2 r30, r20 IID651 + __ push2p(r8, r31); // {load}push2p r31, r8 IID652 + __ movzbq(r28, Address(r8, r14, (Address::ScaleFactor)0, +0x469ae67a)); // movzx r28, byte ptr [r8+r14*1+0x469ae67a] IID653 + __ movzwq(r14, Address(r8, r18, (Address::ScaleFactor)2, -0x48699e02)); // movzx r14, word ptr [r8+r18*4-0x48699e02] IID654 + __ movsbq(r21, Address(rbx, -0x64dae06b)); // movsx r21, byte ptr [rbx-0x64dae06b] IID655 + __ movswq(r19, Address(r31, rbx, (Address::ScaleFactor)2, +0x60318819)); // movsx r19, word ptr [r31+rbx*4+0x60318819] IID656 + __ movzbq(r30, r13); // movzx r30, r13b IID657 + __ movzwq(r30, r18); // movzx r30, r18w IID658 + __ movsbq(r19, r15); // movsx r19, r15b IID659 + __ movswq(r20, r16); // movsx r20, r16w IID660 + __ cmpxchgq(r28, Address(r11, rbx, (Address::ScaleFactor)3, +0xfc3479d)); // cmpxchg qword ptr [r11+rbx*8+0xfc3479d], r28 IID661 + __ eidivq(r20, false); // {EVEX}idiv r20 IID662 + __ eidivq(r30, true); // {NF}idiv r30 IID663 + __ edivq(r22, false); // {EVEX}div r22 IID664 + __ edivq(r11, true); // {NF}div r11 IID665 + __ eimulq(rcx, false); // {EVEX}imul rcx IID666 + __ eimulq(r28, true); // {NF}imul r28 IID667 + __ emulq(r21, false); // {EVEX}mul r21 IID668 + __ emulq(r13, true); // {NF}mul r13 IID669 + __ emulq(Address(r26, r15, (Address::ScaleFactor)2, +0x70a1ce6e), false); // {EVEX}mul qword ptr [r26+r15*4+0x70a1ce6e] IID670 + __ emulq(Address(r24, r19, (Address::ScaleFactor)1, -0x1670855c), true); // {NF}mul qword ptr [r24+r19*2-0x1670855c] IID671 + __ eimulq(r10, r27, false); // {EVEX}imul r10, r27 IID672 + __ eimulq(r17, r17, false); // imul r17 IID673 + __ eimulq(rdx, r22, true); // {NF}imul rdx, r22 IID674 + __ eimulq(rbx, rbx, true); // {NF}imul rbx, rbx IID675 + __ elzcntq(r28, r15, false); // {EVEX}lzcnt r28, r15 IID676 + __ elzcntq(r15, r15, false); // {EVEX}lzcnt r15, r15 IID677 + __ elzcntq(rbx, r12, true); // {NF}lzcnt rbx, r12 IID678 + __ elzcntq(rbx, rbx, true); // {NF}lzcnt rbx, rbx IID679 + __ enegq(r26, r11, false); // {EVEX}neg r26, r11 IID680 + __ enegq(r17, r17, false); // neg r17 IID681 + __ enegq(rdx, r31, true); // {NF}neg rdx, r31 IID682 + __ enegq(r27, r27, true); // {NF}neg r27, r27 IID683 + __ enotq(r31, r15); // {EVEX}not r31, r15 IID684 + __ enotq(r21, r21); // not r21 IID685 + __ epopcntq(rbx, r24, false); // {EVEX}popcnt rbx, r24 IID686 + __ epopcntq(r28, r28, false); // {EVEX}popcnt r28, r28 IID687 + __ epopcntq(r23, r27, true); // {NF}popcnt r23, r27 IID688 + __ epopcntq(r13, r13, true); // {NF}popcnt r13, r13 IID689 + __ erolq(r25, r28, false); // {EVEX}rol r25, r28, cl IID690 + __ erolq(r31, r31, false); // rol r31, cl IID691 + __ erolq(r25, r23, true); // {NF}rol r25, r23, cl IID692 + __ erolq(rcx, rcx, true); // {NF}rol rcx, rcx, cl IID693 + __ erorq(r22, r14, false); // {EVEX}ror r22, r14, cl IID694 + __ erorq(r15, r15, false); // ror r15, cl IID695 + __ erorq(r11, r30, true); // {NF}ror r11, r30, cl IID696 + __ erorq(r24, r24, true); // {NF}ror r24, r24, cl IID697 + __ esalq(r10, r20, false); // {EVEX}sal r10, r20, cl IID698 + __ esalq(r19, r19, false); // sal r19, cl IID699 + __ esalq(r17, r25, true); // {NF}sal r17, r25, cl IID700 + __ esalq(r13, r13, true); // {NF}sal r13, r13, cl IID701 + __ esarq(r31, r30, false); // {EVEX}sar r31, r30, cl IID702 + __ esarq(r18, r18, false); // sar r18, cl IID703 + __ esarq(r25, r25, true); // {NF}sar r25, r25, cl IID704 + __ esarq(r28, r28, true); // {NF}sar r28, r28, cl IID705 + __ edecq(r22, r27, false); // {EVEX}dec r22, r27 IID706 + __ edecq(r12, r12, false); // dec r12 IID707 + __ edecq(r18, r11, true); // {NF}dec r18, r11 IID708 + __ edecq(r10, r10, true); // {NF}dec r10, r10 IID709 + __ eincq(r20, r24, false); // {EVEX}inc r20, r24 IID710 + __ eincq(r18, r18, false); // inc r18 IID711 + __ eincq(rbx, r11, true); // {NF}inc rbx, r11 IID712 + __ eincq(r26, r26, true); // {NF}inc r26, r26 IID713 + __ eshlq(r21, r8, false); // {EVEX}shl r21, r8, cl IID714 + __ eshlq(rbx, rbx, false); // shl rbx, cl IID715 + __ eshlq(r22, r21, true); // {NF}shl r22, r21, cl IID716 + __ eshlq(r27, r27, true); // {NF}shl r27, r27, cl IID717 + __ eshrq(r12, r16, false); // {EVEX}shr r12, r16, cl IID718 + __ eshrq(r8, r8, false); // shr r8, cl IID719 + __ eshrq(rdx, r9, true); // {NF}shr rdx, r9, cl IID720 + __ eshrq(r20, r20, true); // {NF}shr r20, r20, cl IID721 + __ etzcntq(r31, r21, false); // {EVEX}tzcnt r31, r21 IID722 + __ etzcntq(r20, r20, false); // {EVEX}tzcnt r20, r20 IID723 + __ etzcntq(rcx, r16, true); // {NF}tzcnt rcx, r16 IID724 + __ etzcntq(r14, r14, true); // {NF}tzcnt r14, r14 IID725 + __ eimulq(r27, Address(r25, r9, (Address::ScaleFactor)1, +0x445a2393), false); // {EVEX}imul r27, qword ptr [r25+r9*2+0x445a2393] IID726 + __ eimulq(r23, Address(rcx, r9, (Address::ScaleFactor)1, -0x1480ef0c), true); // {NF}imul r23, qword ptr [rcx+r9*2-0x1480ef0c] IID727 + __ elzcntq(r13, Address(r22, r17, (Address::ScaleFactor)1, -0x750c1996), false); // {EVEX}lzcnt r13, qword ptr [r22+r17*2-0x750c1996] IID728 + __ elzcntq(r13, Address(r31, -0x342b6259), true); // {NF}lzcnt r13, qword ptr [r31-0x342b6259] IID729 + __ enegq(r31, Address(r24, r13, (Address::ScaleFactor)1, -0x25b16a0e), false); // {EVEX}neg r31, qword ptr [r24+r13*2-0x25b16a0e] IID730 + __ enegq(r13, Address(r11, r28, (Address::ScaleFactor)3, +0x5c0013ab), true); // {NF}neg r13, qword ptr [r11+r28*8+0x5c0013ab] IID731 + __ epopcntq(rdx, Address(r18, rcx, (Address::ScaleFactor)2, -0x6113eaaf), false); // {EVEX}popcnt rdx, qword ptr [r18+rcx*4-0x6113eaaf] IID732 + __ epopcntq(r9, Address(r10, -0x5ca7d588), true); // {NF}popcnt r9, qword ptr [r10-0x5ca7d588] IID733 + __ esalq(r17, Address(r27, r30, (Address::ScaleFactor)0, +0x1b4cda2c), false); // {EVEX}sal r17, qword ptr [r27+r30*1+0x1b4cda2c], cl IID734 + __ esalq(r25, Address(r12, rdx, (Address::ScaleFactor)1, +0x62823bce), true); // {NF}sal r25, qword ptr [r12+rdx*2+0x62823bce], cl IID735 + __ esarq(r9, Address(r10, r18, (Address::ScaleFactor)2, -0x264a7a48), false); // {EVEX}sar r9, qword ptr [r10+r18*4-0x264a7a48], cl IID736 + __ esarq(rbx, Address(r14, r27, (Address::ScaleFactor)0, +0x20291e00), true); // {NF}sar rbx, qword ptr [r14+r27*1+0x20291e00], cl IID737 + __ edecq(r12, Address(r15, r14, (Address::ScaleFactor)2, -0x20f7dabb), false); // {EVEX}dec r12, qword ptr [r15+r14*4-0x20f7dabb] IID738 + __ edecq(r9, Address(r10, r25, (Address::ScaleFactor)1, +0x21411d84), true); // {NF}dec r9, qword ptr [r10+r25*2+0x21411d84] IID739 + __ eincq(r20, Address(rbx, r25, (Address::ScaleFactor)3, +0x2f0329e), false); // {EVEX}inc r20, qword ptr [rbx+r25*8+0x2f0329e] IID740 + __ eincq(r10, Address(r12, r31, (Address::ScaleFactor)0, -0x37505c8c), true); // {NF}inc r10, qword ptr [r12+r31*1-0x37505c8c] IID741 + __ eshrq(r24, Address(r23, r14, (Address::ScaleFactor)3, -0x71e75ab0), false); // {EVEX}shr r24, qword ptr [r23+r14*8-0x71e75ab0], cl IID742 + __ eshrq(r25, Address(r19, r10, (Address::ScaleFactor)1, +0x507b0a88), true); // {NF}shr r25, qword ptr [r19+r10*2+0x507b0a88], cl IID743 + __ etzcntq(r31, Address(rbx, r16, (Address::ScaleFactor)0, +0x19d5192a), false); // {EVEX}tzcnt r31, qword ptr [rbx+r16*1+0x19d5192a] IID744 + __ etzcntq(r9, Address(r22, r28, (Address::ScaleFactor)2, +0x211007cd), true); // {NF}tzcnt r9, qword ptr [r22+r28*4+0x211007cd] IID745 + __ eaddq(r16, Address(r21, rbx, (Address::ScaleFactor)3, -0x823fa1e), r28, false); // {EVEX}add r16, qword ptr [r21+rbx*8-0x823fa1e], r28 IID746 + __ eaddq(r15, Address(rdx, r8, (Address::ScaleFactor)3, -0x34b9a058), r15, false); // add r15, qword ptr [rdx+r8*8-0x34b9a058] IID747 + __ eaddq(r24, Address(r14, r24, (Address::ScaleFactor)3, +0x6cdc59d2), r13, true); // {NF}add r24, qword ptr [r14+r24*8+0x6cdc59d2], r13 IID748 + __ eaddq(rbx, Address(r27, r14, (Address::ScaleFactor)3, +0x36c5e8de), rbx, true); // {NF}add rbx, qword ptr [r27+r14*8+0x36c5e8de], rbx IID749 + __ eandq(r21, Address(r27, r27, (Address::ScaleFactor)1, -0x2c023b13), r27, false); // {EVEX}and r21, qword ptr [r27+r27*2-0x2c023b13], r27 IID750 + __ eandq(r31, Address(r21, r15, (Address::ScaleFactor)2, +0x6ef2c74a), r31, false); // and r31, qword ptr [r21+r15*4+0x6ef2c74a] IID751 + __ eandq(r13, Address(r31, r25, (Address::ScaleFactor)1, +0x734fe9ab), r27, true); // {NF}and r13, qword ptr [r31+r25*2+0x734fe9ab], r27 IID752 + __ eandq(r15, Address(r14, r29, (Address::ScaleFactor)3, -0x6e68556), r15, true); // {NF}and r15, qword ptr [r14+r29*8-0x6e68556], r15 IID753 + __ eorq(r12, Address(r30, r15, (Address::ScaleFactor)3, +0x3ba33f9e), r28, false); // {EVEX}or r12, qword ptr [r30+r15*8+0x3ba33f9e], r28 IID754 + __ eorq(r16, Address(r12, r9, (Address::ScaleFactor)0, -0x28e03b33), r16, false); // or r16, qword ptr [r12+r9*1-0x28e03b33] IID755 + __ eorq(r8, Address(r8, r25, (Address::ScaleFactor)3, -0x1e42bd95), r27, true); // {NF}or r8, qword ptr [r8+r25*8-0x1e42bd95], r27 IID756 + __ eorq(rcx, Address(r27, rbx, (Address::ScaleFactor)2, +0x7be4bcad), rcx, true); // {NF}or rcx, qword ptr [r27+rbx*4+0x7be4bcad], rcx IID757 + __ esubq(r24, Address(r23, r22, (Address::ScaleFactor)2, +0x6f8827d7), rdx, false); // {EVEX}sub r24, qword ptr [r23+r22*4+0x6f8827d7], rdx IID758 + __ esubq(r21, Address(r10, -0x635b8c8), r21, false); // {EVEX}sub r21, qword ptr [r10-0x635b8c8], r21 IID759 + __ esubq(r23, Address(r27, r26, (Address::ScaleFactor)3, +0x922bcc0), rbx, true); // {NF}sub r23, qword ptr [r27+r26*8+0x922bcc0], rbx IID760 + __ esubq(r25, Address(r23, r15, (Address::ScaleFactor)0, -0x38f494ac), r25, true); // {NF}sub r25, qword ptr [r23+r15*1-0x38f494ac], r25 IID761 + __ exorq(r11, Address(r12, r19, (Address::ScaleFactor)2, -0x5b71ec17), rcx, false); // {EVEX}xor r11, qword ptr [r12+r19*4-0x5b71ec17], rcx IID762 + __ exorq(r28, Address(r19, r18, (Address::ScaleFactor)0, +0x716b9b7e), r28, false); // xor r28, qword ptr [r19+r18*1+0x716b9b7e] IID763 + __ exorq(r21, Address(rcx, r29, (Address::ScaleFactor)0, -0x5af0441e), r16, true); // {NF}xor r21, qword ptr [rcx+r29*1-0x5af0441e], r16 IID764 + __ exorq(r12, Address(r20, r26, (Address::ScaleFactor)0, +0xe0b7fb1), r12, true); // {NF}xor r12, qword ptr [r20+r26*1+0xe0b7fb1], r12 IID765 + __ eaddq(r30, Address(rcx, +0x2d3b7b4f), 1048576, false); // {EVEX}add r30, qword ptr [rcx+0x2d3b7b4f], 1048576 IID766 + __ eaddq(r14, Address(r21, r15, (Address::ScaleFactor)2, -0x1222aee8), 4096, true); // {NF}add r14, qword ptr [r21+r15*4-0x1222aee8], 4096 IID767 + __ eandq(r23, Address(r20, r31, (Address::ScaleFactor)0, -0x96e4d6a), 16, false); // {EVEX}and r23, qword ptr [r20+r31*1-0x96e4d6a], 16 IID768 + __ eandq(r10, Address(rdx, rdx, (Address::ScaleFactor)3, +0x3875f17c), 1, true); // {NF}and r10, qword ptr [rdx+rdx*8+0x3875f17c], 1 IID769 + __ eimulq(r17, Address(rcx, r25, (Address::ScaleFactor)2, +0x32c71076), 4096, false); // {EVEX}imul r17, qword ptr [rcx+r25*4+0x32c71076], 4096 IID770 + __ eimulq(r19, Address(r31, rbx, (Address::ScaleFactor)2, +0x7bada60d), 1048576, true); // {NF}imul r19, qword ptr [r31+rbx*4+0x7bada60d], 1048576 IID771 + __ eorq(r25, Address(r18, r23, (Address::ScaleFactor)1, +0x48147444), 16777216, false); // {EVEX}or r25, qword ptr [r18+r23*2+0x48147444], 16777216 IID772 + __ eorq(r29, Address(r26, r27, (Address::ScaleFactor)1, -0x4b113958), 1048576, true); // {NF}or r29, qword ptr [r26+r27*2-0x4b113958], 1048576 IID773 + __ esalq(r31, Address(r18, -0x46103c74), 2, false); // {EVEX}sal r31, qword ptr [r18-0x46103c74], 2 IID774 + __ esalq(r25, Address(r10, r15, (Address::ScaleFactor)0, +0x48925da4), 16, true); // {NF}sal r25, qword ptr [r10+r15*1+0x48925da4], 16 IID775 + __ esarq(r26, Address(r18, -0x5ea1c542), 8, false); // {EVEX}sar r26, qword ptr [r18-0x5ea1c542], 8 IID776 + __ esarq(r12, Address(r10, r22, (Address::ScaleFactor)2, +0x5d958264), 8, true); // {NF}sar r12, qword ptr [r10+r22*4+0x5d958264], 8 IID777 + __ eshrq(rdx, Address(r17, r20, (Address::ScaleFactor)2, +0x295add23), 16, false); // {EVEX}shr rdx, qword ptr [r17+r20*4+0x295add23], 16 IID778 + __ eshrq(rbx, Address(r22, r28, (Address::ScaleFactor)1, +0x782929cb), 2, true); // {NF}shr rbx, qword ptr [r22+r28*2+0x782929cb], 2 IID779 + __ esubq(r19, Address(r23, -0x49811d72), 1, false); // {EVEX}sub r19, qword ptr [r23-0x49811d72], 1 IID780 + __ esubq(r8, Address(r19, r14, (Address::ScaleFactor)2, -0x1b2bae9a), 1048576, true); // {NF}sub r8, qword ptr [r19+r14*4-0x1b2bae9a], 1048576 IID781 + __ exorq(r19, Address(rcx, r10, (Address::ScaleFactor)0, +0x45a66ee9), 1048576, false); // {EVEX}xor r19, qword ptr [rcx+r10*1+0x45a66ee9], 1048576 IID782 + __ exorq(r28, Address(r9, r29, (Address::ScaleFactor)0, -0x28a19314), 16, true); // {NF}xor r28, qword ptr [r9+r29*1-0x28a19314], 16 IID783 + __ eaddq(r8, rcx, 16777216, false); // {EVEX}add r8, rcx, 16777216 IID784 + __ eaddq(rax, r14, 16777216, false); // {EVEX}add rax, r14, 16777216 IID785 + __ eaddq(r16, r16, 256, false); // add r16, 256 IID786 + __ eaddq(r24, r9, 4096, true); // {NF}add r24, r9, 4096 IID787 + __ eaddq(rax, r18, 4096, true); // {NF}add rax, r18, 4096 IID788 + __ eaddq(r8, r8, 1, true); // {NF}add r8, r8, 1 IID789 + __ eandq(r15, r22, 1048576, false); // {EVEX}and r15, r22, 1048576 IID790 + __ eandq(rax, r26, 1048576, false); // {EVEX}and rax, r26, 1048576 IID791 + __ eandq(rdx, rdx, 4096, false); // and rdx, 4096 IID792 + __ eandq(rdx, r22, 268435456, true); // {NF}and rdx, r22, 268435456 IID793 + __ eandq(rax, r29, 268435456, true); // {NF}and rax, r29, 268435456 IID794 + __ eandq(r23, r23, 16777216, true); // {NF}and r23, r23, 16777216 IID795 + __ eimulq(r9, r13, 1048576, false); // {EVEX}imul r9, r13, 1048576 IID796 + __ eimulq(rax, r18, 1048576, false); // {EVEX}imul rax, r18, 1048576 IID797 + __ eimulq(r16, r16, 1048576, false); // {EVEX}imul r16, r16, 1048576 IID798 + __ eimulq(r17, r23, 1, true); // {NF}imul r17, r23, 1 IID799 + __ eimulq(rax, r12, 1, true); // {NF}imul rax, r12, 1 IID800 + __ eimulq(r10, r10, 268435456, true); // {NF}imul r10, r10, 268435456 IID801 + __ eorq(rdx, r19, 256, false); // {EVEX}or rdx, r19, 256 IID802 + __ eorq(rax, r14, 256, false); // {EVEX}or rax, r14, 256 IID803 + __ eorq(r13, r13, 1, false); // or r13, 1 IID804 + __ eorq(r25, r29, 256, true); // {NF}or r25, r29, 256 IID805 + __ eorq(rax, rdx, 256, true); // {NF}or rax, rdx, 256 IID806 + __ eorq(r16, r16, 16, true); // {NF}or r16, r16, 16 IID807 + __ erclq(r13, r19, 4); // {EVEX}rcl r13, r19, 4 IID808 + __ erclq(rax, r12, 4); // {EVEX}rcl rax, r12, 4 IID809 + __ erclq(r9, r9, 4); // rcl r9, 4 IID810 + __ erolq(r13, r16, 1, false); // {EVEX}rol r13, r16, 1 IID811 + __ erolq(rax, r31, 1, false); // {EVEX}rol rax, r31, 1 IID812 + __ erolq(r30, r30, 8, false); // rol r30, 8 IID813 + __ erolq(r30, r20, 8, true); // {NF}rol r30, r20, 8 IID814 + __ erolq(rax, r31, 8, true); // {NF}rol rax, r31, 8 IID815 + __ erolq(r31, r31, 4, true); // {NF}rol r31, r31, 4 IID816 + __ erorq(r22, r10, 4, false); // {EVEX}ror r22, r10, 4 IID817 + __ erorq(rax, r13, 4, false); // {EVEX}ror rax, r13, 4 IID818 + __ erorq(r24, r24, 16, false); // ror r24, 16 IID819 + __ erorq(r29, r22, 16, true); // {NF}ror r29, r22, 16 IID820 + __ erorq(rax, r20, 16, true); // {NF}ror rax, r20, 16 IID821 + __ erorq(r27, r27, 4, true); // {NF}ror r27, r27, 4 IID822 + __ esalq(r31, r19, 2, false); // {EVEX}sal r31, r19, 2 IID823 + __ esalq(rax, r20, 2, false); // {EVEX}sal rax, r20, 2 IID824 + __ esalq(r11, r11, 8, false); // sal r11, 8 IID825 + __ esalq(rdx, r15, 1, true); // {NF}sal rdx, r15, 1 IID826 + __ esalq(rax, r10, 1, true); // {NF}sal rax, r10, 1 IID827 + __ esalq(r29, r29, 4, true); // {NF}sal r29, r29, 4 IID828 + __ esarq(r20, r16, 1, false); // {EVEX}sar r20, r16, 1 IID829 + __ esarq(rax, r21, 1, false); // {EVEX}sar rax, r21, 1 IID830 + __ esarq(r28, r28, 8, false); // sar r28, 8 IID831 + __ esarq(r30, rcx, 4, true); // {NF}sar r30, rcx, 4 IID832 + __ esarq(rax, r15, 4, true); // {NF}sar rax, r15, 4 IID833 + __ esarq(rcx, rcx, 4, true); // {NF}sar rcx, rcx, 4 IID834 + __ eshlq(rdx, r26, 4, false); // {EVEX}shl rdx, r26, 4 IID835 + __ eshlq(rax, r26, 4, false); // {EVEX}shl rax, r26, 4 IID836 + __ eshlq(r8, r8, 4, false); // shl r8, 4 IID837 + __ eshlq(rcx, rcx, 1, true); // {NF}shl rcx, rcx, 1 IID838 + __ eshlq(rax, rcx, 1, true); // {NF}shl rax, rcx, 1 IID839 + __ eshlq(r13, r13, 2, true); // {NF}shl r13, r13, 2 IID840 + __ eshrq(r14, r27, 2, false); // {EVEX}shr r14, r27, 2 IID841 + __ eshrq(rax, r11, 2, false); // {EVEX}shr rax, r11, 2 IID842 + __ eshrq(r9, r9, 16, false); // shr r9, 16 IID843 + __ eshrq(rdx, r31, 2, true); // {NF}shr rdx, r31, 2 IID844 + __ eshrq(rax, r14, 2, true); // {NF}shr rax, r14, 2 IID845 + __ eshrq(r12, r12, 8, true); // {NF}shr r12, r12, 8 IID846 + __ esubq(r10, r28, 1, false); // {EVEX}sub r10, r28, 1 IID847 + __ esubq(rax, r8, 1, false); // {EVEX}sub rax, r8, 1 IID848 + __ esubq(rcx, rcx, 16777216, false); // sub rcx, 16777216 IID849 + __ esubq(rdx, rbx, 16777216, true); // {NF}sub rdx, rbx, 16777216 IID850 + __ esubq(rax, r18, 16777216, true); // {NF}sub rax, r18, 16777216 IID851 + __ esubq(r27, r27, 65536, true); // {NF}sub r27, r27, 65536 IID852 + __ exorq(r30, rcx, 4096, false); // {EVEX}xor r30, rcx, 4096 IID853 + __ exorq(rax, r21, 4096, false); // {EVEX}xor rax, r21, 4096 IID854 + __ exorq(rcx, rcx, 16777216, false); // xor rcx, 16777216 IID855 + __ exorq(r21, r12, 1, true); // {NF}xor r21, r12, 1 IID856 + __ exorq(rax, rdx, 1, true); // {NF}xor rax, rdx, 1 IID857 + __ exorq(rbx, rbx, 16777216, true); // {NF}xor rbx, rbx, 16777216 IID858 + __ eorq_imm32(r11, rdx, 65536, false); // {EVEX}or r11, rdx, 65536 IID859 + __ eorq_imm32(rax, r14, 65536, false); // {EVEX}or rax, r14, 65536 IID860 + __ eorq_imm32(r14, r14, 262144, false); // or r14, 262144 IID861 + __ eorq_imm32(r25, r29, 262144, false); // {EVEX}or r25, r29, 262144 IID862 + __ eorq_imm32(rax, r21, 262144, false); // {EVEX}or rax, r21, 262144 IID863 + __ eorq_imm32(r11, r11, 16777216, false); // or r11, 16777216 IID864 + __ esubq_imm32(r29, r19, 67108864, false); // {EVEX}sub r29, r19, 67108864 IID865 + __ esubq_imm32(rax, r11, 67108864, false); // {EVEX}sub rax, r11, 67108864 IID866 + __ esubq_imm32(r18, r18, 67108864, false); // sub r18, 67108864 IID867 + __ esubq_imm32(r28, r23, 4194304, true); // {NF}sub r28, r23, 4194304 IID868 + __ esubq_imm32(rax, r21, 4194304, true); // {NF}sub rax, r21, 4194304 IID869 + __ esubq_imm32(r16, r16, 16777216, true); // {NF}sub r16, r16, 16777216 IID870 + __ eaddq(r8, r25, Address(r26, r8, (Address::ScaleFactor)1, +0x10633def), false); // {EVEX}add r8, r25, qword ptr [r26+r8*2+0x10633def] IID871 + __ eaddq(r13, r13, Address(r18, r16, (Address::ScaleFactor)1, -0x74204508), false); // add r13, qword ptr [r18+r16*2-0x74204508] IID872 + __ eaddq(r17, r26, Address(r12, +0x23a80abf), true); // {NF}add r17, r26, qword ptr [r12+0x23a80abf] IID873 + __ eaddq(r9, r9, Address(r29, r19, (Address::ScaleFactor)0, -0x29e9e52), true); // {NF}add r9, r9, qword ptr [r29+r19*1-0x29e9e52] IID874 + __ eandq(r9, r28, Address(rcx, r25, (Address::ScaleFactor)2, +0x4261ffaa), false); // {EVEX}and r9, r28, qword ptr [rcx+r25*4+0x4261ffaa] IID875 + __ eandq(r27, r27, Address(rdx, r28, (Address::ScaleFactor)0, -0x26bdc9c1), false); // and r27, qword ptr [rdx+r28*1-0x26bdc9c1] IID876 + __ eandq(r14, r11, Address(r16, +0x63ba0ddf), true); // {NF}and r14, r11, qword ptr [r16+0x63ba0ddf] IID877 + __ eandq(r8, r8, Address(r22, r25, (Address::ScaleFactor)1, -0x43b6ab44), true); // {NF}and r8, r8, qword ptr [r22+r25*2-0x43b6ab44] IID878 + __ eorq(r19, rcx, Address(r27, rcx, (Address::ScaleFactor)2, -0x7f687fc6), false); // {EVEX}or r19, rcx, qword ptr [r27+rcx*4-0x7f687fc6] IID879 + __ eorq(r19, r19, Address(rbx, r26, (Address::ScaleFactor)1, -0x486db7ea), false); // or r19, qword ptr [rbx+r26*2-0x486db7ea] IID880 + __ eorq(r30, r10, Address(r14, r18, (Address::ScaleFactor)3, +0x14884884), true); // {NF}or r30, r10, qword ptr [r14+r18*8+0x14884884] IID881 + __ eorq(r27, r27, Address(r29, +0x20337180), true); // {NF}or r27, r27, qword ptr [r29+0x20337180] IID882 + __ eimulq(rcx, r21, Address(r21, rbx, (Address::ScaleFactor)0, -0x3303888e), false); // {EVEX}imul rcx, r21, qword ptr [r21+rbx*1-0x3303888e] IID883 + __ eimulq(rdx, rdx, Address(r28, r9, (Address::ScaleFactor)3, -0x7ad8f741), false); // imul rdx, qword ptr [r28+r9*8-0x7ad8f741] IID884 + __ eimulq(r8, r29, Address(r17, r12, (Address::ScaleFactor)0, +0x6e85396a), true); // {NF}imul r8, r29, qword ptr [r17+r12*1+0x6e85396a] IID885 + __ eimulq(r16, r16, Address(r19, r10, (Address::ScaleFactor)3, -0x49599300), true); // {NF}imul r16, r16, qword ptr [r19+r10*8-0x49599300] IID886 + __ esubq(r20, r17, Address(r13, r22, (Address::ScaleFactor)0, +0x1d219a4f), false); // {EVEX}sub r20, r17, qword ptr [r13+r22*1+0x1d219a4f] IID887 + __ esubq(r25, r25, Address(r21, r21, (Address::ScaleFactor)3, -0x6868a8c7), false); // sub r25, qword ptr [r21+r21*8-0x6868a8c7] IID888 + __ esubq(r20, r24, Address(rbx, r20, (Address::ScaleFactor)2, +0x32c59da6), true); // {NF}sub r20, r24, qword ptr [rbx+r20*4+0x32c59da6] IID889 + __ esubq(r8, r8, Address(r12, r17, (Address::ScaleFactor)0, -0x26be2dcf), true); // {NF}sub r8, r8, qword ptr [r12+r17*1-0x26be2dcf] IID890 + __ exorq(rdx, r19, Address(r9, +0x7d903b91), false); // {EVEX}xor rdx, r19, qword ptr [r9+0x7d903b91] IID891 + __ exorq(r28, r28, Address(r29, r27, (Address::ScaleFactor)2, +0x53091f6f), false); // xor r28, qword ptr [r29+r27*4+0x53091f6f] IID892 + __ exorq(r17, r16, Address(r27, +0x7c6e9207), true); // {NF}xor r17, r16, qword ptr [r27+0x7c6e9207] IID893 + __ exorq(r15, r15, Address(r13, r24, (Address::ScaleFactor)3, -0x75c87960), true); // {NF}xor r15, r15, qword ptr [r13+r24*8-0x75c87960] IID894 + __ eaddq(r16, rbx, r18, false); // {load}{EVEX}add r16, rbx, r18 IID895 + __ eaddq(r24, r24, r18, false); // {load}add r24, r18 IID896 + __ eaddq(r9, r15, r9, false); // {load}add r9, r15 IID897 + __ eaddq(r19, r26, r13, true); // {load}{NF}add r19, r26, r13 IID898 + __ eaddq(r28, r28, r22, true); // {load}{NF}add r28, r28, r22 IID899 + __ eaddq(r22, r11, r22, true); // {load}{NF}add r22, r11, r22 IID900 + __ eadcxq(rcx, r12, r13); // {load}{EVEX}adcx rcx, r12, r13 IID901 + __ eadcxq(r30, r30, r12); // {load}adcx r30, r12 IID902 + __ eadoxq(r28, r14, r18); // {load}{EVEX}adox r28, r14, r18 IID903 + __ eadoxq(r30, r30, r19); // {load}adox r30, r19 IID904 + __ eandq(r20, r14, r14, false); // {load}{EVEX}and r20, r14, r14 IID905 + __ eandq(r17, r17, r23, false); // {load}and r17, r23 IID906 + __ eandq(r17, r14, r17, false); // {load}and r17, r14 IID907 + __ eandq(r19, r20, r15, true); // {load}{NF}and r19, r20, r15 IID908 + __ eandq(rbx, rbx, r13, true); // {load}{NF}and rbx, rbx, r13 IID909 + __ eandq(r22, r30, r22, true); // {load}{NF}and r22, r30, r22 IID910 + __ eimulq(r17, r24, rcx, false); // {load}{EVEX}imul r17, r24, rcx IID911 + __ eimulq(r21, r21, r8, false); // {load}imul r21, r8 IID912 + __ eimulq(r29, r21, r29, false); // {load}imul r29, r21 IID913 + __ eimulq(r27, r13, r23, true); // {load}{NF}imul r27, r13, r23 IID914 + __ eimulq(r26, r26, r8, true); // {load}{NF}imul r26, r26, r8 IID915 + __ eimulq(r22, r13, r22, true); // {load}{NF}imul r22, r13, r22 IID916 + __ eorq(r11, rdx, r29, false); // {load}{EVEX}or r11, rdx, r29 IID917 + __ eorq(rdx, rdx, r31, false); // {load}or rdx, r31 IID918 + __ eorq(r10, r29, r10, false); // {load}or r10, r29 IID919 + __ eorq(r27, r28, rcx, true); // {load}{NF}or r27, r28, rcx IID920 + __ eorq(r25, r25, r9, true); // {load}{NF}or r25, r25, r9 IID921 + __ eorq(rcx, r8, rcx, true); // {load}{NF}or rcx, r8, rcx IID922 + __ esubq(rcx, r10, r16, false); // {load}{EVEX}sub rcx, r10, r16 IID923 + __ esubq(r17, r17, rcx, false); // {load}sub r17, rcx IID924 + __ esubq(r13, r21, r24, true); // {load}{NF}sub r13, r21, r24 IID925 + __ esubq(r31, r31, r28, true); // {load}{NF}sub r31, r31, r28 IID926 + __ exorq(r23, r28, r23, false); // {load}xor r23, r28 IID927 + __ exorq(r10, r10, r11, false); // {load}xor r10, r11 IID928 + __ exorq(r19, r18, r19, false); // {load}xor r19, r18 IID929 + __ exorq(r31, r9, rdx, true); // {load}{NF}xor r31, r9, rdx IID930 + __ exorq(r13, r13, r9, true); // {load}{NF}xor r13, r13, r9 IID931 + __ exorq(rcx, r10, rcx, true); // {load}{NF}xor rcx, r10, rcx IID932 + __ eshldq(r12, r24, r22, 8, false); // {EVEX}shld r12, r24, r22, 8 IID933 + __ eshldq(r25, r25, r25, 8, false); // shld r25, r25, 8 IID934 + __ eshldq(r21, r20, r15, 8, true); // {NF}shld r21, r20, r15, 8 IID935 + __ eshldq(r21, r21, r10, 8, true); // {NF}shld r21, r21, r10, 8 IID936 + __ eshrdq(r18, r18, r8, 2, false); // shrd r18, r8, 2 IID937 + __ eshrdq(r26, r26, r29, 8, false); // shrd r26, r29, 8 IID938 + __ eshrdq(r29, r26, r19, 2, true); // {NF}shrd r29, r26, r19, 2 IID939 + __ eshrdq(r12, r12, rcx, 4, true); // {NF}shrd r12, r12, rcx, 4 IID940 + __ ecmovq (Assembler::Condition::overflow, r21, r22, r23); // cmovo r21, r22, r23 IID941 + __ ecmovq (Assembler::Condition::overflow, r9, r9, r13); // cmovo r9, r13 IID942 + __ ecmovq (Assembler::Condition::noOverflow, rcx, r23, r24); // cmovno rcx, r23, r24 IID943 + __ ecmovq (Assembler::Condition::noOverflow, r28, r28, rdx); // cmovno r28, rdx IID944 + __ ecmovq (Assembler::Condition::below, r14, r31, r23); // cmovb r14, r31, r23 IID945 + __ ecmovq (Assembler::Condition::below, r30, r30, r23); // cmovb r30, r23 IID946 + __ ecmovq (Assembler::Condition::aboveEqual, r10, r29, r22); // cmovae r10, r29, r22 IID947 + __ ecmovq (Assembler::Condition::aboveEqual, rbx, rbx, r26); // cmovae rbx, r26 IID948 + __ ecmovq (Assembler::Condition::zero, r23, r21, r13); // cmovz r23, r21, r13 IID949 + __ ecmovq (Assembler::Condition::zero, r10, r10, r20); // cmovz r10, r20 IID950 + __ ecmovq (Assembler::Condition::notZero, rbx, r9, r29); // cmovnz rbx, r9, r29 IID951 + __ ecmovq (Assembler::Condition::notZero, r16, r16, r30); // cmovnz r16, r30 IID952 + __ ecmovq (Assembler::Condition::belowEqual, r13, rcx, r29); // cmovbe r13, rcx, r29 IID953 + __ ecmovq (Assembler::Condition::belowEqual, r31, r31, r13); // cmovbe r31, r13 IID954 + __ ecmovq (Assembler::Condition::above, r27, r9, r30); // cmova r27, r9, r30 IID955 + __ ecmovq (Assembler::Condition::above, r26, r26, r20); // cmova r26, r20 IID956 + __ ecmovq (Assembler::Condition::negative, r8, r12, r22); // cmovs r8, r12, r22 IID957 + __ ecmovq (Assembler::Condition::negative, r31, r31, r17); // cmovs r31, r17 IID958 + __ ecmovq (Assembler::Condition::positive, r29, rcx, r25); // cmovns r29, rcx, r25 IID959 + __ ecmovq (Assembler::Condition::positive, r22, r22, r14); // cmovns r22, r14 IID960 + __ ecmovq (Assembler::Condition::parity, rcx, r27, r9); // cmovp rcx, r27, r9 IID961 + __ ecmovq (Assembler::Condition::parity, r22, r22, r11); // cmovp r22, r11 IID962 + __ ecmovq (Assembler::Condition::noParity, r14, r19, r24); // cmovnp r14, r19, r24 IID963 + __ ecmovq (Assembler::Condition::noParity, r24, r24, r17); // cmovnp r24, r17 IID964 + __ ecmovq (Assembler::Condition::less, r17, r19, r30); // cmovl r17, r19, r30 IID965 + __ ecmovq (Assembler::Condition::less, r19, r19, r14); // cmovl r19, r14 IID966 + __ ecmovq (Assembler::Condition::greaterEqual, r25, r11, r29); // cmovge r25, r11, r29 IID967 + __ ecmovq (Assembler::Condition::greaterEqual, r12, r12, r26); // cmovge r12, r26 IID968 + __ ecmovq (Assembler::Condition::lessEqual, r11, rbx, r10); // cmovle r11, rbx, r10 IID969 + __ ecmovq (Assembler::Condition::lessEqual, rdx, rdx, r22); // cmovle rdx, r22 IID970 + __ ecmovq (Assembler::Condition::greater, r14, r15, r23); // cmovg r14, r15, r23 IID971 + __ ecmovq (Assembler::Condition::greater, r8, r8, r24); // cmovg r8, r24 IID972 + __ ecmovq (Assembler::Condition::overflow, rbx, r31, Address(r10, r8, (Address::ScaleFactor)3, -0x313f60e0)); // cmovo rbx, r31, qword ptr [r10+r8*8-0x313f60e0] IID973 + __ ecmovq (Assembler::Condition::overflow, r23, r23, Address(rcx, r24, (Address::ScaleFactor)2, +0x17f41d9c)); // cmovo r23, qword ptr [rcx+r24*4+0x17f41d9c] IID974 + __ ecmovq (Assembler::Condition::noOverflow, r31, r11, Address(r16, +0x2c018942)); // cmovno r31, r11, qword ptr [r16+0x2c018942] IID975 + __ ecmovq (Assembler::Condition::noOverflow, r11, r11, Address(r16, r20, (Address::ScaleFactor)3, +0x674b6a55)); // cmovno r11, qword ptr [r16+r20*8+0x674b6a55] IID976 + __ ecmovq (Assembler::Condition::below, r9, r13, Address(r9, rcx, (Address::ScaleFactor)0, +0x394a11df)); // cmovb r9, r13, qword ptr [r9+rcx*1+0x394a11df] IID977 + __ ecmovq (Assembler::Condition::below, r30, r30, Address(rdx, r22, (Address::ScaleFactor)1, -0x6c362b88)); // cmovb r30, qword ptr [rdx+r22*2-0x6c362b88] IID978 + __ ecmovq (Assembler::Condition::aboveEqual, r13, rcx, Address(r24, rcx, (Address::ScaleFactor)3, +0x46500b66)); // cmovae r13, rcx, qword ptr [r24+rcx*8+0x46500b66] IID979 + __ ecmovq (Assembler::Condition::aboveEqual, r24, r24, Address(r18, r25, (Address::ScaleFactor)1, +0x53283b7c)); // cmovae r24, qword ptr [r18+r25*2+0x53283b7c] IID980 + __ ecmovq (Assembler::Condition::zero, r23, r25, Address(r15, r9, (Address::ScaleFactor)0, -0x5f03031e)); // cmovz r23, r25, qword ptr [r15+r9*1-0x5f03031e] IID981 + __ ecmovq (Assembler::Condition::zero, r25, r25, Address(r28, r16, (Address::ScaleFactor)1, -0x53cef514)); // cmovz r25, qword ptr [r28+r16*2-0x53cef514] IID982 + __ ecmovq (Assembler::Condition::notZero, rbx, r25, Address(r24, r25, (Address::ScaleFactor)2, -0x66caac87)); // cmovnz rbx, r25, qword ptr [r24+r25*4-0x66caac87] IID983 + __ ecmovq (Assembler::Condition::notZero, r16, r16, Address(r27, r30, (Address::ScaleFactor)3, +0x797f455d)); // cmovnz r16, qword ptr [r27+r30*8+0x797f455d] IID984 + __ ecmovq (Assembler::Condition::belowEqual, r25, r30, Address(r18, r18, (Address::ScaleFactor)1, +0x1c9daacd)); // cmovbe r25, r30, qword ptr [r18+r18*2+0x1c9daacd] IID985 + __ ecmovq (Assembler::Condition::belowEqual, r22, r22, Address(rcx, r25, (Address::ScaleFactor)1, -0x3dcbfaa9)); // cmovbe r22, qword ptr [rcx+r25*2-0x3dcbfaa9] IID986 + __ ecmovq (Assembler::Condition::above, r24, r26, Address(r25, +0x747060b5)); // cmova r24, r26, qword ptr [r25+0x747060b5] IID987 + __ ecmovq (Assembler::Condition::above, r8, r8, Address(r24, r20, (Address::ScaleFactor)3, +0x47d285f6)); // cmova r8, qword ptr [r24+r20*8+0x47d285f6] IID988 + __ ecmovq (Assembler::Condition::negative, r12, r16, Address(r13, r10, (Address::ScaleFactor)2, +0x34e5b214)); // cmovs r12, r16, qword ptr [r13+r10*4+0x34e5b214] IID989 + __ ecmovq (Assembler::Condition::negative, rdx, rdx, Address(r15, r19, (Address::ScaleFactor)0, -0x405138b1)); // cmovs rdx, qword ptr [r15+r19*1-0x405138b1] IID990 + __ ecmovq (Assembler::Condition::positive, r18, r21, Address(rbx, r13, (Address::ScaleFactor)2, +0x51b19197)); // cmovns r18, r21, qword ptr [rbx+r13*4+0x51b19197] IID991 + __ ecmovq (Assembler::Condition::positive, r24, r24, Address(r11, r31, (Address::ScaleFactor)3, +0x3e01520a)); // cmovns r24, qword ptr [r11+r31*8+0x3e01520a] IID992 + __ ecmovq (Assembler::Condition::parity, r29, r26, Address(r10, r25, (Address::ScaleFactor)3, -0x5f7c3872)); // cmovp r29, r26, qword ptr [r10+r25*8-0x5f7c3872] IID993 + __ ecmovq (Assembler::Condition::parity, r11, r11, Address(r22, r10, (Address::ScaleFactor)3, -0x68731453)); // cmovp r11, qword ptr [r22+r10*8-0x68731453] IID994 + __ ecmovq (Assembler::Condition::noParity, r20, r15, Address(r9, r25, (Address::ScaleFactor)0, +0x4a37edaa)); // cmovnp r20, r15, qword ptr [r9+r25*1+0x4a37edaa] IID995 + __ ecmovq (Assembler::Condition::noParity, r31, r31, Address(r9, r20, (Address::ScaleFactor)0, +0x4f999f86)); // cmovnp r31, qword ptr [r9+r20*1+0x4f999f86] IID996 + __ ecmovq (Assembler::Condition::less, r18, r23, Address(r9, r27, (Address::ScaleFactor)0, -0x3410441d)); // cmovl r18, r23, qword ptr [r9+r27*1-0x3410441d] IID997 + __ ecmovq (Assembler::Condition::less, r16, r16, Address(r24, r10, (Address::ScaleFactor)3, +0x52ed66ee)); // cmovl r16, qword ptr [r24+r10*8+0x52ed66ee] IID998 + __ ecmovq (Assembler::Condition::greaterEqual, r11, r18, Address(rcx, +0x1de09163)); // cmovge r11, r18, qword ptr [rcx+0x1de09163] IID999 + __ ecmovq (Assembler::Condition::greaterEqual, r14, r14, Address(r24, r23, (Address::ScaleFactor)1, +0x5df3b4da)); // cmovge r14, qword ptr [r24+r23*2+0x5df3b4da] IID1000 + __ ecmovq (Assembler::Condition::lessEqual, r15, r14, Address(r30, r20, (Address::ScaleFactor)1, +0x5c9ab976)); // cmovle r15, r14, qword ptr [r30+r20*2+0x5c9ab976] IID1001 + __ ecmovq (Assembler::Condition::lessEqual, r26, r26, Address(r18, r27, (Address::ScaleFactor)2, -0xd8c329)); // cmovle r26, qword ptr [r18+r27*4-0xd8c329] IID1002 + __ ecmovq (Assembler::Condition::greater, r29, r9, Address(r30, r20, (Address::ScaleFactor)3, -0x37a9cf8d)); // cmovg r29, r9, qword ptr [r30+r20*8-0x37a9cf8d] IID1003 + __ ecmovq (Assembler::Condition::greater, r20, r20, Address(r8, rbx, (Address::ScaleFactor)1, +0x1bdc7def)); // cmovg r20, qword ptr [r8+rbx*2+0x1bdc7def] IID1004 #endif // _LP64 static const uint8_t insns[] = @@ -1243,665 +1327,749 @@ 0x62, 0xd4, 0x68, 0x18, 0x81, 0xb4, 0x82, 0xb9, 0xe2, 0xe1, 0xe9, 0x00, 0x00, 0x00, 0x01, // IID265 0x62, 0xdc, 0x68, 0x1c, 0x81, 0xb4, 0x7d, 0xf8, 0xe2, 0x34, 0x1b, 0x00, 0x00, 0x00, 0x01, // IID266 0x62, 0x0c, 0x60, 0x10, 0x01, 0xac, 0x3b, 0xd8, 0xe7, 0x3c, 0x1f, // IID267 - 0x62, 0x4c, 0x1c, 0x10, 0x01, 0xa4, 0xc8, 0x3e, 0x12, 0xac, 0x9f, // IID268 + 0xd5, 0x55, 0x03, 0xa4, 0xc8, 0x3e, 0x12, 0xac, 0x9f, // IID268 0x62, 0x2c, 0x70, 0x14, 0x01, 0xac, 0xc2, 0x88, 0xe0, 0x08, 0xe4, // IID269 0x62, 0x94, 0x70, 0x1c, 0x01, 0x8c, 0x67, 0x16, 0x82, 0x5b, 0x01, // IID270 - 0x62, 0x64, 0x0c, 0x10, 0x09, 0xa4, 0xd3, 0x4c, 0xbf, 0xca, 0xb9, // IID271 - 0x62, 0x8c, 0x6c, 0x10, 0x09, 0x94, 0xd4, 0x3b, 0xa7, 0x23, 0x35, // IID272 - 0x62, 0x84, 0x34, 0x1c, 0x09, 0xac, 0x7f, 0xaa, 0x22, 0xf4, 0xd5, // IID273 - 0x62, 0xec, 0x7c, 0x14, 0x09, 0x87, 0x01, 0x9b, 0xaf, 0xe9, // IID274 - 0x62, 0x8c, 0x1c, 0x10, 0x08, 0xa4, 0x1e, 0x3a, 0x1e, 0x28, 0x17, // IID275 - 0x62, 0xb4, 0x68, 0x18, 0x08, 0x94, 0xbb, 0xbb, 0xb5, 0x77, 0x24, // IID276 - 0x62, 0x44, 0x7c, 0x14, 0x08, 0x84, 0x4b, 0x51, 0x2e, 0x8a, 0xce, // IID277 - 0x62, 0xd4, 0x60, 0x1c, 0x08, 0x9c, 0xe3, 0x2d, 0x84, 0x29, 0xdd, // IID278 - 0x62, 0x9c, 0x28, 0x10, 0x29, 0x94, 0x73, 0xd2, 0x31, 0x64, 0xc2, // IID279 - 0x62, 0x2c, 0x00, 0x10, 0x29, 0xbc, 0x6e, 0x19, 0x85, 0x21, 0x14, // IID280 - 0x62, 0x54, 0x54, 0x14, 0x29, 0xa9, 0x86, 0xed, 0xaf, 0xef, // IID281 - 0x62, 0x04, 0x04, 0x14, 0x29, 0xbc, 0x01, 0x9f, 0x76, 0x1e, 0xf5, // IID282 - 0x62, 0x7c, 0x04, 0x18, 0x31, 0xa2, 0xe5, 0xbc, 0x2b, 0x5c, // IID283 - 0x62, 0x4c, 0x20, 0x10, 0x31, 0x9c, 0x39, 0xb3, 0x78, 0x60, 0x5c, // IID284 - 0x62, 0x54, 0x6c, 0x14, 0x31, 0xb4, 0xd0, 0x7f, 0xc7, 0x12, 0xf6, // IID285 - 0x62, 0x54, 0x34, 0x1c, 0x31, 0x8f, 0xad, 0xcd, 0x5a, 0x77, // IID286 - 0x62, 0xac, 0x50, 0x10, 0x30, 0xbc, 0x52, 0xd5, 0x1f, 0xe3, 0x2f, // IID287 - 0x62, 0x5c, 0x2c, 0x18, 0x30, 0x93, 0xde, 0x50, 0x31, 0x0a, // IID288 - 0x62, 0x2c, 0x68, 0x14, 0x30, 0x84, 0xf6, 0x97, 0xe8, 0xd4, 0x1a, // IID289 - 0x62, 0x7c, 0x38, 0x1c, 0x30, 0x84, 0x20, 0x82, 0xae, 0x6e, 0x62, // IID290 - 0x62, 0xd4, 0x54, 0x10, 0x81, 0xc7, 0x00, 0x00, 0x10, 0x00, // IID291 - 0x62, 0xfc, 0x7c, 0x18, 0x81, 0xc2, 0x00, 0x00, 0x10, 0x00, // IID292 - 0xd5, 0x10, 0x81, 0xc2, 0x00, 0x01, 0x00, 0x00, // IID293 - 0x62, 0xfc, 0x14, 0x1c, 0x83, 0xc3, 0x10, // IID294 - 0x62, 0xfc, 0x7c, 0x1c, 0x83, 0xc7, 0x10, // IID295 - 0x62, 0xdc, 0x34, 0x14, 0x81, 0xc1, 0x00, 0x00, 0x00, 0x01, // IID296 - 0x62, 0xfc, 0x14, 0x10, 0x81, 0xe2, 0x00, 0x00, 0x10, 0x00, // IID297 - 0x62, 0xd4, 0x7c, 0x18, 0x81, 0xe6, 0x00, 0x00, 0x10, 0x00, // IID298 - 0xd5, 0x10, 0x81, 0xe3, 0x00, 0x00, 0x01, 0x00, // IID299 - 0x62, 0xdc, 0x24, 0x14, 0x81, 0xe1, 0x00, 0x00, 0x10, 0x00, // IID300 - 0x62, 0xfc, 0x7c, 0x1c, 0x81, 0xe4, 0x00, 0x00, 0x10, 0x00, // IID301 - 0x62, 0xdc, 0x1c, 0x14, 0x83, 0xe4, 0x10, // IID302 - 0x62, 0x6c, 0x7c, 0x08, 0x69, 0xfe, 0x00, 0x10, 0x00, 0x00, // IID303 -#endif // _LP64 - 0x62, 0xf4, 0x7c, 0x08, 0x69, 0xc3, 0x00, 0x10, 0x00, 0x00, // IID304 -#ifdef _LP64 - 0x62, 0x4c, 0x7c, 0x08, 0x69, 0xc0, 0x00, 0x00, 0x10, 0x00, // IID305 - 0x62, 0xec, 0x7c, 0x0c, 0x69, 0xe8, 0x00, 0x00, 0x01, 0x00, // IID306 - 0x62, 0xdc, 0x7c, 0x0c, 0x69, 0xc0, 0x00, 0x00, 0x01, 0x00, // IID307 - 0x62, 0x54, 0x7c, 0x0c, 0x6b, 0xed, 0x10, // IID308 - 0x62, 0xd4, 0x14, 0x10, 0x81, 0xc8, 0x00, 0x00, 0x00, 0x01, // IID309 - 0x62, 0xd4, 0x7c, 0x18, 0x81, 0xcc, 0x00, 0x00, 0x00, 0x01, // IID310 - 0xd5, 0x11, 0x81, 0xce, 0x00, 0x10, 0x00, 0x00, // IID311 - 0x62, 0xf4, 0x3c, 0x14, 0x83, 0xca, 0x10, // IID312 - 0x62, 0xd4, 0x7c, 0x1c, 0x83, 0xc8, 0x10, // IID313 - 0x62, 0xd4, 0x14, 0x1c, 0x81, 0xcd, 0x00, 0x10, 0x00, 0x00, // IID314 - 0x62, 0xd4, 0x34, 0x10, 0xd1, 0xd5, // IID315 - 0x62, 0xfc, 0x7c, 0x18, 0xd1, 0xd2, // IID316 - 0x41, 0xc1, 0xd1, 0x10, // IID317 - 0x62, 0xdc, 0x2c, 0x10, 0xc1, 0xc1, 0x08, // IID318 + 0x62, 0x64, 0x0c, 0x10, 0x21, 0xa4, 0xd3, 0x4c, 0xbf, 0xca, 0xb9, // IID271 + 0xd5, 0x53, 0x23, 0x94, 0xd4, 0x3b, 0xa7, 0x23, 0x35, // IID272 + 0x62, 0x84, 0x34, 0x1c, 0x21, 0xac, 0x7f, 0xaa, 0x22, 0xf4, 0xd5, // IID273 + 0x62, 0xec, 0x7c, 0x14, 0x21, 0x87, 0x01, 0x9b, 0xaf, 0xe9, // IID274 + 0x62, 0x8c, 0x1c, 0x10, 0x09, 0xa4, 0x1e, 0x3a, 0x1e, 0x28, 0x17, // IID275 + 0xd5, 0x22, 0x0b, 0x94, 0xbb, 0xbb, 0xb5, 0x77, 0x24, // IID276 + 0x62, 0x44, 0x7c, 0x14, 0x09, 0x84, 0x4b, 0x51, 0x2e, 0x8a, 0xce, // IID277 + 0x62, 0xd4, 0x60, 0x1c, 0x09, 0x9c, 0xe3, 0x2d, 0x84, 0x29, 0xdd, // IID278 + 0x62, 0x9c, 0x28, 0x10, 0x08, 0x94, 0x73, 0xd2, 0x31, 0x64, 0xc2, // IID279 + 0xd5, 0x76, 0x0a, 0xbc, 0x6e, 0x19, 0x85, 0x21, 0x14, // IID280 + 0x62, 0x54, 0x54, 0x14, 0x08, 0xa9, 0x86, 0xed, 0xaf, 0xef, // IID281 + 0x62, 0x04, 0x04, 0x14, 0x08, 0xbc, 0x01, 0x9f, 0x76, 0x1e, 0xf5, // IID282 + 0x62, 0x7c, 0x04, 0x18, 0x29, 0xa2, 0xe5, 0xbc, 0x2b, 0x5c, // IID283 + 0x62, 0x4c, 0x20, 0x10, 0x29, 0x9c, 0x39, 0xb3, 0x78, 0x60, 0x5c, // IID284 + 0x62, 0x54, 0x6c, 0x14, 0x29, 0xb4, 0xd0, 0x7f, 0xc7, 0x12, 0xf6, // IID285 + 0x62, 0x54, 0x34, 0x1c, 0x29, 0x8f, 0xad, 0xcd, 0x5a, 0x77, // IID286 + 0x62, 0xac, 0x50, 0x10, 0x31, 0xbc, 0x52, 0xd5, 0x1f, 0xe3, 0x2f, // IID287 + 0xd5, 0x15, 0x33, 0x93, 0xde, 0x50, 0x31, 0x0a, // IID288 + 0x62, 0x2c, 0x68, 0x14, 0x31, 0x84, 0xf6, 0x97, 0xe8, 0xd4, 0x1a, // IID289 + 0x62, 0x7c, 0x38, 0x1c, 0x31, 0x84, 0x20, 0x82, 0xae, 0x6e, 0x62, // IID290 + 0x62, 0xac, 0x7c, 0x10, 0x30, 0x94, 0x3d, 0xf3, 0x49, 0xfc, 0xeb, // IID291 + 0xd5, 0x34, 0x32, 0xac, 0xbb, 0xe1, 0xf1, 0x7e, 0x23, // IID292 + 0x62, 0x3c, 0x14, 0x14, 0x30, 0xb4, 0xb2, 0x5b, 0x09, 0xc0, 0x5c, // IID293 + 0x62, 0x4c, 0x20, 0x14, 0x30, 0x9c, 0xe1, 0x58, 0xb9, 0xf7, 0x1c, // IID294 + 0x62, 0xdc, 0x7c, 0x10, 0x83, 0xc0, 0x10, // IID295 + 0x62, 0xdc, 0x7c, 0x18, 0x83, 0xc0, 0x10, // IID296 + 0xd5, 0x10, 0x81, 0xc5, 0x00, 0x00, 0x01, 0x00, // IID297 + 0x62, 0xd4, 0x3c, 0x14, 0x81, 0xc0, 0x00, 0x00, 0x10, 0x00, // IID298 + 0x62, 0xd4, 0x7c, 0x1c, 0x81, 0xc5, 0x00, 0x00, 0x10, 0x00, // IID299 + 0x62, 0xdc, 0x14, 0x14, 0x81, 0xc5, 0x00, 0x00, 0x00, 0x01, // IID300 + 0x41, 0x83, 0xe4, 0x10, // IID301 + 0x62, 0xdc, 0x7c, 0x18, 0x83, 0xe6, 0x10, // IID302 + 0xd5, 0x11, 0x83, 0xe0, 0x10, // IID303 + 0x62, 0xd4, 0x3c, 0x1c, 0x83, 0xe4, 0x01, // IID304 + 0x62, 0xd4, 0x7c, 0x1c, 0x83, 0xe5, 0x01, // IID305 + 0x62, 0xdc, 0x34, 0x14, 0x83, 0xe1, 0x10, // IID306 + 0x62, 0xec, 0x7c, 0x08, 0x69, 0xd7, 0x00, 0x00, 0x01, 0x00, // IID307 + 0x62, 0xd4, 0x7c, 0x08, 0x69, 0xc1, 0x00, 0x00, 0x01, 0x00, // IID308 + 0x62, 0x4c, 0x7c, 0x08, 0x69, 0xd2, 0x00, 0x00, 0x00, 0x10, // IID309 + 0x62, 0x6c, 0x7c, 0x0c, 0x6b, 0xcd, 0x01, // IID310 + 0x62, 0xdc, 0x7c, 0x0c, 0x6b, 0xc0, 0x01, // IID311 + 0x62, 0x4c, 0x7c, 0x0c, 0x69, 0xc0, 0x00, 0x00, 0x00, 0x01, // IID312 + 0x62, 0xdc, 0x0c, 0x10, 0x83, 0xca, 0x01, // IID313 + 0x62, 0xfc, 0x7c, 0x18, 0x83, 0xce, 0x01, // IID314 + 0xd5, 0x10, 0x81, 0xc9, 0x00, 0x00, 0x10, 0x00, // IID315 + 0x62, 0xd4, 0x3c, 0x14, 0x83, 0xc8, 0x01, // IID316 + 0x62, 0xdc, 0x7c, 0x1c, 0x83, 0xcb, 0x01, // IID317 #endif // _LP64 - 0x62, 0xf4, 0x7c, 0x18, 0xc1, 0xc2, 0x08, // IID319 + 0x62, 0xf4, 0x6c, 0x1c, 0x81, 0xca, 0x00, 0x00, 0x00, 0x10, // IID318 #ifdef _LP64 - 0xd5, 0x11, 0xc1, 0xc0, 0x10, // IID320 - 0x62, 0xf4, 0x3c, 0x14, 0xc1, 0xc1, 0x08, // IID321 - 0x62, 0xdc, 0x7c, 0x1c, 0xc1, 0xc6, 0x08, // IID322 - 0x62, 0xdc, 0x1c, 0x14, 0xc1, 0xc4, 0x10, // IID323 - 0x62, 0xdc, 0x74, 0x10, 0xc1, 0xcc, 0x04, // IID324 + 0xd5, 0x10, 0xc1, 0xd6, 0x08, // IID319 + 0x62, 0xfc, 0x7c, 0x18, 0xc1, 0xd7, 0x08, // IID320 + 0xd5, 0x10, 0xc1, 0xd3, 0x04, // IID321 + 0x62, 0xdc, 0x0c, 0x10, 0xc1, 0xc0, 0x02, // IID322 + 0x62, 0xdc, 0x7c, 0x18, 0xc1, 0xc5, 0x02, // IID323 + 0x41, 0xc1, 0xc0, 0x02, // IID324 + 0x62, 0xdc, 0x6c, 0x14, 0xc1, 0xc0, 0x10, // IID325 + 0x62, 0xd4, 0x7c, 0x1c, 0xc1, 0xc5, 0x10, // IID326 + 0x62, 0xdc, 0x3c, 0x14, 0xd1, 0xc0, // IID327 + 0x62, 0xfc, 0x1c, 0x10, 0xc1, 0xc9, 0x10, // IID328 + 0x62, 0xdc, 0x7c, 0x18, 0xc1, 0xc8, 0x10, // IID329 + 0xd5, 0x10, 0xc1, 0xc9, 0x04, // IID330 + 0x62, 0xf4, 0x3c, 0x14, 0xc1, 0xc9, 0x04, // IID331 + 0x62, 0xfc, 0x7c, 0x1c, 0xc1, 0xc8, 0x04, // IID332 + 0x62, 0xd4, 0x04, 0x1c, 0xc1, 0xcf, 0x02, // IID333 + 0x62, 0xdc, 0x0c, 0x18, 0xc1, 0xe3, 0x04, // IID334 + 0x62, 0xfc, 0x7c, 0x18, 0xc1, 0xe7, 0x04, // IID335 + 0xd5, 0x11, 0xc1, 0xe6, 0x04, // IID336 + 0x62, 0xf4, 0x24, 0x14, 0xc1, 0xe2, 0x02, // IID337 + 0x62, 0xfc, 0x7c, 0x1c, 0xc1, 0xe3, 0x02, // IID338 + 0x62, 0xfc, 0x5c, 0x14, 0xc1, 0xe4, 0x02, // IID339 + 0x62, 0xfc, 0x54, 0x10, 0xd1, 0xff, // IID340 + 0x62, 0xdc, 0x7c, 0x18, 0xd1, 0xfe, // IID341 + 0xd5, 0x11, 0xc1, 0xf9, 0x02, // IID342 + 0x62, 0xfc, 0x3c, 0x14, 0xc1, 0xfb, 0x04, // IID343 + 0x62, 0xd4, 0x7c, 0x1c, 0xc1, 0xfe, 0x04, // IID344 + 0x62, 0xdc, 0x2c, 0x14, 0xc1, 0xfa, 0x10, // IID345 + 0x62, 0xd4, 0x4c, 0x10, 0xc1, 0xe5, 0x08, // IID346 + 0x62, 0xdc, 0x7c, 0x18, 0xc1, 0xe0, 0x08, // IID347 + 0x41, 0xc1, 0xe6, 0x10, // IID348 + 0x62, 0xdc, 0x1c, 0x14, 0xc1, 0xe1, 0x08, // IID349 + 0x62, 0xd4, 0x7c, 0x1c, 0xc1, 0xe2, 0x08, // IID350 + 0x62, 0xfc, 0x5c, 0x14, 0xd1, 0xe4, // IID351 + 0x62, 0xf4, 0x1c, 0x18, 0xc1, 0xeb, 0x04, // IID352 + 0x62, 0xfc, 0x7c, 0x18, 0xc1, 0xef, 0x04, // IID353 + 0xd5, 0x11, 0xc1, 0xec, 0x10, // IID354 + 0x62, 0xdc, 0x3c, 0x14, 0xc1, 0xee, 0x04, // IID355 + 0x62, 0xdc, 0x7c, 0x1c, 0xc1, 0xef, 0x04, // IID356 + 0x62, 0xdc, 0x04, 0x14, 0xc1, 0xef, 0x02, // IID357 + 0x62, 0xd4, 0x5c, 0x10, 0x81, 0xea, 0x00, 0x01, 0x00, 0x00, // IID358 + 0x62, 0xd4, 0x7c, 0x18, 0x81, 0xed, 0x00, 0x01, 0x00, 0x00, // IID359 + 0xd5, 0x11, 0x81, 0xe9, 0x00, 0x01, 0x00, 0x00, // IID360 + 0x62, 0xd4, 0x44, 0x14, 0x81, 0xec, 0x00, 0x00, 0x00, 0x10, // IID361 + 0x62, 0xfc, 0x7c, 0x1c, 0x81, 0xe8, 0x00, 0x00, 0x00, 0x10, // IID362 + 0x62, 0xdc, 0x04, 0x14, 0x83, 0xef, 0x01, // IID363 + 0x62, 0xd4, 0x34, 0x18, 0x81, 0xf7, 0x00, 0x00, 0x00, 0x01, // IID364 + 0x62, 0xd4, 0x7c, 0x18, 0x81, 0xf5, 0x00, 0x00, 0x00, 0x01, // IID365 + 0xd5, 0x11, 0x83, 0xf4, 0x10, // IID366 + 0x62, 0xfc, 0x14, 0x14, 0x83, 0xf6, 0x10, // IID367 #endif // _LP64 - 0x62, 0xf4, 0x7c, 0x18, 0xc1, 0xca, 0x04, // IID325 + 0x62, 0xf4, 0x7c, 0x1c, 0x83, 0xf3, 0x10, // IID368 #ifdef _LP64 - 0x41, 0xc1, 0xc8, 0x10, // IID326 - 0x62, 0xf4, 0x64, 0x14, 0xc1, 0xca, 0x10, // IID327 - 0x62, 0xdc, 0x7c, 0x1c, 0xc1, 0xcf, 0x10, // IID328 - 0x62, 0xfc, 0x4c, 0x14, 0xc1, 0xce, 0x08, // IID329 - 0x62, 0xdc, 0x44, 0x10, 0xc1, 0xe1, 0x10, // IID330 - 0x62, 0xd4, 0x7c, 0x18, 0xc1, 0xe6, 0x10, // IID331 - 0xd5, 0x11, 0xc1, 0xe7, 0x08, // IID332 - 0x62, 0xdc, 0x0c, 0x14, 0xc1, 0xe0, 0x02, // IID333 - 0x62, 0xdc, 0x7c, 0x1c, 0xc1, 0xe5, 0x02, // IID334 - 0x62, 0xd4, 0x3c, 0x1c, 0xc1, 0xe0, 0x02, // IID335 - 0x62, 0xdc, 0x6c, 0x10, 0xc1, 0xf8, 0x10, // IID336 - 0x62, 0xd4, 0x7c, 0x18, 0xc1, 0xfd, 0x10, // IID337 - 0xd5, 0x11, 0xd1, 0xf8, // IID338 - 0x62, 0xfc, 0x1c, 0x14, 0xc1, 0xf9, 0x10, // IID339 - 0x62, 0xdc, 0x7c, 0x1c, 0xc1, 0xf8, 0x10, // IID340 - 0x62, 0xfc, 0x74, 0x14, 0xc1, 0xf9, 0x04, // IID341 - 0x62, 0xf4, 0x3c, 0x10, 0xc1, 0xe1, 0x04, // IID342 - 0x62, 0xfc, 0x7c, 0x18, 0xc1, 0xe0, 0x04, // IID343 - 0x41, 0xc1, 0xe7, 0x02, // IID344 - 0x62, 0xdc, 0x0c, 0x1c, 0xc1, 0xe3, 0x04, // IID345 - 0x62, 0xfc, 0x7c, 0x1c, 0xc1, 0xe7, 0x04, // IID346 - 0x62, 0xdc, 0x0c, 0x14, 0xc1, 0xe6, 0x04, // IID347 - 0x62, 0xf4, 0x24, 0x10, 0xc1, 0xea, 0x02, // IID348 - 0x62, 0xfc, 0x7c, 0x18, 0xc1, 0xeb, 0x02, // IID349 - 0xd5, 0x10, 0xc1, 0xec, 0x02, // IID350 - 0x62, 0xfc, 0x54, 0x14, 0xd1, 0xef, // IID351 - 0x62, 0xdc, 0x7c, 0x1c, 0xd1, 0xee, // IID352 - 0x62, 0xdc, 0x34, 0x14, 0xc1, 0xe9, 0x02, // IID353 - 0x62, 0xfc, 0x3c, 0x10, 0x81, 0xeb, 0x00, 0x00, 0x10, 0x00, // IID354 - 0x62, 0xd4, 0x7c, 0x18, 0x81, 0xee, 0x00, 0x00, 0x10, 0x00, // IID355 - 0xd5, 0x10, 0x81, 0xee, 0x00, 0x00, 0x00, 0x10, // IID356 - 0x62, 0xdc, 0x3c, 0x14, 0x81, 0xe8, 0x00, 0x00, 0x01, 0x00, // IID357 - 0x62, 0xd4, 0x7c, 0x1c, 0x81, 0xee, 0x00, 0x00, 0x01, 0x00, // IID358 - 0x62, 0xdc, 0x1c, 0x14, 0x81, 0xec, 0x00, 0x00, 0x00, 0x10, // IID359 - 0x62, 0xfc, 0x64, 0x18, 0x81, 0xf4, 0x00, 0x01, 0x00, 0x00, // IID360 - 0x62, 0xd4, 0x7c, 0x18, 0x81, 0xf7, 0x00, 0x01, 0x00, 0x00, // IID361 + 0x62, 0xd4, 0x3c, 0x1c, 0x83, 0xf0, 0x10, // IID369 + 0x62, 0xd4, 0x7c, 0x10, 0x81, 0xed, 0x00, 0x00, 0x40, 0x00, // IID370 + 0x62, 0xd4, 0x7c, 0x18, 0x81, 0xec, 0x00, 0x00, 0x40, 0x00, // IID371 + 0xd5, 0x10, 0x81, 0xe9, 0x00, 0x00, 0x00, 0x04, // IID372 + 0x62, 0xdc, 0x4c, 0x14, 0x81, 0xea, 0x00, 0x00, 0x00, 0x40, // IID373 + 0x62, 0xd4, 0x7c, 0x1c, 0x81, 0xea, 0x00, 0x00, 0x00, 0x40, // IID374 + 0x62, 0xd4, 0x24, 0x1c, 0x81, 0xeb, 0x00, 0x00, 0x00, 0x40, // IID375 + 0x62, 0x1c, 0x64, 0x10, 0x03, 0xa4, 0x06, 0x73, 0x0a, 0x1a, 0x6a, // IID376 + 0xd5, 0x74, 0x03, 0xb4, 0x9a, 0xcf, 0x90, 0xf9, 0x25, // IID377 + 0x62, 0x6c, 0x70, 0x1c, 0x03, 0x8c, 0x03, 0xbc, 0x5d, 0x2d, 0x48, // IID378 + 0x62, 0x54, 0x34, 0x1c, 0x03, 0x8b, 0x01, 0xee, 0xd5, 0x43, // IID379 + 0x62, 0xac, 0x74, 0x18, 0x23, 0xbc, 0xbd, 0xbc, 0xc2, 0x25, 0x28, // IID380 + 0xd5, 0x47, 0x23, 0x9c, 0xfd, 0x6b, 0x47, 0x97, 0xed, // IID381 + 0x62, 0xac, 0x30, 0x1c, 0x23, 0xbc, 0x36, 0x45, 0x53, 0xea, 0xf8, // IID382 + 0x62, 0xdc, 0x60, 0x1c, 0x23, 0x9c, 0x84, 0xee, 0x23, 0x02, 0x0b, // IID383 + 0x62, 0x04, 0x00, 0x18, 0xaf, 0xac, 0x67, 0x97, 0x85, 0xd6, 0xe0, // IID384 + 0xd5, 0xd0, 0xaf, 0x8c, 0x5f, 0x45, 0x75, 0xdc, 0x0a, // IID385 + 0x62, 0x74, 0x20, 0x14, 0xaf, 0x8c, 0xb2, 0x9f, 0xf0, 0x26, 0xbc, // IID386 + 0x62, 0xdc, 0x60, 0x1c, 0xaf, 0x9c, 0xf4, 0xd9, 0x65, 0x62, 0xae, // IID387 + 0x62, 0xd4, 0x74, 0x10, 0x0b, 0x8e, 0x23, 0x22, 0x64, 0x10, // IID388 + 0xd5, 0x55, 0x0b, 0x97, 0x46, 0x7c, 0x65, 0x85, // IID389 + 0x62, 0x84, 0x04, 0x1c, 0x0b, 0xb4, 0xa4, 0x97, 0x69, 0x3b, 0x74, // IID390 + 0x62, 0x74, 0x38, 0x1c, 0x0b, 0x84, 0xf2, 0x24, 0xeb, 0x7b, 0xa7, // IID391 + 0x62, 0x0c, 0x74, 0x18, 0x2b, 0xa4, 0xae, 0xe5, 0x10, 0x93, 0x0e, // IID392 + 0xd5, 0x13, 0x2b, 0x8c, 0x56, 0x2f, 0x91, 0xf8, 0xe4, // IID393 + 0x62, 0xcc, 0x34, 0x1c, 0x2b, 0xae, 0xd3, 0xff, 0x79, 0x2f, // IID394 + 0x62, 0xa4, 0x7c, 0x14, 0x2b, 0x84, 0xb2, 0xc1, 0x71, 0x5d, 0x67, // IID395 + 0x62, 0x24, 0x20, 0x10, 0x33, 0xa4, 0x93, 0x7f, 0xf4, 0x3d, 0x87, // IID396 + 0xd5, 0x35, 0x33, 0xb4, 0x5f, 0x34, 0xae, 0x0d, 0xb0, // IID397 + 0x62, 0xc4, 0x58, 0x14, 0x33, 0x94, 0x85, 0x1e, 0x39, 0x10, 0xe6, // IID398 + 0x62, 0xc4, 0x60, 0x14, 0x33, 0x9c, 0x7d, 0x56, 0x27, 0xe4, 0xd2, // IID399 + 0x62, 0xa4, 0x10, 0x10, 0x32, 0x8c, 0xaa, 0x84, 0x3e, 0x57, 0x66, // IID400 + 0xd5, 0x73, 0x32, 0xb4, 0xc8, 0x3f, 0xa9, 0x94, 0x3a, // IID401 + 0x62, 0x44, 0x10, 0x1c, 0x32, 0xac, 0x7f, 0x32, 0x35, 0xd4, 0x76, // IID402 + 0x62, 0x14, 0x04, 0x1c, 0x32, 0xbc, 0x0d, 0xe6, 0x92, 0xb1, 0xb8, // IID403 + 0x62, 0xec, 0x75, 0x10, 0x33, 0x84, 0x17, 0x91, 0xa2, 0x62, 0x05, // IID404 + 0x66, 0xd5, 0x76, 0x33, 0xac, 0xe2, 0x0e, 0x98, 0xe6, 0xab, // IID405 + 0x62, 0x54, 0x25, 0x14, 0x33, 0x9a, 0x5a, 0x1c, 0x91, 0x0a, // IID406 + 0x62, 0x4c, 0x01, 0x14, 0x33, 0xbc, 0x9e, 0x26, 0x5c, 0x09, 0xff, // IID407 + 0x62, 0x7c, 0x1c, 0x18, 0x03, 0xef, // IID408 + 0xd5, 0x54, 0x03, 0xe4, // IID409 + 0xd5, 0x51, 0x03, 0xe0, // IID410 + 0x62, 0x54, 0x24, 0x1c, 0x03, 0xd7, // IID411 + 0x62, 0xec, 0x64, 0x14, 0x03, 0xdc, // IID412 + 0x62, 0x7c, 0x44, 0x14, 0x03, 0xff, // IID413 + 0x62, 0xcc, 0x2c, 0x10, 0x23, 0xd8, // IID414 + 0xd5, 0x51, 0x23, 0xfc, // IID415 + 0x45, 0x23, 0xdd, // IID416 + 0x62, 0xdc, 0x14, 0x1c, 0x23, 0xd7, // IID417 + 0x62, 0xec, 0x44, 0x14, 0x23, 0xff, // IID418 + 0x62, 0x44, 0x34, 0x1c, 0x23, 0xd9, // IID419 + 0x62, 0xcc, 0x54, 0x10, 0xaf, 0xe0, // IID420 + 0xd5, 0xd1, 0xaf, 0xed, // IID421 + 0x41, 0x0f, 0xaf, 0xdb, // IID422 + 0x62, 0xf4, 0x54, 0x14, 0xaf, 0xd9, // IID423 + 0x62, 0x6c, 0x04, 0x14, 0xaf, 0xfd, // IID424 + 0x62, 0x44, 0x04, 0x1c, 0xaf, 0xcf, // IID425 + 0x62, 0xcc, 0x0d, 0x10, 0x0b, 0xf9, // IID426 + 0x66, 0xd5, 0x40, 0x0b, 0xd1, // IID427 + 0x66, 0x44, 0x0b, 0xd1, // IID428 + 0x62, 0xcc, 0x05, 0x14, 0x0b, 0xea, // IID429 + 0x62, 0xec, 0x55, 0x14, 0x0b, 0xeb, // IID430 #endif // _LP64 - 0x81, 0xf3, 0x00, 0x10, 0x00, 0x00, // IID362 + 0x62, 0xf4, 0x6d, 0x1c, 0x0b, 0xda, // IID431 #ifdef _LP64 - 0x62, 0xdc, 0x3c, 0x14, 0x81, 0xf6, 0x00, 0x00, 0x01, 0x00, // IID363 - 0x62, 0xdc, 0x7c, 0x1c, 0x81, 0xf7, 0x00, 0x00, 0x01, 0x00, // IID364 - 0x62, 0xdc, 0x04, 0x14, 0x81, 0xf7, 0x00, 0x10, 0x00, 0x00, // IID365 - 0x62, 0xd4, 0x5c, 0x10, 0x81, 0xea, 0x00, 0x00, 0x10, 0x00, // IID366 - 0x62, 0xd4, 0x7c, 0x18, 0x81, 0xed, 0x00, 0x00, 0x10, 0x00, // IID367 - 0xd5, 0x11, 0x81, 0xe9, 0x00, 0x00, 0x10, 0x00, // IID368 - 0x62, 0xd4, 0x44, 0x14, 0x81, 0xec, 0x00, 0x00, 0x00, 0x40, // IID369 - 0x62, 0xfc, 0x7c, 0x1c, 0x81, 0xe8, 0x00, 0x00, 0x00, 0x40, // IID370 - 0x62, 0xdc, 0x04, 0x14, 0x81, 0xef, 0x00, 0x00, 0x01, 0x00, // IID371 - 0x62, 0x54, 0x74, 0x10, 0x03, 0xa9, 0x98, 0x2f, 0xef, 0x7f, // IID372 - 0x62, 0x7c, 0x14, 0x14, 0x03, 0x86, 0x54, 0xf5, 0x08, 0xb2, // IID373 - 0x62, 0x84, 0x14, 0x18, 0x23, 0x8c, 0xfc, 0x02, 0xa9, 0xa8, 0x50, // IID374 - 0x62, 0x0c, 0x4c, 0x14, 0x23, 0x8c, 0x92, 0x54, 0x27, 0xea, 0x70, // IID375 - 0x62, 0x1c, 0x64, 0x10, 0xaf, 0xa4, 0x06, 0x73, 0x0a, 0x1a, 0x6a, // IID376 - 0x62, 0xec, 0x08, 0x14, 0xaf, 0x94, 0x9a, 0x39, 0xd7, 0x32, 0x80, // IID377 - 0x62, 0x0c, 0x7c, 0x10, 0x0b, 0xbc, 0xd9, 0xbc, 0x5d, 0x2d, 0x48, // IID378 - 0x62, 0x44, 0x34, 0x1c, 0x0b, 0x9b, 0x01, 0xee, 0xd5, 0x43, // IID379 - 0x62, 0xac, 0x74, 0x18, 0x2b, 0xbc, 0xbd, 0xbc, 0xc2, 0x25, 0x28, // IID380 - 0x62, 0x84, 0x24, 0x14, 0x2b, 0xb4, 0x7d, 0xa7, 0x0d, 0x1f, 0x77, // IID381 - 0x62, 0x44, 0x30, 0x18, 0x33, 0xb4, 0xf1, 0x72, 0x37, 0x29, 0xb5, // IID382 - 0x62, 0xa4, 0x20, 0x1c, 0x33, 0x84, 0xa3, 0xee, 0x23, 0x02, 0x0b, // IID383 - 0x62, 0x04, 0x00, 0x18, 0x32, 0xac, 0x67, 0x97, 0x85, 0xd6, 0xe0, // IID384 - 0x62, 0x6c, 0x74, 0x14, 0x32, 0xb4, 0x5f, 0x45, 0x75, 0xdc, 0x0a, // IID385 - 0x62, 0x74, 0x21, 0x10, 0x33, 0x8c, 0xb2, 0x9f, 0xf0, 0x26, 0xbc, // IID386 - 0x62, 0xcc, 0x61, 0x1c, 0x33, 0xb4, 0x34, 0x4f, 0x5f, 0xcf, 0x82, // IID387 - 0x62, 0x64, 0x0c, 0x18, 0x03, 0xc1, // IID388 - 0xd5, 0x14, 0x03, 0xc1, // IID389 - 0x62, 0x44, 0x2c, 0x14, 0x03, 0xc4, // IID390 - 0x62, 0x6c, 0x3c, 0x14, 0x03, 0xc7, // IID391 - 0x62, 0x4c, 0x14, 0x18, 0x23, 0xd7, // IID392 - 0x45, 0x23, 0xd8, // IID393 - 0x62, 0xc4, 0x74, 0x1c, 0x23, 0xdf, // IID394 - 0x62, 0x54, 0x1c, 0x1c, 0x23, 0xe4, // IID395 - 0x62, 0xec, 0x4c, 0x10, 0xaf, 0xe3, // IID396 - 0x44, 0x0f, 0xaf, 0xc2, // IID397 - 0x62, 0x6c, 0x4c, 0x14, 0xaf, 0xdf, // IID398 - 0x62, 0x7c, 0x34, 0x1c, 0xaf, 0xca, // IID399 - 0x62, 0x44, 0x75, 0x18, 0x0b, 0xf5, // IID400 - 0x66, 0xd5, 0x54, 0x0b, 0xe3, // IID401 - 0x62, 0x4c, 0x1d, 0x1c, 0x0b, 0xf3, // IID402 - 0x62, 0x7c, 0x3d, 0x1c, 0x0b, 0xc6, // IID403 - 0x62, 0xdc, 0x7c, 0x10, 0x0b, 0xce, // IID404 - 0xd5, 0x15, 0x0b, 0xd1, // IID405 - 0x62, 0xec, 0x04, 0x1c, 0x0b, 0xc9, // IID406 - 0x62, 0x5c, 0x34, 0x1c, 0x0b, 0xce, // IID407 - 0x62, 0x7c, 0x5c, 0x10, 0xa5, 0xc5, // IID408 - 0xd5, 0x95, 0xa5, 0xf2, // IID409 - 0x62, 0x74, 0x7c, 0x14, 0xa5, 0xf2, // IID410 - 0x62, 0x7c, 0x64, 0x14, 0xa5, 0xc3, // IID411 - 0x62, 0x64, 0x24, 0x10, 0xad, 0xd3, // IID412 - 0xd5, 0xd1, 0xad, 0xdc, // IID413 - 0x62, 0x54, 0x74, 0x1c, 0xad, 0xf3, // IID414 - 0x62, 0xcc, 0x04, 0x14, 0xad, 0xdf, // IID415 - 0x62, 0x5c, 0x2c, 0x10, 0x2b, 0xe9, // IID416 - 0xd5, 0x45, 0x2b, 0xc3, // IID417 - 0x62, 0xc4, 0x6c, 0x14, 0x2b, 0xe5, // IID418 - 0x62, 0xec, 0x7c, 0x14, 0x2b, 0xc2, // IID419 - 0x62, 0xc4, 0x64, 0x10, 0x33, 0xc8, // IID420 - 0xd5, 0x41, 0x33, 0xdd, // IID421 - 0x62, 0x54, 0x44, 0x14, 0x33, 0xef, // IID422 - 0x62, 0x5c, 0x24, 0x1c, 0x33, 0xdd, // IID423 - 0x62, 0xec, 0x14, 0x10, 0x24, 0xc9, 0x01, // IID424 - 0xd5, 0xd4, 0xa4, 0xc6, 0x04, // IID425 - 0x62, 0x5c, 0x3c, 0x1c, 0x24, 0xdc, 0x10, // IID426 - 0x62, 0xc4, 0x04, 0x1c, 0x24, 0xff, 0x04, // IID427 - 0x62, 0xec, 0x14, 0x10, 0x2c, 0xc6, 0x04, // IID428 - 0x45, 0x0f, 0xac, 0xcd, 0x04, // IID429 - 0x62, 0x7c, 0x04, 0x1c, 0x2c, 0xe5, 0x02, // IID430 - 0x62, 0xec, 0x74, 0x14, 0x2c, 0xf9, 0x02, // IID431 - 0x62, 0xcc, 0x6c, 0x18, 0x40, 0xc5, // IID432 - 0xd5, 0x94, 0x40, 0xd5, // IID433 - 0x62, 0x6c, 0x74, 0x10, 0x41, 0xea, // IID434 - 0xd5, 0xd5, 0x41, 0xe0, // IID435 - 0x62, 0xcc, 0x2c, 0x18, 0x42, 0xe3, // IID436 - 0x45, 0x0f, 0x42, 0xd6, // IID437 - 0x62, 0x64, 0x24, 0x18, 0x43, 0xd9, // IID438 - 0xd5, 0xc1, 0x43, 0xf7, // IID439 - 0x62, 0x6c, 0x04, 0x10, 0x44, 0xf3, // IID440 - 0xd5, 0xd1, 0x44, 0xda, // IID441 - 0x62, 0x5c, 0x54, 0x10, 0x45, 0xf2, // IID442 - 0xd5, 0xc1, 0x45, 0xe7, // IID443 - 0x62, 0x7c, 0x1c, 0x18, 0x46, 0xef, // IID444 - 0xd5, 0xd4, 0x46, 0xe4, // IID445 - 0x62, 0x44, 0x5c, 0x10, 0x47, 0xc3, // IID446 - 0x45, 0x0f, 0x47, 0xd7, // IID447 - 0x62, 0xec, 0x64, 0x10, 0x48, 0xe7, // IID448 - 0xd5, 0x95, 0x48, 0xfa, // IID449 - 0x62, 0x6c, 0x64, 0x10, 0x49, 0xc7, // IID450 - 0xd5, 0xc5, 0x49, 0xe3, // IID451 - 0x44, 0x0f, 0x4a, 0xea, // IID452 - 0xd5, 0xd4, 0x4a, 0xff, // IID453 - 0x62, 0x5c, 0x44, 0x10, 0x4b, 0xcb, // IID454 - 0xd5, 0xd0, 0x4b, 0xec, // IID455 - 0x62, 0xcc, 0x3c, 0x10, 0x4c, 0xed, // IID456 - 0x41, 0x0f, 0x4c, 0xdb, // IID457 - 0x62, 0xf4, 0x54, 0x10, 0x4d, 0xd9, // IID458 - 0xd5, 0xd4, 0x4d, 0xfd, // IID459 - 0x62, 0x4c, 0x04, 0x18, 0x4e, 0xce, // IID460 - 0xd5, 0xd1, 0x4e, 0xf9, // IID461 - 0x62, 0xd4, 0x6c, 0x10, 0x4f, 0xca, // IID462 - 0xd5, 0x91, 0x4f, 0xcf, // IID463 - 0x62, 0xcc, 0x54, 0x10, 0x40, 0x9a, 0x8d, 0xf7, 0xd6, 0x91, // IID464 - 0x62, 0xec, 0x3c, 0x10, 0x41, 0x9c, 0x0e, 0x9a, 0x5f, 0xf8, 0x11, // IID465 - 0x62, 0x6c, 0x74, 0x10, 0x42, 0x84, 0x24, 0x5e, 0x77, 0x4d, 0x53, // IID466 - 0x62, 0xec, 0x5c, 0x10, 0x43, 0x94, 0x24, 0x33, 0xb1, 0x36, 0xb8, // IID467 - 0x62, 0x7c, 0x34, 0x18, 0x44, 0xaf, 0x9d, 0x3a, 0x7c, 0xb4, // IID468 - 0x62, 0x0c, 0x24, 0x18, 0x45, 0x8c, 0x70, 0x51, 0xf8, 0x9a, 0xbb, // IID469 - 0x62, 0x0c, 0x0c, 0x18, 0x46, 0x84, 0xae, 0x1d, 0x66, 0xd0, 0x00, // IID470 - 0x62, 0x04, 0x10, 0x18, 0x47, 0x8c, 0xde, 0x03, 0x14, 0x7e, 0x04, // IID471 - 0x62, 0xe4, 0x3c, 0x10, 0x48, 0x9c, 0xd1, 0xe8, 0xac, 0xb5, 0x9b, // IID472 - 0x62, 0x6c, 0x28, 0x10, 0x49, 0x84, 0x36, 0x46, 0x24, 0x35, 0x70, // IID473 - 0x62, 0x04, 0x60, 0x10, 0x4a, 0x94, 0xb0, 0x5c, 0x2f, 0xa1, 0x78, // IID474 - 0x62, 0x5c, 0x10, 0x10, 0x4b, 0x9c, 0x21, 0x3a, 0x30, 0xa8, 0x27, // IID475 - 0x62, 0x4c, 0x48, 0x10, 0x4c, 0x84, 0x43, 0x10, 0x1a, 0x54, 0x02, // IID476 - 0x62, 0x54, 0x00, 0x10, 0x4d, 0xbc, 0xc0, 0x51, 0x32, 0x8e, 0x55, // IID477 - 0x62, 0x84, 0x24, 0x10, 0x4e, 0x94, 0x10, 0x49, 0x78, 0xe6, 0xb8, // IID478 - 0x62, 0xec, 0x68, 0x10, 0x4f, 0x84, 0x9a, 0xe2, 0x17, 0xf5, 0xed, // IID479 - 0xd5, 0x19, 0x13, 0xdf, // IID480 - 0xd5, 0x5d, 0x3b, 0xf7, // IID481 - 0xd5, 0xdd, 0xaf, 0xec, // IID482 - 0xf3, 0xd5, 0xcd, 0xb8, 0xca, // IID483 - 0xd5, 0x5c, 0x1b, 0xc4, // IID484 - 0xd5, 0x48, 0x2b, 0xc2, // IID485 - 0xf3, 0xd5, 0xdd, 0xbc, 0xd4, // IID486 - 0xf3, 0xd5, 0xcd, 0xbd, 0xe1, // IID487 - 0xd5, 0x59, 0x03, 0xe0, // IID488 - 0xd5, 0x5d, 0x23, 0xc5, // IID489 - 0xd5, 0x59, 0x0b, 0xfb, // IID490 - 0x4d, 0x33, 0xfc, // IID491 - 0xd5, 0x58, 0x8b, 0xd3, // IID492 - 0xd5, 0xcc, 0xbc, 0xf9, // IID493 - 0x4d, 0x0f, 0xbd, 0xcd, // IID494 - 0xd5, 0x98, 0xa3, 0xcc, // IID495 - 0xd5, 0x1c, 0x87, 0xc5, // IID496 - 0xd5, 0x4d, 0x85, 0xc6, // IID497 - 0xd5, 0x6c, 0x01, 0xac, 0xb9, 0x4d, 0x6c, 0xf0, 0x4f, // IID498 - 0xd5, 0x5f, 0x21, 0x94, 0x50, 0x77, 0x5e, 0x26, 0x8a, // IID499 - 0xd5, 0x48, 0x39, 0x8c, 0x1b, 0x9c, 0xd5, 0x33, 0x40, // IID500 - 0xd5, 0x5a, 0x09, 0x94, 0xe6, 0x83, 0xcb, 0x6c, 0xc7, // IID501 - 0xd5, 0x3c, 0x31, 0xa4, 0xfc, 0x60, 0x15, 0x31, 0x4b, // IID502 - 0xd5, 0x6f, 0x29, 0xac, 0xa2, 0x57, 0x26, 0x3a, 0x5c, // IID503 - 0xd5, 0x6b, 0x89, 0xb4, 0xcd, 0x3f, 0x6f, 0x3d, 0x1a, // IID504 - 0xd5, 0xfe, 0xc1, 0x8c, 0xc1, 0x28, 0x24, 0x52, 0xca, // IID505 - 0xd5, 0x19, 0x81, 0xa1, 0xc3, 0x84, 0x21, 0x63, 0x00, 0x00, 0x00, 0x01, // IID506 - 0x4b, 0x81, 0x84, 0x2d, 0x3a, 0x15, 0x8d, 0xc6, 0x00, 0x00, 0x00, 0x01, // IID507 - 0x49, 0x81, 0xb9, 0xfa, 0x37, 0x4b, 0xec, 0x00, 0x10, 0x00, 0x00, // IID508 - 0xd5, 0x19, 0xd1, 0xbf, 0x51, 0xf5, 0xa7, 0x4f, // IID509 - 0xd5, 0x3a, 0xd1, 0xa4, 0xbd, 0x32, 0x82, 0xaa, 0x31, // IID510 - 0xd5, 0x3b, 0x81, 0x9c, 0xb8, 0x49, 0xc7, 0x9a, 0xb9, 0x00, 0x00, 0x00, 0x10, // IID511 - 0xd5, 0x39, 0xc1, 0xac, 0x34, 0x4f, 0x7a, 0x01, 0xc1, 0x02, // IID512 - 0xd5, 0x18, 0x81, 0xa8, 0x15, 0x5c, 0x76, 0xec, 0x00, 0x00, 0x10, 0x00, // IID513 - 0xd5, 0x1b, 0x83, 0xb4, 0x05, 0x15, 0x26, 0x02, 0x1d, 0x10, // IID514 - 0xd5, 0x2b, 0x83, 0x8c, 0x64, 0x1e, 0x67, 0x37, 0xcb, 0x01, // IID515 - 0xd5, 0x2a, 0xc7, 0x84, 0x81, 0xf8, 0x14, 0xbb, 0xe9, 0x00, 0x01, 0x00, 0x00, // IID516 - 0xd5, 0x19, 0xf7, 0x85, 0xf5, 0x76, 0xdc, 0x82, 0x00, 0x00, 0xff, 0xff, // IID517 - 0xd5, 0x68, 0x03, 0xbc, 0x99, 0x54, 0xc6, 0xea, 0x70, // IID518 - 0xd5, 0x1b, 0x23, 0x94, 0x38, 0x57, 0x25, 0xb2, 0xdf, // IID519 - 0xd5, 0x1a, 0x3b, 0x94, 0xdf, 0xbd, 0x30, 0xc9, 0x32, // IID520 - 0xf3, 0xd5, 0xcc, 0xbd, 0xa2, 0x71, 0x3d, 0xcc, 0xab, // IID521 - 0xd5, 0x5a, 0x0b, 0xb4, 0x73, 0xc8, 0x82, 0x39, 0xd3, // IID522 - 0x4d, 0x13, 0x92, 0x9f, 0xc5, 0xd7, 0x03, // IID523 - 0x4f, 0x0f, 0xaf, 0x94, 0xc0, 0xd3, 0x79, 0x9e, 0xf1, // IID524 - 0xf3, 0xd5, 0xd9, 0xb8, 0xbd, 0x93, 0x26, 0x81, 0x88, // IID525 - 0xd5, 0x28, 0x1b, 0x8c, 0x5b, 0xcb, 0x01, 0xc6, 0x53, // IID526 - 0xd5, 0x1c, 0x2b, 0xb4, 0x19, 0x8d, 0x0f, 0x74, 0x89, // IID527 - 0xf3, 0xd5, 0xed, 0xbc, 0xac, 0x5a, 0x3c, 0x8d, 0xc9, 0x30, // IID528 - 0xd5, 0x3e, 0x33, 0x94, 0x18, 0xfe, 0x29, 0xf7, 0xc2, // IID529 - 0xd5, 0x7b, 0x8b, 0x94, 0xe4, 0x6f, 0x53, 0x04, 0x9d, // IID530 - 0x48, 0x8d, 0x99, 0xa5, 0x02, 0x06, 0x45, // IID531 - 0xf2, 0xd5, 0xbf, 0x2c, 0xa4, 0x3e, 0xd0, 0x59, 0x67, 0x98, // IID532 - 0xd5, 0x5f, 0x87, 0xbc, 0x50, 0x13, 0xed, 0x98, 0x8f, // IID533 - 0xd5, 0x2d, 0x85, 0xb4, 0xe5, 0xf2, 0x81, 0x10, 0x17, // IID534 - 0xd5, 0x19, 0x83, 0xc7, 0x10, // IID535 - 0xd5, 0x19, 0x83, 0xe1, 0x10, // IID536 - 0xd5, 0x18, 0x81, 0xd7, 0x00, 0x01, 0x00, 0x00, // IID537 - 0xd5, 0x18, 0x81, 0xfb, 0x00, 0x00, 0x00, 0x10, // IID538 - 0xd5, 0x19, 0xd1, 0xd7, // IID539 - 0xd5, 0x18, 0xd1, 0xd9, // IID540 - 0xd5, 0x19, 0xc1, 0xc1, 0x02, // IID541 - 0xd5, 0x18, 0xc1, 0xc9, 0x04, // IID542 - 0xd5, 0x19, 0xd1, 0xfc, // IID543 - 0x49, 0xc1, 0xe7, 0x04, // IID544 - 0x48, 0x81, 0xdb, 0x00, 0x00, 0x01, 0x00, // IID545 - 0xd5, 0x18, 0xd1, 0xe5, // IID546 - 0x49, 0xd1, 0xea, // IID547 - 0x49, 0x83, 0xee, 0x10, // IID548 - 0xd5, 0x18, 0x81, 0xf2, 0x00, 0x00, 0x00, 0x10, // IID549 - 0xd5, 0x18, 0xc7, 0xc7, 0x10, 0x00, 0x00, 0x00, // IID550 - 0x49, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, // IID551 - 0x49, 0x0f, 0xba, 0xe6, 0x04, // IID552 - 0xd5, 0x19, 0xf7, 0xc0, 0x00, 0xf0, 0xff, 0xff, // IID553 - 0xd5, 0x18, 0x81, 0xcb, 0x00, 0x00, 0x10, 0x00, // IID554 - 0x48, 0x81, 0xe9, 0x00, 0x00, 0x00, 0x10, // IID555 - 0xd5, 0x98, 0x40, 0x94, 0xdb, 0xc4, 0xc8, 0x11, 0x02, // IID556 - 0xd5, 0x98, 0x41, 0x9d, 0x43, 0x77, 0x26, 0x49, // IID557 - 0xd5, 0xeb, 0x42, 0xac, 0x60, 0xba, 0xd6, 0x73, 0xb3, // IID558 - 0xd5, 0xbd, 0x43, 0xa4, 0x22, 0x64, 0x07, 0xb2, 0xd9, // IID559 - 0xd5, 0xdb, 0x44, 0x8c, 0x8c, 0x6b, 0x19, 0x97, 0x34, // IID560 - 0xd5, 0xad, 0x45, 0xac, 0x7f, 0x67, 0xf6, 0x5c, 0xd8, // IID561 - 0xd5, 0xd8, 0x46, 0xb6, 0x05, 0xab, 0x39, 0x0f, // IID562 - 0xd5, 0xba, 0x47, 0x8c, 0xd6, 0xb4, 0x6a, 0x73, 0xfb, // IID563 - 0xd5, 0xfc, 0x48, 0x8c, 0x2b, 0x0b, 0x5b, 0x40, 0x0e, // IID564 - 0xd5, 0xbe, 0x49, 0xa4, 0xeb, 0xb5, 0xfb, 0x9d, 0x88, // IID565 - 0xd5, 0x9b, 0x4a, 0x9c, 0x56, 0xdd, 0x7c, 0x86, 0xe6, // IID566 - 0xd5, 0xfb, 0x4b, 0xac, 0x38, 0xd5, 0x9a, 0xce, 0xa8, // IID567 - 0xd5, 0xcb, 0x4c, 0x94, 0x50, 0x77, 0x41, 0xec, 0xa9, // IID568 - 0xd5, 0xfc, 0x4d, 0xa4, 0xed, 0xc4, 0xfd, 0xa0, 0x65, // IID569 - 0xd5, 0xe9, 0x4e, 0xbc, 0x13, 0xf4, 0x0e, 0xe5, 0xe2, // IID570 - 0xd5, 0xda, 0x4f, 0xb4, 0x62, 0x38, 0x1c, 0x5f, 0x1a, // IID571 - 0xd5, 0x10, 0xff, 0xd7, // IID572 - 0xd5, 0x19, 0xf7, 0xf6, // IID573 - 0xd5, 0x18, 0xf7, 0xfb, // IID574 - 0x49, 0xf7, 0xe9, // IID575 - 0x49, 0xf7, 0xe5, // IID576 - 0xd5, 0x18, 0xf7, 0xd8, // IID577 - 0xd5, 0x19, 0xf7, 0xd5, // IID578 - 0x48, 0xd3, 0xc1, // IID579 - 0xd5, 0x19, 0xd3, 0xc9, // IID580 - 0x49, 0xd3, 0xf8, // IID581 - 0xd5, 0x19, 0xd3, 0xe3, // IID582 - 0xd5, 0x19, 0xd3, 0xe6, // IID583 - 0xd5, 0x18, 0xd3, 0xef, // IID584 - 0x48, 0xff, 0xc3, // IID585 - 0x49, 0xff, 0xce, // IID586 - 0xd5, 0x18, 0x55, // IID587 - 0xd5, 0x18, 0x5d, // IID588 - 0xd5, 0x30, 0xff, 0x94, 0x6c, 0x2f, 0xaf, 0xc6, 0x56, // IID589 - 0xd5, 0x39, 0xf7, 0xa4, 0xdf, 0xdd, 0x14, 0x4b, 0xfe, // IID590 - 0xd5, 0x3b, 0xf7, 0x9c, 0x1b, 0xe1, 0x03, 0x24, 0xa7, // IID591 - 0xd5, 0x28, 0xd3, 0xbc, 0xb3, 0x2f, 0xb6, 0x9c, 0x9f, // IID592 - 0xd5, 0x39, 0xd3, 0xa4, 0xfa, 0x79, 0xa0, 0x95, 0x0b, // IID593 - 0xd5, 0x2b, 0xd3, 0xac, 0x16, 0x09, 0x4e, 0x54, 0x03, // IID594 - 0xd5, 0x19, 0xff, 0x84, 0x13, 0x50, 0x32, 0x0b, 0x12, // IID595 - 0xd5, 0x2b, 0xff, 0x8c, 0x89, 0x35, 0x13, 0x55, 0xcb, // IID596 - 0xd5, 0x7a, 0x69, 0xa4, 0x60, 0x5b, 0xfa, 0x21, 0xa6, 0x00, 0x00, 0x10, 0x00, // IID597 - 0xd5, 0x58, 0x69, 0xcf, 0x00, 0x01, 0x00, 0x00, // IID598 - 0xd5, 0x9c, 0xa4, 0xdb, 0x08, // IID599 - 0xd5, 0x9d, 0xac, 0xd4, 0x08, // IID600 - 0x62, 0xdc, 0x2c, 0x10, 0x8f, 0xc5, // IID601 - 0x62, 0xfc, 0xac, 0x18, 0x8f, 0xc6, // IID602 - 0x62, 0xdc, 0x0c, 0x10, 0xff, 0xf1, // IID603 - 0x62, 0xdc, 0x84, 0x18, 0xff, 0xf4, // IID604 - 0xd5, 0xbd, 0xb6, 0x9c, 0x9d, 0xcc, 0x72, 0xc9, 0xed, // IID605 - 0xd5, 0xaf, 0xb7, 0xb4, 0xb0, 0x22, 0x6d, 0x6c, 0xb5, // IID606 - 0xd5, 0xde, 0xbe, 0xa4, 0x3f, 0x54, 0xcb, 0x89, 0x61, // IID607 - 0xd5, 0xec, 0xbf, 0xa4, 0xfb, 0x9f, 0x9a, 0x17, 0xd2, // IID608 - 0x4c, 0x0f, 0xb6, 0xd9, // IID609 - 0xd5, 0xcd, 0xb7, 0xf7, // IID610 - 0x4c, 0x0f, 0xbe, 0xf1, // IID611 - 0xd5, 0xc9, 0xbf, 0xf9, // IID612 - 0x4f, 0x0f, 0xb1, 0xa4, 0x55, 0xc6, 0xd3, 0x39, 0xf8, // IID613 - 0x62, 0xf4, 0xfc, 0x08, 0xf7, 0xf9, // IID614 - 0x62, 0xd4, 0xfc, 0x0c, 0xf7, 0xff, // IID615 - 0x62, 0xfc, 0xfc, 0x08, 0xf7, 0xf7, // IID616 - 0x62, 0xdc, 0xfc, 0x0c, 0xf7, 0xf0, // IID617 - 0x62, 0xdc, 0xfc, 0x08, 0xf7, 0xeb, // IID618 - 0x62, 0xdc, 0xfc, 0x0c, 0xf7, 0xee, // IID619 - 0x62, 0xd4, 0xfc, 0x08, 0xf7, 0xe4, // IID620 - 0x62, 0xf4, 0xfc, 0x0c, 0xf7, 0xe1, // IID621 - 0x62, 0x94, 0xfc, 0x08, 0xf7, 0xa4, 0xcd, 0x6c, 0x54, 0x95, 0xdd, // IID622 - 0x62, 0x94, 0xf8, 0x0c, 0xf7, 0xa4, 0xc5, 0xfb, 0x89, 0x93, 0xd7, // IID623 - 0x62, 0xcc, 0xfc, 0x08, 0xaf, 0xee, // IID624 - 0xd5, 0x18, 0xf7, 0xe9, // IID625 - 0x62, 0x44, 0xfc, 0x0c, 0xaf, 0xec, // IID626 - 0x62, 0x4c, 0xfc, 0x0c, 0xaf, 0xf6, // IID627 - 0x62, 0x44, 0xfc, 0x08, 0xf5, 0xc7, // IID628 - 0x62, 0x4c, 0xfc, 0x08, 0xf5, 0xc9, // IID629 - 0x62, 0x6c, 0xfc, 0x0c, 0xf5, 0xcd, // IID630 - 0x62, 0xec, 0xfc, 0x0c, 0xf5, 0xf6, // IID631 - 0x62, 0xdc, 0xf4, 0x10, 0xf7, 0xde, // IID632 - 0xd5, 0x18, 0xf7, 0xd9, // IID633 - 0x62, 0xfc, 0x84, 0x14, 0xf7, 0xd9, // IID634 - 0x62, 0xdc, 0x94, 0x14, 0xf7, 0xdd, // IID635 - 0x62, 0xd4, 0xac, 0x18, 0xf7, 0xd1, // IID636 - 0xd5, 0x19, 0xf7, 0xd0, // IID637 - 0x62, 0x44, 0xfc, 0x08, 0x88, 0xe7, // IID638 - 0x62, 0x54, 0xfc, 0x08, 0x88, 0xd2, // IID639 - 0x62, 0x4c, 0xfc, 0x0c, 0x88, 0xde, // IID640 - 0x62, 0x4c, 0xfc, 0x0c, 0x88, 0xe4, // IID641 - 0x62, 0xd4, 0x9c, 0x10, 0xd3, 0xc6, // IID642 - 0xd5, 0x18, 0xd3, 0xc7, // IID643 - 0x62, 0xdc, 0xc4, 0x14, 0xd3, 0xc0, // IID644 - 0x62, 0xfc, 0xd4, 0x14, 0xd3, 0xc5, // IID645 - 0x62, 0xfc, 0x84, 0x10, 0xd3, 0xce, // IID646 - 0xd5, 0x19, 0xd3, 0xcc, // IID647 - 0x62, 0xd4, 0xf4, 0x14, 0xd3, 0xca, // IID648 - 0x62, 0xd4, 0xb4, 0x1c, 0xd3, 0xc9, // IID649 - 0x62, 0xdc, 0x94, 0x10, 0xd3, 0xe6, // IID650 - 0x49, 0xd3, 0xe3, // IID651 - 0x62, 0xd4, 0xac, 0x14, 0xd3, 0xe3, // IID652 - 0x62, 0xfc, 0xfc, 0x14, 0xd3, 0xe0, // IID653 - 0x62, 0xd4, 0xe4, 0x18, 0xd3, 0xff, // IID654 - 0x49, 0xd3, 0xfe, // IID655 - 0x62, 0xfc, 0xb4, 0x14, 0xd3, 0xf8, // IID656 - 0x62, 0xd4, 0xbc, 0x1c, 0xd3, 0xf8, // IID657 - 0x62, 0xd4, 0xa4, 0x18, 0xff, 0xcd, // IID658 - 0x48, 0xff, 0xc9, // IID659 - 0x62, 0xfc, 0xd4, 0x14, 0xff, 0xca, // IID660 - 0x62, 0xdc, 0x9c, 0x14, 0xff, 0xcc, // IID661 - 0xd5, 0x18, 0xff, 0xc0, // IID662 - 0xd5, 0x19, 0xff, 0xc5, // IID663 - 0x62, 0xd4, 0xec, 0x14, 0xff, 0xc1, // IID664 - 0x62, 0xfc, 0xe4, 0x14, 0xff, 0xc3, // IID665 - 0x62, 0xfc, 0xe4, 0x10, 0xd3, 0xe2, // IID666 - 0x49, 0xd3, 0xe0, // IID667 - 0x62, 0xd4, 0x9c, 0x1c, 0xd3, 0xe7, // IID668 - 0x62, 0xdc, 0x94, 0x14, 0xd3, 0xe5, // IID669 - 0x62, 0xdc, 0x9c, 0x10, 0xd3, 0xe8, // IID670 - 0xd5, 0x18, 0xd3, 0xeb, // IID671 - 0x62, 0xdc, 0xbc, 0x1c, 0xd3, 0xec, // IID672 - 0x62, 0xfc, 0xf4, 0x14, 0xd3, 0xe9, // IID673 - 0x62, 0x6c, 0xfc, 0x08, 0xf4, 0xe0, // IID674 - 0x62, 0x54, 0xfc, 0x08, 0xf4, 0xf6, // IID675 - 0x62, 0x5c, 0xfc, 0x0c, 0xf4, 0xe7, // IID676 - 0x62, 0x54, 0xfc, 0x0c, 0xf4, 0xf6, // IID677 - 0x62, 0x44, 0xfc, 0x08, 0xaf, 0xbd, 0xae, 0x4c, 0x3b, 0x96, // IID678 - 0x62, 0xec, 0xfc, 0x0c, 0xaf, 0x8a, 0xfb, 0xee, 0x54, 0x9f, // IID679 - 0x62, 0x04, 0xf8, 0x08, 0xf5, 0x9c, 0x8e, 0x83, 0xbf, 0x98, 0x27, // IID680 - 0x62, 0x84, 0xfc, 0x0c, 0xf5, 0xbc, 0x1a, 0xa3, 0x9c, 0x71, 0xc8, // IID681 - 0x62, 0xbc, 0xf4, 0x18, 0xf7, 0x9c, 0xcb, 0xc0, 0x2b, 0xb8, 0x97, // IID682 - 0x62, 0xf4, 0xf4, 0x1c, 0xf7, 0x9c, 0x0b, 0x8d, 0xd3, 0x92, 0x6f, // IID683 - 0x62, 0xc4, 0xfc, 0x08, 0x88, 0xa4, 0x24, 0x2a, 0xd8, 0x74, 0xd5, // IID684 - 0x62, 0x4c, 0xfc, 0x0c, 0x88, 0xbe, 0xd0, 0xf6, 0x03, 0x46, // IID685 - 0x62, 0xdc, 0xe4, 0x18, 0xd3, 0xa0, 0xf9, 0x06, 0x7d, 0x56, // IID686 - 0x62, 0x9c, 0x98, 0x1c, 0xd3, 0xa4, 0x20, 0xb2, 0xa7, 0xb3, 0xe3, // IID687 - 0x62, 0xbc, 0x98, 0x18, 0xd3, 0xbc, 0x87, 0x46, 0x43, 0xa8, 0xce, // IID688 - 0x62, 0x94, 0xb8, 0x1c, 0xd3, 0xbc, 0x86, 0x5b, 0x6f, 0xbd, 0x8e, // IID689 - 0x62, 0x94, 0xc4, 0x10, 0xff, 0x8c, 0x78, 0x23, 0x8d, 0x1d, 0xa5, // IID690 - 0x62, 0x9c, 0x94, 0x1c, 0xff, 0x8c, 0xcd, 0x57, 0x8b, 0xae, 0xa4, // IID691 - 0x62, 0xbc, 0xa0, 0x18, 0xff, 0x84, 0xfd, 0x24, 0x4b, 0x89, 0xde, // IID692 - 0x62, 0xf4, 0x90, 0x1c, 0xff, 0x84, 0x01, 0x37, 0xb7, 0x4b, 0xc9, // IID693 - 0x62, 0xdc, 0xac, 0x10, 0xd3, 0xac, 0x89, 0x6d, 0xb6, 0x76, 0xa0, // IID694 - 0x62, 0xd4, 0xb4, 0x14, 0xd3, 0xa9, 0x21, 0x8d, 0x79, 0x51, // IID695 - 0x62, 0x04, 0xf8, 0x08, 0xf4, 0xa4, 0x95, 0xf6, 0x96, 0x71, 0x20, // IID696 - 0x62, 0xbc, 0xfc, 0x0c, 0xf4, 0x9c, 0x2b, 0x2b, 0xc8, 0x26, 0xdb, // IID697 - 0x62, 0x4c, 0xf4, 0x10, 0x01, 0xbe, 0xff, 0xcc, 0x35, 0x39, // IID698 - 0x62, 0x1c, 0x8c, 0x18, 0x01, 0xb4, 0x93, 0x55, 0x64, 0x52, 0xcb, // IID699 - 0x62, 0x6c, 0xe8, 0x14, 0x01, 0xb4, 0x3c, 0x4b, 0xed, 0xd3, 0x5a, // IID700 - 0x62, 0xe4, 0xdc, 0x14, 0x01, 0xa2, 0x1b, 0x66, 0xd5, 0xcd, // IID701 - 0x62, 0xa4, 0x80, 0x10, 0x21, 0x8c, 0xdb, 0xd2, 0x47, 0xe2, 0x4c, // IID702 - 0x62, 0x6c, 0x88, 0x10, 0x21, 0xb4, 0x5a, 0xec, 0xc2, 0x11, 0xfb, // IID703 - 0x62, 0x44, 0x9c, 0x14, 0x21, 0x84, 0xdb, 0x41, 0xb4, 0x66, 0xd7, // IID704 - 0x62, 0x6c, 0x8c, 0x14, 0x21, 0xb6, 0x24, 0x1c, 0xd2, 0x07, // IID705 - 0x62, 0xc4, 0xa8, 0x10, 0x09, 0xa4, 0xdf, 0x92, 0x17, 0xc2, 0x58, // IID706 - 0x62, 0x14, 0x90, 0x18, 0x09, 0xac, 0x9a, 0xcd, 0x2c, 0x8f, 0xd3, // IID707 - 0x62, 0x44, 0xe4, 0x1c, 0x09, 0x94, 0x1c, 0x44, 0x0e, 0x4f, 0xe0, // IID708 - 0x62, 0x0c, 0x80, 0x14, 0x09, 0xbc, 0x7b, 0x56, 0x17, 0x8d, 0x02, // IID709 - 0x62, 0x4c, 0xb8, 0x10, 0x29, 0x9c, 0x7c, 0x10, 0xf6, 0x80, 0x69, // IID710 - 0x62, 0x14, 0x80, 0x18, 0x29, 0xbc, 0xf3, 0x19, 0x88, 0x68, 0xfb, // IID711 - 0x62, 0x0c, 0xf4, 0x14, 0x29, 0xbc, 0xa9, 0x46, 0x9e, 0x61, 0x31, // IID712 - 0x62, 0x84, 0xec, 0x14, 0x29, 0x94, 0x93, 0x1a, 0x86, 0x22, 0x19, // IID713 - 0x62, 0xc4, 0xe4, 0x18, 0x31, 0xab, 0xe0, 0x2b, 0xe9, 0xb8, // IID714 - 0x62, 0x34, 0xbc, 0x18, 0x31, 0x84, 0x8a, 0x64, 0x1c, 0x30, 0xfb, // IID715 - 0x62, 0x04, 0xf8, 0x14, 0x31, 0x8c, 0x1e, 0xd9, 0x54, 0x66, 0x7c, // IID716 - 0x62, 0x44, 0x94, 0x14, 0x31, 0xaf, 0x87, 0x4b, 0x05, 0xa1, // IID717 - 0x62, 0xd4, 0xe0, 0x10, 0x81, 0x84, 0xb5, 0x59, 0x45, 0xb6, 0x68, 0x00, 0x00, 0x00, 0x01, // IID718 - 0x62, 0x94, 0xf8, 0x14, 0x83, 0x84, 0xfd, 0x0b, 0xc5, 0xeb, 0x9a, 0x01, // IID719 - 0x62, 0x9c, 0x84, 0x10, 0x83, 0xa4, 0x68, 0xf2, 0x95, 0x4e, 0xda, 0x01, // IID720 - 0x62, 0xdc, 0xa4, 0x1c, 0x81, 0xa4, 0x24, 0xda, 0xb4, 0x92, 0xf0, 0x00, 0x00, 0x01, 0x00, // IID721 - 0x62, 0xbc, 0xfc, 0x08, 0x69, 0x8c, 0x12, 0xa1, 0x6d, 0xec, 0x46, 0x00, 0x00, 0x00, 0x01, // IID722 - 0x62, 0x14, 0xfc, 0x0c, 0x6b, 0xbc, 0xd1, 0x0d, 0x95, 0x3c, 0x80, 0x10, // IID723 - 0x62, 0x9c, 0xf0, 0x10, 0x83, 0x8c, 0x33, 0x2c, 0xda, 0x4c, 0x1b, 0x01, // IID724 - 0x62, 0x9c, 0xec, 0x1c, 0x81, 0x8c, 0xb1, 0x7b, 0x94, 0x55, 0xa6, 0x00, 0x10, 0x00, 0x00, // IID725 - 0x62, 0xdc, 0xf0, 0x10, 0xc1, 0xa4, 0x6a, 0xa1, 0x0e, 0x4e, 0x95, 0x08, // IID726 - 0x62, 0xfc, 0x98, 0x1c, 0xc1, 0xa4, 0x0e, 0x55, 0xeb, 0x53, 0xbc, 0x02, // IID727 - 0x62, 0xfc, 0x90, 0x10, 0xc1, 0xbc, 0x02, 0x9f, 0xf3, 0x23, 0xa6, 0x04, // IID728 - 0x62, 0xd4, 0xfc, 0x14, 0xc1, 0xbb, 0xec, 0x2c, 0x42, 0xf8, 0x04, // IID729 - 0x62, 0xbc, 0xa8, 0x10, 0xc1, 0xac, 0xdf, 0xec, 0xdc, 0x46, 0xaa, 0x10, // IID730 - 0x62, 0xbc, 0xc0, 0x14, 0xc1, 0xac, 0x68, 0x1d, 0x1a, 0x31, 0x71, 0x02, // IID731 - 0x62, 0xd4, 0xb4, 0x10, 0x81, 0xa9, 0x54, 0xd4, 0xac, 0xf6, 0x00, 0x00, 0x10, 0x00, // IID732 - 0x62, 0xd4, 0xf0, 0x14, 0x81, 0xac, 0x38, 0xa2, 0x6c, 0xd0, 0x55, 0x00, 0x00, 0x10, 0x00, // IID733 - 0x62, 0x94, 0x90, 0x10, 0x81, 0xb4, 0x01, 0x3f, 0xbe, 0x3e, 0xfd, 0x00, 0x00, 0x10, 0x00, // IID734 - 0x62, 0xfc, 0x98, 0x14, 0x83, 0xb4, 0x5e, 0x43, 0x65, 0x62, 0xd2, 0x10, // IID735 - 0x62, 0xd4, 0xcc, 0x10, 0x83, 0xc6, 0x10, // IID736 - 0x62, 0xd4, 0xfc, 0x18, 0x83, 0xc4, 0x10, // IID737 - 0xd5, 0x19, 0x81, 0xc0, 0x00, 0x00, 0x01, 0x00, // IID738 - 0x62, 0xf4, 0xd4, 0x14, 0x81, 0xc3, 0x00, 0x00, 0x01, 0x00, // IID739 - 0x62, 0xf4, 0xfc, 0x1c, 0x81, 0xc3, 0x00, 0x00, 0x01, 0x00, // IID740 - 0x62, 0xdc, 0xbc, 0x14, 0x81, 0xc0, 0x00, 0x00, 0x01, 0x00, // IID741 - 0x62, 0xdc, 0xd4, 0x10, 0x81, 0xe3, 0x00, 0x00, 0x00, 0x01, // IID742 - 0x62, 0xdc, 0xfc, 0x18, 0x81, 0xe3, 0x00, 0x00, 0x00, 0x01, // IID743 - 0xd5, 0x19, 0x81, 0xe0, 0x00, 0x00, 0x01, 0x00, // IID744 - 0x62, 0xdc, 0x94, 0x1c, 0x81, 0xe7, 0x00, 0x00, 0x10, 0x00, // IID745 - 0x62, 0xfc, 0xfc, 0x1c, 0x81, 0xe5, 0x00, 0x00, 0x10, 0x00, // IID746 - 0x62, 0xdc, 0x8c, 0x14, 0x81, 0xe6, 0x00, 0x00, 0x10, 0x00, // IID747 - 0x62, 0x54, 0xfc, 0x08, 0x69, 0xc5, 0x00, 0x00, 0x00, 0x10, // IID748 - 0x62, 0xdc, 0xfc, 0x08, 0x69, 0xc7, 0x00, 0x00, 0x00, 0x10, // IID749 - 0x62, 0x54, 0xfc, 0x08, 0x69, 0xed, 0x00, 0x00, 0x01, 0x00, // IID750 - 0x62, 0x5c, 0xfc, 0x0c, 0x69, 0xf5, 0x00, 0x00, 0x10, 0x00, // IID751 - 0x62, 0xfc, 0xfc, 0x0c, 0x69, 0xc6, 0x00, 0x00, 0x10, 0x00, // IID752 - 0x62, 0x54, 0xfc, 0x0c, 0x69, 0xc0, 0x00, 0x00, 0x00, 0x10, // IID753 - 0x62, 0xd4, 0x8c, 0x10, 0x81, 0xcf, 0x00, 0x10, 0x00, 0x00, // IID754 - 0x62, 0xdc, 0xfc, 0x18, 0x81, 0xcc, 0x00, 0x10, 0x00, 0x00, // IID755 - 0xd5, 0x19, 0x81, 0xca, 0x00, 0x00, 0x10, 0x00, // IID756 - 0x62, 0xd4, 0xfc, 0x14, 0x81, 0xcc, 0x00, 0x00, 0x00, 0x10, // IID757 - 0x62, 0xd4, 0xfc, 0x1c, 0x81, 0xc9, 0x00, 0x00, 0x00, 0x10, // IID758 - 0x62, 0xfc, 0xc4, 0x14, 0x81, 0xcf, 0x00, 0x01, 0x00, 0x00, // IID759 - 0x62, 0xd4, 0x84, 0x18, 0xc1, 0xd1, 0x10, // IID760 - 0x62, 0xd4, 0xfc, 0x18, 0xc1, 0xd0, 0x10, // IID761 - 0xd5, 0x19, 0xd1, 0xd1, // IID762 - 0x62, 0xfc, 0xb4, 0x18, 0xc1, 0xc1, 0x10, // IID763 - 0x62, 0xfc, 0xfc, 0x18, 0xc1, 0xc4, 0x10, // IID764 - 0xd5, 0x19, 0xd1, 0xc3, // IID765 - 0x62, 0xdc, 0xdc, 0x14, 0xd1, 0xc7, // IID766 - 0x62, 0xfc, 0xfc, 0x1c, 0xd1, 0xc2, // IID767 - 0x62, 0xdc, 0x9c, 0x14, 0xc1, 0xc4, 0x10, // IID768 - 0x62, 0xfc, 0xac, 0x10, 0xc1, 0xca, 0x10, // IID769 - 0x62, 0xdc, 0xfc, 0x18, 0xc1, 0xc8, 0x10, // IID770 - 0xd5, 0x18, 0xc1, 0xce, 0x10, // IID771 - 0x62, 0xdc, 0xa4, 0x14, 0xd1, 0xcd, // IID772 - 0x62, 0xfc, 0xfc, 0x1c, 0xd1, 0xca, // IID773 - 0x62, 0xfc, 0xd4, 0x14, 0xd1, 0xcd, // IID774 - 0x62, 0xf4, 0x9c, 0x18, 0xc1, 0xe1, 0x02, // IID775 - 0x62, 0xdc, 0xfc, 0x18, 0xc1, 0xe0, 0x02, // IID776 - 0xd5, 0x18, 0xc1, 0xe6, 0x08, // IID777 - 0x62, 0xfc, 0xf4, 0x14, 0xc1, 0xe7, 0x08, // IID778 - 0x62, 0xdc, 0xfc, 0x1c, 0xc1, 0xe3, 0x08, // IID779 - 0x62, 0xfc, 0xc4, 0x14, 0xd1, 0xe7, // IID780 - 0x62, 0xdc, 0xbc, 0x18, 0xc1, 0xf9, 0x10, // IID781 - 0x62, 0xfc, 0xfc, 0x18, 0xc1, 0xff, 0x10, // IID782 - 0x49, 0xc1, 0xf9, 0x04, // IID783 - 0x62, 0xd4, 0xcc, 0x14, 0xd1, 0xfd, // IID784 - 0x62, 0xd4, 0xfc, 0x1c, 0xd1, 0xfb, // IID785 - 0x62, 0xd4, 0x9c, 0x1c, 0xc1, 0xfc, 0x02, // IID786 - 0x62, 0xdc, 0xf4, 0x18, 0xc1, 0xe6, 0x08, // IID787 - 0x62, 0xfc, 0xfc, 0x18, 0xc1, 0xe3, 0x08, // IID788 - 0x49, 0xc1, 0xe5, 0x02, // IID789 - 0x62, 0xd4, 0xec, 0x14, 0xc1, 0xe3, 0x08, // IID790 - 0x62, 0xd4, 0xfc, 0x1c, 0xc1, 0xe1, 0x08, // IID791 - 0x62, 0xf4, 0xf4, 0x1c, 0xc1, 0xe1, 0x10, // IID792 - 0x62, 0xfc, 0xac, 0x18, 0xc1, 0xee, 0x04, // IID793 - 0x62, 0xd4, 0xfc, 0x18, 0xc1, 0xe9, 0x04, // IID794 - 0x49, 0xc1, 0xec, 0x02, // IID795 - 0x62, 0xdc, 0xac, 0x14, 0xc1, 0xef, 0x08, // IID796 - 0x62, 0xd4, 0xfc, 0x1c, 0xc1, 0xec, 0x08, // IID797 - 0x62, 0xdc, 0x9c, 0x14, 0xd1, 0xec, // IID798 - 0x62, 0xdc, 0x84, 0x18, 0x81, 0xee, 0x00, 0x00, 0x01, 0x00, // IID799 - 0x62, 0xf4, 0xfc, 0x18, 0x81, 0xe9, 0x00, 0x00, 0x01, 0x00, // IID800 - 0xd5, 0x19, 0x83, 0xea, 0x10, // IID801 - 0x62, 0xd4, 0x9c, 0x1c, 0x83, 0xee, 0x01, // IID802 - 0x62, 0xfc, 0xfc, 0x1c, 0x83, 0xed, 0x01, // IID803 - 0x62, 0xfc, 0xdc, 0x14, 0x81, 0xec, 0x00, 0x00, 0x10, 0x00, // IID804 - 0x62, 0xf4, 0xa4, 0x18, 0x81, 0xf3, 0x00, 0x00, 0x00, 0x01, // IID805 - 0x62, 0xfc, 0xfc, 0x18, 0x81, 0xf7, 0x00, 0x00, 0x00, 0x01, // IID806 - 0xd5, 0x19, 0x81, 0xf7, 0x00, 0x00, 0x00, 0x10, // IID807 - 0x62, 0xdc, 0x94, 0x14, 0x81, 0xf4, 0x00, 0x10, 0x00, 0x00, // IID808 - 0x62, 0xfc, 0xfc, 0x1c, 0x81, 0xf3, 0x00, 0x10, 0x00, 0x00, // IID809 - 0x62, 0xf4, 0xec, 0x1c, 0x81, 0xf2, 0x00, 0x00, 0x00, 0x10, // IID810 - 0x48, 0x81, 0xca, 0x00, 0x00, 0x10, 0x00, // IID811 - 0x62, 0xfc, 0xfc, 0x18, 0x81, 0xce, 0x00, 0x00, 0x10, 0x00, // IID812 - 0xd5, 0x19, 0x81, 0xcd, 0x00, 0x00, 0x10, 0x00, // IID813 - 0x62, 0xf4, 0xf4, 0x10, 0x81, 0xc9, 0x00, 0x00, 0x40, 0x00, // IID814 - 0x62, 0xdc, 0xfc, 0x18, 0x81, 0xc9, 0x00, 0x00, 0x40, 0x00, // IID815 - 0xd5, 0x19, 0x81, 0xcb, 0x00, 0x00, 0x00, 0x40, // IID816 - 0x62, 0xfc, 0xfc, 0x10, 0x81, 0xeb, 0x00, 0x00, 0x40, 0x00, // IID817 - 0x62, 0xdc, 0xfc, 0x18, 0x81, 0xef, 0x00, 0x00, 0x40, 0x00, // IID818 - 0xd5, 0x19, 0x81, 0xea, 0x00, 0x00, 0x04, 0x00, // IID819 - 0x62, 0xfc, 0xf4, 0x14, 0x81, 0xee, 0x00, 0x00, 0x00, 0x40, // IID820 - 0x62, 0xfc, 0xfc, 0x1c, 0x81, 0xea, 0x00, 0x00, 0x00, 0x40, // IID821 - 0x62, 0xfc, 0xc4, 0x14, 0x81, 0xef, 0x00, 0x00, 0x00, 0x10, // IID822 - 0x62, 0x4c, 0x90, 0x18, 0x03, 0xb4, 0x58, 0x3b, 0x3a, 0xea, 0x56, // IID823 - 0x62, 0x1c, 0x90, 0x14, 0x03, 0xbc, 0xda, 0xa8, 0xc6, 0xee, 0xb4, // IID824 - 0x62, 0x4c, 0x9c, 0x18, 0x23, 0xb7, 0x8c, 0xc3, 0xef, 0xb9, // IID825 - 0x62, 0x3c, 0xa0, 0x14, 0x23, 0x94, 0x4e, 0xe5, 0xbe, 0x1e, 0x6a, // IID826 - 0x62, 0x44, 0x88, 0x10, 0x0b, 0x94, 0x93, 0xd7, 0x00, 0x60, 0xd4, // IID827 - 0x62, 0x7c, 0xb0, 0x1c, 0x0b, 0xa4, 0x0a, 0xf6, 0x59, 0x48, 0x0b, // IID828 - 0x62, 0xcc, 0xec, 0x18, 0xaf, 0x8c, 0x90, 0xd8, 0x4c, 0x28, 0x3d, // IID829 - 0x62, 0x0c, 0x94, 0x14, 0xaf, 0x94, 0x66, 0x24, 0x31, 0x81, 0x6e, // IID830 - 0x62, 0x7c, 0xe4, 0x18, 0x2b, 0xae, 0x62, 0xd7, 0xd5, 0x8f, // IID831 - 0x62, 0x4c, 0xc4, 0x14, 0x2b, 0xac, 0x11, 0x13, 0x58, 0xad, 0x9d, // IID832 - 0x62, 0xac, 0xbc, 0x18, 0x33, 0x94, 0xb3, 0x69, 0x59, 0x40, 0xf1, // IID833 - 0x62, 0x4c, 0xac, 0x1c, 0x33, 0xa2, 0xca, 0x81, 0x83, 0x16, // IID834 - 0x62, 0xc4, 0xf4, 0x18, 0x03, 0xd0, // IID835 - 0x49, 0x03, 0xce, // IID836 - 0x62, 0x7c, 0xc4, 0x14, 0x03, 0xd0, // IID837 - 0x62, 0x5c, 0xa4, 0x1c, 0x03, 0xd8, // IID838 - 0x62, 0xe4, 0xb5, 0x18, 0x66, 0xd2, // IID839 - 0x66, 0x4d, 0x0f, 0x38, 0xf6, 0xc7, // IID840 - 0x62, 0xcc, 0x86, 0x18, 0x66, 0xf2, // IID841 - 0xf3, 0x4c, 0x0f, 0x38, 0xf6, 0xda, // IID842 - 0x62, 0xfc, 0xe4, 0x10, 0x23, 0xd6, // IID843 - 0xd5, 0x5c, 0x23, 0xe9, // IID844 - 0x62, 0x44, 0xc4, 0x14, 0x23, 0xdf, // IID845 - 0x62, 0x54, 0xb4, 0x1c, 0x23, 0xcd, // IID846 - 0x62, 0x7c, 0xec, 0x10, 0xaf, 0xf8, // IID847 - 0xd5, 0x98, 0xaf, 0xc9, // IID848 - 0x62, 0x7c, 0xc4, 0x14, 0xaf, 0xe4, // IID849 - 0x62, 0x54, 0xac, 0x1c, 0xaf, 0xd1, // IID850 - 0x62, 0xc4, 0xec, 0x18, 0x0b, 0xde, // IID851 - 0x49, 0x0b, 0xcd, // IID852 - 0x62, 0x4c, 0xb4, 0x1c, 0x0b, 0xcd, // IID853 - 0x62, 0xdc, 0xec, 0x1c, 0x0b, 0xd1, // IID854 - 0x62, 0x7c, 0xc4, 0x10, 0x2b, 0xc0, // IID855 - 0x4d, 0x2b, 0xed, // IID856 - 0x62, 0x54, 0xe4, 0x14, 0x2b, 0xe7, // IID857 - 0x62, 0x74, 0xb4, 0x1c, 0x2b, 0xca, // IID858 - 0x62, 0xcc, 0x94, 0x18, 0x33, 0xc7, // IID859 - 0xd5, 0x59, 0x33, 0xce, // IID860 - 0x62, 0x6c, 0xe4, 0x14, 0x33, 0xf4, // IID861 - 0x62, 0x44, 0x84, 0x14, 0x33, 0xfd, // IID862 - 0x62, 0x54, 0xcc, 0x10, 0x24, 0xea, 0x04, // IID863 - 0xd5, 0xd9, 0xa4, 0xe8, 0x10, // IID864 - 0x62, 0x44, 0xdc, 0x14, 0x24, 0xdd, 0x10, // IID865 - 0x62, 0xcc, 0x84, 0x14, 0x24, 0xdf, 0x02, // IID866 - 0x62, 0x7c, 0x8c, 0x10, 0x2c, 0xdc, 0x08, // IID867 - 0x4c, 0x0f, 0xac, 0xfa, 0x01, // IID868 - 0x62, 0x5c, 0x9c, 0x14, 0x2c, 0xf6, 0x02, // IID869 - 0x62, 0xec, 0xdc, 0x14, 0x2c, 0xc4, 0x01, // IID870 - 0x62, 0xcc, 0xd4, 0x10, 0x40, 0xcc, // IID871 - 0xd5, 0x9d, 0x40, 0xfe, // IID872 - 0x62, 0x54, 0xf4, 0x18, 0x41, 0xff, // IID873 - 0x49, 0x0f, 0x41, 0xcd, // IID874 - 0x62, 0x4c, 0xec, 0x18, 0x42, 0xd2, // IID875 - 0xd5, 0xcd, 0x42, 0xe7, // IID876 - 0x62, 0xf4, 0xbc, 0x18, 0x43, 0xd1, // IID877 - 0x48, 0x0f, 0x43, 0xc9, // IID878 - 0x62, 0x54, 0xac, 0x18, 0x44, 0xe9, // IID879 - 0xd5, 0x9d, 0x44, 0xf3, // IID880 - 0x62, 0xc4, 0xa4, 0x18, 0x45, 0xf9, // IID881 - 0x4c, 0x0f, 0x45, 0xda, // IID882 - 0x62, 0x5c, 0x84, 0x10, 0x46, 0xf1, // IID883 - 0xd5, 0xc9, 0x46, 0xe4, // IID884 - 0x62, 0x5c, 0xec, 0x18, 0x47, 0xd4, // IID885 - 0xd5, 0x9c, 0x47, 0xc1, // IID886 - 0x62, 0x6c, 0xf4, 0x18, 0x48, 0xf7, // IID887 - 0xd5, 0xdc, 0x48, 0xd2, // IID888 - 0x62, 0xfc, 0xec, 0x18, 0x49, 0xda, // IID889 - 0xd5, 0xc9, 0x49, 0xed, // IID890 - 0x62, 0x4c, 0xa4, 0x10, 0x4a, 0xe3, // IID891 - 0xd5, 0x9d, 0x4a, 0xde, // IID892 - 0x62, 0xec, 0xf4, 0x18, 0x4b, 0xea, // IID893 - 0xd5, 0x99, 0x4b, 0xcd, // IID894 - 0x62, 0xc4, 0xec, 0x18, 0x4c, 0xec, // IID895 - 0xd5, 0x99, 0x4c, 0xd2, // IID896 - 0x62, 0xfc, 0xf4, 0x10, 0x4d, 0xde, // IID897 - 0x49, 0x0f, 0x4d, 0xd3, // IID898 - 0x62, 0x54, 0xec, 0x18, 0x4e, 0xf0, // IID899 - 0x4d, 0x0f, 0x4e, 0xf0, // IID900 - 0x62, 0x6c, 0xb4, 0x10, 0x4f, 0xed, // IID901 - 0xd5, 0xdd, 0x4f, 0xd6, // IID902 - 0x62, 0x84, 0xbc, 0x10, 0x40, 0xac, 0x5d, 0x1e, 0x52, 0x9c, 0x43, // IID903 - 0x62, 0xcc, 0xa0, 0x18, 0x41, 0x94, 0x05, 0x7f, 0x12, 0x32, 0x06, // IID904 - 0x62, 0x14, 0xf8, 0x10, 0x42, 0x84, 0x50, 0xef, 0x3d, 0x63, 0x10, // IID905 - 0x62, 0x7c, 0x94, 0x18, 0x43, 0xb2, 0xc8, 0x61, 0x09, 0xab, // IID906 - 0x62, 0x1c, 0x98, 0x18, 0x44, 0x84, 0x57, 0x86, 0xbb, 0xe1, 0x85, // IID907 - 0xd5, 0xde, 0x45, 0xac, 0x9b, 0x2e, 0xd2, 0x27, 0xca, // IID908 - 0x62, 0x8c, 0xf0, 0x18, 0x46, 0x94, 0x21, 0xa0, 0x64, 0xbe, 0x30, // IID909 - 0x62, 0x54, 0x98, 0x10, 0x47, 0xa4, 0x42, 0x06, 0x01, 0x47, 0xdd, // IID910 - 0x62, 0x34, 0xa4, 0x18, 0x48, 0x84, 0xdb, 0x96, 0x9e, 0xcc, 0x25, // IID911 - 0x62, 0x44, 0x9c, 0x18, 0x49, 0x9b, 0x02, 0x8f, 0xd2, 0xf3, // IID912 - 0x62, 0x6c, 0xbc, 0x18, 0x4a, 0x94, 0x5b, 0x16, 0x48, 0x92, 0xb7, // IID913 - 0x62, 0x54, 0x88, 0x10, 0x4b, 0x94, 0xd6, 0x84, 0x48, 0x88, 0x14, // IID914 - 0x62, 0x1c, 0xa4, 0x10, 0x4c, 0x84, 0xb5, 0xa8, 0xb7, 0x92, 0x00, // IID915 - 0x62, 0x6c, 0x8c, 0x18, 0x4d, 0xa4, 0x13, 0x45, 0x2d, 0x9c, 0x00, // IID916 - 0x62, 0x74, 0xb0, 0x10, 0x4e, 0x84, 0x91, 0x6b, 0xc8, 0x55, 0x66, // IID917 - 0x62, 0x84, 0xe0, 0x10, 0x4f, 0xac, 0x0a, 0xf5, 0xbc, 0xfa, 0xef, // IID918 + 0x62, 0x6c, 0x74, 0x18, 0x0b, 0xc6, // IID432 + 0xd5, 0x10, 0x0b, 0xcb, // IID433 + 0xd5, 0x55, 0x0b, 0xdb, // IID434 + 0x62, 0x54, 0x04, 0x14, 0x0b, 0xcd, // IID435 + 0x62, 0x6c, 0x04, 0x14, 0x0b, 0xff, // IID436 + 0x62, 0xec, 0x64, 0x14, 0x0b, 0xcb, // IID437 + 0x62, 0x6c, 0x5c, 0x10, 0xa5, 0xc0, // IID438 + 0x44, 0x0f, 0xa5, 0xe2, // IID439 + 0x62, 0x44, 0x14, 0x14, 0xa5, 0xf9, // IID440 + 0x62, 0xec, 0x74, 0x14, 0xa5, 0xe1, // IID441 + 0x62, 0xc4, 0x5c, 0x10, 0xad, 0xd7, // IID442 + 0x44, 0x0f, 0xad, 0xe1, // IID443 + 0x62, 0xc4, 0x0c, 0x1c, 0xad, 0xf9, // IID444 + 0x62, 0x7c, 0x64, 0x14, 0xad, 0xeb, // IID445 + 0x62, 0x4c, 0x0c, 0x10, 0x2b, 0xdb, // IID446 + 0x41, 0x2b, 0xd3, // IID447 + 0x62, 0x5c, 0x04, 0x1c, 0x2b, 0xd8, // IID448 + 0x62, 0x5c, 0x0c, 0x1c, 0x2b, 0xf1, // IID449 + 0x62, 0xc4, 0x04, 0x10, 0x33, 0xc4, // IID450 + 0xd5, 0x41, 0x33, 0xe6, // IID451 + 0xd5, 0x45, 0x33, 0xf5, // IID452 + 0x62, 0xec, 0x3c, 0x14, 0x33, 0xc9, // IID453 + 0x62, 0x6c, 0x2c, 0x14, 0x33, 0xd5, // IID454 + 0x62, 0x54, 0x24, 0x1c, 0x33, 0xeb, // IID455 + 0x62, 0xcc, 0x24, 0x10, 0x24, 0xe9, 0x04, // IID456 + 0xd5, 0x94, 0xa4, 0xd6, 0x04, // IID457 + 0x62, 0x44, 0x54, 0x14, 0x24, 0xc7, 0x10, // IID458 + 0x62, 0xe4, 0x6c, 0x1c, 0x24, 0xda, 0x01, // IID459 + 0x62, 0x54, 0x44, 0x10, 0x2c, 0xc5, 0x10, // IID460 + 0xd5, 0xd1, 0xac, 0xf2, 0x01, // IID461 + 0x62, 0x44, 0x3c, 0x14, 0x2c, 0xf1, 0x10, // IID462 + 0x62, 0x7c, 0x64, 0x14, 0x2c, 0xc3, 0x04, // IID463 + 0x62, 0x6c, 0x0c, 0x10, 0x40, 0xd1, // IID464 + 0xd5, 0x95, 0x40, 0xf2, // IID465 + 0x62, 0xcc, 0x3c, 0x10, 0x41, 0xdd, // IID466 + 0xd5, 0xd4, 0x41, 0xcc, // IID467 + 0x62, 0x54, 0x24, 0x18, 0x42, 0xd6, // IID468 + 0xd5, 0xd5, 0x42, 0xf1, // IID469 + 0x62, 0xcc, 0x14, 0x18, 0x43, 0xf3, // IID470 + 0xd5, 0xd1, 0x43, 0xc0, // IID471 + 0x62, 0x5c, 0x1c, 0x10, 0x44, 0xee, // IID472 + 0xd5, 0xd5, 0x44, 0xf0, // IID473 + 0x62, 0xcc, 0x54, 0x10, 0x45, 0xe7, // IID474 + 0xd5, 0x94, 0x45, 0xc0, // IID475 + 0x62, 0x6c, 0x04, 0x18, 0x46, 0xd6, // IID476 + 0xd5, 0xc4, 0x46, 0xfa, // IID477 + 0x62, 0x54, 0x24, 0x10, 0x47, 0xc2, // IID478 + 0xd5, 0xc1, 0x47, 0xd3, // IID479 + 0x62, 0xfc, 0x24, 0x10, 0x48, 0xdd, // IID480 + 0xd5, 0x95, 0x48, 0xe7, // IID481 + 0x62, 0xfc, 0x1c, 0x18, 0x49, 0xd2, // IID482 + 0xd5, 0xd0, 0x49, 0xd3, // IID483 + 0x62, 0xec, 0x7c, 0x10, 0x4a, 0xe7, // IID484 + 0xd5, 0xd0, 0x4a, 0xd0, // IID485 + 0x62, 0x4c, 0x64, 0x18, 0x4b, 0xfe, // IID486 + 0xd5, 0xd5, 0x4b, 0xfd, // IID487 + 0x62, 0x44, 0x1c, 0x10, 0x4c, 0xca, // IID488 + 0xd5, 0xd4, 0x4c, 0xc4, // IID489 + 0x62, 0xdc, 0x7c, 0x10, 0x4d, 0xd2, // IID490 + 0xd5, 0xd5, 0x4d, 0xe4, // IID491 + 0x62, 0xcc, 0x34, 0x18, 0x4e, 0xe0, // IID492 + 0xd5, 0xd5, 0x4e, 0xc5, // IID493 + 0x62, 0x44, 0x44, 0x10, 0x4f, 0xdf, // IID494 + 0xd5, 0x94, 0x4f, 0xe2, // IID495 + 0x62, 0x5c, 0x64, 0x10, 0x40, 0x8c, 0x4f, 0x43, 0x67, 0x41, 0xfd, // IID496 + 0xd5, 0xb6, 0x40, 0x84, 0x45, 0xcb, 0xa0, 0xe6, 0x41, // IID497 + 0x62, 0x3c, 0x40, 0x10, 0x41, 0xbc, 0xf3, 0xd3, 0x01, 0x52, 0xaa, // IID498 + 0xd5, 0x91, 0x41, 0x94, 0x13, 0xcb, 0xd8, 0x5e, 0xe5, // IID499 + 0x62, 0x0c, 0x64, 0x18, 0x42, 0xac, 0x27, 0x46, 0x22, 0xd4, 0x0b, // IID500 + 0xd5, 0xf0, 0x42, 0xac, 0x6b, 0xe8, 0x77, 0xae, 0xbe, // IID501 + 0x62, 0x2c, 0x44, 0x10, 0x43, 0xac, 0x8e, 0x28, 0x24, 0x52, 0xca, // IID502 + 0xd5, 0xd1, 0x43, 0x91, 0xc3, 0x84, 0x21, 0x63, // IID503 + 0x62, 0x3c, 0x14, 0x10, 0x44, 0xac, 0x2a, 0x3a, 0x15, 0x8d, 0xc6, // IID504 + 0xd5, 0xc7, 0x44, 0xac, 0xcc, 0x2e, 0x20, 0x73, 0x99, // IID505 + 0x62, 0xc4, 0x30, 0x10, 0x45, 0x94, 0xb1, 0x1f, 0xc9, 0x6a, 0x7f, // IID506 + 0xd5, 0xd5, 0x45, 0xa6, 0x94, 0x65, 0x2e, 0x56, // IID507 + 0x62, 0x44, 0x20, 0x10, 0x46, 0x84, 0xa7, 0x49, 0xc7, 0x9a, 0xb9, // IID508 + 0xd5, 0xd7, 0x46, 0x8c, 0xda, 0x57, 0xed, 0xc7, 0xa6, // IID509 + 0x62, 0xec, 0x74, 0x18, 0x47, 0xa0, 0x15, 0x5c, 0x76, 0xec, // IID510 + 0xd5, 0x93, 0x47, 0x9c, 0x05, 0x15, 0x26, 0x02, 0x1d, // IID511 + 0x62, 0x14, 0x68, 0x18, 0x48, 0xb4, 0x64, 0x6f, 0xa5, 0x8d, 0xae, // IID512 + 0xd5, 0xf4, 0x48, 0x84, 0x51, 0x1c, 0x3b, 0xda, 0xe8, // IID513 + 0xd5, 0xa1, 0x49, 0x8c, 0xbf, 0x31, 0xd3, 0x2d, 0x94, // IID514 + 0xd5, 0xc7, 0x49, 0x84, 0x57, 0xf7, 0xc2, 0x04, 0x80, // IID515 + 0x62, 0xd4, 0x40, 0x10, 0x4a, 0x8c, 0x3b, 0x85, 0xc5, 0x38, 0x37, // IID516 + 0xd5, 0xd7, 0x4a, 0x84, 0x16, 0xa8, 0x15, 0xcc, 0x0f, // IID517 + 0x62, 0x44, 0x08, 0x18, 0x4b, 0x94, 0x6e, 0x61, 0x31, 0xcf, 0xbb, // IID518 + 0xd5, 0x95, 0x4b, 0x94, 0x24, 0x9f, 0xc5, 0xd7, 0x03, // IID519 + 0x62, 0x84, 0x2c, 0x18, 0x4c, 0xac, 0xc0, 0xb4, 0x84, 0x65, 0x4a, // IID520 + 0xd5, 0xf4, 0x4c, 0x94, 0xe3, 0xef, 0x60, 0xc6, 0x47, // IID521 + 0x62, 0x74, 0x2c, 0x10, 0x4d, 0x91, 0x97, 0x7a, 0x97, 0x61, // IID522 + 0xd5, 0xe5, 0x4d, 0xb4, 0xdf, 0xcb, 0x01, 0xc6, 0x53, // IID523 + 0x62, 0x7c, 0x0c, 0x18, 0x4e, 0x89, 0x1e, 0x11, 0x93, 0xa9, // IID524 + 0xd5, 0xb5, 0x4e, 0xbc, 0x23, 0x92, 0x47, 0x16, 0x76, // IID525 + 0x62, 0x14, 0x24, 0x10, 0x4f, 0xb4, 0xa9, 0xd7, 0x52, 0x57, 0x0f, // IID526 + 0x44, 0x0f, 0x4f, 0xa4, 0xcb, 0x3a, 0x4b, 0xfe, 0xaa, // IID527 + 0xd5, 0x5d, 0x13, 0xf7, // IID528 + 0x4c, 0x3b, 0xe2, // IID529 + 0xd5, 0xd9, 0xaf, 0xe8, // IID530 + 0xf3, 0xd5, 0x9d, 0xb8, 0xc9, // IID531 + 0x4d, 0x1b, 0xc4, // IID532 + 0xd5, 0x5d, 0x2b, 0xf8, // IID533 + 0xf3, 0xd5, 0x9c, 0xbc, 0xd0, // IID534 + 0xf3, 0xd5, 0xd8, 0xbd, 0xe5, // IID535 + 0xd5, 0x18, 0x03, 0xd1, // IID536 + 0x4d, 0x23, 0xf5, // IID537 + 0xd5, 0x59, 0x0b, 0xe0, // IID538 + 0xd5, 0x58, 0x33, 0xee, // IID539 + 0xd5, 0x1d, 0x8b, 0xe3, // IID540 + 0xd5, 0xc8, 0xbc, 0xfa, // IID541 + 0xd5, 0xdd, 0xbd, 0xfc, // IID542 + 0xd5, 0xcd, 0xa3, 0xc8, // IID543 + 0xd5, 0x48, 0x87, 0xeb, // IID544 + 0xd5, 0x58, 0x85, 0xff, // IID545 + 0xd5, 0x1c, 0x01, 0x93, 0x5f, 0xc1, 0xf2, 0xe7, // IID546 + 0xd5, 0x6d, 0x21, 0x8c, 0x4b, 0x18, 0x94, 0x68, 0x87, // IID547 + 0xd5, 0x2e, 0x39, 0xac, 0xe3, 0x02, 0x21, 0xf7, 0x35, // IID548 + 0xd5, 0x49, 0x09, 0xa8, 0xef, 0xaf, 0xb9, 0xcb, // IID549 + 0xd5, 0x58, 0x31, 0x93, 0x23, 0xdd, 0xb4, 0xbf, // IID550 + 0xd5, 0x3e, 0x29, 0xb4, 0xdf, 0xba, 0xd9, 0x72, 0xbd, // IID551 + 0xd5, 0x4d, 0x89, 0xa4, 0x89, 0x9f, 0xe9, 0x9e, 0x8d, // IID552 + 0xd5, 0xb9, 0xc1, 0x9c, 0xa8, 0x90, 0xe9, 0x6b, 0x3a, // IID553 + 0xd5, 0x1a, 0x81, 0xa4, 0x16, 0xdd, 0x8b, 0xef, 0x07, 0x00, 0x00, 0x10, 0x00, // IID554 + 0xd5, 0x2b, 0x81, 0x84, 0x25, 0x4f, 0x76, 0xb8, 0x8a, 0x00, 0x00, 0x01, 0x00, // IID555 + 0x49, 0x81, 0xba, 0x26, 0x57, 0x2d, 0xf4, 0x00, 0x00, 0x00, 0x10, // IID556 + 0xd5, 0x1a, 0xc1, 0xbc, 0x77, 0xf5, 0xd9, 0x16, 0x6a, 0x04, // IID557 + 0xd5, 0x28, 0xc1, 0xa4, 0x69, 0x1e, 0xac, 0x66, 0x5f, 0x08, // IID558 + 0xd5, 0x28, 0x81, 0x9c, 0xf1, 0xb4, 0x6a, 0x73, 0xfb, 0x00, 0x00, 0x00, 0x10, // IID559 + 0xd5, 0x3a, 0xc1, 0xac, 0x35, 0x0b, 0x5b, 0x40, 0x0e, 0x08, // IID560 + 0xd5, 0x3a, 0x81, 0xac, 0xeb, 0xb5, 0xfb, 0x9d, 0x88, 0x00, 0x10, 0x00, 0x00, // IID561 + 0xd5, 0x1b, 0x83, 0xb4, 0x56, 0xdd, 0x7c, 0x86, 0xe6, 0x10, // IID562 + 0xd5, 0x2a, 0x81, 0x8c, 0xc2, 0x16, 0xb3, 0xd9, 0x18, 0x00, 0x10, 0x00, 0x00, // IID563 + 0x48, 0xc7, 0x83, 0xb3, 0xf8, 0xa7, 0xcf, 0x00, 0x01, 0x00, 0x00, // IID564 + 0xd5, 0x39, 0xf7, 0x84, 0xec, 0xc4, 0xfd, 0xa0, 0x65, 0x00, 0x00, 0x00, 0xf0, // IID565 + 0xd5, 0x69, 0x03, 0xbc, 0x13, 0xf4, 0x0e, 0xe5, 0xe2, // IID566 + 0xd5, 0x5a, 0x23, 0xb4, 0x62, 0x38, 0x1c, 0x5f, 0x1a, // IID567 + 0xd5, 0x79, 0x3b, 0xbc, 0x1e, 0x81, 0xd0, 0x6e, 0xc1, // IID568 + 0xf3, 0xd5, 0xcc, 0xbd, 0xa9, 0xe4, 0xfb, 0xe3, 0x12, // IID569 + 0xd5, 0x3c, 0x0b, 0xb4, 0xad, 0x42, 0x30, 0xd7, 0x00, // IID570 + 0xd5, 0x7e, 0x13, 0xbc, 0xb9, 0x12, 0xe9, 0xbd, 0x0a, // IID571 + 0xd5, 0xeb, 0xaf, 0xa4, 0x1d, 0xe1, 0x03, 0x24, 0xa7, // IID572 + 0xf3, 0xd5, 0x98, 0xb8, 0x9e, 0xdd, 0x93, 0x39, 0x8d, // IID573 + 0xd5, 0x4d, 0x1b, 0x91, 0x09, 0xba, 0x4a, 0x33, // IID574 + 0xd5, 0x2f, 0x2b, 0x8c, 0xf1, 0xfe, 0x9e, 0x65, 0xde, // IID575 + 0xf3, 0xd5, 0xdc, 0xbc, 0x8c, 0x24, 0x4f, 0x45, 0xce, 0xde, // IID576 + 0xd5, 0x79, 0x33, 0x84, 0x44, 0xb9, 0x83, 0xc4, 0x48, // IID577 + 0xd5, 0x6d, 0x8b, 0xb4, 0x01, 0xb1, 0x17, 0x73, 0xf7, // IID578 + 0xd5, 0x3f, 0x8d, 0x9c, 0xae, 0xd0, 0x8f, 0xeb, 0x3e, // IID579 + 0xf2, 0xd5, 0xdf, 0x2c, 0x94, 0xd5, 0x2e, 0x82, 0xf4, 0x3e, // IID580 + 0xd5, 0x7c, 0x87, 0xac, 0xa3, 0x47, 0xc2, 0xf0, 0xc0, // IID581 + 0xd5, 0x3d, 0x85, 0x84, 0x26, 0x17, 0x6a, 0xb5, 0x15, // IID582 + 0xd5, 0x19, 0x81, 0xc2, 0x00, 0x10, 0x00, 0x00, // IID583 + 0xd5, 0x18, 0x83, 0xe4, 0x10, // IID584 + 0xd5, 0x18, 0x81, 0xd7, 0x00, 0x00, 0x10, 0x00, // IID585 + 0x49, 0x81, 0xfc, 0x00, 0x10, 0x00, 0x00, // IID586 + 0x48, 0xc1, 0xd1, 0x04, // IID587 + 0x49, 0xd1, 0xde, // IID588 + 0xd5, 0x18, 0xc1, 0xc7, 0x02, // IID589 + 0x49, 0xc1, 0xcc, 0x04, // IID590 + 0x49, 0xc1, 0xfa, 0x04, // IID591 + 0xd5, 0x18, 0xc1, 0xe4, 0x04, // IID592 + 0x48, 0x81, 0xd9, 0x00, 0x00, 0x10, 0x00, // IID593 + 0xd5, 0x18, 0xc1, 0xe7, 0x10, // IID594 + 0xd5, 0x19, 0xc1, 0xeb, 0x02, // IID595 + 0x48, 0x81, 0xe9, 0x00, 0x00, 0x01, 0x00, // IID596 + 0x49, 0x81, 0xf1, 0x00, 0x00, 0x10, 0x00, // IID597 + 0xd5, 0x18, 0xc7, 0xc0, 0x00, 0x00, 0x01, 0x00, // IID598 + 0xd5, 0x19, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, // IID599 + 0xd5, 0x98, 0xba, 0xe2, 0x40, // IID600 + 0xd5, 0x19, 0xf7, 0xc5, 0x00, 0xf0, 0xff, 0xff, // IID601 + 0xd5, 0x19, 0x81, 0xce, 0x00, 0x00, 0x00, 0x04, // IID602 + 0xd5, 0x19, 0x81, 0xe9, 0x00, 0x00, 0x00, 0x10, // IID603 + 0xd5, 0xfe, 0x40, 0xb4, 0xb9, 0xf0, 0x92, 0xff, 0x47, // IID604 + 0xd5, 0xbf, 0x41, 0x8c, 0x60, 0xc0, 0x04, 0x49, 0x38, // IID605 + 0xd5, 0xfa, 0x42, 0xbc, 0xc7, 0x9a, 0xed, 0x80, 0xe6, // IID606 + 0xd5, 0xbf, 0x43, 0x8c, 0x35, 0xc8, 0x49, 0x5d, 0x2b, // IID607 + 0xd5, 0xca, 0x44, 0x84, 0x7b, 0x81, 0x93, 0x37, 0x22, // IID608 + 0x4d, 0x0f, 0x45, 0x83, 0xa0, 0x67, 0x9d, 0x04, // IID609 + 0xd5, 0xfc, 0x46, 0xa4, 0x80, 0x57, 0xe2, 0x6b, 0xa1, // IID610 + 0xd5, 0xda, 0x47, 0x9c, 0x02, 0x14, 0xaa, 0xa1, 0xf5, // IID611 + 0xd5, 0xfe, 0x48, 0xa4, 0x61, 0xf4, 0xdd, 0x9b, 0xcd, // IID612 + 0xd5, 0xef, 0x49, 0xbc, 0x7e, 0x5a, 0xbc, 0x01, 0x50, // IID613 + 0xd5, 0xb8, 0x4a, 0x9c, 0x8a, 0x87, 0xdc, 0x90, 0xd7, // IID614 + 0xd5, 0xd8, 0x4b, 0x8c, 0x24, 0xc8, 0x07, 0xb6, 0xaa, // IID615 + 0xd5, 0xef, 0x4c, 0xb4, 0x61, 0x0d, 0xf3, 0x4f, 0xda, // IID616 + 0xd5, 0xc9, 0x4d, 0x99, 0xd4, 0x0d, 0x54, 0xd5, // IID617 + 0x4a, 0x0f, 0x4e, 0x9c, 0x61, 0x34, 0x97, 0xd2, 0xbc, // IID618 + 0xd5, 0xa9, 0x4f, 0x9c, 0xcf, 0xa2, 0xa9, 0x68, 0xd4, // IID619 + 0xd5, 0x11, 0xff, 0xd0, // IID620 + 0x49, 0xf7, 0xf1, // IID621 + 0xd5, 0x19, 0xf7, 0xfc, // IID622 + 0x48, 0xf7, 0xea, // IID623 + 0xd5, 0x19, 0xf7, 0xe7, // IID624 + 0x49, 0xf7, 0xdc, // IID625 + 0x49, 0xf7, 0xd4, // IID626 + 0xd5, 0x19, 0xd3, 0xc0, // IID627 + 0xd5, 0x19, 0xd3, 0xcc, // IID628 + 0x49, 0xd3, 0xfb, // IID629 + 0xd5, 0x19, 0xd3, 0xe3, // IID630 + 0xd5, 0x18, 0xd3, 0xe7, // IID631 + 0xd5, 0x18, 0xd3, 0xe9, // IID632 + 0xd5, 0x18, 0xff, 0xc0, // IID633 + 0x49, 0xff, 0xcc, // IID634 + 0xd5, 0x18, 0x57, // IID635 + 0xd5, 0x19, 0x58, // IID636 + 0xd5, 0x12, 0xff, 0x94, 0x32, 0xce, 0x62, 0x9c, 0x99, // IID637 + 0xd5, 0x19, 0xf7, 0xa0, 0xdf, 0xdb, 0xf5, 0x99, // IID638 + 0xd5, 0x29, 0xf7, 0x9c, 0x16, 0x6e, 0x93, 0xf3, 0x40, // IID639 + 0x4b, 0xd3, 0xbc, 0x2a, 0x72, 0xcb, 0x04, 0x7d, // IID640 + 0xd5, 0x1a, 0xd3, 0xa4, 0xda, 0x24, 0x4b, 0x89, 0xde, // IID641 + 0x49, 0xd3, 0xac, 0x4d, 0x80, 0xaa, 0x96, 0x79, // IID642 + 0x49, 0xff, 0x86, 0x2a, 0xd0, 0xc2, 0x67, // IID643 + 0xd5, 0x3a, 0xff, 0x8c, 0x16, 0xc0, 0x62, 0x4f, 0x22, // IID644 + 0xd5, 0x19, 0x69, 0x94, 0x5f, 0x10, 0xbb, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x01, // IID645 + 0xd5, 0x59, 0x69, 0xef, 0x00, 0x10, 0x00, 0x00, // IID646 + 0xd5, 0xc8, 0xa4, 0xdb, 0x01, // IID647 + 0xd5, 0xc9, 0xac, 0xfb, 0x04, // IID648 + 0x62, 0xfc, 0x0c, 0x10, 0x8f, 0xc0, // IID649 + 0x62, 0xfc, 0xe4, 0x18, 0x8f, 0xc1, // IID650 + 0x62, 0xfc, 0x0c, 0x10, 0xff, 0xf4, // IID651 + 0x62, 0xd4, 0x84, 0x10, 0xff, 0xf0, // IID652 + 0xd5, 0xcf, 0xb6, 0xa4, 0x30, 0x7a, 0xe6, 0x9a, 0x46, // IID653 + 0xd5, 0xad, 0xb7, 0xb4, 0x90, 0xfe, 0x61, 0x96, 0xb7, // IID654 + 0xd5, 0xc8, 0xbe, 0xab, 0x95, 0x1f, 0x25, 0x9b, // IID655 + 0xd5, 0xd9, 0xbf, 0x9c, 0x9f, 0x19, 0x88, 0x31, 0x60, // IID656 + 0xd5, 0xcd, 0xb6, 0xf5, // IID657 + 0xd5, 0xdc, 0xb7, 0xf2, // IID658 + 0xd5, 0xc9, 0xbe, 0xdf, // IID659 + 0xd5, 0xd8, 0xbf, 0xe0, // IID660 + 0xd5, 0xcd, 0xb1, 0xa4, 0xdb, 0x9d, 0x47, 0xc3, 0x0f, // IID661 + 0x62, 0xfc, 0xfc, 0x08, 0xf7, 0xfc, // IID662 + 0x62, 0xdc, 0xfc, 0x0c, 0xf7, 0xfe, // IID663 + 0x62, 0xfc, 0xfc, 0x08, 0xf7, 0xf6, // IID664 + 0x62, 0xd4, 0xfc, 0x0c, 0xf7, 0xf3, // IID665 + 0x62, 0xf4, 0xfc, 0x08, 0xf7, 0xe9, // IID666 + 0x62, 0xdc, 0xfc, 0x0c, 0xf7, 0xec, // IID667 + 0x62, 0xfc, 0xfc, 0x08, 0xf7, 0xe5, // IID668 + 0x62, 0xd4, 0xfc, 0x0c, 0xf7, 0xe5, // IID669 + 0x62, 0x9c, 0xfc, 0x08, 0xf7, 0xa4, 0xba, 0x6e, 0xce, 0xa1, 0x70, // IID670 + 0x62, 0xdc, 0xf8, 0x0c, 0xf7, 0xa4, 0x58, 0xa4, 0x7a, 0x8f, 0xe9, // IID671 + 0x62, 0x5c, 0xfc, 0x08, 0xaf, 0xd3, // IID672 + 0xd5, 0x18, 0xf7, 0xe9, // IID673 + 0x62, 0xfc, 0xfc, 0x0c, 0xaf, 0xd6, // IID674 + 0x62, 0xf4, 0xfc, 0x0c, 0xaf, 0xdb, // IID675 + 0x62, 0x44, 0xfc, 0x08, 0xf5, 0xe7, // IID676 + 0x62, 0x54, 0xfc, 0x08, 0xf5, 0xff, // IID677 + 0x62, 0xd4, 0xfc, 0x0c, 0xf5, 0xdc, // IID678 + 0x62, 0xf4, 0xfc, 0x0c, 0xf5, 0xdb, // IID679 + 0x62, 0xd4, 0xac, 0x10, 0xf7, 0xdb, // IID680 + 0xd5, 0x18, 0xf7, 0xd9, // IID681 + 0x62, 0xdc, 0xec, 0x1c, 0xf7, 0xdf, // IID682 + 0x62, 0xdc, 0xa4, 0x14, 0xf7, 0xdb, // IID683 + 0x62, 0xd4, 0x84, 0x10, 0xf7, 0xd7, // IID684 + 0xd5, 0x18, 0xf7, 0xd5, // IID685 + 0x62, 0xdc, 0xfc, 0x08, 0x88, 0xd8, // IID686 + 0x62, 0x4c, 0xfc, 0x08, 0x88, 0xe4, // IID687 + 0x62, 0xcc, 0xfc, 0x0c, 0x88, 0xfb, // IID688 + 0x62, 0x54, 0xfc, 0x0c, 0x88, 0xed, // IID689 + 0x62, 0xdc, 0xb4, 0x10, 0xd3, 0xc4, // IID690 + 0xd5, 0x19, 0xd3, 0xc7, // IID691 + 0x62, 0xfc, 0xb4, 0x14, 0xd3, 0xc7, // IID692 + 0x62, 0xf4, 0xf4, 0x1c, 0xd3, 0xc1, // IID693 + 0x62, 0xd4, 0xcc, 0x10, 0xd3, 0xce, // IID694 + 0x49, 0xd3, 0xcf, // IID695 + 0x62, 0xdc, 0xa4, 0x1c, 0xd3, 0xce, // IID696 + 0x62, 0xdc, 0xbc, 0x14, 0xd3, 0xc8, // IID697 + 0x62, 0xfc, 0xac, 0x18, 0xd3, 0xe4, // IID698 + 0xd5, 0x18, 0xd3, 0xe3, // IID699 + 0x62, 0xdc, 0xf4, 0x14, 0xd3, 0xe1, // IID700 + 0x62, 0xd4, 0x94, 0x1c, 0xd3, 0xe5, // IID701 + 0x62, 0xdc, 0x84, 0x10, 0xd3, 0xfe, // IID702 + 0xd5, 0x18, 0xd3, 0xfa, // IID703 + 0x62, 0xdc, 0xb4, 0x14, 0xd3, 0xf9, // IID704 + 0x62, 0xdc, 0x9c, 0x14, 0xd3, 0xfc, // IID705 + 0x62, 0xdc, 0xcc, 0x10, 0xff, 0xcb, // IID706 + 0x49, 0xff, 0xcc, // IID707 + 0x62, 0xd4, 0xec, 0x14, 0xff, 0xcb, // IID708 + 0x62, 0xd4, 0xac, 0x1c, 0xff, 0xca, // IID709 + 0x62, 0xdc, 0xdc, 0x10, 0xff, 0xc0, // IID710 + 0xd5, 0x18, 0xff, 0xc2, // IID711 + 0x62, 0xd4, 0xe4, 0x1c, 0xff, 0xc3, // IID712 + 0x62, 0xdc, 0xac, 0x14, 0xff, 0xc2, // IID713 + 0x62, 0xd4, 0xd4, 0x10, 0xd3, 0xe0, // IID714 + 0x48, 0xd3, 0xe3, // IID715 + 0x62, 0xfc, 0xcc, 0x14, 0xd3, 0xe5, // IID716 + 0x62, 0xdc, 0xa4, 0x14, 0xd3, 0xe3, // IID717 + 0x62, 0xfc, 0x9c, 0x18, 0xd3, 0xe8, // IID718 + 0x49, 0xd3, 0xe8, // IID719 + 0x62, 0xd4, 0xec, 0x1c, 0xd3, 0xe9, // IID720 + 0x62, 0xfc, 0xdc, 0x14, 0xd3, 0xec, // IID721 + 0x62, 0x6c, 0xfc, 0x08, 0xf4, 0xfd, // IID722 + 0x62, 0xec, 0xfc, 0x08, 0xf4, 0xe4, // IID723 + 0x62, 0xfc, 0xfc, 0x0c, 0xf4, 0xc8, // IID724 + 0x62, 0x54, 0xfc, 0x0c, 0xf4, 0xf6, // IID725 + 0x62, 0x0c, 0xfc, 0x08, 0xaf, 0x9c, 0x49, 0x93, 0x23, 0x5a, 0x44, // IID726 + 0x62, 0xa4, 0xfc, 0x0c, 0xaf, 0xbc, 0x49, 0xf4, 0x10, 0x7f, 0xeb, // IID727 + 0x62, 0x7c, 0xf8, 0x08, 0xf5, 0xac, 0x4e, 0x6a, 0xe6, 0xf3, 0x8a, // IID728 + 0x62, 0x5c, 0xfc, 0x0c, 0xf5, 0xaf, 0xa7, 0x9d, 0xd4, 0xcb, // IID729 + 0x62, 0x9c, 0x84, 0x10, 0xf7, 0x9c, 0x68, 0xf2, 0x95, 0x4e, 0xda, // IID730 + 0x62, 0x94, 0x90, 0x1c, 0xf7, 0x9c, 0xe3, 0xab, 0x13, 0x00, 0x5c, // IID731 + 0x62, 0xfc, 0xfc, 0x08, 0x88, 0x94, 0x8a, 0x51, 0x15, 0xec, 0x9e, // IID732 + 0x62, 0x54, 0xfc, 0x0c, 0x88, 0x8a, 0x78, 0x2a, 0x58, 0xa3, // IID733 + 0x62, 0x9c, 0xf0, 0x10, 0xd3, 0xa4, 0x33, 0x2c, 0xda, 0x4c, 0x1b, // IID734 + 0x62, 0xd4, 0xb4, 0x14, 0xd3, 0xa4, 0x54, 0xce, 0x3b, 0x82, 0x62, // IID735 + 0x62, 0xd4, 0xb0, 0x18, 0xd3, 0xbc, 0x92, 0xb8, 0x85, 0xb5, 0xd9, // IID736 + 0x62, 0x94, 0xe0, 0x1c, 0xd3, 0xbc, 0x1e, 0x00, 0x1e, 0x29, 0x20, // IID737 + 0x62, 0x94, 0x9c, 0x18, 0xff, 0x8c, 0xb7, 0x45, 0x25, 0x08, 0xdf, // IID738 + 0x62, 0x94, 0xb0, 0x1c, 0xff, 0x8c, 0x4a, 0x84, 0x1d, 0x41, 0x21, // IID739 + 0x62, 0xb4, 0xd8, 0x10, 0xff, 0x84, 0xcb, 0x9e, 0x32, 0xf0, 0x02, // IID740 + 0x62, 0x94, 0xa8, 0x1c, 0xff, 0x84, 0x3c, 0x74, 0xa3, 0xaf, 0xc8, // IID741 + 0x62, 0xbc, 0xbc, 0x10, 0xd3, 0xac, 0xf7, 0x50, 0xa5, 0x18, 0x8e, // IID742 + 0x62, 0xbc, 0xb4, 0x14, 0xd3, 0xac, 0x53, 0x88, 0x0a, 0x7b, 0x50, // IID743 + 0x62, 0x64, 0xf8, 0x08, 0xf4, 0xbc, 0x03, 0x2a, 0x19, 0xd5, 0x19, // IID744 + 0x62, 0x3c, 0xf8, 0x0c, 0xf4, 0x8c, 0xa6, 0xcd, 0x07, 0x10, 0x21, // IID745 + 0x62, 0x6c, 0xfc, 0x10, 0x01, 0xa4, 0xdd, 0xe2, 0x05, 0xdc, 0xf7, // IID746 + 0x4e, 0x03, 0xbc, 0xc2, 0xa8, 0x5f, 0x46, 0xcb, // IID747 + 0x62, 0x14, 0xb8, 0x14, 0x01, 0xac, 0xc6, 0xd2, 0x59, 0xdc, 0x6c, // IID748 + 0x62, 0x9c, 0xe4, 0x1c, 0x01, 0x9c, 0xf3, 0xde, 0xe8, 0xc5, 0x36, // IID749 + 0x62, 0x0c, 0xd0, 0x10, 0x21, 0x9c, 0x5b, 0xed, 0xc4, 0xfd, 0xd3, // IID750 + 0xd5, 0x5e, 0x23, 0xbc, 0xbd, 0x4a, 0xc7, 0xf2, 0x6e, // IID751 + 0x62, 0x0c, 0x90, 0x1c, 0x21, 0x9c, 0x4f, 0xab, 0xe9, 0x4f, 0x73, // IID752 + 0x62, 0x14, 0x80, 0x1c, 0x21, 0xbc, 0xee, 0xaa, 0x7a, 0x19, 0xf9, // IID753 + 0x62, 0x0c, 0x9c, 0x18, 0x09, 0xa4, 0xfe, 0x9e, 0x3f, 0xa3, 0x3b, // IID754 + 0xd5, 0x4b, 0x0b, 0x84, 0x0c, 0xcd, 0xc4, 0x1f, 0xd7, // IID755 + 0x62, 0x04, 0xb8, 0x1c, 0x09, 0x9c, 0xc8, 0x6b, 0x42, 0xbd, 0xe1, // IID756 + 0x62, 0xdc, 0xf4, 0x1c, 0x09, 0x8c, 0x9b, 0xad, 0xbc, 0xe4, 0x7b, // IID757 + 0x62, 0xfc, 0xb8, 0x10, 0x29, 0x94, 0xb7, 0xd7, 0x27, 0x88, 0x6f, // IID758 + 0x62, 0xc4, 0xd4, 0x10, 0x29, 0xaa, 0x38, 0x47, 0xca, 0xf9, // IID759 + 0x62, 0x9c, 0xc0, 0x14, 0x29, 0x9c, 0xd3, 0xc0, 0xbc, 0x22, 0x09, // IID760 + 0x62, 0x2c, 0xb4, 0x14, 0x29, 0x8c, 0x3f, 0x54, 0x6b, 0x0b, 0xc7, // IID761 + 0x62, 0xd4, 0xa0, 0x18, 0x31, 0x8c, 0x9c, 0xe9, 0x13, 0x8e, 0xa4, // IID762 + 0xd5, 0x7c, 0x33, 0xa4, 0x13, 0x7e, 0x9b, 0x6b, 0x71, // IID763 + 0x62, 0xa4, 0xd0, 0x14, 0x31, 0x84, 0x29, 0xe2, 0xbb, 0x0f, 0xa5, // IID764 + 0x62, 0x3c, 0x98, 0x1c, 0x31, 0xa4, 0x14, 0xb1, 0x7f, 0x0b, 0x0e, // IID765 + 0x62, 0xf4, 0x8c, 0x10, 0x81, 0x81, 0x4f, 0x7b, 0x3b, 0x2d, 0x00, 0x00, 0x10, 0x00, // IID766 + 0x62, 0xbc, 0x8c, 0x1c, 0x81, 0x84, 0xbd, 0x18, 0x51, 0xdd, 0xed, 0x00, 0x10, 0x00, 0x00, // IID767 + 0x62, 0xbc, 0xc0, 0x10, 0x83, 0xa4, 0x3c, 0x96, 0xb2, 0x91, 0xf6, 0x10, // IID768 + 0x62, 0xf4, 0xac, 0x1c, 0x83, 0xa4, 0xd2, 0x7c, 0xf1, 0x75, 0x38, 0x01, // IID769 + 0x62, 0xa4, 0xf8, 0x08, 0x69, 0x8c, 0x89, 0x76, 0x10, 0xc7, 0x32, 0x00, 0x10, 0x00, 0x00, // IID770 + 0x62, 0xcc, 0xfc, 0x0c, 0x69, 0x9c, 0x9f, 0x0d, 0xa6, 0xad, 0x7b, 0x00, 0x00, 0x10, 0x00, // IID771 + 0x62, 0xfc, 0xb0, 0x10, 0x81, 0x8c, 0x7a, 0x44, 0x74, 0x14, 0x48, 0x00, 0x00, 0x00, 0x01, // IID772 + 0x62, 0x9c, 0x90, 0x14, 0x81, 0x8c, 0x5a, 0xa8, 0xc6, 0xee, 0xb4, 0x00, 0x00, 0x10, 0x00, // IID773 + 0x62, 0xfc, 0x84, 0x10, 0xc1, 0xa2, 0x8c, 0xc3, 0xef, 0xb9, 0x02, // IID774 + 0x62, 0x94, 0xb4, 0x14, 0xc1, 0xa4, 0x3a, 0xa4, 0x5d, 0x92, 0x48, 0x10, // IID775 + 0x62, 0xfc, 0xac, 0x10, 0xc1, 0xba, 0xbe, 0x3a, 0x5e, 0xa1, 0x08, // IID776 + 0x62, 0xd4, 0x98, 0x1c, 0xc1, 0xbc, 0xb2, 0x64, 0x82, 0x95, 0x5d, 0x08, // IID777 + 0x62, 0xfc, 0xe8, 0x18, 0xc1, 0xac, 0xa1, 0x23, 0xdd, 0x5a, 0x29, 0x10, // IID778 + 0x62, 0xbc, 0xe0, 0x1c, 0xc1, 0xac, 0x66, 0xcb, 0x29, 0x29, 0x78, 0x02, // IID779 + 0x62, 0xfc, 0xe4, 0x10, 0x83, 0xaf, 0x8e, 0xe2, 0x7e, 0xb6, 0x01, // IID780 + 0x62, 0xbc, 0xbc, 0x1c, 0x81, 0xac, 0xb3, 0x66, 0x51, 0xd4, 0xe4, 0x00, 0x00, 0x10, 0x00, // IID781 + 0x62, 0xb4, 0xe4, 0x10, 0x81, 0xb4, 0x11, 0xe9, 0x6e, 0xa6, 0x45, 0x00, 0x00, 0x10, 0x00, // IID782 + 0x62, 0x94, 0x98, 0x14, 0x83, 0xb4, 0x29, 0xec, 0x6c, 0x5e, 0xd7, 0x10, // IID783 + 0x62, 0xf4, 0xbc, 0x18, 0x81, 0xc1, 0x00, 0x00, 0x00, 0x01, // IID784 + 0x62, 0xd4, 0xfc, 0x18, 0x81, 0xc6, 0x00, 0x00, 0x00, 0x01, // IID785 + 0xd5, 0x18, 0x81, 0xc0, 0x00, 0x01, 0x00, 0x00, // IID786 + 0x62, 0xd4, 0xbc, 0x14, 0x81, 0xc1, 0x00, 0x10, 0x00, 0x00, // IID787 + 0x62, 0xfc, 0xfc, 0x1c, 0x81, 0xc2, 0x00, 0x10, 0x00, 0x00, // IID788 + 0x62, 0xd4, 0xbc, 0x1c, 0x83, 0xc0, 0x01, // IID789 + 0x62, 0xfc, 0x84, 0x18, 0x81, 0xe6, 0x00, 0x00, 0x10, 0x00, // IID790 + 0x62, 0xdc, 0xfc, 0x18, 0x81, 0xe2, 0x00, 0x00, 0x10, 0x00, // IID791 + 0x48, 0x81, 0xe2, 0x00, 0x10, 0x00, 0x00, // IID792 + 0x62, 0xfc, 0xec, 0x1c, 0x81, 0xe6, 0x00, 0x00, 0x00, 0x10, // IID793 + 0x62, 0xdc, 0xfc, 0x1c, 0x81, 0xe5, 0x00, 0x00, 0x00, 0x10, // IID794 + 0x62, 0xfc, 0xc4, 0x14, 0x81, 0xe7, 0x00, 0x00, 0x00, 0x01, // IID795 + 0x62, 0x54, 0xfc, 0x08, 0x69, 0xcd, 0x00, 0x00, 0x10, 0x00, // IID796 + 0x62, 0xfc, 0xfc, 0x08, 0x69, 0xc2, 0x00, 0x00, 0x10, 0x00, // IID797 + 0x62, 0xec, 0xfc, 0x08, 0x69, 0xc0, 0x00, 0x00, 0x10, 0x00, // IID798 + 0x62, 0xec, 0xfc, 0x0c, 0x6b, 0xcf, 0x01, // IID799 + 0x62, 0xd4, 0xfc, 0x0c, 0x6b, 0xc4, 0x01, // IID800 + 0x62, 0x54, 0xfc, 0x0c, 0x69, 0xd2, 0x00, 0x00, 0x00, 0x10, // IID801 + 0x62, 0xfc, 0xec, 0x18, 0x81, 0xcb, 0x00, 0x01, 0x00, 0x00, // IID802 + 0x62, 0xd4, 0xfc, 0x18, 0x81, 0xce, 0x00, 0x01, 0x00, 0x00, // IID803 + 0x49, 0x83, 0xcd, 0x01, // IID804 + 0x62, 0xdc, 0xb4, 0x14, 0x81, 0xcd, 0x00, 0x01, 0x00, 0x00, // IID805 + 0x62, 0xf4, 0xfc, 0x1c, 0x81, 0xca, 0x00, 0x01, 0x00, 0x00, // IID806 + 0x62, 0xfc, 0xfc, 0x14, 0x83, 0xc8, 0x10, // IID807 + 0x62, 0xfc, 0x94, 0x18, 0xc1, 0xd3, 0x04, // IID808 + 0x62, 0xd4, 0xfc, 0x18, 0xc1, 0xd4, 0x04, // IID809 + 0x49, 0xc1, 0xd1, 0x04, // IID810 + 0x62, 0xfc, 0x94, 0x18, 0xd1, 0xc0, // IID811 + 0x62, 0xdc, 0xfc, 0x18, 0xd1, 0xc7, // IID812 + 0xd5, 0x19, 0xc1, 0xc6, 0x08, // IID813 + 0x62, 0xfc, 0x8c, 0x14, 0xc1, 0xc4, 0x08, // IID814 + 0x62, 0xdc, 0xfc, 0x1c, 0xc1, 0xc7, 0x08, // IID815 + 0x62, 0xdc, 0x84, 0x14, 0xc1, 0xc7, 0x04, // IID816 + 0x62, 0xd4, 0xcc, 0x10, 0xc1, 0xca, 0x04, // IID817 + 0x62, 0xd4, 0xfc, 0x18, 0xc1, 0xcd, 0x04, // IID818 + 0xd5, 0x19, 0xc1, 0xc8, 0x10, // IID819 + 0x62, 0xfc, 0x94, 0x14, 0xc1, 0xce, 0x10, // IID820 + 0x62, 0xfc, 0xfc, 0x1c, 0xc1, 0xcc, 0x10, // IID821 + 0x62, 0xdc, 0xa4, 0x14, 0xc1, 0xcb, 0x04, // IID822 + 0x62, 0xfc, 0x84, 0x10, 0xc1, 0xe3, 0x02, // IID823 + 0x62, 0xfc, 0xfc, 0x18, 0xc1, 0xe4, 0x02, // IID824 + 0x49, 0xc1, 0xe3, 0x08, // IID825 + 0x62, 0xd4, 0xec, 0x1c, 0xd1, 0xe7, // IID826 + 0x62, 0xd4, 0xfc, 0x1c, 0xd1, 0xe2, // IID827 + 0x62, 0xdc, 0x94, 0x14, 0xc1, 0xe5, 0x04, // IID828 + 0x62, 0xfc, 0xdc, 0x10, 0xd1, 0xf8, // IID829 + 0x62, 0xfc, 0xfc, 0x18, 0xd1, 0xfd, // IID830 + 0xd5, 0x19, 0xc1, 0xfc, 0x08, // IID831 + 0x62, 0xf4, 0x8c, 0x14, 0xc1, 0xf9, 0x04, // IID832 + 0x62, 0xd4, 0xfc, 0x1c, 0xc1, 0xff, 0x04, // IID833 + 0x62, 0xf4, 0xf4, 0x1c, 0xc1, 0xf9, 0x04, // IID834 + 0x62, 0xdc, 0xec, 0x18, 0xc1, 0xe2, 0x04, // IID835 + 0x62, 0xdc, 0xfc, 0x18, 0xc1, 0xe2, 0x04, // IID836 + 0x49, 0xc1, 0xe0, 0x04, // IID837 + 0x62, 0xf4, 0xf4, 0x1c, 0xd1, 0xe1, // IID838 + 0x62, 0xf4, 0xfc, 0x1c, 0xd1, 0xe1, // IID839 + 0x62, 0xd4, 0x94, 0x1c, 0xc1, 0xe5, 0x02, // IID840 + 0x62, 0xdc, 0x8c, 0x18, 0xc1, 0xeb, 0x02, // IID841 + 0x62, 0xd4, 0xfc, 0x18, 0xc1, 0xeb, 0x02, // IID842 + 0x49, 0xc1, 0xe9, 0x10, // IID843 + 0x62, 0xdc, 0xec, 0x1c, 0xc1, 0xef, 0x02, // IID844 + 0x62, 0xd4, 0xfc, 0x1c, 0xc1, 0xee, 0x02, // IID845 + 0x62, 0xd4, 0x9c, 0x1c, 0xc1, 0xec, 0x08, // IID846 + 0x62, 0xdc, 0xac, 0x18, 0x83, 0xec, 0x01, // IID847 + 0x62, 0xd4, 0xfc, 0x18, 0x83, 0xe8, 0x01, // IID848 + 0x48, 0x81, 0xe9, 0x00, 0x00, 0x00, 0x01, // IID849 + 0x62, 0xf4, 0xec, 0x1c, 0x81, 0xeb, 0x00, 0x00, 0x00, 0x01, // IID850 + 0x62, 0xfc, 0xfc, 0x1c, 0x81, 0xea, 0x00, 0x00, 0x00, 0x01, // IID851 + 0x62, 0xdc, 0xa4, 0x14, 0x81, 0xeb, 0x00, 0x00, 0x01, 0x00, // IID852 + 0x62, 0xf4, 0x8c, 0x10, 0x81, 0xf1, 0x00, 0x10, 0x00, 0x00, // IID853 + 0x62, 0xfc, 0xfc, 0x18, 0x81, 0xf5, 0x00, 0x10, 0x00, 0x00, // IID854 + 0x48, 0x81, 0xf1, 0x00, 0x00, 0x00, 0x01, // IID855 + 0x62, 0xd4, 0xd4, 0x14, 0x83, 0xf4, 0x01, // IID856 + 0x62, 0xf4, 0xfc, 0x1c, 0x83, 0xf2, 0x01, // IID857 + 0x62, 0xf4, 0xe4, 0x1c, 0x81, 0xf3, 0x00, 0x00, 0x00, 0x01, // IID858 + 0x62, 0xf4, 0xa4, 0x18, 0x81, 0xca, 0x00, 0x00, 0x01, 0x00, // IID859 + 0x62, 0xd4, 0xfc, 0x18, 0x81, 0xce, 0x00, 0x00, 0x01, 0x00, // IID860 + 0x49, 0x81, 0xce, 0x00, 0x00, 0x04, 0x00, // IID861 + 0x62, 0xdc, 0xb4, 0x10, 0x81, 0xcd, 0x00, 0x00, 0x04, 0x00, // IID862 + 0x62, 0xfc, 0xfc, 0x18, 0x81, 0xcd, 0x00, 0x00, 0x04, 0x00, // IID863 + 0x49, 0x81, 0xcb, 0x00, 0x00, 0x00, 0x01, // IID864 + 0x62, 0xfc, 0x94, 0x10, 0x81, 0xeb, 0x00, 0x00, 0x00, 0x04, // IID865 + 0x62, 0xd4, 0xfc, 0x18, 0x81, 0xeb, 0x00, 0x00, 0x00, 0x04, // IID866 + 0xd5, 0x18, 0x81, 0xea, 0x00, 0x00, 0x00, 0x04, // IID867 + 0x62, 0xfc, 0x9c, 0x14, 0x81, 0xef, 0x00, 0x00, 0x40, 0x00, // IID868 + 0x62, 0xfc, 0xfc, 0x1c, 0x81, 0xed, 0x00, 0x00, 0x40, 0x00, // IID869 + 0x62, 0xfc, 0xfc, 0x14, 0x81, 0xe8, 0x00, 0x00, 0x00, 0x01, // IID870 + 0x62, 0x0c, 0xbc, 0x18, 0x03, 0x8c, 0x42, 0xef, 0x3d, 0x63, 0x10, // IID871 + 0xd5, 0x3c, 0x03, 0xac, 0x42, 0xf8, 0xba, 0xdf, 0x8b, // IID872 + 0x62, 0x44, 0xf4, 0x14, 0x03, 0x94, 0x24, 0xbf, 0x0a, 0xa8, 0x23, // IID873 + 0x62, 0x5c, 0xb0, 0x1c, 0x03, 0x8c, 0x1d, 0xae, 0x61, 0x61, 0xfd, // IID874 + 0x62, 0x24, 0xb0, 0x18, 0x23, 0xa4, 0x89, 0xaa, 0xff, 0x61, 0x42, // IID875 + 0xd5, 0x6e, 0x23, 0x9c, 0x22, 0x3f, 0x36, 0x42, 0xd9, // IID876 + 0x62, 0x7c, 0x8c, 0x1c, 0x23, 0x98, 0xdf, 0x0d, 0xba, 0x63, // IID877 + 0x62, 0x3c, 0xb8, 0x1c, 0x23, 0x84, 0x4e, 0xbc, 0x54, 0x49, 0xbc, // IID878 + 0x62, 0xdc, 0xe4, 0x10, 0x0b, 0x8c, 0x8b, 0x3a, 0x80, 0x97, 0x80, // IID879 + 0xd5, 0x6a, 0x0b, 0x9c, 0x53, 0x16, 0x48, 0x92, 0xb7, // IID880 + 0x62, 0x54, 0x88, 0x14, 0x0b, 0x94, 0xd6, 0x84, 0x48, 0x88, 0x14, // IID881 + 0x62, 0x4c, 0xa4, 0x14, 0x0b, 0x9d, 0x80, 0x71, 0x33, 0x20, // IID882 + 0x62, 0xec, 0xf4, 0x18, 0xaf, 0xac, 0x1d, 0x72, 0x77, 0xfc, 0xcc, // IID883 + 0xd5, 0x9b, 0xaf, 0x94, 0xcc, 0xbf, 0x08, 0x27, 0x85, // IID884 + 0x62, 0x2c, 0xbc, 0x1c, 0xaf, 0xac, 0x21, 0x6a, 0x39, 0x85, 0x6e, // IID885 + 0x62, 0xac, 0xfc, 0x14, 0xaf, 0x84, 0xd3, 0x00, 0x6d, 0xa6, 0xb6, // IID886 + 0x62, 0xc4, 0xd8, 0x10, 0x2b, 0x8c, 0x35, 0x4f, 0x9a, 0x21, 0x1d, // IID887 + 0xd5, 0x7c, 0x2b, 0x8c, 0xed, 0x39, 0x57, 0x97, 0x97, // IID888 + 0x62, 0x64, 0xd8, 0x14, 0x2b, 0x84, 0xa3, 0xa6, 0x9d, 0xc5, 0x32, // IID889 + 0x62, 0x54, 0xb8, 0x1c, 0x2b, 0x84, 0x0c, 0x31, 0xd2, 0x41, 0xd9, // IID890 + 0x62, 0xc4, 0xec, 0x18, 0x33, 0x99, 0x91, 0x3b, 0x90, 0x7d, // IID891 + 0xd5, 0x7f, 0x33, 0xa4, 0x9d, 0x6f, 0x1f, 0x09, 0x53, // IID892 + 0x62, 0xcc, 0xf4, 0x14, 0x33, 0x83, 0x07, 0x92, 0x6e, 0x7c, // IID893 + 0x62, 0x14, 0x80, 0x1c, 0x33, 0xbc, 0xc5, 0xa0, 0x86, 0x37, 0x8a, // IID894 + 0x62, 0xfc, 0xfc, 0x10, 0x03, 0xda, // IID895 + 0xd5, 0x5c, 0x03, 0xc2, // IID896 + 0x4d, 0x03, 0xcf, // IID897 + 0x62, 0x44, 0xe4, 0x14, 0x03, 0xd5, // IID898 + 0x62, 0x6c, 0x9c, 0x14, 0x03, 0xe6, // IID899 + 0x62, 0x7c, 0xcc, 0x14, 0x03, 0xde, // IID900 + 0x62, 0x54, 0xf5, 0x18, 0x66, 0xe5, // IID901 + 0x62, 0x44, 0xfd, 0x08, 0x66, 0xf4, // IID902 + 0x62, 0x7c, 0x9e, 0x10, 0x66, 0xf2, // IID903 + 0x62, 0x6c, 0xfe, 0x08, 0x66, 0xf3, // IID904 + 0x62, 0x54, 0xdc, 0x10, 0x23, 0xf6, // IID905 + 0xd5, 0x58, 0x23, 0xcf, // IID906 + 0xd5, 0x49, 0x23, 0xce, // IID907 + 0x62, 0xc4, 0xe4, 0x14, 0x23, 0xe7, // IID908 + 0x62, 0xd4, 0xe4, 0x1c, 0x23, 0xdd, // IID909 + 0x62, 0x6c, 0xcc, 0x14, 0x23, 0xf6, // IID910 + 0x62, 0x64, 0xf4, 0x10, 0xaf, 0xc1, // IID911 + 0xd5, 0xc9, 0xaf, 0xe8, // IID912 + 0xd5, 0xdc, 0xaf, 0xed, // IID913 + 0x62, 0x7c, 0xa4, 0x14, 0xaf, 0xef, // IID914 + 0x62, 0x44, 0xac, 0x14, 0xaf, 0xd0, // IID915 + 0x62, 0x7c, 0xcc, 0x14, 0xaf, 0xee, // IID916 + 0x62, 0xdc, 0xa4, 0x18, 0x0b, 0xd5, // IID917 + 0xd5, 0x19, 0x0b, 0xd7, // IID918 + 0xd5, 0x1d, 0x0b, 0xd5, // IID919 + 0x62, 0x64, 0xa4, 0x14, 0x0b, 0xe1, // IID920 + 0x62, 0x44, 0xb4, 0x14, 0x0b, 0xc9, // IID921 + 0x62, 0x74, 0xf4, 0x1c, 0x0b, 0xc1, // IID922 + 0x62, 0x7c, 0xf4, 0x18, 0x2b, 0xd0, // IID923 + 0xd5, 0x48, 0x2b, 0xc9, // IID924 + 0x62, 0xcc, 0x94, 0x1c, 0x2b, 0xe8, // IID925 + 0x62, 0x4c, 0x84, 0x14, 0x2b, 0xfc, // IID926 + 0xd5, 0x59, 0x33, 0xfc, // IID927 + 0x4d, 0x33, 0xd3, // IID928 + 0xd5, 0x58, 0x33, 0xda, // IID929 + 0x62, 0x74, 0x84, 0x14, 0x33, 0xca, // IID930 + 0x62, 0x54, 0x94, 0x1c, 0x33, 0xe9, // IID931 + 0x62, 0x74, 0xf4, 0x1c, 0x33, 0xd1, // IID932 + 0x62, 0xcc, 0x9c, 0x18, 0x24, 0xf0, 0x08, // IID933 + 0xd5, 0xdd, 0xa4, 0xc9, 0x08, // IID934 + 0x62, 0x7c, 0xd4, 0x14, 0x24, 0xfc, 0x08, // IID935 + 0x62, 0x7c, 0xd4, 0x14, 0x24, 0xd5, 0x08, // IID936 + 0xd5, 0x9c, 0xac, 0xc2, 0x02, // IID937 + 0xd5, 0xdd, 0xac, 0xea, 0x08, // IID938 + 0x62, 0xcc, 0x94, 0x14, 0x2c, 0xda, 0x02, // IID939 + 0x62, 0xd4, 0x9c, 0x1c, 0x2c, 0xcc, 0x04, // IID940 + 0x62, 0xec, 0xd4, 0x10, 0x40, 0xf7, // IID941 + 0x4d, 0x0f, 0x40, 0xcd, // IID942 + 0x62, 0xcc, 0xf4, 0x18, 0x41, 0xf8, // IID943 + 0xd5, 0xcc, 0x41, 0xe2, // IID944 + 0x62, 0x6c, 0x8c, 0x18, 0x42, 0xff, // IID945 + 0xd5, 0xdc, 0x42, 0xf7, // IID946 + 0x62, 0x6c, 0xac, 0x18, 0x43, 0xee, // IID947 + 0xd5, 0x99, 0x43, 0xda, // IID948 + 0x62, 0xc4, 0xc4, 0x10, 0x44, 0xed, // IID949 + 0xd5, 0x9c, 0x44, 0xd4, // IID950 + 0x62, 0x5c, 0xe4, 0x18, 0x45, 0xcd, // IID951 + 0xd5, 0xd9, 0x45, 0xc6, // IID952 + 0x62, 0xdc, 0x94, 0x18, 0x46, 0xcd, // IID953 + 0xd5, 0xcd, 0x46, 0xfd, // IID954 + 0x62, 0x5c, 0xa4, 0x10, 0x47, 0xce, // IID955 + 0xd5, 0xdc, 0x47, 0xd4, // IID956 + 0x62, 0x7c, 0xbc, 0x18, 0x48, 0xe6, // IID957 + 0xd5, 0xdc, 0x48, 0xf9, // IID958 + 0x62, 0xdc, 0x94, 0x10, 0x49, 0xc9, // IID959 + 0xd5, 0xc9, 0x49, 0xf6, // IID960 + 0x62, 0x44, 0xf4, 0x18, 0x4a, 0xd9, // IID961 + 0xd5, 0xc9, 0x4a, 0xf3, // IID962 + 0x62, 0xcc, 0x8c, 0x18, 0x4b, 0xd8, // IID963 + 0xd5, 0xdc, 0x4b, 0xc1, // IID964 + 0x62, 0xcc, 0xf4, 0x10, 0x4c, 0xde, // IID965 + 0xd5, 0xc9, 0x4c, 0xde, // IID966 + 0x62, 0x5c, 0xb4, 0x10, 0x4d, 0xdd, // IID967 + 0xd5, 0x9d, 0x4d, 0xe2, // IID968 + 0x62, 0xd4, 0xa4, 0x18, 0x4e, 0xda, // IID969 + 0xd5, 0x98, 0x4e, 0xd6, // IID970 + 0x62, 0x7c, 0x8c, 0x18, 0x4f, 0xff, // IID971 + 0xd5, 0x9d, 0x4f, 0xc0, // IID972 + 0x62, 0x04, 0xe4, 0x18, 0x40, 0xbc, 0xc2, 0x20, 0x9f, 0xc0, 0xce, // IID973 + 0xd5, 0xea, 0x40, 0xbc, 0x81, 0x9c, 0x1d, 0xf4, 0x17, // IID974 + 0x62, 0x7c, 0x84, 0x10, 0x41, 0x98, 0x42, 0x89, 0x01, 0x2c, // IID975 + 0xd5, 0xbc, 0x41, 0x9c, 0xe0, 0x55, 0x6a, 0x4b, 0x67, // IID976 + 0x62, 0x54, 0xb4, 0x18, 0x42, 0xac, 0x09, 0xdf, 0x11, 0x4a, 0x39, // IID977 + 0xd5, 0xec, 0x42, 0xb4, 0x72, 0x78, 0xd4, 0xc9, 0x93, // IID978 + 0x62, 0xdc, 0x94, 0x18, 0x43, 0x8c, 0xc8, 0x66, 0x0b, 0x50, 0x46, // IID979 + 0xd5, 0xfe, 0x43, 0x84, 0x4a, 0x7c, 0x3b, 0x28, 0x53, // IID980 + 0x62, 0x04, 0xc4, 0x10, 0x44, 0x8c, 0x0f, 0xe2, 0xfc, 0xfc, 0xa0, // IID981 + 0xd5, 0xfd, 0x44, 0x8c, 0x44, 0xec, 0x0a, 0x31, 0xac, // IID982 + 0x62, 0x0c, 0xe0, 0x18, 0x45, 0x8c, 0x88, 0x79, 0x53, 0x35, 0x99, // IID983 + 0xd5, 0xfb, 0x45, 0x84, 0xf3, 0x5d, 0x45, 0x7f, 0x79, // IID984 + 0x62, 0x6c, 0xb0, 0x10, 0x46, 0xb4, 0x52, 0xcd, 0xaa, 0x9d, 0x1c, // IID985 + 0xd5, 0xea, 0x46, 0xb4, 0x49, 0x57, 0x05, 0x34, 0xc2, // IID986 + 0x62, 0x4c, 0xbc, 0x10, 0x47, 0x91, 0xb5, 0x60, 0x70, 0x74, // IID987 + 0xd5, 0xbd, 0x47, 0x84, 0xe0, 0xf6, 0x85, 0xd2, 0x47, // IID988 + 0x62, 0x84, 0x9c, 0x18, 0x48, 0x84, 0x95, 0x14, 0xb2, 0xe5, 0x34, // IID989 + 0xd5, 0xa9, 0x48, 0x94, 0x1f, 0x4f, 0xc7, 0xae, 0xbf, // IID990 + 0x62, 0xa4, 0xec, 0x10, 0x49, 0xac, 0xab, 0x97, 0x91, 0xb1, 0x51, // IID991 + 0xd5, 0xef, 0x49, 0x84, 0xfb, 0x0a, 0x52, 0x01, 0x3e, // IID992 + 0x62, 0x04, 0x90, 0x10, 0x4a, 0x94, 0xca, 0x8e, 0xc7, 0x83, 0xa0, // IID993 + 0xd5, 0x9e, 0x4a, 0x9c, 0xd6, 0xad, 0xeb, 0x8c, 0x97, // IID994 + 0x62, 0x14, 0xd8, 0x10, 0x4b, 0xbc, 0x09, 0xaa, 0xed, 0x37, 0x4a, // IID995 + 0xd5, 0xed, 0x4b, 0xbc, 0x21, 0x86, 0x9f, 0x99, 0x4f, // IID996 + 0x62, 0x84, 0xe8, 0x10, 0x4c, 0xbc, 0x19, 0xe3, 0xbb, 0xef, 0xcb, // IID997 + 0xd5, 0xdb, 0x4c, 0x84, 0xd0, 0xee, 0x66, 0xed, 0x52, // IID998 + 0x62, 0xe4, 0xa4, 0x18, 0x4d, 0x91, 0x63, 0x91, 0xe0, 0x1d, // IID999 + 0xd5, 0xbd, 0x4d, 0xb4, 0x78, 0xda, 0xb4, 0xf3, 0x5d, // IID1000 + 0x62, 0x5c, 0x80, 0x18, 0x4e, 0xb4, 0x66, 0x76, 0xb9, 0x9a, 0x5c, // IID1001 + 0xd5, 0xfe, 0x4e, 0x94, 0x9a, 0xd7, 0x3c, 0x27, 0xff, // IID1002 + 0x62, 0x5c, 0x90, 0x10, 0x4f, 0x8c, 0xe6, 0x73, 0x30, 0x56, 0xc8, // IID1003 + 0xd5, 0xc9, 0x4f, 0xa4, 0x58, 0xef, 0x7d, 0xdc, 0x1b, // IID1004 #endif // _LP64 }; @@ -2196,19 +2364,19 @@ 15, // IID265 15, // IID266 11, // IID267 - 11, // IID268 + 9, // IID268 11, // IID269 11, // IID270 11, // IID271 - 11, // IID272 + 9, // IID272 11, // IID273 10, // IID274 11, // IID275 - 11, // IID276 + 9, // IID276 11, // IID277 11, // IID278 11, // IID279 - 11, // IID280 + 9, // IID280 10, // IID281 11, // IID282 10, // IID283 @@ -2216,645 +2384,729 @@ 11, // IID285 10, // IID286 11, // IID287 - 10, // IID288 + 8, // IID288 11, // IID289 11, // IID290 - 10, // IID291 - 10, // IID292 - 8, // IID293 - 7, // IID294 + 11, // IID291 + 9, // IID292 + 11, // IID293 + 11, // IID294 7, // IID295 - 10, // IID296 - 10, // IID297 + 7, // IID296 + 8, // IID297 10, // IID298 - 8, // IID299 + 10, // IID299 10, // IID300 - 10, // IID301 + 4, // IID301 7, // IID302 - 10, // IID303 -#endif // _LP64 - 10, // IID304 -#ifdef _LP64 - 10, // IID305 - 10, // IID306 + 5, // IID303 + 7, // IID304 + 7, // IID305 + 7, // IID306 10, // IID307 - 7, // IID308 + 10, // IID308 10, // IID309 - 10, // IID310 - 8, // IID311 - 7, // IID312 + 7, // IID310 + 7, // IID311 + 10, // IID312 7, // IID313 - 10, // IID314 - 6, // IID315 - 6, // IID316 - 4, // IID317 - 7, // IID318 + 7, // IID314 + 8, // IID315 + 7, // IID316 + 7, // IID317 #endif // _LP64 - 7, // IID319 + 10, // IID318 #ifdef _LP64 - 5, // IID320 - 7, // IID321 + 5, // IID319 + 7, // IID320 + 5, // IID321 7, // IID322 7, // IID323 - 7, // IID324 -#endif // _LP64 + 4, // IID324 7, // IID325 -#ifdef _LP64 - 4, // IID326 - 7, // IID327 + 7, // IID326 + 6, // IID327 7, // IID328 7, // IID329 - 7, // IID330 + 5, // IID330 7, // IID331 - 5, // IID332 + 7, // IID332 7, // IID333 7, // IID334 7, // IID335 - 7, // IID336 + 5, // IID336 7, // IID337 - 4, // IID338 + 7, // IID338 7, // IID339 - 7, // IID340 - 7, // IID341 - 7, // IID342 + 6, // IID340 + 6, // IID341 + 5, // IID342 7, // IID343 - 4, // IID344 + 7, // IID344 7, // IID345 7, // IID346 7, // IID347 - 7, // IID348 + 4, // IID348 7, // IID349 - 5, // IID350 + 7, // IID350 6, // IID351 - 6, // IID352 + 7, // IID352 7, // IID353 - 10, // IID354 - 10, // IID355 - 8, // IID356 - 10, // IID357 + 5, // IID354 + 7, // IID355 + 7, // IID356 + 7, // IID357 10, // IID358 10, // IID359 - 10, // IID360 + 8, // IID360 10, // IID361 -#endif // _LP64 - 6, // IID362 -#ifdef _LP64 - 10, // IID363 + 10, // IID362 + 7, // IID363 10, // IID364 10, // IID365 - 10, // IID366 - 10, // IID367 - 8, // IID368 - 10, // IID369 + 5, // IID366 + 7, // IID367 +#endif // _LP64 + 7, // IID368 +#ifdef _LP64 + 7, // IID369 10, // IID370 10, // IID371 - 10, // IID372 + 8, // IID372 10, // IID373 - 11, // IID374 - 11, // IID375 + 10, // IID374 + 10, // IID375 11, // IID376 - 11, // IID377 + 9, // IID377 11, // IID378 10, // IID379 11, // IID380 - 11, // IID381 + 9, // IID381 11, // IID382 11, // IID383 11, // IID384 - 11, // IID385 + 9, // IID385 11, // IID386 11, // IID387 - 6, // IID388 - 4, // IID389 - 6, // IID390 - 6, // IID391 - 6, // IID392 - 3, // IID393 - 6, // IID394 - 6, // IID395 - 6, // IID396 - 4, // IID397 - 6, // IID398 - 6, // IID399 - 6, // IID400 - 5, // IID401 - 6, // IID402 - 6, // IID403 - 6, // IID404 - 4, // IID405 - 6, // IID406 - 6, // IID407 + 10, // IID388 + 8, // IID389 + 11, // IID390 + 11, // IID391 + 11, // IID392 + 9, // IID393 + 10, // IID394 + 11, // IID395 + 11, // IID396 + 9, // IID397 + 11, // IID398 + 11, // IID399 + 11, // IID400 + 9, // IID401 + 11, // IID402 + 11, // IID403 + 11, // IID404 + 10, // IID405 + 10, // IID406 + 11, // IID407 6, // IID408 4, // IID409 - 6, // IID410 + 4, // IID410 6, // IID411 6, // IID412 - 4, // IID413 + 6, // IID413 6, // IID414 - 6, // IID415 - 6, // IID416 - 4, // IID417 + 4, // IID415 + 3, // IID416 + 6, // IID417 6, // IID418 6, // IID419 6, // IID420 4, // IID421 - 6, // IID422 + 4, // IID422 6, // IID423 - 7, // IID424 - 5, // IID425 - 7, // IID426 - 7, // IID427 - 7, // IID428 - 5, // IID429 - 7, // IID430 - 7, // IID431 + 6, // IID424 + 6, // IID425 + 6, // IID426 + 5, // IID427 + 4, // IID428 + 6, // IID429 + 6, // IID430 +#endif // _LP64 + 6, // IID431 +#ifdef _LP64 6, // IID432 4, // IID433 - 6, // IID434 - 4, // IID435 + 4, // IID434 + 6, // IID435 6, // IID436 - 4, // IID437 + 6, // IID437 6, // IID438 4, // IID439 6, // IID440 - 4, // IID441 + 6, // IID441 6, // IID442 4, // IID443 6, // IID444 - 4, // IID445 + 6, // IID445 6, // IID446 - 4, // IID447 + 3, // IID447 6, // IID448 - 4, // IID449 + 6, // IID449 6, // IID450 4, // IID451 4, // IID452 - 4, // IID453 + 6, // IID453 6, // IID454 - 4, // IID455 - 6, // IID456 - 4, // IID457 - 6, // IID458 - 4, // IID459 - 6, // IID460 - 4, // IID461 - 6, // IID462 - 4, // IID463 - 10, // IID464 - 11, // IID465 - 11, // IID466 - 11, // IID467 - 10, // IID468 - 11, // IID469 - 11, // IID470 - 11, // IID471 - 11, // IID472 - 11, // IID473 - 11, // IID474 - 11, // IID475 - 11, // IID476 - 11, // IID477 - 11, // IID478 - 11, // IID479 - 4, // IID480 + 6, // IID455 + 7, // IID456 + 5, // IID457 + 7, // IID458 + 7, // IID459 + 7, // IID460 + 5, // IID461 + 7, // IID462 + 7, // IID463 + 6, // IID464 + 4, // IID465 + 6, // IID466 + 4, // IID467 + 6, // IID468 + 4, // IID469 + 6, // IID470 + 4, // IID471 + 6, // IID472 + 4, // IID473 + 6, // IID474 + 4, // IID475 + 6, // IID476 + 4, // IID477 + 6, // IID478 + 4, // IID479 + 6, // IID480 4, // IID481 - 4, // IID482 - 5, // IID483 - 4, // IID484 + 6, // IID482 + 4, // IID483 + 6, // IID484 4, // IID485 - 5, // IID486 - 5, // IID487 - 4, // IID488 + 6, // IID486 + 4, // IID487 + 6, // IID488 4, // IID489 - 4, // IID490 - 3, // IID491 - 4, // IID492 + 6, // IID490 + 4, // IID491 + 6, // IID492 4, // IID493 - 4, // IID494 + 6, // IID494 4, // IID495 - 4, // IID496 - 4, // IID497 - 9, // IID498 + 11, // IID496 + 9, // IID497 + 11, // IID498 9, // IID499 - 9, // IID500 + 11, // IID500 9, // IID501 - 9, // IID502 - 9, // IID503 - 9, // IID504 + 11, // IID502 + 8, // IID503 + 11, // IID504 9, // IID505 - 12, // IID506 - 12, // IID507 + 11, // IID506 + 8, // IID507 11, // IID508 - 8, // IID509 - 9, // IID510 - 13, // IID511 - 10, // IID512 - 12, // IID513 - 10, // IID514 - 10, // IID515 - 13, // IID516 - 12, // IID517 - 9, // IID518 + 9, // IID509 + 10, // IID510 + 9, // IID511 + 11, // IID512 + 9, // IID513 + 9, // IID514 + 9, // IID515 + 11, // IID516 + 9, // IID517 + 11, // IID518 9, // IID519 - 9, // IID520 + 11, // IID520 9, // IID521 - 9, // IID522 - 7, // IID523 - 9, // IID524 + 10, // IID522 + 9, // IID523 + 10, // IID524 9, // IID525 - 9, // IID526 + 11, // IID526 9, // IID527 - 10, // IID528 - 9, // IID529 - 9, // IID530 - 7, // IID531 - 10, // IID532 - 9, // IID533 - 9, // IID534 + 4, // IID528 + 3, // IID529 + 4, // IID530 + 5, // IID531 + 3, // IID532 + 4, // IID533 + 5, // IID534 5, // IID535 - 5, // IID536 - 8, // IID537 - 8, // IID538 + 4, // IID536 + 3, // IID537 + 4, // IID538 4, // IID539 4, // IID540 - 5, // IID541 - 5, // IID542 + 4, // IID541 + 4, // IID542 4, // IID543 4, // IID544 - 7, // IID545 - 4, // IID546 - 3, // IID547 - 4, // IID548 + 4, // IID545 + 8, // IID546 + 9, // IID547 + 9, // IID548 8, // IID549 8, // IID550 - 10, // IID551 - 5, // IID552 - 8, // IID553 - 8, // IID554 - 7, // IID555 - 9, // IID556 - 8, // IID557 - 9, // IID558 - 9, // IID559 - 9, // IID560 - 9, // IID561 - 8, // IID562 - 9, // IID563 - 9, // IID564 - 9, // IID565 + 9, // IID551 + 9, // IID552 + 9, // IID553 + 13, // IID554 + 13, // IID555 + 11, // IID556 + 10, // IID557 + 10, // IID558 + 13, // IID559 + 10, // IID560 + 13, // IID561 + 10, // IID562 + 13, // IID563 + 11, // IID564 + 13, // IID565 9, // IID566 9, // IID567 9, // IID568 9, // IID569 9, // IID570 9, // IID571 - 4, // IID572 - 4, // IID573 - 4, // IID574 - 3, // IID575 - 3, // IID576 - 4, // IID577 - 4, // IID578 - 3, // IID579 - 4, // IID580 - 3, // IID581 - 4, // IID582 - 4, // IID583 - 4, // IID584 - 3, // IID585 - 3, // IID586 - 3, // IID587 + 9, // IID572 + 9, // IID573 + 8, // IID574 + 9, // IID575 + 10, // IID576 + 9, // IID577 + 9, // IID578 + 9, // IID579 + 10, // IID580 + 9, // IID581 + 9, // IID582 + 8, // IID583 + 5, // IID584 + 8, // IID585 + 7, // IID586 + 4, // IID587 3, // IID588 - 9, // IID589 - 9, // IID590 - 9, // IID591 - 9, // IID592 - 9, // IID593 - 9, // IID594 - 9, // IID595 - 9, // IID596 - 13, // IID597 + 5, // IID589 + 4, // IID590 + 4, // IID591 + 5, // IID592 + 7, // IID593 + 5, // IID594 + 5, // IID595 + 7, // IID596 + 7, // IID597 8, // IID598 - 5, // IID599 + 11, // IID599 5, // IID600 - 6, // IID601 - 6, // IID602 - 6, // IID603 - 6, // IID604 + 8, // IID601 + 8, // IID602 + 8, // IID603 + 9, // IID604 9, // IID605 9, // IID606 9, // IID607 9, // IID608 - 4, // IID609 - 4, // IID610 - 4, // IID611 - 4, // IID612 + 8, // IID609 + 9, // IID610 + 9, // IID611 + 9, // IID612 9, // IID613 - 6, // IID614 - 6, // IID615 - 6, // IID616 - 6, // IID617 - 6, // IID618 - 6, // IID619 - 6, // IID620 - 6, // IID621 - 11, // IID622 - 11, // IID623 - 6, // IID624 - 4, // IID625 - 6, // IID626 - 6, // IID627 - 6, // IID628 - 6, // IID629 - 6, // IID630 - 6, // IID631 - 6, // IID632 + 9, // IID614 + 9, // IID615 + 9, // IID616 + 8, // IID617 + 9, // IID618 + 9, // IID619 + 4, // IID620 + 3, // IID621 + 4, // IID622 + 3, // IID623 + 4, // IID624 + 3, // IID625 + 3, // IID626 + 4, // IID627 + 4, // IID628 + 3, // IID629 + 4, // IID630 + 4, // IID631 + 4, // IID632 4, // IID633 - 6, // IID634 - 6, // IID635 - 6, // IID636 - 4, // IID637 - 6, // IID638 - 6, // IID639 - 6, // IID640 - 6, // IID641 - 6, // IID642 - 4, // IID643 - 6, // IID644 - 6, // IID645 - 6, // IID646 - 4, // IID647 - 6, // IID648 + 3, // IID634 + 3, // IID635 + 3, // IID636 + 9, // IID637 + 8, // IID638 + 9, // IID639 + 8, // IID640 + 9, // IID641 + 8, // IID642 + 7, // IID643 + 9, // IID644 + 13, // IID645 + 8, // IID646 + 5, // IID647 + 5, // IID648 6, // IID649 6, // IID650 - 3, // IID651 + 6, // IID651 6, // IID652 - 6, // IID653 - 6, // IID654 - 3, // IID655 - 6, // IID656 - 6, // IID657 - 6, // IID658 - 3, // IID659 - 6, // IID660 - 6, // IID661 - 4, // IID662 - 4, // IID663 + 9, // IID653 + 9, // IID654 + 8, // IID655 + 9, // IID656 + 4, // IID657 + 4, // IID658 + 4, // IID659 + 4, // IID660 + 9, // IID661 + 6, // IID662 + 6, // IID663 6, // IID664 6, // IID665 6, // IID666 - 3, // IID667 + 6, // IID667 6, // IID668 6, // IID669 - 6, // IID670 - 4, // IID671 + 11, // IID670 + 11, // IID671 6, // IID672 - 6, // IID673 + 4, // IID673 6, // IID674 6, // IID675 6, // IID676 6, // IID677 - 10, // IID678 - 10, // IID679 - 11, // IID680 - 11, // IID681 - 11, // IID682 - 11, // IID683 - 11, // IID684 - 10, // IID685 - 10, // IID686 - 11, // IID687 - 11, // IID688 - 11, // IID689 - 11, // IID690 - 11, // IID691 - 11, // IID692 - 11, // IID693 - 11, // IID694 - 10, // IID695 - 11, // IID696 - 11, // IID697 - 10, // IID698 - 11, // IID699 - 11, // IID700 - 10, // IID701 - 11, // IID702 - 11, // IID703 - 11, // IID704 - 10, // IID705 - 11, // IID706 - 11, // IID707 - 11, // IID708 - 11, // IID709 - 11, // IID710 - 11, // IID711 - 11, // IID712 - 11, // IID713 - 10, // IID714 - 11, // IID715 - 11, // IID716 - 10, // IID717 - 15, // IID718 - 12, // IID719 - 12, // IID720 - 15, // IID721 - 15, // IID722 - 12, // IID723 - 12, // IID724 - 15, // IID725 - 12, // IID726 - 12, // IID727 - 12, // IID728 - 11, // IID729 - 12, // IID730 - 12, // IID731 - 14, // IID732 - 15, // IID733 - 15, // IID734 - 12, // IID735 - 7, // IID736 - 7, // IID737 - 8, // IID738 - 10, // IID739 - 10, // IID740 - 10, // IID741 - 10, // IID742 - 10, // IID743 - 8, // IID744 - 10, // IID745 - 10, // IID746 - 10, // IID747 - 10, // IID748 - 10, // IID749 - 10, // IID750 - 10, // IID751 - 10, // IID752 - 10, // IID753 - 10, // IID754 - 10, // IID755 - 8, // IID756 - 10, // IID757 - 10, // IID758 + 6, // IID678 + 6, // IID679 + 6, // IID680 + 4, // IID681 + 6, // IID682 + 6, // IID683 + 6, // IID684 + 4, // IID685 + 6, // IID686 + 6, // IID687 + 6, // IID688 + 6, // IID689 + 6, // IID690 + 4, // IID691 + 6, // IID692 + 6, // IID693 + 6, // IID694 + 3, // IID695 + 6, // IID696 + 6, // IID697 + 6, // IID698 + 4, // IID699 + 6, // IID700 + 6, // IID701 + 6, // IID702 + 4, // IID703 + 6, // IID704 + 6, // IID705 + 6, // IID706 + 3, // IID707 + 6, // IID708 + 6, // IID709 + 6, // IID710 + 4, // IID711 + 6, // IID712 + 6, // IID713 + 6, // IID714 + 3, // IID715 + 6, // IID716 + 6, // IID717 + 6, // IID718 + 3, // IID719 + 6, // IID720 + 6, // IID721 + 6, // IID722 + 6, // IID723 + 6, // IID724 + 6, // IID725 + 11, // IID726 + 11, // IID727 + 11, // IID728 + 10, // IID729 + 11, // IID730 + 11, // IID731 + 11, // IID732 + 10, // IID733 + 11, // IID734 + 11, // IID735 + 11, // IID736 + 11, // IID737 + 11, // IID738 + 11, // IID739 + 11, // IID740 + 11, // IID741 + 11, // IID742 + 11, // IID743 + 11, // IID744 + 11, // IID745 + 11, // IID746 + 8, // IID747 + 11, // IID748 + 11, // IID749 + 11, // IID750 + 9, // IID751 + 11, // IID752 + 11, // IID753 + 11, // IID754 + 9, // IID755 + 11, // IID756 + 11, // IID757 + 11, // IID758 10, // IID759 - 7, // IID760 - 7, // IID761 - 4, // IID762 - 7, // IID763 - 7, // IID764 - 4, // IID765 - 6, // IID766 - 6, // IID767 - 7, // IID768 - 7, // IID769 - 7, // IID770 - 5, // IID771 - 6, // IID772 - 6, // IID773 - 6, // IID774 - 7, // IID775 - 7, // IID776 - 5, // IID777 - 7, // IID778 - 7, // IID779 - 6, // IID780 - 7, // IID781 - 7, // IID782 - 4, // IID783 - 6, // IID784 - 6, // IID785 - 7, // IID786 - 7, // IID787 - 7, // IID788 - 4, // IID789 - 7, // IID790 - 7, // IID791 + 11, // IID760 + 11, // IID761 + 11, // IID762 + 9, // IID763 + 11, // IID764 + 11, // IID765 + 14, // IID766 + 15, // IID767 + 12, // IID768 + 12, // IID769 + 15, // IID770 + 15, // IID771 + 15, // IID772 + 15, // IID773 + 11, // IID774 + 12, // IID775 + 11, // IID776 + 12, // IID777 + 12, // IID778 + 12, // IID779 + 11, // IID780 + 15, // IID781 + 15, // IID782 + 12, // IID783 + 10, // IID784 + 10, // IID785 + 8, // IID786 + 10, // IID787 + 10, // IID788 + 7, // IID789 + 10, // IID790 + 10, // IID791 7, // IID792 - 7, // IID793 - 7, // IID794 - 4, // IID795 - 7, // IID796 - 7, // IID797 - 6, // IID798 - 10, // IID799 - 10, // IID800 - 5, // IID801 - 7, // IID802 - 7, // IID803 - 10, // IID804 + 10, // IID793 + 10, // IID794 + 10, // IID795 + 10, // IID796 + 10, // IID797 + 10, // IID798 + 7, // IID799 + 7, // IID800 + 10, // IID801 + 10, // IID802 + 10, // IID803 + 4, // IID804 10, // IID805 10, // IID806 - 8, // IID807 - 10, // IID808 - 10, // IID809 - 10, // IID810 - 7, // IID811 - 10, // IID812 - 8, // IID813 - 10, // IID814 - 10, // IID815 - 8, // IID816 - 10, // IID817 - 10, // IID818 - 8, // IID819 - 10, // IID820 - 10, // IID821 - 10, // IID822 - 11, // IID823 - 11, // IID824 - 10, // IID825 - 11, // IID826 - 11, // IID827 - 11, // IID828 - 11, // IID829 - 11, // IID830 - 10, // IID831 - 11, // IID832 - 11, // IID833 - 10, // IID834 - 6, // IID835 - 3, // IID836 - 6, // IID837 + 7, // IID807 + 7, // IID808 + 7, // IID809 + 4, // IID810 + 6, // IID811 + 6, // IID812 + 5, // IID813 + 7, // IID814 + 7, // IID815 + 7, // IID816 + 7, // IID817 + 7, // IID818 + 5, // IID819 + 7, // IID820 + 7, // IID821 + 7, // IID822 + 7, // IID823 + 7, // IID824 + 4, // IID825 + 6, // IID826 + 6, // IID827 + 7, // IID828 + 6, // IID829 + 6, // IID830 + 5, // IID831 + 7, // IID832 + 7, // IID833 + 7, // IID834 + 7, // IID835 + 7, // IID836 + 4, // IID837 6, // IID838 6, // IID839 - 6, // IID840 - 6, // IID841 - 6, // IID842 - 6, // IID843 - 4, // IID844 - 6, // IID845 - 6, // IID846 - 6, // IID847 - 4, // IID848 - 6, // IID849 - 6, // IID850 - 6, // IID851 - 3, // IID852 - 6, // IID853 - 6, // IID854 - 6, // IID855 - 3, // IID856 - 6, // IID857 - 6, // IID858 - 6, // IID859 - 4, // IID860 - 6, // IID861 - 6, // IID862 - 7, // IID863 - 5, // IID864 - 7, // IID865 - 7, // IID866 - 7, // IID867 - 5, // IID868 - 7, // IID869 - 7, // IID870 - 6, // IID871 - 4, // IID872 - 6, // IID873 - 4, // IID874 - 6, // IID875 - 4, // IID876 - 6, // IID877 - 4, // IID878 - 6, // IID879 - 4, // IID880 - 6, // IID881 - 4, // IID882 - 6, // IID883 - 4, // IID884 - 6, // IID885 - 4, // IID886 - 6, // IID887 - 4, // IID888 - 6, // IID889 - 4, // IID890 - 6, // IID891 - 4, // IID892 - 6, // IID893 - 4, // IID894 + 7, // IID840 + 7, // IID841 + 7, // IID842 + 4, // IID843 + 7, // IID844 + 7, // IID845 + 7, // IID846 + 7, // IID847 + 7, // IID848 + 7, // IID849 + 10, // IID850 + 10, // IID851 + 10, // IID852 + 10, // IID853 + 10, // IID854 + 7, // IID855 + 7, // IID856 + 7, // IID857 + 10, // IID858 + 10, // IID859 + 10, // IID860 + 7, // IID861 + 10, // IID862 + 10, // IID863 + 7, // IID864 + 10, // IID865 + 10, // IID866 + 8, // IID867 + 10, // IID868 + 10, // IID869 + 10, // IID870 + 11, // IID871 + 9, // IID872 + 11, // IID873 + 11, // IID874 + 11, // IID875 + 9, // IID876 + 10, // IID877 + 11, // IID878 + 11, // IID879 + 9, // IID880 + 11, // IID881 + 10, // IID882 + 11, // IID883 + 9, // IID884 + 11, // IID885 + 11, // IID886 + 11, // IID887 + 9, // IID888 + 11, // IID889 + 11, // IID890 + 10, // IID891 + 9, // IID892 + 10, // IID893 + 11, // IID894 6, // IID895 4, // IID896 - 6, // IID897 - 4, // IID898 + 3, // IID897 + 6, // IID898 6, // IID899 - 4, // IID900 + 6, // IID900 6, // IID901 - 4, // IID902 - 11, // IID903 - 11, // IID904 - 11, // IID905 - 10, // IID906 - 11, // IID907 - 9, // IID908 - 11, // IID909 - 11, // IID910 - 11, // IID911 - 10, // IID912 - 11, // IID913 - 11, // IID914 - 11, // IID915 - 11, // IID916 - 11, // IID917 - 11, // IID918 + 6, // IID902 + 6, // IID903 + 6, // IID904 + 6, // IID905 + 4, // IID906 + 4, // IID907 + 6, // IID908 + 6, // IID909 + 6, // IID910 + 6, // IID911 + 4, // IID912 + 4, // IID913 + 6, // IID914 + 6, // IID915 + 6, // IID916 + 6, // IID917 + 4, // IID918 + 4, // IID919 + 6, // IID920 + 6, // IID921 + 6, // IID922 + 6, // IID923 + 4, // IID924 + 6, // IID925 + 6, // IID926 + 4, // IID927 + 3, // IID928 + 4, // IID929 + 6, // IID930 + 6, // IID931 + 6, // IID932 + 7, // IID933 + 5, // IID934 + 7, // IID935 + 7, // IID936 + 5, // IID937 + 5, // IID938 + 7, // IID939 + 7, // IID940 + 6, // IID941 + 4, // IID942 + 6, // IID943 + 4, // IID944 + 6, // IID945 + 4, // IID946 + 6, // IID947 + 4, // IID948 + 6, // IID949 + 4, // IID950 + 6, // IID951 + 4, // IID952 + 6, // IID953 + 4, // IID954 + 6, // IID955 + 4, // IID956 + 6, // IID957 + 4, // IID958 + 6, // IID959 + 4, // IID960 + 6, // IID961 + 4, // IID962 + 6, // IID963 + 4, // IID964 + 6, // IID965 + 4, // IID966 + 6, // IID967 + 4, // IID968 + 6, // IID969 + 4, // IID970 + 6, // IID971 + 4, // IID972 + 11, // IID973 + 9, // IID974 + 10, // IID975 + 9, // IID976 + 11, // IID977 + 9, // IID978 + 11, // IID979 + 9, // IID980 + 11, // IID981 + 9, // IID982 + 11, // IID983 + 9, // IID984 + 11, // IID985 + 9, // IID986 + 10, // IID987 + 9, // IID988 + 11, // IID989 + 9, // IID990 + 11, // IID991 + 9, // IID992 + 11, // IID993 + 9, // IID994 + 11, // IID995 + 9, // IID996 + 11, // IID997 + 9, // IID998 + 10, // IID999 + 9, // IID1000 + 11, // IID1001 + 9, // IID1002 + 11, // IID1003 + 9, // IID1004 #endif // _LP64 }; @@ -3152,662 +3404,746 @@ "__ eaddl(r28, Address(r24, rcx, (Address::ScaleFactor)3, -0x6053edc2), r28, false);", // IID268 "__ eaddl(r17, Address(r18, r24, (Address::ScaleFactor)3, -0x1bf71f78), r29, true);", // IID269 "__ eaddl(rcx, Address(r15, r28, (Address::ScaleFactor)1, +0x15b8216), rcx, true);", // IID270 - "__ eorl(r30, Address(rbx, rdx, (Address::ScaleFactor)3, -0x463540b4), r28, false);", // IID271 - "__ eorl(r18, Address(r28, r10, (Address::ScaleFactor)3, +0x3523a73b), r18, false);", // IID272 - "__ eorl(r9, Address(r15, r15, (Address::ScaleFactor)1, -0x2a0bdd56), r21, true);", // IID273 - "__ eorl(r16, Address(r23, -0x165064ff), r16, true);", // IID274 - "__ eorb(r28, Address(r30, r11, (Address::ScaleFactor)0, +0x17281e3a), r20, false);", // IID275 - "__ eorb(rdx, Address(rbx, r31, (Address::ScaleFactor)2, +0x2477b5bb), rdx, false);", // IID276 - "__ eorb(r16, Address(r11, rcx, (Address::ScaleFactor)1, -0x3175d1af), r24, true);", // IID277 - "__ eorb(rbx, Address(r11, r20, (Address::ScaleFactor)3, -0x22d67bd3), rbx, true);", // IID278 - "__ esubl(r26, Address(r27, r30, (Address::ScaleFactor)1, -0x3d9bce2e), rdx, false);", // IID279 - "__ esubl(r31, Address(r22, r29, (Address::ScaleFactor)1, +0x14218519), r31, false);", // IID280 - "__ esubl(r21, Address(r9, -0x1050127a), r13, true);", // IID281 - "__ esubl(r31, Address(r9, r8, (Address::ScaleFactor)0, -0xae18961), r31, true);", // IID282 - "__ exorl(r15, Address(r18, +0x5c2bbce5), r12, false);", // IID283 - "__ exorl(r27, Address(r25, r23, (Address::ScaleFactor)0, +0x5c6078b3), r27, false);", // IID284 - "__ exorl(r18, Address(r8, rdx, (Address::ScaleFactor)3, -0x9ed3881), r14, true);", // IID285 - "__ exorl(r9, Address(r15, +0x775acdad), r9, true);", // IID286 - "__ exorb(r21, Address(r18, r26, (Address::ScaleFactor)1, +0x2fe31fd5), r23, false);", // IID287 - "__ exorb(r10, Address(r27, +0xa3150de), r10, false);", // IID288 - "__ exorb(r18, Address(r22, r30, (Address::ScaleFactor)3, +0x1ad4e897), r24, true);", // IID289 - "__ exorb(r8, Address(r16, r20, (Address::ScaleFactor)0, +0x626eae82), r8, true);", // IID290 - "__ eaddl(r21, r15, 1048576, false);", // IID291 - "__ eaddl(rax, r18, 1048576, false);", // IID292 - "__ eaddl(r18, r18, 256, false);", // IID293 - "__ eaddl(r13, r19, 16, true);", // IID294 - "__ eaddl(rax, r23, 16, true);", // IID295 - "__ eaddl(r25, r25, 16777216, true);", // IID296 - "__ eandl(r29, r18, 1048576, false);", // IID297 - "__ eandl(rax, r14, 1048576, false);", // IID298 - "__ eandl(r19, r19, 65536, false);", // IID299 - "__ eandl(r27, r25, 1048576, true);", // IID300 - "__ eandl(rax, r20, 1048576, true);", // IID301 - "__ eandl(r28, r28, 16, true);", // IID302 - "__ eimull(r31, r22, 4096, false);", // IID303 -#endif // _LP64 - "__ eimull(rax, rbx, 4096, false);", // IID304 -#ifdef _LP64 - "__ eimull(r24, r24, 1048576, false);", // IID305 - "__ eimull(r21, r16, 65536, true);", // IID306 - "__ eimull(rax, r24, 65536, true);", // IID307 - "__ eimull(r13, r13, 16, true);", // IID308 - "__ eorl(r29, r8, 16777216, false);", // IID309 - "__ eorl(rax, r12, 16777216, false);", // IID310 - "__ eorl(r30, r30, 4096, false);", // IID311 - "__ eorl(r24, rdx, 16, true);", // IID312 - "__ eorl(rax, r8, 16, true);", // IID313 - "__ eorl(r13, r13, 4096, true);", // IID314 - "__ ercll(r25, r13, 1);", // IID315 - "__ ercll(rax, r18, 1);", // IID316 - "__ ercll(r9, r9, 16);", // IID317 - "__ eroll(r26, r25, 8, false);", // IID318 + "__ eandl(r30, Address(rbx, rdx, (Address::ScaleFactor)3, -0x463540b4), r28, false);", // IID271 + "__ eandl(r18, Address(r28, r10, (Address::ScaleFactor)3, +0x3523a73b), r18, false);", // IID272 + "__ eandl(r9, Address(r15, r15, (Address::ScaleFactor)1, -0x2a0bdd56), r21, true);", // IID273 + "__ eandl(r16, Address(r23, -0x165064ff), r16, true);", // IID274 + "__ eorl(r28, Address(r30, r11, (Address::ScaleFactor)0, +0x17281e3a), r20, false);", // IID275 + "__ eorl(rdx, Address(rbx, r31, (Address::ScaleFactor)2, +0x2477b5bb), rdx, false);", // IID276 + "__ eorl(r16, Address(r11, rcx, (Address::ScaleFactor)1, -0x3175d1af), r24, true);", // IID277 + "__ eorl(rbx, Address(r11, r20, (Address::ScaleFactor)3, -0x22d67bd3), rbx, true);", // IID278 + "__ eorb(r26, Address(r27, r30, (Address::ScaleFactor)1, -0x3d9bce2e), rdx, false);", // IID279 + "__ eorb(r31, Address(r22, r29, (Address::ScaleFactor)1, +0x14218519), r31, false);", // IID280 + "__ eorb(r21, Address(r9, -0x1050127a), r13, true);", // IID281 + "__ eorb(r31, Address(r9, r8, (Address::ScaleFactor)0, -0xae18961), r31, true);", // IID282 + "__ esubl(r15, Address(r18, +0x5c2bbce5), r12, false);", // IID283 + "__ esubl(r27, Address(r25, r23, (Address::ScaleFactor)0, +0x5c6078b3), r27, false);", // IID284 + "__ esubl(r18, Address(r8, rdx, (Address::ScaleFactor)3, -0x9ed3881), r14, true);", // IID285 + "__ esubl(r9, Address(r15, +0x775acdad), r9, true);", // IID286 + "__ exorl(r21, Address(r18, r26, (Address::ScaleFactor)1, +0x2fe31fd5), r23, false);", // IID287 + "__ exorl(r10, Address(r27, +0xa3150de), r10, false);", // IID288 + "__ exorl(r18, Address(r22, r30, (Address::ScaleFactor)3, +0x1ad4e897), r24, true);", // IID289 + "__ exorl(r8, Address(r16, r20, (Address::ScaleFactor)0, +0x626eae82), r8, true);", // IID290 + "__ exorb(r16, Address(r21, r15, (Address::ScaleFactor)0, -0x1403b60d), r18, false);", // IID291 + "__ exorb(r13, Address(r19, r23, (Address::ScaleFactor)2, +0x237ef1e1), r13, false);", // IID292 + "__ exorb(r29, Address(r18, r14, (Address::ScaleFactor)2, +0x5cc0095b), r14, true);", // IID293 + "__ exorb(r27, Address(r25, r20, (Address::ScaleFactor)3, +0x1cf7b958), r27, true);", // IID294 + "__ eaddl(r16, r24, 16, false);", // IID295 + "__ eaddl(rax, r24, 16, false);", // IID296 + "__ eaddl(r21, r21, 65536, false);", // IID297 + "__ eaddl(r24, r8, 1048576, true);", // IID298 + "__ eaddl(rax, r13, 1048576, true);", // IID299 + "__ eaddl(r29, r29, 16777216, true);", // IID300 + "__ eandl(r12, r12, 16, false);", // IID301 + "__ eandl(rax, r30, 16, false);", // IID302 + "__ eandl(r24, r24, 16, false);", // IID303 + "__ eandl(r8, r12, 1, true);", // IID304 + "__ eandl(rax, r13, 1, true);", // IID305 + "__ eandl(r25, r25, 16, true);", // IID306 + "__ eimull(r18, r23, 65536, false);", // IID307 + "__ eimull(rax, r9, 65536, false);", // IID308 + "__ eimull(r26, r26, 268435456, false);", // IID309 + "__ eimull(r25, r21, 1, true);", // IID310 + "__ eimull(rax, r24, 1, true);", // IID311 + "__ eimull(r24, r24, 16777216, true);", // IID312 + "__ eorl(r30, r26, 1, false);", // IID313 + "__ eorl(rax, r22, 1, false);", // IID314 + "__ eorl(r17, r17, 1048576, false);", // IID315 + "__ eorl(r24, r8, 1, true);", // IID316 + "__ eorl(rax, r27, 1, true);", // IID317 #endif // _LP64 - "__ eroll(rax, rdx, 8, false);", // IID319 + "__ eorl(rdx, rdx, 268435456, true);", // IID318 #ifdef _LP64 - "__ eroll(r24, r24, 16, false);", // IID320 - "__ eroll(r24, rcx, 8, true);", // IID321 - "__ eroll(rax, r30, 8, true);", // IID322 - "__ eroll(r28, r28, 16, true);", // IID323 - "__ erorl(r17, r28, 4, false);", // IID324 + "__ ercll(r22, r22, 8);", // IID319 + "__ ercll(rax, r23, 8);", // IID320 + "__ ercll(r19, r19, 4);", // IID321 + "__ eroll(r30, r24, 2, false);", // IID322 + "__ eroll(rax, r29, 2, false);", // IID323 + "__ eroll(r8, r8, 2, false);", // IID324 + "__ eroll(r18, r24, 16, true);", // IID325 + "__ eroll(rax, r13, 16, true);", // IID326 + "__ eroll(r24, r24, 1, true);", // IID327 + "__ erorl(r28, r17, 16, false);", // IID328 + "__ erorl(rax, r24, 16, false);", // IID329 + "__ erorl(r17, r17, 4, false);", // IID330 + "__ erorl(r24, rcx, 4, true);", // IID331 + "__ erorl(rax, r16, 4, true);", // IID332 + "__ erorl(r15, r15, 2, true);", // IID333 + "__ esall(r14, r27, 4, false);", // IID334 + "__ esall(rax, r23, 4, false);", // IID335 + "__ esall(r30, r30, 4, false);", // IID336 + "__ esall(r27, rdx, 2, true);", // IID337 + "__ esall(rax, r19, 2, true);", // IID338 + "__ esall(r20, r20, 2, true);", // IID339 + "__ esarl(r21, r23, 1, false);", // IID340 + "__ esarl(rax, r30, 1, false);", // IID341 + "__ esarl(r25, r25, 2, false);", // IID342 + "__ esarl(r24, r19, 4, true);", // IID343 + "__ esarl(rax, r14, 4, true);", // IID344 + "__ esarl(r26, r26, 16, true);", // IID345 + "__ eshll(r22, r13, 8, false);", // IID346 + "__ eshll(rax, r24, 8, false);", // IID347 + "__ eshll(r14, r14, 16, false);", // IID348 + "__ eshll(r28, r25, 8, true);", // IID349 + "__ eshll(rax, r10, 8, true);", // IID350 + "__ eshll(r20, r20, 1, true);", // IID351 + "__ eshrl(r12, rbx, 4, false);", // IID352 + "__ eshrl(rax, r23, 4, false);", // IID353 + "__ eshrl(r28, r28, 16, false);", // IID354 + "__ eshrl(r24, r30, 4, true);", // IID355 + "__ eshrl(rax, r31, 4, true);", // IID356 + "__ eshrl(r31, r31, 2, true);", // IID357 + "__ esubl(r20, r10, 256, false);", // IID358 + "__ esubl(rax, r13, 256, false);", // IID359 + "__ esubl(r25, r25, 256, false);", // IID360 + "__ esubl(r23, r12, 268435456, true);", // IID361 + "__ esubl(rax, r16, 268435456, true);", // IID362 + "__ esubl(r31, r31, 1, true);", // IID363 + "__ exorl(r9, r15, 16777216, false);", // IID364 + "__ exorl(rax, r13, 16777216, false);", // IID365 + "__ exorl(r28, r28, 16, false);", // IID366 + "__ exorl(r29, r22, 16, true);", // IID367 #endif // _LP64 - "__ erorl(rax, rdx, 4, false);", // IID325 + "__ exorl(rax, rbx, 16, true);", // IID368 #ifdef _LP64 - "__ erorl(r8, r8, 16, false);", // IID326 - "__ erorl(r19, rdx, 16, true);", // IID327 - "__ erorl(rax, r31, 16, true);", // IID328 - "__ erorl(r22, r22, 8, true);", // IID329 - "__ esall(r23, r25, 16, false);", // IID330 - "__ esall(rax, r14, 16, false);", // IID331 - "__ esall(r31, r31, 8, false);", // IID332 - "__ esall(r30, r24, 2, true);", // IID333 - "__ esall(rax, r29, 2, true);", // IID334 - "__ esall(r8, r8, 2, true);", // IID335 - "__ esarl(r18, r24, 16, false);", // IID336 - "__ esarl(rax, r13, 16, false);", // IID337 - "__ esarl(r24, r24, 1, false);", // IID338 - "__ esarl(r28, r17, 16, true);", // IID339 - "__ esarl(rax, r24, 16, true);", // IID340 - "__ esarl(r17, r17, 4, true);", // IID341 - "__ eshll(r24, rcx, 4, false);", // IID342 - "__ eshll(rax, r16, 4, false);", // IID343 - "__ eshll(r15, r15, 2, false);", // IID344 - "__ eshll(r14, r27, 4, true);", // IID345 - "__ eshll(rax, r23, 4, true);", // IID346 - "__ eshll(r30, r30, 4, true);", // IID347 - "__ eshrl(r27, rdx, 2, false);", // IID348 - "__ eshrl(rax, r19, 2, false);", // IID349 - "__ eshrl(r20, r20, 2, false);", // IID350 - "__ eshrl(r21, r23, 1, true);", // IID351 - "__ eshrl(rax, r30, 1, true);", // IID352 - "__ eshrl(r25, r25, 2, true);", // IID353 - "__ esubl(r24, r19, 1048576, false);", // IID354 - "__ esubl(rax, r14, 1048576, false);", // IID355 - "__ esubl(r22, r22, 268435456, false);", // IID356 - "__ esubl(r24, r24, 65536, true);", // IID357 - "__ esubl(rax, r14, 65536, true);", // IID358 - "__ esubl(r28, r28, 268435456, true);", // IID359 - "__ exorl(rbx, r20, 256, false);", // IID360 - "__ exorl(rax, r15, 256, false);", // IID361 + "__ exorl(r8, r8, 16, true);", // IID369 + "__ esubl_imm32(r16, r13, 4194304, false);", // IID370 + "__ esubl_imm32(rax, r12, 4194304, false);", // IID371 + "__ esubl_imm32(r17, r17, 67108864, false);", // IID372 + "__ esubl_imm32(r22, r26, 1073741824, true);", // IID373 + "__ esubl_imm32(rax, r10, 1073741824, true);", // IID374 + "__ esubl_imm32(r11, r11, 1073741824, true);", // IID375 + "__ eaddl(r19, r12, Address(r30, r8, (Address::ScaleFactor)0, +0x6a1a0a73), false);", // IID376 + "__ eaddl(r30, r30, Address(r18, r19, (Address::ScaleFactor)2, +0x25f990cf), false);", // IID377 + "__ eaddl(rcx, r25, Address(r19, r16, (Address::ScaleFactor)0, +0x482d5dbc), true);", // IID378 + "__ eaddl(r9, r9, Address(r11, +0x43d5ee01), true);", // IID379 + "__ eandl(rcx, r23, Address(r21, r15, (Address::ScaleFactor)2, +0x2825c2bc), false);", // IID380 + "__ eandl(r27, r27, Address(r13, r15, (Address::ScaleFactor)3, -0x1268b895), false);", // IID381 + "__ eandl(r9, r23, Address(r22, r30, (Address::ScaleFactor)0, -0x715acbb), true);", // IID382 + "__ eandl(rbx, rbx, Address(r28, r16, (Address::ScaleFactor)2, +0xb0223ee), true);", // IID383 + "__ eimull(r15, r29, Address(r15, r28, (Address::ScaleFactor)1, -0x1f297a69), false);", // IID384 + "__ eimull(r17, r17, Address(r23, rbx, (Address::ScaleFactor)1, +0xadc7545), false);", // IID385 + "__ eimull(r27, r9, Address(rdx, r22, (Address::ScaleFactor)2, -0x43d90f61), true);", // IID386 + "__ eimull(rbx, rbx, Address(r28, r22, (Address::ScaleFactor)3, -0x519d9a27), true);", // IID387 + "__ eorl(r17, rcx, Address(r14, +0x10642223), false);", // IID388 + "__ eorl(r26, r26, Address(r31, -0x7a9a83ba), false);", // IID389 + "__ eorl(r15, r22, Address(r12, r12, (Address::ScaleFactor)2, +0x743b6997), true);", // IID390 + "__ eorl(r8, r8, Address(rdx, r22, (Address::ScaleFactor)3, -0x588414dc), true);", // IID391 + "__ esubl(rcx, r28, Address(r30, r13, (Address::ScaleFactor)2, +0xe9310e5), false);", // IID392 + "__ esubl(rcx, rcx, Address(r30, r10, (Address::ScaleFactor)1, -0x1b076ed1), false);", // IID393 + "__ esubl(r9, r21, Address(r30, +0x2f79ffd3), true);", // IID394 + "__ esubl(r16, r16, Address(rdx, r14, (Address::ScaleFactor)2, +0x675d71c1), true);", // IID395 + "__ exorl(r27, r28, Address(rbx, r26, (Address::ScaleFactor)2, -0x78c20b81), false);", // IID396 + "__ exorl(r14, r14, Address(r31, r19, (Address::ScaleFactor)1, -0x4ff251cc), false);", // IID397 + "__ exorl(r20, r18, Address(r13, r16, (Address::ScaleFactor)2, -0x19efc6e2), true);", // IID398 + "__ exorl(r19, r19, Address(r13, r23, (Address::ScaleFactor)1, -0x2d1bd8aa), true);", // IID399 + "__ exorb(r29, r17, Address(rdx, r29, (Address::ScaleFactor)2, +0x66573e84), false);", // IID400 + "__ exorb(r22, r22, Address(r24, r25, (Address::ScaleFactor)3, +0x3a94a93f), false);", // IID401 + "__ exorb(r13, r29, Address(r15, r23, (Address::ScaleFactor)1, +0x76d43532), true);", // IID402 + "__ exorb(r15, r15, Address(r13, r9, (Address::ScaleFactor)0, -0x474e6d1a), true);", // IID403 + "__ exorw(r17, r16, Address(r23, rdx, (Address::ScaleFactor)0, +0x562a291), false);", // IID404 + "__ exorw(r29, r29, Address(r18, r28, (Address::ScaleFactor)3, -0x541967f2), false);", // IID405 + "__ exorw(r27, r11, Address(r10, +0xa911c5a), true);", // IID406 + "__ exorw(r31, r31, Address(r30, r19, (Address::ScaleFactor)2, -0xf6a3da), true);", // IID407 + "__ eaddl(r12, r13, r23, false);", // IID408 + "__ eaddl(r28, r28, r20, false);", // IID409 + "__ eaddl(r20, r24, r20, false);", // IID410 + "__ eaddl(r11, r10, r15, true);", // IID411 + "__ eaddl(r19, r19, r20, true);", // IID412 + "__ eaddl(r23, r15, r23, true);", // IID413 + "__ eandl(r26, r19, r24, false);", // IID414 + "__ eandl(r23, r23, r28, false);", // IID415 + "__ eandl(r11, r13, r11, false);", // IID416 + "__ eandl(r13, rdx, r31, true);", // IID417 + "__ eandl(r23, r23, r23, true);", // IID418 + "__ eandl(r9, r27, r9, true);", // IID419 + "__ eimull(r21, r20, r24, false);", // IID420 + "__ eimull(r21, r21, r29, false);", // IID421 + "__ eimull(rbx, r11, rbx, false);", // IID422 + "__ eimull(r21, rbx, rcx, true);", // IID423 + "__ eimull(r31, r31, r21, true);", // IID424 + "__ eimull(r15, r25, r15, true);", // IID425 + "__ eorw(r30, r23, r25, false);", // IID426 + "__ eorw(r18, r18, rcx, false);", // IID427 + "__ eorw(r10, rcx, r10, false);", // IID428 + "__ eorw(r31, r21, r26, true);", // IID429 + "__ eorw(r21, r21, r19, true);", // IID430 #endif // _LP64 - "__ exorl(rbx, rbx, 4096, false);", // IID362 + "__ eorw(rdx, rbx, rdx, true);", // IID431 #ifdef _LP64 - "__ exorl(r24, r30, 65536, true);", // IID363 - "__ exorl(rax, r31, 65536, true);", // IID364 - "__ exorl(r31, r31, 4096, true);", // IID365 - "__ esubl_imm32(r20, r10, 1048576, false);", // IID366 - "__ esubl_imm32(rax, r13, 1048576, false);", // IID367 - "__ esubl_imm32(r25, r25, 1048576, false);", // IID368 - "__ esubl_imm32(r23, r12, 1073741824, true);", // IID369 - "__ esubl_imm32(rax, r16, 1073741824, true);", // IID370 - "__ esubl_imm32(r31, r31, 65536, true);", // IID371 - "__ eaddl(r17, r13, Address(r9, +0x7fef2f98), false);", // IID372 - "__ eaddl(r29, r8, Address(r22, -0x4df70aac), true);", // IID373 - "__ eandl(r13, r17, Address(r12, r15, (Address::ScaleFactor)3, +0x50a8a902), false);", // IID374 - "__ eandl(r22, r25, Address(r26, r10, (Address::ScaleFactor)2, +0x70ea2754), true);", // IID375 - "__ eimull(r19, r12, Address(r30, r8, (Address::ScaleFactor)0, +0x6a1a0a73), false);", // IID376 - "__ eimull(r30, r18, Address(r18, r19, (Address::ScaleFactor)2, -0x7fcd28c7), true);", // IID377 - "__ eorl(r16, r31, Address(r25, r11, (Address::ScaleFactor)3, +0x482d5dbc), false);", // IID378 - "__ eorl(r9, r27, Address(r11, +0x43d5ee01), true);", // IID379 - "__ esubl(rcx, r23, Address(r21, r15, (Address::ScaleFactor)2, +0x2825c2bc), false);", // IID380 - "__ esubl(r27, r22, Address(r13, r15, (Address::ScaleFactor)1, +0x771f0da7), true);", // IID381 - "__ exorl(r9, r30, Address(r9, r22, (Address::ScaleFactor)3, -0x4ad6c88e), false);", // IID382 - "__ exorl(r11, r16, Address(rbx, r28, (Address::ScaleFactor)2, +0xb0223ee), true);", // IID383 - "__ exorb(r15, r29, Address(r15, r28, (Address::ScaleFactor)1, -0x1f297a69), false);", // IID384 - "__ exorb(r17, r30, Address(r23, rbx, (Address::ScaleFactor)1, +0xadc7545), true);", // IID385 - "__ exorw(r27, r9, Address(rdx, r22, (Address::ScaleFactor)2, -0x43d90f61), false);", // IID386 - "__ exorw(rbx, r22, Address(r28, r22, (Address::ScaleFactor)0, -0x7d30a0b1), true);", // IID387 - "__ eaddl(r14, r24, rcx, false);", // IID388 - "__ eaddl(r8, r8, r17, false);", // IID389 - "__ eaddl(r26, r24, r12, true);", // IID390 - "__ eaddl(r24, r24, r23, true);", // IID391 - "__ eandl(r13, r26, r31, false);", // IID392 - "__ eandl(r11, r11, r8, false);", // IID393 - "__ eandl(rcx, r19, r15, true);", // IID394 - "__ eandl(r12, r12, r12, true);", // IID395 - "__ eimull(r22, r20, r19, false);", // IID396 - "__ eimull(r8, r8, rdx, false);", // IID397 - "__ eimull(r22, r27, r23, true);", // IID398 - "__ eimull(r9, r9, r18, true);", // IID399 - "__ eorw(rcx, r30, r13, false);", // IID400 - "__ eorw(r28, r28, r19, false);", // IID401 - "__ eorw(r12, r30, r27, true);", // IID402 - "__ eorw(r8, r8, r22, true);", // IID403 - "__ eorl(r16, rcx, r30, false);", // IID404 - "__ eorl(r10, r10, r25, false);", // IID405 - "__ eorl(r15, r17, r17, true);", // IID406 - "__ eorl(r9, r9, r30, true);", // IID407 - "__ eshldl(r20, r21, r8, false);", // IID408 - "__ eshldl(r26, r26, r14, false);", // IID409 - "__ eshldl(r16, rdx, r14, true);", // IID410 - "__ eshldl(r19, r19, r8, true);", // IID411 - "__ eshrdl(r27, rbx, r26, false);", // IID412 - "__ eshrdl(r28, r28, r19, false);", // IID413 - "__ eshrdl(rcx, r11, r14, true);", // IID414 - "__ eshrdl(r31, r31, r19, true);", // IID415 - "__ esubl(r26, r13, r25, false);", // IID416 - "__ esubl(r24, r24, r11, false);", // IID417 - "__ esubl(r18, r20, r13, true);", // IID418 - "__ esubl(r16, r16, r18, true);", // IID419 - "__ exorl(r19, r17, r8, false);", // IID420 - "__ exorl(r19, r19, r13, false);", // IID421 - "__ exorl(r23, r13, r15, true);", // IID422 - "__ exorl(r11, r11, r29, true);", // IID423 - "__ eshldl(r29, r17, r17, 1, false);", // IID424 - "__ eshldl(r22, r22, r24, 4, false);", // IID425 - "__ eshldl(r8, r28, r11, 16, true);", // IID426 - "__ eshldl(r15, r15, r23, 4, true);", // IID427 - "__ eshrdl(r29, r22, r16, 4, false);", // IID428 - "__ eshrdl(r13, r13, r9, 4, false);", // IID429 - "__ eshrdl(r15, r21, r12, 2, true);", // IID430 - "__ eshrdl(r17, r17, r23, 2, true);", // IID431 - "__ ecmovl (Assembler::Condition::overflow, rdx, r16, r29);", // IID432 - "__ ecmovl (Assembler::Condition::overflow, r10, r10, r21);", // IID433 - "__ ecmovl (Assembler::Condition::noOverflow, r17, r29, r18);", // IID434 - "__ ecmovl (Assembler::Condition::noOverflow, r28, r28, r24);", // IID435 - "__ ecmovl (Assembler::Condition::below, r10, r20, r27);", // IID436 - "__ ecmovl (Assembler::Condition::below, r10, r10, r14);", // IID437 - "__ ecmovl (Assembler::Condition::aboveEqual, r11, r27, rcx);", // IID438 - "__ ecmovl (Assembler::Condition::aboveEqual, r22, r22, r15);", // IID439 - "__ ecmovl (Assembler::Condition::zero, r31, r30, r19);", // IID440 - "__ ecmovl (Assembler::Condition::zero, r19, r19, r26);", // IID441 - "__ ecmovl (Assembler::Condition::notZero, r21, r14, r26);", // IID442 - "__ ecmovl (Assembler::Condition::notZero, r20, r20, r15);", // IID443 - "__ ecmovl (Assembler::Condition::belowEqual, r12, r13, r23);", // IID444 - "__ ecmovl (Assembler::Condition::belowEqual, r28, r28, r20);", // IID445 - "__ ecmovl (Assembler::Condition::above, r20, r24, r11);", // IID446 - "__ ecmovl (Assembler::Condition::above, r10, r10, r15);", // IID447 - "__ ecmovl (Assembler::Condition::negative, r19, r20, r23);", // IID448 - "__ ecmovl (Assembler::Condition::negative, r15, r15, r26);", // IID449 - "__ ecmovl (Assembler::Condition::positive, r19, r24, r23);", // IID450 - "__ ecmovl (Assembler::Condition::positive, r28, r28, r11);", // IID451 - "__ ecmovl (Assembler::Condition::parity, r13, r13, rdx);", // IID452 - "__ ecmovl (Assembler::Condition::parity, r31, r31, r23);", // IID453 - "__ ecmovl (Assembler::Condition::noParity, r23, r9, r27);", // IID454 - "__ ecmovl (Assembler::Condition::noParity, r21, r21, r20);", // IID455 - "__ ecmovl (Assembler::Condition::less, r24, r21, r29);", // IID456 - "__ ecmovl (Assembler::Condition::less, rbx, rbx, r11);", // IID457 - "__ ecmovl (Assembler::Condition::greaterEqual, r21, rbx, rcx);", // IID458 - "__ ecmovl (Assembler::Condition::greaterEqual, r31, r31, r21);", // IID459 - "__ ecmovl (Assembler::Condition::lessEqual, r15, r25, r30);", // IID460 - "__ ecmovl (Assembler::Condition::lessEqual, r23, r23, r25);", // IID461 - "__ ecmovl (Assembler::Condition::greater, r18, rcx, r10);", // IID462 - "__ ecmovl (Assembler::Condition::greater, rcx, rcx, r31);", // IID463 - "__ ecmovl (Assembler::Condition::overflow, r21, r19, Address(r26, -0x6e290873));", // IID464 - "__ ecmovl (Assembler::Condition::noOverflow, r24, r19, Address(r22, rcx, (Address::ScaleFactor)0, +0x11f85f9a));", // IID465 - "__ ecmovl (Assembler::Condition::below, r17, r24, Address(r20, +0x534d775e));", // IID466 - "__ ecmovl (Assembler::Condition::aboveEqual, r20, r18, Address(r20, -0x47c94ecd));", // IID467 - "__ ecmovl (Assembler::Condition::zero, r9, r13, Address(r23, -0x4b83c563));", // IID468 - "__ ecmovl (Assembler::Condition::notZero, r11, r25, Address(r24, r14, (Address::ScaleFactor)1, -0x446507af));", // IID469 - "__ ecmovl (Assembler::Condition::belowEqual, r14, r24, Address(r30, r13, (Address::ScaleFactor)2, +0xd0661d));", // IID470 - "__ ecmovl (Assembler::Condition::above, r13, r25, Address(r14, r27, (Address::ScaleFactor)3, +0x47e1403));", // IID471 - "__ ecmovl (Assembler::Condition::negative, r24, r19, Address(rcx, rdx, (Address::ScaleFactor)3, -0x644a5318));", // IID472 - "__ ecmovl (Assembler::Condition::positive, r26, r24, Address(r22, r22, (Address::ScaleFactor)0, +0x70352446));", // IID473 - "__ ecmovl (Assembler::Condition::parity, r19, r26, Address(r8, r30, (Address::ScaleFactor)2, +0x78a12f5c));", // IID474 - "__ ecmovl (Assembler::Condition::noParity, r29, r11, Address(r25, r20, (Address::ScaleFactor)0, +0x27a8303a));", // IID475 - "__ ecmovl (Assembler::Condition::less, r22, r24, Address(r27, r16, (Address::ScaleFactor)1, +0x2541a10));", // IID476 - "__ ecmovl (Assembler::Condition::greaterEqual, r31, r15, Address(r8, r16, (Address::ScaleFactor)3, +0x558e3251));", // IID477 - "__ ecmovl (Assembler::Condition::lessEqual, r27, r18, Address(r8, r10, (Address::ScaleFactor)0, -0x471987b7));", // IID478 - "__ ecmovl (Assembler::Condition::greater, r18, r16, Address(r18, r19, (Address::ScaleFactor)2, -0x120ae81e));", // IID479 - "__ adcq(rbx, r31);", // IID480 - "__ cmpq(r30, r31);", // IID481 - "__ imulq(r29, r28);", // IID482 - "__ popcntq(r25, r10);", // IID483 - "__ sbbq(r24, r20);", // IID484 - "__ subq(r16, rdx);", // IID485 - "__ tzcntq(r26, r28);", // IID486 - "__ lzcntq(r28, r9);", // IID487 - "__ addq(r20, r24);", // IID488 - "__ andq(r24, r29);", // IID489 - "__ orq(r23, r27);", // IID490 - "__ xorq(r15, r12);", // IID491 - "__ movq(r18, r19);", // IID492 - "__ bsfq(r31, rcx);", // IID493 - "__ bsrq(r9, r13);", // IID494 - "__ btq(r20, rcx);", // IID495 - "__ xchgq(r8, r21);", // IID496 - "__ testq(r24, r14);", // IID497 - "__ addq(Address(rcx, r23, (Address::ScaleFactor)2, +0x4ff06c4d), r29);", // IID498 - "__ andq(Address(r24, r10, (Address::ScaleFactor)1, -0x75d9a189), r26);", // IID499 - "__ cmpq(Address(rbx, rbx, (Address::ScaleFactor)0, +0x4033d59c), r17);", // IID500 - "__ orq(Address(r22, r12, (Address::ScaleFactor)3, -0x3893347d), r18);", // IID501 - "__ xorq(Address(r20, r23, (Address::ScaleFactor)3, +0x4b311560), r12);", // IID502 - "__ subq(Address(r10, r28, (Address::ScaleFactor)2, +0x5c3a2657), r29);", // IID503 - "__ movq(Address(r13, r25, (Address::ScaleFactor)3, +0x1a3d6f3f), r22);", // IID504 - "__ xaddq(Address(r17, r24, (Address::ScaleFactor)3, -0x35addbd8), r25);", // IID505 - "__ andq(Address(r25, +0x632184c3), 16777216);", // IID506 - "__ addq(Address(r13, r13, (Address::ScaleFactor)0, -0x3972eac6), 16777216);", // IID507 - "__ cmpq(Address(r9, -0x13b4c806), 4096);", // IID508 - "__ sarq(Address(r31, +0x4fa7f551), 1);", // IID509 - "__ salq(Address(r21, r31, (Address::ScaleFactor)2, +0x31aa8232), 1);", // IID510 - "__ sbbq(Address(r24, r31, (Address::ScaleFactor)2, -0x466538b7), 268435456);", // IID511 - "__ shrq(Address(r28, r22, (Address::ScaleFactor)0, -0x3efe85b1), 2);", // IID512 - "__ subq(Address(r16, -0x1389a3eb), 1048576);", // IID513 - "__ xorq(Address(r29, r8, (Address::ScaleFactor)0, +0x1d022615), 16);", // IID514 - "__ orq(Address(r12, r28, (Address::ScaleFactor)1, -0x34c898e2), 1);", // IID515 - "__ movq(Address(rcx, r24, (Address::ScaleFactor)2, -0x1644eb08), 256);", // IID516 - "__ testq(Address(r29, -0x7d23890b), -65536);", // IID517 - "__ addq(r23, Address(rcx, r19, (Address::ScaleFactor)2, +0x70eac654));", // IID518 - "__ andq(rdx, Address(r24, r15, (Address::ScaleFactor)0, -0x204ddaa9));", // IID519 - "__ cmpq(rdx, Address(r23, r11, (Address::ScaleFactor)3, +0x32c930bd));", // IID520 - "__ lzcntq(r28, Address(rdx, -0x5433c28f));", // IID521 - "__ orq(r22, Address(r19, r14, (Address::ScaleFactor)1, -0x2cc67d38));", // IID522 - "__ adcq(r10, Address(r10, +0x3d7c59f));", // IID523 - "__ imulq(r10, Address(r8, r8, (Address::ScaleFactor)3, -0xe61862d));", // IID524 - "__ popcntq(r23, Address(r29, -0x777ed96d));", // IID525 - "__ sbbq(rcx, Address(rbx, r19, (Address::ScaleFactor)1, +0x53c601cb));", // IID526 - "__ subq(r14, Address(r17, rbx, (Address::ScaleFactor)0, -0x768bf073));", // IID527 - "__ tzcntq(r29, Address(r10, r19, (Address::ScaleFactor)1, +0x30c98d3c));", // IID528 - "__ xorq(r10, Address(r16, r27, (Address::ScaleFactor)0, -0x3d08d602));", // IID529 - "__ movq(r18, Address(r28, r28, (Address::ScaleFactor)3, -0x62fbac91));", // IID530 - "__ leaq(rbx, Address(rcx, +0x450602a5));", // IID531 - "__ cvttsd2siq(r12, Address(r30, r31, (Address::ScaleFactor)0, -0x6798a630));", // IID532 - "__ xchgq(r31, Address(r24, r10, (Address::ScaleFactor)1, -0x706712ed));", // IID533 - "__ testq(r14, Address(r13, r20, (Address::ScaleFactor)3, +0x171081f2));", // IID534 - "__ addq(r31, 16);", // IID535 - "__ andq(r25, 16);", // IID536 - "__ adcq(r23, 256);", // IID537 - "__ cmpq(r19, 268435456);", // IID538 - "__ rclq(r31, 1);", // IID539 - "__ rcrq(r17, 1);", // IID540 - "__ rolq(r25, 2);", // IID541 - "__ rorq(r17, 4);", // IID542 - "__ sarq(r28, 1);", // IID543 - "__ salq(r15, 4);", // IID544 - "__ sbbq(rbx, 65536);", // IID545 - "__ shlq(r21, 1);", // IID546 - "__ shrq(r10, 1);", // IID547 - "__ subq(r14, 16);", // IID548 - "__ xorq(r18, 268435456);", // IID549 - "__ movq(r23, 16);", // IID550 - "__ mov64(r12, 1099511627776);", // IID551 - "__ btq(r14, 4);", // IID552 - "__ testq(r24, -4096);", // IID553 - "__ orq_imm32(r19, 1048576);", // IID554 - "__ subq_imm32(rcx, 268435456);", // IID555 - "__ cmovq(Assembler::Condition::overflow, rdx, Address(r19, rbx, (Address::ScaleFactor)3, +0x211c8c4));", // IID556 - "__ cmovq(Assembler::Condition::noOverflow, rbx, Address(r21, +0x49267743));", // IID557 - "__ cmovq(Assembler::Condition::below, r21, Address(r8, r28, (Address::ScaleFactor)1, -0x4c8c2946));", // IID558 - "__ cmovq(Assembler::Condition::aboveEqual, r12, Address(r26, r20, (Address::ScaleFactor)0, -0x264df89c));", // IID559 - "__ cmovq(Assembler::Condition::zero, r17, Address(r28, r9, (Address::ScaleFactor)2, +0x3497196b));", // IID560 - "__ cmovq(Assembler::Condition::notZero, r13, Address(r15, r23, (Address::ScaleFactor)1, -0x27a30999));", // IID561 - "__ cmovq(Assembler::Condition::belowEqual, r22, Address(r22, +0xf39ab05));", // IID562 - "__ cmovq(Assembler::Condition::above, rcx, Address(r22, r26, (Address::ScaleFactor)3, -0x48c954c));", // IID563 - "__ cmovq(Assembler::Condition::negative, r25, Address(r19, r21, (Address::ScaleFactor)0, +0xe405b0b));", // IID564 - "__ cmovq(Assembler::Condition::positive, r12, Address(r19, r29, (Address::ScaleFactor)3, -0x7762044b));", // IID565 - "__ cmovq(Assembler::Condition::parity, rbx, Address(r30, r10, (Address::ScaleFactor)1, -0x19798323));", // IID566 - "__ cmovq(Assembler::Condition::noParity, r21, Address(r24, r31, (Address::ScaleFactor)0, -0x5731652b));", // IID567 - "__ cmovq(Assembler::Condition::less, r18, Address(r8, r10, (Address::ScaleFactor)1, -0x5613be89));", // IID568 - "__ cmovq(Assembler::Condition::greaterEqual, r28, Address(r21, r21, (Address::ScaleFactor)3, +0x65a0fdc4));", // IID569 - "__ cmovq(Assembler::Condition::lessEqual, r23, Address(r11, r18, (Address::ScaleFactor)0, -0x1d1af10c));", // IID570 - "__ cmovq(Assembler::Condition::greater, r22, Address(r18, r12, (Address::ScaleFactor)1, +0x1a5f1c38));", // IID571 - "__ call(r23);", // IID572 - "__ divq(r30);", // IID573 - "__ idivq(r19);", // IID574 - "__ imulq(r9);", // IID575 - "__ mulq(r13);", // IID576 - "__ negq(r16);", // IID577 - "__ notq(r29);", // IID578 - "__ rolq(rcx);", // IID579 - "__ rorq(r25);", // IID580 - "__ sarq(r8);", // IID581 - "__ salq(r27);", // IID582 - "__ shlq(r30);", // IID583 - "__ shrq(r23);", // IID584 - "__ incrementq(rbx);", // IID585 - "__ decrementq(r14);", // IID586 - "__ pushp(r21);", // IID587 - "__ popp(r21);", // IID588 - "__ call(Address(r20, r21, (Address::ScaleFactor)1, +0x56c6af2f));", // IID589 - "__ mulq(Address(r31, r19, (Address::ScaleFactor)3, -0x1b4eb23));", // IID590 - "__ negq(Address(r27, r27, (Address::ScaleFactor)0, -0x58dbfc1f));", // IID591 - "__ sarq(Address(rbx, r22, (Address::ScaleFactor)2, -0x606349d1));", // IID592 - "__ salq(Address(r26, r23, (Address::ScaleFactor)3, +0xb95a079));", // IID593 - "__ shrq(Address(r14, r26, (Address::ScaleFactor)0, +0x3544e09));", // IID594 - "__ incrementq(Address(r27, rdx, (Address::ScaleFactor)0, +0x120b3250));", // IID595 - "__ decrementq(Address(r9, r25, (Address::ScaleFactor)2, -0x34aaeccb));", // IID596 - "__ imulq(r20, Address(r16, r28, (Address::ScaleFactor)1, -0x59de05a5), 1048576);", // IID597 - "__ imulq(r17, r23, 256);", // IID598 - "__ shldq(r19, r11, 8);", // IID599 - "__ shrdq(r28, r10, 8);", // IID600 - "__ pop2(r29, r26);", // IID601 - "__ pop2p(r22, r10);", // IID602 - "__ push2(r25, r30);", // IID603 - "__ push2p(r28, r15);", // IID604 - "__ movzbq(r11, Address(r29, r19, (Address::ScaleFactor)2, -0x12368d34));", // IID605 - "__ movzwq(r14, Address(r8, r30, (Address::ScaleFactor)2, -0x4a9392de));", // IID606 - "__ movsbq(r28, Address(r23, r15, (Address::ScaleFactor)0, +0x6189cb54));", // IID607 - "__ movswq(r28, Address(rbx, r23, (Address::ScaleFactor)3, -0x2de86561));", // IID608 - "__ movzbq(r11, rcx);", // IID609 - "__ movzwq(r30, r15);", // IID610 - "__ movsbq(r14, rcx);", // IID611 - "__ movswq(r23, r9);", // IID612 - "__ cmpxchgq(r12, Address(r13, r10, (Address::ScaleFactor)1, -0x7c62c3a));", // IID613 - "__ eidivq(rcx, false);", // IID614 - "__ eidivq(r15, true);", // IID615 - "__ edivq(r23, false);", // IID616 - "__ edivq(r24, true);", // IID617 - "__ eimulq(r27, false);", // IID618 - "__ eimulq(r30, true);", // IID619 - "__ emulq(r12, false);", // IID620 - "__ emulq(rcx, true);", // IID621 - "__ emulq(Address(r13, r9, (Address::ScaleFactor)3, -0x226aab94), false);", // IID622 - "__ emulq(Address(r13, r24, (Address::ScaleFactor)3, -0x286c7605), true);", // IID623 - "__ eimulq(r21, r30, false);", // IID624 - "__ eimulq(r17, r17, false);", // IID625 - "__ eimulq(r29, r12, true);", // IID626 - "__ eimulq(r30, r30, true);", // IID627 - "__ elzcntq(r24, r15, false);", // IID628 - "__ elzcntq(r25, r25, false);", // IID629 - "__ elzcntq(r25, r21, true);", // IID630 - "__ elzcntq(r22, r22, true);", // IID631 - "__ enegq(r17, r30, false);", // IID632 - "__ enegq(r17, r17, false);", // IID633 - "__ enegq(r31, r17, true);", // IID634 - "__ enegq(r29, r29, true);", // IID635 - "__ enotq(r10, r9);", // IID636 - "__ enotq(r24, r24);", // IID637 - "__ epopcntq(r28, r15, false);", // IID638 - "__ epopcntq(r10, r10, false);", // IID639 - "__ epopcntq(r27, r30, true);", // IID640 - "__ epopcntq(r28, r28, true);", // IID641 - "__ erolq(r28, r14, false);", // IID642 - "__ erolq(r23, r23, false);", // IID643 - "__ erolq(r23, r24, true);", // IID644 - "__ erolq(r21, r21, true);", // IID645 - "__ erorq(r31, r22, false);", // IID646 - "__ erorq(r28, r28, false);", // IID647 - "__ erorq(r17, r10, true);", // IID648 - "__ erorq(r9, r9, true);", // IID649 - "__ esalq(r29, r30, false);", // IID650 - "__ esalq(r11, r11, false);", // IID651 - "__ esalq(r26, r11, true);", // IID652 - "__ esalq(r16, r16, true);", // IID653 - "__ esarq(rbx, r15, false);", // IID654 - "__ esarq(r14, r14, false);", // IID655 - "__ esarq(r25, r16, true);", // IID656 - "__ esarq(r8, r8, true);", // IID657 - "__ edecq(r11, r13, false);", // IID658 - "__ edecq(rcx, rcx, false);", // IID659 - "__ edecq(r21, r18, true);", // IID660 - "__ edecq(r28, r28, true);", // IID661 - "__ eincq(r16, r16, false);", // IID662 - "__ eincq(r29, r29, false);", // IID663 - "__ eincq(r18, r9, true);", // IID664 - "__ eincq(r19, r19, true);", // IID665 - "__ eshlq(r19, r18, false);", // IID666 - "__ eshlq(r8, r8, false);", // IID667 - "__ eshlq(r12, r15, true);", // IID668 - "__ eshlq(r29, r29, true);", // IID669 - "__ eshrq(r28, r24, false);", // IID670 - "__ eshrq(r19, r19, false);", // IID671 - "__ eshrq(r8, r28, true);", // IID672 - "__ eshrq(r17, r17, true);", // IID673 - "__ etzcntq(r28, r16, false);", // IID674 - "__ etzcntq(r14, r14, false);", // IID675 - "__ etzcntq(r12, r31, true);", // IID676 - "__ etzcntq(r14, r14, true);", // IID677 - "__ eimulq(r31, Address(r13, -0x69c4b352), false);", // IID678 - "__ eimulq(r17, Address(r18, -0x60ab1105), true);", // IID679 - "__ elzcntq(r27, Address(r14, r25, (Address::ScaleFactor)2, +0x2798bf83), false);", // IID680 - "__ elzcntq(r23, Address(r10, r11, (Address::ScaleFactor)0, -0x378e635d), true);", // IID681 - "__ enegq(rcx, Address(r19, r9, (Address::ScaleFactor)3, -0x6847d440), false);", // IID682 - "__ enegq(rcx, Address(rbx, rcx, (Address::ScaleFactor)0, +0x6f92d38d), true);", // IID683 - "__ epopcntq(r20, Address(r12, -0x2a8b27d6), false);", // IID684 - "__ epopcntq(r31, Address(r30, +0x4603f6d0), true);", // IID685 - "__ esalq(rbx, Address(r24, +0x567d06f9), false);", // IID686 - "__ esalq(r12, Address(r24, r28, (Address::ScaleFactor)0, -0x1c4c584e), true);", // IID687 - "__ esarq(r12, Address(r23, r24, (Address::ScaleFactor)2, -0x3157bcba), false);", // IID688 - "__ esarq(r8, Address(r14, r24, (Address::ScaleFactor)2, -0x714290a5), true);", // IID689 - "__ edecq(r23, Address(r8, r15, (Address::ScaleFactor)1, -0x5ae272dd), false);", // IID690 - "__ edecq(r13, Address(r29, r9, (Address::ScaleFactor)3, -0x5b5174a9), true);", // IID691 - "__ eincq(r11, Address(r21, r31, (Address::ScaleFactor)3, -0x2176b4dc), false);", // IID692 - "__ eincq(r13, Address(rcx, r16, (Address::ScaleFactor)0, -0x36b448c9), true);", // IID693 - "__ eshrq(r26, Address(r25, rcx, (Address::ScaleFactor)2, -0x5f894993), false);", // IID694 - "__ eshrq(r25, Address(r9, +0x51798d21), true);", // IID695 - "__ etzcntq(r28, Address(r13, r26, (Address::ScaleFactor)2, +0x207196f6), false);", // IID696 - "__ etzcntq(rbx, Address(r19, r13, (Address::ScaleFactor)0, -0x24d937d5), true);", // IID697 - "__ eaddq(r17, Address(r30, +0x3935ccff), r31, false);", // IID698 - "__ eaddq(r14, Address(r27, r10, (Address::ScaleFactor)2, -0x34ad9bab), r14, false);", // IID699 - "__ eaddq(r18, Address(r20, r23, (Address::ScaleFactor)0, +0x5ad3ed4b), r30, true);", // IID700 - "__ eaddq(r20, Address(rdx, -0x322a99e5), r20, true);", // IID701 - "__ eandq(r31, Address(rbx, r27, (Address::ScaleFactor)3, +0x4ce247d2), r17, false);", // IID702 - "__ eandq(r30, Address(r18, r19, (Address::ScaleFactor)1, -0x4ee3d14), r30, false);", // IID703 - "__ eandq(r28, Address(r11, rbx, (Address::ScaleFactor)3, -0x28994bbf), r24, true);", // IID704 - "__ eandq(r30, Address(r22, +0x7d21c24), r30, true);", // IID705 - "__ eorq(r26, Address(r15, r19, (Address::ScaleFactor)3, +0x58c21792), r20, false);", // IID706 - "__ eorq(r13, Address(r10, r27, (Address::ScaleFactor)2, -0x2c70d333), r13, false);", // IID707 - "__ eorq(rbx, Address(r12, rbx, (Address::ScaleFactor)0, -0x1fb0f1bc), r26, true);", // IID708 - "__ eorq(r31, Address(r27, r31, (Address::ScaleFactor)1, +0x28d1756), r31, true);", // IID709 - "__ esubq(r24, Address(r28, r23, (Address::ScaleFactor)1, +0x6980f610), r27, false);", // IID710 - "__ esubq(r15, Address(r11, r30, (Address::ScaleFactor)3, -0x49777e7), r15, false);", // IID711 - "__ esubq(r17, Address(r25, r13, (Address::ScaleFactor)2, +0x31619e46), r31, true);", // IID712 - "__ esubq(r18, Address(r11, r10, (Address::ScaleFactor)2, +0x1922861a), r18, true);", // IID713 - "__ exorq(rbx, Address(r11, -0x4716d420), r21, false);", // IID714 - "__ exorq(r8, Address(rdx, r9, (Address::ScaleFactor)2, -0x4cfe39c), r8, false);", // IID715 - "__ exorq(r16, Address(r14, r27, (Address::ScaleFactor)0, +0x7c6654d9), r25, true);", // IID716 - "__ exorq(r29, Address(r15, -0x5efab479), r29, true);", // IID717 - "__ eaddq(r19, Address(r13, r22, (Address::ScaleFactor)2, +0x68b64559), 16777216, false);", // IID718 - "__ eaddq(r16, Address(r13, r31, (Address::ScaleFactor)3, -0x65143af5), 1, true);", // IID719 - "__ eandq(r31, Address(r24, r13, (Address::ScaleFactor)1, -0x25b16a0e), 1, false);", // IID720 - "__ eandq(r11, Address(r28, -0xf6d4b26), 65536, true);", // IID721 - "__ eimulq(rcx, Address(r18, r10, (Address::ScaleFactor)0, +0x46ec6da1), 16777216, false);", // IID722 - "__ eimulq(r15, Address(r9, r10, (Address::ScaleFactor)3, -0x7fc36af3), 16, true);", // IID723 - "__ eorq(r17, Address(r27, r30, (Address::ScaleFactor)0, +0x1b4cda2c), 1, false);", // IID724 - "__ eorq(rdx, Address(r25, r14, (Address::ScaleFactor)2, -0x59aa6b85), 4096, true);", // IID725 - "__ esalq(r17, Address(r26, r21, (Address::ScaleFactor)1, -0x6ab1f15f), 8, false);", // IID726 - "__ esalq(r12, Address(r22, r17, (Address::ScaleFactor)0, -0x43ac14ab), 2, true);", // IID727 - "__ esarq(r29, Address(r18, r16, (Address::ScaleFactor)0, -0x59dc0c61), 4, false);", // IID728 - "__ esarq(r16, Address(r11, -0x7bdd314), 4, true);", // IID729 - "__ eshrq(r26, Address(r23, r27, (Address::ScaleFactor)3, -0x55b92314), 16, false);", // IID730 - "__ eshrq(r23, Address(r16, r29, (Address::ScaleFactor)1, +0x71311a1d), 2, true);", // IID731 - "__ esubq(r25, Address(r9, -0x9532bac), 1048576, false);", // IID732 - "__ esubq(r17, Address(r8, r23, (Address::ScaleFactor)0, +0x55d06ca2), 1048576, true);", // IID733 - "__ exorq(r29, Address(r9, r24, (Address::ScaleFactor)0, -0x2c141c1), 1048576, false);", // IID734 - "__ exorq(r28, Address(r22, r19, (Address::ScaleFactor)1, -0x2d9d9abd), 16, true);", // IID735 - "__ eaddq(r22, r14, 16, false);", // IID736 - "__ eaddq(rax, r12, 16, false);", // IID737 - "__ eaddq(r24, r24, 65536, false);", // IID738 - "__ eaddq(r21, rbx, 65536, true);", // IID739 - "__ eaddq(rax, rbx, 65536, true);", // IID740 - "__ eaddq(r24, r24, 65536, true);", // IID741 - "__ eandq(r21, r27, 16777216, false);", // IID742 - "__ eandq(rax, r27, 16777216, false);", // IID743 - "__ eandq(r24, r24, 65536, false);", // IID744 - "__ eandq(r13, r31, 1048576, true);", // IID745 - "__ eandq(rax, r21, 1048576, true);", // IID746 - "__ eandq(r30, r30, 1048576, true);", // IID747 - "__ eimulq(r8, r13, 268435456, false);", // IID748 - "__ eimulq(rax, r31, 268435456, false);", // IID749 - "__ eimulq(r13, r13, 65536, false);", // IID750 - "__ eimulq(r14, r29, 1048576, true);", // IID751 - "__ eimulq(rax, r22, 1048576, true);", // IID752 - "__ eimulq(r8, r8, 268435456, true);", // IID753 - "__ eorq(r30, r15, 4096, false);", // IID754 - "__ eorq(rax, r28, 4096, false);", // IID755 - "__ eorq(r26, r26, 1048576, false);", // IID756 - "__ eorq(r16, r12, 268435456, true);", // IID757 - "__ eorq(rax, r9, 268435456, true);", // IID758 - "__ eorq(r23, r23, 256, true);", // IID759 - "__ erclq(r15, r9, 16);", // IID760 - "__ erclq(rax, r8, 16);", // IID761 - "__ erclq(r25, r25, 1);", // IID762 - "__ erolq(r9, r17, 16, false);", // IID763 - "__ erolq(rax, r20, 16, false);", // IID764 - "__ erolq(r27, r27, 1, false);", // IID765 - "__ erolq(r20, r31, 1, true);", // IID766 - "__ erolq(rax, r18, 1, true);", // IID767 - "__ erolq(r28, r28, 16, true);", // IID768 - "__ erorq(r26, r18, 16, false);", // IID769 - "__ erorq(rax, r24, 16, false);", // IID770 - "__ erorq(r22, r22, 16, false);", // IID771 - "__ erorq(r27, r29, 1, true);", // IID772 - "__ erorq(rax, r18, 1, true);", // IID773 - "__ erorq(r21, r21, 1, true);", // IID774 - "__ esalq(r12, rcx, 2, false);", // IID775 - "__ esalq(rax, r24, 2, false);", // IID776 - "__ esalq(r22, r22, 8, false);", // IID777 - "__ esalq(r17, r23, 8, true);", // IID778 - "__ esalq(rax, r27, 8, true);", // IID779 - "__ esalq(r23, r23, 1, true);", // IID780 - "__ esarq(r8, r25, 16, false);", // IID781 - "__ esarq(rax, r23, 16, false);", // IID782 - "__ esarq(r9, r9, 4, false);", // IID783 - "__ esarq(r22, r13, 1, true);", // IID784 - "__ esarq(rax, r11, 1, true);", // IID785 - "__ esarq(r12, r12, 2, true);", // IID786 - "__ eshlq(rcx, r30, 8, false);", // IID787 - "__ eshlq(rax, r19, 8, false);", // IID788 - "__ eshlq(r13, r13, 2, false);", // IID789 - "__ eshlq(r18, r11, 8, true);", // IID790 - "__ eshlq(rax, r9, 8, true);", // IID791 - "__ eshlq(rcx, rcx, 16, true);", // IID792 - "__ eshrq(r10, r22, 4, false);", // IID793 - "__ eshrq(rax, r9, 4, false);", // IID794 - "__ eshrq(r12, r12, 2, false);", // IID795 - "__ eshrq(r26, r31, 8, true);", // IID796 - "__ eshrq(rax, r12, 8, true);", // IID797 - "__ eshrq(r28, r28, 1, true);", // IID798 - "__ esubq(r15, r30, 65536, false);", // IID799 - "__ esubq(rax, rcx, 65536, false);", // IID800 - "__ esubq(r26, r26, 16, false);", // IID801 - "__ esubq(r12, r14, 1, true);", // IID802 - "__ esubq(rax, r21, 1, true);", // IID803 - "__ esubq(r20, r20, 1048576, true);", // IID804 - "__ exorq(r11, rbx, 16777216, false);", // IID805 - "__ exorq(rax, r23, 16777216, false);", // IID806 - "__ exorq(r31, r31, 268435456, false);", // IID807 - "__ exorq(r29, r28, 4096, true);", // IID808 - "__ exorq(rax, r19, 4096, true);", // IID809 - "__ exorq(rdx, rdx, 268435456, true);", // IID810 - "__ eorq_imm32(rdx, rdx, 1048576, false);", // IID811 - "__ eorq_imm32(rax, r22, 1048576, false);", // IID812 - "__ eorq_imm32(r29, r29, 1048576, false);", // IID813 - "__ eorq_imm32(r17, rcx, 4194304, false);", // IID814 - "__ eorq_imm32(rax, r25, 4194304, false);", // IID815 - "__ eorq_imm32(r27, r27, 1073741824, false);", // IID816 - "__ esubq_imm32(r16, r19, 4194304, false);", // IID817 - "__ esubq_imm32(rax, r31, 4194304, false);", // IID818 - "__ esubq_imm32(r26, r26, 262144, false);", // IID819 - "__ esubq_imm32(r17, r22, 1073741824, true);", // IID820 - "__ esubq_imm32(rax, r18, 1073741824, true);", // IID821 - "__ esubq_imm32(r23, r23, 268435456, true);", // IID822 - "__ eaddq(r13, r30, Address(r24, r19, (Address::ScaleFactor)1, +0x56ea3a3b), false);", // IID823 - "__ eaddq(r29, r15, Address(r26, r27, (Address::ScaleFactor)3, -0x4b113958), true);", // IID824 - "__ eandq(r12, r30, Address(r31, -0x46103c74), false);", // IID825 - "__ eandq(r27, r10, Address(r22, r25, (Address::ScaleFactor)1, +0x6a1ebee5), true);", // IID826 - "__ eorq(r30, r26, Address(r11, r18, (Address::ScaleFactor)2, -0x2b9fff29), false);", // IID827 - "__ eorq(r9, r12, Address(r18, r17, (Address::ScaleFactor)0, +0xb4859f6), true);", // IID828 - "__ eimulq(rdx, r17, Address(r24, rdx, (Address::ScaleFactor)2, +0x3d284cd8), false);", // IID829 - "__ eimulq(r29, r26, Address(r30, r12, (Address::ScaleFactor)1, +0x6e813124), true);", // IID830 - "__ esubq(rbx, r13, Address(r22, -0x702a289e), false);", // IID831 - "__ esubq(r23, r29, Address(r25, rdx, (Address::ScaleFactor)0, -0x6252a7ed), true);", // IID832 - "__ exorq(r8, r18, Address(r19, r14, (Address::ScaleFactor)2, -0xebfa697), false);", // IID833 - "__ exorq(r10, r28, Address(r26, +0x168381ca), true);", // IID834 - "__ eaddq(rcx, r18, r8, false);", // IID835 - "__ eaddq(rcx, rcx, r14, false);", // IID836 - "__ eaddq(r23, r10, r16, true);", // IID837 - "__ eaddq(r11, r11, r24, true);", // IID838 - "__ eadcxq(r9, r18, rdx);", // IID839 - "__ eadcxq(r8, r8, r15);", // IID840 - "__ eadoxq(r15, r22, r26);", // IID841 - "__ eadoxq(r11, r11, rdx);", // IID842 - "__ eandq(r19, rdx, r22, false);", // IID843 - "__ eandq(r29, r29, r17, false);", // IID844 - "__ eandq(r23, r27, r15, true);", // IID845 - "__ eandq(r9, r9, r13, true);", // IID846 - "__ eimulq(r18, r15, r16, false);", // IID847 - "__ eimulq(rcx, rcx, r17, false);", // IID848 - "__ eimulq(r23, r12, r20, true);", // IID849 - "__ eimulq(r10, r10, r9, true);", // IID850 - "__ eorq(rdx, r19, r14, false);", // IID851 - "__ eorq(rcx, rcx, r13, false);", // IID852 - "__ eorq(r9, r25, r29, true);", // IID853 - "__ eorq(rdx, rdx, r25, true);", // IID854 - "__ esubq(r23, r8, r16, false);", // IID855 - "__ esubq(r13, r13, r13, false);", // IID856 - "__ esubq(r19, r12, r15, true);", // IID857 - "__ esubq(r9, r9, rdx, true);", // IID858 - "__ exorq(r13, r16, r31, false);", // IID859 - "__ exorq(r17, r17, r30, false);", // IID860 - "__ exorq(r19, r30, r20, true);", // IID861 - "__ exorq(r31, r31, r13, true);", // IID862 - "__ eshldq(r22, r10, r13, 4, false);", // IID863 - "__ eshldq(r24, r24, r21, 16, false);", // IID864 - "__ eshldq(r20, r13, r27, 16, true);", // IID865 - "__ eshldq(r31, r31, r19, 2, true);", // IID866 - "__ eshrdq(r30, r20, r11, 8, false);", // IID867 - "__ eshrdq(rdx, rdx, r15, 1, false);", // IID868 - "__ eshrdq(r28, r30, r14, 2, true);", // IID869 - "__ eshrdq(r20, r20, r16, 1, true);", // IID870 - "__ ecmovq (Assembler::Condition::overflow, r21, r17, r28);", // IID871 - "__ ecmovq (Assembler::Condition::overflow, r15, r15, r30);", // IID872 - "__ ecmovq (Assembler::Condition::noOverflow, rcx, r15, r15);", // IID873 - "__ ecmovq (Assembler::Condition::noOverflow, rcx, rcx, r13);", // IID874 - "__ ecmovq (Assembler::Condition::below, rdx, r26, r26);", // IID875 - "__ ecmovq (Assembler::Condition::below, r28, r28, r15);", // IID876 - "__ ecmovq (Assembler::Condition::aboveEqual, r8, rdx, rcx);", // IID877 - "__ ecmovq (Assembler::Condition::aboveEqual, rcx, rcx, rcx);", // IID878 - "__ ecmovq (Assembler::Condition::zero, r10, r13, r9);", // IID879 - "__ ecmovq (Assembler::Condition::zero, r14, r14, r27);", // IID880 - "__ ecmovq (Assembler::Condition::notZero, r11, r23, r9);", // IID881 - "__ ecmovq (Assembler::Condition::notZero, r11, r11, rdx);", // IID882 - "__ ecmovq (Assembler::Condition::belowEqual, r31, r14, r25);", // IID883 - "__ ecmovq (Assembler::Condition::belowEqual, r20, r20, r12);", // IID884 - "__ ecmovq (Assembler::Condition::above, rdx, r10, r28);", // IID885 - "__ ecmovq (Assembler::Condition::above, r8, r8, r17);", // IID886 - "__ ecmovq (Assembler::Condition::negative, rcx, r30, r23);", // IID887 - "__ ecmovq (Assembler::Condition::negative, r26, r26, r18);", // IID888 - "__ ecmovq (Assembler::Condition::positive, rdx, rbx, r18);", // IID889 - "__ ecmovq (Assembler::Condition::positive, r21, r21, r13);", // IID890 - "__ ecmovq (Assembler::Condition::parity, r27, r28, r27);", // IID891 - "__ ecmovq (Assembler::Condition::parity, r11, r11, r30);", // IID892 - "__ ecmovq (Assembler::Condition::noParity, rcx, r21, r18);", // IID893 - "__ ecmovq (Assembler::Condition::noParity, rcx, rcx, r29);", // IID894 - "__ ecmovq (Assembler::Condition::less, rdx, r21, r12);", // IID895 - "__ ecmovq (Assembler::Condition::less, rdx, rdx, r26);", // IID896 - "__ ecmovq (Assembler::Condition::greaterEqual, r17, rbx, r22);", // IID897 - "__ ecmovq (Assembler::Condition::greaterEqual, rdx, rdx, r11);", // IID898 - "__ ecmovq (Assembler::Condition::lessEqual, rdx, r14, r8);", // IID899 - "__ ecmovq (Assembler::Condition::lessEqual, r14, r14, r8);", // IID900 - "__ ecmovq (Assembler::Condition::greater, r25, r29, r21);", // IID901 - "__ ecmovq (Assembler::Condition::greater, r26, r26, r30);", // IID902 - "__ ecmovq (Assembler::Condition::overflow, r24, r21, Address(r13, r11, (Address::ScaleFactor)1, +0x439c521e));", // IID903 - "__ ecmovq (Assembler::Condition::noOverflow, r11, r18, Address(r29, r16, (Address::ScaleFactor)0, +0x632127f));", // IID904 - "__ ecmovq (Assembler::Condition::below, r16, r8, Address(r8, r26, (Address::ScaleFactor)1, +0x10633def));", // IID905 - "__ ecmovq (Assembler::Condition::aboveEqual, r13, r14, Address(r18, -0x54f69e38));", // IID906 - "__ ecmovq (Assembler::Condition::zero, r12, r8, Address(r31, r26, (Address::ScaleFactor)1, -0x7a1e447a));", // IID907 - "__ ecmovq (Assembler::Condition::notZero, r29, r29, Address(r19, r11, (Address::ScaleFactor)2, -0x35d82dd2));", // IID908 - "__ ecmovq (Assembler::Condition::belowEqual, rcx, r18, Address(r25, r28, (Address::ScaleFactor)0, +0x30be64a0));", // IID909 - "__ ecmovq (Assembler::Condition::above, r28, r12, Address(r10, r16, (Address::ScaleFactor)1, -0x22b8fefa));", // IID910 - "__ ecmovq (Assembler::Condition::negative, r11, r8, Address(rbx, r11, (Address::ScaleFactor)3, +0x25cc9e96));", // IID911 - "__ ecmovq (Assembler::Condition::positive, r12, r27, Address(r11, -0xc2d70fe));", // IID912 - "__ ecmovq (Assembler::Condition::parity, r8, r26, Address(r19, rbx, (Address::ScaleFactor)1, -0x486db7ea));", // IID913 - "__ ecmovq (Assembler::Condition::noParity, r30, r10, Address(r14, r18, (Address::ScaleFactor)3, +0x14884884));", // IID914 - "__ ecmovq (Assembler::Condition::less, r27, r8, Address(r29, r14, (Address::ScaleFactor)2, +0x92b7a8));", // IID915 - "__ ecmovq (Assembler::Condition::greaterEqual, r14, r28, Address(r19, rdx, (Address::ScaleFactor)0, +0x9c2d45));", // IID916 - "__ ecmovq (Assembler::Condition::lessEqual, r25, r8, Address(rcx, r18, (Address::ScaleFactor)2, +0x6655c86b));", // IID917 - "__ ecmovq (Assembler::Condition::greater, r19, r21, Address(r10, r25, (Address::ScaleFactor)0, -0x1005430b));", // IID918 + "__ eorl(rcx, r24, r22, false);", // IID432 + "__ eorl(rcx, rcx, r19, false);", // IID433 + "__ eorl(r27, r27, r27, false);", // IID434 + "__ eorl(r31, r9, r13, true);", // IID435 + "__ eorl(r31, r31, r23, true);", // IID436 + "__ eorl(r19, r17, r19, true);", // IID437 + "__ eshldl(r20, r16, r24, false);", // IID438 + "__ eshldl(rdx, rdx, r12, false);", // IID439 + "__ eshldl(r29, r9, r31, true);", // IID440 + "__ eshldl(r17, r17, r20, true);", // IID441 + "__ eshrdl(r20, r15, r18, false);", // IID442 + "__ eshrdl(rcx, rcx, r12, false);", // IID443 + "__ eshrdl(r14, r9, r23, true);", // IID444 + "__ eshrdl(r19, r19, r13, true);", // IID445 + "__ esubl(r30, r27, r27, false);", // IID446 + "__ esubl(rdx, rdx, r11, false);", // IID447 + "__ esubl(r15, r11, r24, true);", // IID448 + "__ esubl(r14, r14, r25, true);", // IID449 + "__ exorl(r31, r16, r12, false);", // IID450 + "__ exorl(r20, r20, r14, false);", // IID451 + "__ exorl(r30, r13, r30, false);", // IID452 + "__ exorl(r24, r17, r17, true);", // IID453 + "__ exorl(r26, r26, r21, true);", // IID454 + "__ exorl(r11, r13, r11, true);", // IID455 + "__ eshldl(r27, r25, r21, 4, false);", // IID456 + "__ eshldl(r22, r22, r10, 4, false);", // IID457 + "__ eshldl(r21, r15, r24, 16, true);", // IID458 + "__ eshldl(rdx, rdx, r19, 1, true);", // IID459 + "__ eshrdl(r23, r13, r8, 16, false);", // IID460 + "__ eshrdl(r26, r26, r22, 1, false);", // IID461 + "__ eshrdl(r24, r9, r30, 16, true);", // IID462 + "__ eshrdl(r19, r19, r8, 4, true);", // IID463 + "__ ecmovl (Assembler::Condition::overflow, r30, r26, r17);", // IID464 + "__ ecmovl (Assembler::Condition::overflow, r14, r14, r26);", // IID465 + "__ ecmovl (Assembler::Condition::noOverflow, r24, r19, r29);", // IID466 + "__ ecmovl (Assembler::Condition::noOverflow, r25, r25, r20);", // IID467 + "__ ecmovl (Assembler::Condition::below, r11, r10, r14);", // IID468 + "__ ecmovl (Assembler::Condition::below, r30, r30, r25);", // IID469 + "__ ecmovl (Assembler::Condition::aboveEqual, r13, r22, r27);", // IID470 + "__ ecmovl (Assembler::Condition::aboveEqual, r16, r16, r24);", // IID471 + "__ ecmovl (Assembler::Condition::zero, r28, r13, r30);", // IID472 + "__ ecmovl (Assembler::Condition::zero, r30, r30, r24);", // IID473 + "__ ecmovl (Assembler::Condition::notZero, r21, r20, r31);", // IID474 + "__ ecmovl (Assembler::Condition::notZero, r8, r8, r16);", // IID475 + "__ ecmovl (Assembler::Condition::belowEqual, r15, r26, r22);", // IID476 + "__ ecmovl (Assembler::Condition::belowEqual, r31, r31, rdx);", // IID477 + "__ ecmovl (Assembler::Condition::above, r27, r8, r10);", // IID478 + "__ ecmovl (Assembler::Condition::above, r18, r18, r11);", // IID479 + "__ ecmovl (Assembler::Condition::negative, r27, rbx, r21);", // IID480 + "__ ecmovl (Assembler::Condition::negative, r12, r12, r31);", // IID481 + "__ ecmovl (Assembler::Condition::positive, r12, rdx, r18);", // IID482 + "__ ecmovl (Assembler::Condition::positive, r18, r18, r19);", // IID483 + "__ ecmovl (Assembler::Condition::parity, r16, r20, r23);", // IID484 + "__ ecmovl (Assembler::Condition::parity, r18, r18, r16);", // IID485 + "__ ecmovl (Assembler::Condition::noParity, rbx, r31, r30);", // IID486 + "__ ecmovl (Assembler::Condition::noParity, r31, r31, r29);", // IID487 + "__ ecmovl (Assembler::Condition::less, r28, r25, r10);", // IID488 + "__ ecmovl (Assembler::Condition::less, r24, r24, r20);", // IID489 + "__ ecmovl (Assembler::Condition::greaterEqual, r16, rdx, r26);", // IID490 + "__ ecmovl (Assembler::Condition::greaterEqual, r28, r28, r28);", // IID491 + "__ ecmovl (Assembler::Condition::lessEqual, r9, r20, r24);", // IID492 + "__ ecmovl (Assembler::Condition::lessEqual, r24, r24, r29);", // IID493 + "__ ecmovl (Assembler::Condition::greater, r23, r27, r15);", // IID494 + "__ ecmovl (Assembler::Condition::greater, r12, r12, r18);", // IID495 + "__ ecmovl (Assembler::Condition::overflow, r19, r9, Address(r31, rcx, (Address::ScaleFactor)1, -0x2be98bd));", // IID496 + "__ ecmovl (Assembler::Condition::overflow, r8, r8, Address(r21, r24, (Address::ScaleFactor)1, +0x41e6a0cb));", // IID497 + "__ ecmovl (Assembler::Condition::noOverflow, r23, r15, Address(r19, r30, (Address::ScaleFactor)3, -0x55adfe2d));", // IID498 + "__ ecmovl (Assembler::Condition::noOverflow, rdx, rdx, Address(r27, rdx, (Address::ScaleFactor)0, -0x1aa12735));", // IID499 + "__ ecmovl (Assembler::Condition::below, rbx, r29, Address(r31, r12, (Address::ScaleFactor)0, +0xbd42246));", // IID500 + "__ ecmovl (Assembler::Condition::below, r21, r21, Address(r19, r21, (Address::ScaleFactor)1, -0x41518818));", // IID501 + "__ ecmovl (Assembler::Condition::aboveEqual, r23, r29, Address(r22, r9, (Address::ScaleFactor)2, -0x35addbd8));", // IID502 + "__ ecmovl (Assembler::Condition::aboveEqual, r18, r18, Address(r25, +0x632184c3));", // IID503 + "__ ecmovl (Assembler::Condition::zero, r29, r13, Address(r18, r13, (Address::ScaleFactor)0, -0x3972eac6));", // IID504 + "__ ecmovl (Assembler::Condition::zero, r29, r29, Address(r12, r9, (Address::ScaleFactor)3, -0x668cdfd2));", // IID505 + "__ ecmovl (Assembler::Condition::notZero, r25, r18, Address(r9, r22, (Address::ScaleFactor)2, +0x7f6ac91f));", // IID506 + "__ ecmovl (Assembler::Condition::notZero, r28, r28, Address(r30, +0x562e6594));", // IID507 + "__ ecmovl (Assembler::Condition::belowEqual, r27, r24, Address(r15, r20, (Address::ScaleFactor)2, -0x466538b7));", // IID508 + "__ ecmovl (Assembler::Condition::belowEqual, r25, r25, Address(r26, r11, (Address::ScaleFactor)3, -0x593812a9));", // IID509 + "__ ecmovl (Assembler::Condition::above, rcx, r20, Address(r16, -0x1389a3eb));", // IID510 + "__ ecmovl (Assembler::Condition::above, rbx, rbx, Address(r29, r8, (Address::ScaleFactor)0, +0x1d022615));", // IID511 + "__ ecmovl (Assembler::Condition::negative, rdx, r14, Address(r12, r28, (Address::ScaleFactor)1, -0x51725a91));", // IID512 + "__ ecmovl (Assembler::Condition::negative, r24, r24, Address(r17, r18, (Address::ScaleFactor)1, -0x1725c4e4));", // IID513 + "__ ecmovl (Assembler::Condition::positive, rcx, rcx, Address(r15, r23, (Address::ScaleFactor)2, -0x6bd22ccf));", // IID514 + "__ ecmovl (Assembler::Condition::positive, r24, r24, Address(r15, r10, (Address::ScaleFactor)1, -0x7ffb3d09));", // IID515 + "__ ecmovl (Assembler::Condition::parity, r23, rcx, Address(r11, r23, (Address::ScaleFactor)0, +0x3738c585));", // IID516 + "__ ecmovl (Assembler::Condition::parity, r24, r24, Address(r30, r10, (Address::ScaleFactor)0, +0xfcc15a8));", // IID517 + "__ ecmovl (Assembler::Condition::noParity, r14, r26, Address(r14, r21, (Address::ScaleFactor)1, -0x4430ce9f));", // IID518 + "__ ecmovl (Assembler::Condition::noParity, r10, r10, Address(r28, +0x3d7c59f));", // IID519 + "__ ecmovl (Assembler::Condition::less, r10, r21, Address(r8, r8, (Address::ScaleFactor)3, +0x4a6584b4));", // IID520 + "__ ecmovl (Assembler::Condition::less, r26, r26, Address(r19, r20, (Address::ScaleFactor)3, +0x47c660ef));", // IID521 + "__ ecmovl (Assembler::Condition::greaterEqual, r26, r10, Address(rcx, +0x61977a97));", // IID522 + "__ ecmovl (Assembler::Condition::greaterEqual, r30, r30, Address(r15, r19, (Address::ScaleFactor)3, +0x53c601cb));", // IID523 + "__ ecmovl (Assembler::Condition::lessEqual, r14, r9, Address(r17, -0x566ceee2));", // IID524 + "__ ecmovl (Assembler::Condition::lessEqual, r15, r15, Address(r27, r20, (Address::ScaleFactor)0, +0x76164792));", // IID525 + "__ ecmovl (Assembler::Condition::greater, r27, r14, Address(r9, r13, (Address::ScaleFactor)2, +0xf5752d7));", // IID526 + "__ ecmovl (Assembler::Condition::greater, r12, r12, Address(rbx, rcx, (Address::ScaleFactor)3, -0x5501b4c6));", // IID527 + "__ adcq(r30, r31);", // IID528 + "__ cmpq(r12, rdx);", // IID529 + "__ imulq(r21, r24);", // IID530 + "__ popcntq(r9, r25);", // IID531 + "__ sbbq(r8, r12);", // IID532 + "__ subq(r31, r24);", // IID533 + "__ tzcntq(r10, r16);", // IID534 + "__ lzcntq(r20, r21);", // IID535 + "__ addq(rdx, r17);", // IID536 + "__ andq(r14, r13);", // IID537 + "__ orq(r20, r24);", // IID538 + "__ xorq(r21, r22);", // IID539 + "__ movq(r12, r27);", // IID540 + "__ bsfq(r23, rdx);", // IID541 + "__ bsrq(r31, r28);", // IID542 + "__ btq(r8, r25);", // IID543 + "__ xchgq(r21, rbx);", // IID544 + "__ testq(r23, r23);", // IID545 + "__ addq(Address(r19, -0x180d3ea1), r10);", // IID546 + "__ andq(Address(r11, r17, (Address::ScaleFactor)1, -0x78976be8), r25);", // IID547 + "__ cmpq(Address(rbx, r28, (Address::ScaleFactor)3, +0x35f72102), r13);", // IID548 + "__ orq(Address(r8, -0x34465011), r21);", // IID549 + "__ xorq(Address(r19, -0x404b22dd), r18);", // IID550 + "__ subq(Address(r23, r27, (Address::ScaleFactor)3, -0x428d2646), r14);", // IID551 + "__ movq(Address(r9, rcx, (Address::ScaleFactor)2, -0x72611661), r28);", // IID552 + "__ xaddq(Address(r24, r21, (Address::ScaleFactor)2, +0x3a6be990), rbx);", // IID553 + "__ andq(Address(r22, r10, (Address::ScaleFactor)0, +0x7ef8bdd), 1048576);", // IID554 + "__ addq(Address(r13, r28, (Address::ScaleFactor)0, -0x754789b1), 65536);", // IID555 + "__ cmpq(Address(r10, -0xbd2a8da), 268435456);", // IID556 + "__ sarq(Address(r23, r14, (Address::ScaleFactor)1, +0x6a16d9f5), 4);", // IID557 + "__ salq(Address(rcx, r21, (Address::ScaleFactor)1, +0x5f66ac1e), 8);", // IID558 + "__ sbbq(Address(rcx, r22, (Address::ScaleFactor)3, -0x48c954c), 268435456);", // IID559 + "__ shrq(Address(r21, r30, (Address::ScaleFactor)0, +0xe405b0b), 8);", // IID560 + "__ subq(Address(r19, r29, (Address::ScaleFactor)3, -0x7762044b), 4096);", // IID561 + "__ xorq(Address(r30, r10, (Address::ScaleFactor)1, -0x19798323), 16);", // IID562 + "__ orq(Address(rdx, r24, (Address::ScaleFactor)3, +0x18d9b316), 4096);", // IID563 + "__ movq(Address(rbx, -0x3058074d), 256);", // IID564 + "__ testq(Address(r28, r21, (Address::ScaleFactor)3, +0x65a0fdc4), -268435456);", // IID565 + "__ addq(r23, Address(r11, r18, (Address::ScaleFactor)0, -0x1d1af10c));", // IID566 + "__ andq(r22, Address(r18, r12, (Address::ScaleFactor)1, +0x1a5f1c38));", // IID567 + "__ cmpq(r23, Address(r30, r19, (Address::ScaleFactor)0, -0x3e912f7f));", // IID568 + "__ lzcntq(r29, Address(rcx, +0x12e3fbe4));", // IID569 + "__ orq(r14, Address(r21, r21, (Address::ScaleFactor)2, +0xd73042));", // IID570 + "__ adcq(r31, Address(r17, r31, (Address::ScaleFactor)2, +0xabde912));", // IID571 + "__ imulq(r20, Address(r13, r27, (Address::ScaleFactor)0, -0x58dbfc1f));", // IID572 + "__ popcntq(rbx, Address(r22, -0x72c66c23));", // IID573 + "__ sbbq(r26, Address(r9, +0x334aba09));", // IID574 + "__ subq(r9, Address(r9, r30, (Address::ScaleFactor)3, -0x219a6102));", // IID575 + "__ tzcntq(r25, Address(r20, -0x2131bab1));", // IID576 + "__ xorq(r16, Address(r28, r16, (Address::ScaleFactor)1, +0x48c483b9));", // IID577 + "__ movq(r30, Address(r9, r16, (Address::ScaleFactor)0, -0x88ce84f));", // IID578 + "__ leaq(r11, Address(r30, r29, (Address::ScaleFactor)2, +0x3eeb8fd0));", // IID579 + "__ cvttsd2siq(r26, Address(r29, r10, (Address::ScaleFactor)3, +0x3ef4822e));", // IID580 + "__ xchgq(r29, Address(r19, r20, (Address::ScaleFactor)2, -0x3f0f3db9));", // IID581 + "__ testq(r8, Address(r30, r20, (Address::ScaleFactor)0, +0x15b56a17));", // IID582 + "__ addq(r26, 4096);", // IID583 + "__ andq(r20, 16);", // IID584 + "__ adcq(r23, 1048576);", // IID585 + "__ cmpq(r12, 4096);", // IID586 + "__ rclq(rcx, 4);", // IID587 + "__ rcrq(r14, 1);", // IID588 + "__ rolq(r23, 2);", // IID589 + "__ rorq(r12, 4);", // IID590 + "__ sarq(r10, 4);", // IID591 + "__ salq(r20, 4);", // IID592 + "__ sbbq(rcx, 1048576);", // IID593 + "__ shlq(r23, 16);", // IID594 + "__ shrq(r27, 2);", // IID595 + "__ subq(rcx, 65536);", // IID596 + "__ xorq(r9, 1048576);", // IID597 + "__ movq(r16, 65536);", // IID598 + "__ mov64(r24, 4503599627370496);", // IID599 + "__ btq(r18, 64);", // IID600 + "__ testq(r29, -4096);", // IID601 + "__ orq_imm32(r30, 67108864);", // IID602 + "__ subq_imm32(r25, 268435456);", // IID603 + "__ cmovq(Assembler::Condition::overflow, r30, Address(r17, r31, (Address::ScaleFactor)2, +0x47ff92f0));", // IID604 + "__ cmovq(Assembler::Condition::noOverflow, r9, Address(r24, r28, (Address::ScaleFactor)1, +0x384904c0));", // IID605 + "__ cmovq(Assembler::Condition::below, r23, Address(r23, r24, (Address::ScaleFactor)3, -0x197f1266));", // IID606 + "__ cmovq(Assembler::Condition::aboveEqual, r9, Address(r29, r30, (Address::ScaleFactor)0, +0x2b5d49c8));", // IID607 + "__ cmovq(Assembler::Condition::zero, r16, Address(rbx, r15, (Address::ScaleFactor)1, +0x22379381));", // IID608 + "__ cmovq(Assembler::Condition::notZero, r8, Address(r11, +0x49d67a0));", // IID609 + "__ cmovq(Assembler::Condition::belowEqual, r28, Address(r16, r16, (Address::ScaleFactor)2, -0x5e941da9));", // IID610 + "__ cmovq(Assembler::Condition::above, r19, Address(r18, r8, (Address::ScaleFactor)0, -0xa5e55ec));", // IID611 + "__ cmovq(Assembler::Condition::negative, r28, Address(r17, r28, (Address::ScaleFactor)1, -0x3264220c));", // IID612 + "__ cmovq(Assembler::Condition::positive, r31, Address(r14, r31, (Address::ScaleFactor)1, +0x5001bc5a));", // IID613 + "__ cmovq(Assembler::Condition::parity, rbx, Address(r18, r17, (Address::ScaleFactor)2, -0x286f2379));", // IID614 + "__ cmovq(Assembler::Condition::noParity, r17, Address(r20, -0x5549f838));", // IID615 + "__ cmovq(Assembler::Condition::less, r30, Address(r9, r28, (Address::ScaleFactor)1, -0x25b00cf3));", // IID616 + "__ cmovq(Assembler::Condition::greaterEqual, r19, Address(r9, -0x2aabf22c));", // IID617 + "__ cmovq(Assembler::Condition::lessEqual, rbx, Address(rcx, r12, (Address::ScaleFactor)1, -0x432d68cc));", // IID618 + "__ cmovq(Assembler::Condition::greater, rbx, Address(r15, r17, (Address::ScaleFactor)3, -0x2b97565e));", // IID619 + "__ call(r24);", // IID620 + "__ divq(r9);", // IID621 + "__ idivq(r28);", // IID622 + "__ imulq(rdx);", // IID623 + "__ mulq(r31);", // IID624 + "__ negq(r12);", // IID625 + "__ notq(r12);", // IID626 + "__ rolq(r24);", // IID627 + "__ rorq(r28);", // IID628 + "__ sarq(r11);", // IID629 + "__ salq(r27);", // IID630 + "__ shlq(r23);", // IID631 + "__ shrq(r17);", // IID632 + "__ incrementq(r16);", // IID633 + "__ decrementq(r12);", // IID634 + "__ pushp(r23);", // IID635 + "__ popp(r24);", // IID636 + "__ call(Address(r18, r14, (Address::ScaleFactor)0, -0x66639d32));", // IID637 + "__ mulq(Address(r24, -0x660a2421));", // IID638 + "__ negq(Address(r14, r18, (Address::ScaleFactor)0, +0x40f3936e));", // IID639 + "__ sarq(Address(r10, r13, (Address::ScaleFactor)0, +0x7d04cb72));", // IID640 + "__ salq(Address(r18, r11, (Address::ScaleFactor)3, -0x2176b4dc));", // IID641 + "__ shrq(Address(r13, rcx, (Address::ScaleFactor)1, +0x7996aa80));", // IID642 + "__ incrementq(Address(r14, +0x67c2d02a));", // IID643 + "__ decrementq(Address(r22, r26, (Address::ScaleFactor)0, +0x224f62c0));", // IID644 + "__ imulq(rdx, Address(r31, rbx, (Address::ScaleFactor)1, +0x2b00bb10), 16777216);", // IID645 + "__ imulq(r21, r31, 4096);", // IID646 + "__ shldq(rbx, r19, 1);", // IID647 + "__ shrdq(r11, r23, 4);", // IID648 + "__ pop2(r16, r30);", // IID649 + "__ pop2p(r17, rbx);", // IID650 + "__ push2(r20, r30);", // IID651 + "__ push2p(r8, r31);", // IID652 + "__ movzbq(r28, Address(r8, r14, (Address::ScaleFactor)0, +0x469ae67a));", // IID653 + "__ movzwq(r14, Address(r8, r18, (Address::ScaleFactor)2, -0x48699e02));", // IID654 + "__ movsbq(r21, Address(rbx, -0x64dae06b));", // IID655 + "__ movswq(r19, Address(r31, rbx, (Address::ScaleFactor)2, +0x60318819));", // IID656 + "__ movzbq(r30, r13);", // IID657 + "__ movzwq(r30, r18);", // IID658 + "__ movsbq(r19, r15);", // IID659 + "__ movswq(r20, r16);", // IID660 + "__ cmpxchgq(r28, Address(r11, rbx, (Address::ScaleFactor)3, +0xfc3479d));", // IID661 + "__ eidivq(r20, false);", // IID662 + "__ eidivq(r30, true);", // IID663 + "__ edivq(r22, false);", // IID664 + "__ edivq(r11, true);", // IID665 + "__ eimulq(rcx, false);", // IID666 + "__ eimulq(r28, true);", // IID667 + "__ emulq(r21, false);", // IID668 + "__ emulq(r13, true);", // IID669 + "__ emulq(Address(r26, r15, (Address::ScaleFactor)2, +0x70a1ce6e), false);", // IID670 + "__ emulq(Address(r24, r19, (Address::ScaleFactor)1, -0x1670855c), true);", // IID671 + "__ eimulq(r10, r27, false);", // IID672 + "__ eimulq(r17, r17, false);", // IID673 + "__ eimulq(rdx, r22, true);", // IID674 + "__ eimulq(rbx, rbx, true);", // IID675 + "__ elzcntq(r28, r15, false);", // IID676 + "__ elzcntq(r15, r15, false);", // IID677 + "__ elzcntq(rbx, r12, true);", // IID678 + "__ elzcntq(rbx, rbx, true);", // IID679 + "__ enegq(r26, r11, false);", // IID680 + "__ enegq(r17, r17, false);", // IID681 + "__ enegq(rdx, r31, true);", // IID682 + "__ enegq(r27, r27, true);", // IID683 + "__ enotq(r31, r15);", // IID684 + "__ enotq(r21, r21);", // IID685 + "__ epopcntq(rbx, r24, false);", // IID686 + "__ epopcntq(r28, r28, false);", // IID687 + "__ epopcntq(r23, r27, true);", // IID688 + "__ epopcntq(r13, r13, true);", // IID689 + "__ erolq(r25, r28, false);", // IID690 + "__ erolq(r31, r31, false);", // IID691 + "__ erolq(r25, r23, true);", // IID692 + "__ erolq(rcx, rcx, true);", // IID693 + "__ erorq(r22, r14, false);", // IID694 + "__ erorq(r15, r15, false);", // IID695 + "__ erorq(r11, r30, true);", // IID696 + "__ erorq(r24, r24, true);", // IID697 + "__ esalq(r10, r20, false);", // IID698 + "__ esalq(r19, r19, false);", // IID699 + "__ esalq(r17, r25, true);", // IID700 + "__ esalq(r13, r13, true);", // IID701 + "__ esarq(r31, r30, false);", // IID702 + "__ esarq(r18, r18, false);", // IID703 + "__ esarq(r25, r25, true);", // IID704 + "__ esarq(r28, r28, true);", // IID705 + "__ edecq(r22, r27, false);", // IID706 + "__ edecq(r12, r12, false);", // IID707 + "__ edecq(r18, r11, true);", // IID708 + "__ edecq(r10, r10, true);", // IID709 + "__ eincq(r20, r24, false);", // IID710 + "__ eincq(r18, r18, false);", // IID711 + "__ eincq(rbx, r11, true);", // IID712 + "__ eincq(r26, r26, true);", // IID713 + "__ eshlq(r21, r8, false);", // IID714 + "__ eshlq(rbx, rbx, false);", // IID715 + "__ eshlq(r22, r21, true);", // IID716 + "__ eshlq(r27, r27, true);", // IID717 + "__ eshrq(r12, r16, false);", // IID718 + "__ eshrq(r8, r8, false);", // IID719 + "__ eshrq(rdx, r9, true);", // IID720 + "__ eshrq(r20, r20, true);", // IID721 + "__ etzcntq(r31, r21, false);", // IID722 + "__ etzcntq(r20, r20, false);", // IID723 + "__ etzcntq(rcx, r16, true);", // IID724 + "__ etzcntq(r14, r14, true);", // IID725 + "__ eimulq(r27, Address(r25, r9, (Address::ScaleFactor)1, +0x445a2393), false);", // IID726 + "__ eimulq(r23, Address(rcx, r9, (Address::ScaleFactor)1, -0x1480ef0c), true);", // IID727 + "__ elzcntq(r13, Address(r22, r17, (Address::ScaleFactor)1, -0x750c1996), false);", // IID728 + "__ elzcntq(r13, Address(r31, -0x342b6259), true);", // IID729 + "__ enegq(r31, Address(r24, r13, (Address::ScaleFactor)1, -0x25b16a0e), false);", // IID730 + "__ enegq(r13, Address(r11, r28, (Address::ScaleFactor)3, +0x5c0013ab), true);", // IID731 + "__ epopcntq(rdx, Address(r18, rcx, (Address::ScaleFactor)2, -0x6113eaaf), false);", // IID732 + "__ epopcntq(r9, Address(r10, -0x5ca7d588), true);", // IID733 + "__ esalq(r17, Address(r27, r30, (Address::ScaleFactor)0, +0x1b4cda2c), false);", // IID734 + "__ esalq(r25, Address(r12, rdx, (Address::ScaleFactor)1, +0x62823bce), true);", // IID735 + "__ esarq(r9, Address(r10, r18, (Address::ScaleFactor)2, -0x264a7a48), false);", // IID736 + "__ esarq(rbx, Address(r14, r27, (Address::ScaleFactor)0, +0x20291e00), true);", // IID737 + "__ edecq(r12, Address(r15, r14, (Address::ScaleFactor)2, -0x20f7dabb), false);", // IID738 + "__ edecq(r9, Address(r10, r25, (Address::ScaleFactor)1, +0x21411d84), true);", // IID739 + "__ eincq(r20, Address(rbx, r25, (Address::ScaleFactor)3, +0x2f0329e), false);", // IID740 + "__ eincq(r10, Address(r12, r31, (Address::ScaleFactor)0, -0x37505c8c), true);", // IID741 + "__ eshrq(r24, Address(r23, r14, (Address::ScaleFactor)3, -0x71e75ab0), false);", // IID742 + "__ eshrq(r25, Address(r19, r10, (Address::ScaleFactor)1, +0x507b0a88), true);", // IID743 + "__ etzcntq(r31, Address(rbx, r16, (Address::ScaleFactor)0, +0x19d5192a), false);", // IID744 + "__ etzcntq(r9, Address(r22, r28, (Address::ScaleFactor)2, +0x211007cd), true);", // IID745 + "__ eaddq(r16, Address(r21, rbx, (Address::ScaleFactor)3, -0x823fa1e), r28, false);", // IID746 + "__ eaddq(r15, Address(rdx, r8, (Address::ScaleFactor)3, -0x34b9a058), r15, false);", // IID747 + "__ eaddq(r24, Address(r14, r24, (Address::ScaleFactor)3, +0x6cdc59d2), r13, true);", // IID748 + "__ eaddq(rbx, Address(r27, r14, (Address::ScaleFactor)3, +0x36c5e8de), rbx, true);", // IID749 + "__ eandq(r21, Address(r27, r27, (Address::ScaleFactor)1, -0x2c023b13), r27, false);", // IID750 + "__ eandq(r31, Address(r21, r15, (Address::ScaleFactor)2, +0x6ef2c74a), r31, false);", // IID751 + "__ eandq(r13, Address(r31, r25, (Address::ScaleFactor)1, +0x734fe9ab), r27, true);", // IID752 + "__ eandq(r15, Address(r14, r29, (Address::ScaleFactor)3, -0x6e68556), r15, true);", // IID753 + "__ eorq(r12, Address(r30, r15, (Address::ScaleFactor)3, +0x3ba33f9e), r28, false);", // IID754 + "__ eorq(r16, Address(r12, r9, (Address::ScaleFactor)0, -0x28e03b33), r16, false);", // IID755 + "__ eorq(r8, Address(r8, r25, (Address::ScaleFactor)3, -0x1e42bd95), r27, true);", // IID756 + "__ eorq(rcx, Address(r27, rbx, (Address::ScaleFactor)2, +0x7be4bcad), rcx, true);", // IID757 + "__ esubq(r24, Address(r23, r22, (Address::ScaleFactor)2, +0x6f8827d7), rdx, false);", // IID758 + "__ esubq(r21, Address(r10, -0x635b8c8), r21, false);", // IID759 + "__ esubq(r23, Address(r27, r26, (Address::ScaleFactor)3, +0x922bcc0), rbx, true);", // IID760 + "__ esubq(r25, Address(r23, r15, (Address::ScaleFactor)0, -0x38f494ac), r25, true);", // IID761 + "__ exorq(r11, Address(r12, r19, (Address::ScaleFactor)2, -0x5b71ec17), rcx, false);", // IID762 + "__ exorq(r28, Address(r19, r18, (Address::ScaleFactor)0, +0x716b9b7e), r28, false);", // IID763 + "__ exorq(r21, Address(rcx, r29, (Address::ScaleFactor)0, -0x5af0441e), r16, true);", // IID764 + "__ exorq(r12, Address(r20, r26, (Address::ScaleFactor)0, +0xe0b7fb1), r12, true);", // IID765 + "__ eaddq(r30, Address(rcx, +0x2d3b7b4f), 1048576, false);", // IID766 + "__ eaddq(r14, Address(r21, r15, (Address::ScaleFactor)2, -0x1222aee8), 4096, true);", // IID767 + "__ eandq(r23, Address(r20, r31, (Address::ScaleFactor)0, -0x96e4d6a), 16, false);", // IID768 + "__ eandq(r10, Address(rdx, rdx, (Address::ScaleFactor)3, +0x3875f17c), 1, true);", // IID769 + "__ eimulq(r17, Address(rcx, r25, (Address::ScaleFactor)2, +0x32c71076), 4096, false);", // IID770 + "__ eimulq(r19, Address(r31, rbx, (Address::ScaleFactor)2, +0x7bada60d), 1048576, true);", // IID771 + "__ eorq(r25, Address(r18, r23, (Address::ScaleFactor)1, +0x48147444), 16777216, false);", // IID772 + "__ eorq(r29, Address(r26, r27, (Address::ScaleFactor)1, -0x4b113958), 1048576, true);", // IID773 + "__ esalq(r31, Address(r18, -0x46103c74), 2, false);", // IID774 + "__ esalq(r25, Address(r10, r15, (Address::ScaleFactor)0, +0x48925da4), 16, true);", // IID775 + "__ esarq(r26, Address(r18, -0x5ea1c542), 8, false);", // IID776 + "__ esarq(r12, Address(r10, r22, (Address::ScaleFactor)2, +0x5d958264), 8, true);", // IID777 + "__ eshrq(rdx, Address(r17, r20, (Address::ScaleFactor)2, +0x295add23), 16, false);", // IID778 + "__ eshrq(rbx, Address(r22, r28, (Address::ScaleFactor)1, +0x782929cb), 2, true);", // IID779 + "__ esubq(r19, Address(r23, -0x49811d72), 1, false);", // IID780 + "__ esubq(r8, Address(r19, r14, (Address::ScaleFactor)2, -0x1b2bae9a), 1048576, true);", // IID781 + "__ exorq(r19, Address(rcx, r10, (Address::ScaleFactor)0, +0x45a66ee9), 1048576, false);", // IID782 + "__ exorq(r28, Address(r9, r29, (Address::ScaleFactor)0, -0x28a19314), 16, true);", // IID783 + "__ eaddq(r8, rcx, 16777216, false);", // IID784 + "__ eaddq(rax, r14, 16777216, false);", // IID785 + "__ eaddq(r16, r16, 256, false);", // IID786 + "__ eaddq(r24, r9, 4096, true);", // IID787 + "__ eaddq(rax, r18, 4096, true);", // IID788 + "__ eaddq(r8, r8, 1, true);", // IID789 + "__ eandq(r15, r22, 1048576, false);", // IID790 + "__ eandq(rax, r26, 1048576, false);", // IID791 + "__ eandq(rdx, rdx, 4096, false);", // IID792 + "__ eandq(rdx, r22, 268435456, true);", // IID793 + "__ eandq(rax, r29, 268435456, true);", // IID794 + "__ eandq(r23, r23, 16777216, true);", // IID795 + "__ eimulq(r9, r13, 1048576, false);", // IID796 + "__ eimulq(rax, r18, 1048576, false);", // IID797 + "__ eimulq(r16, r16, 1048576, false);", // IID798 + "__ eimulq(r17, r23, 1, true);", // IID799 + "__ eimulq(rax, r12, 1, true);", // IID800 + "__ eimulq(r10, r10, 268435456, true);", // IID801 + "__ eorq(rdx, r19, 256, false);", // IID802 + "__ eorq(rax, r14, 256, false);", // IID803 + "__ eorq(r13, r13, 1, false);", // IID804 + "__ eorq(r25, r29, 256, true);", // IID805 + "__ eorq(rax, rdx, 256, true);", // IID806 + "__ eorq(r16, r16, 16, true);", // IID807 + "__ erclq(r13, r19, 4);", // IID808 + "__ erclq(rax, r12, 4);", // IID809 + "__ erclq(r9, r9, 4);", // IID810 + "__ erolq(r13, r16, 1, false);", // IID811 + "__ erolq(rax, r31, 1, false);", // IID812 + "__ erolq(r30, r30, 8, false);", // IID813 + "__ erolq(r30, r20, 8, true);", // IID814 + "__ erolq(rax, r31, 8, true);", // IID815 + "__ erolq(r31, r31, 4, true);", // IID816 + "__ erorq(r22, r10, 4, false);", // IID817 + "__ erorq(rax, r13, 4, false);", // IID818 + "__ erorq(r24, r24, 16, false);", // IID819 + "__ erorq(r29, r22, 16, true);", // IID820 + "__ erorq(rax, r20, 16, true);", // IID821 + "__ erorq(r27, r27, 4, true);", // IID822 + "__ esalq(r31, r19, 2, false);", // IID823 + "__ esalq(rax, r20, 2, false);", // IID824 + "__ esalq(r11, r11, 8, false);", // IID825 + "__ esalq(rdx, r15, 1, true);", // IID826 + "__ esalq(rax, r10, 1, true);", // IID827 + "__ esalq(r29, r29, 4, true);", // IID828 + "__ esarq(r20, r16, 1, false);", // IID829 + "__ esarq(rax, r21, 1, false);", // IID830 + "__ esarq(r28, r28, 8, false);", // IID831 + "__ esarq(r30, rcx, 4, true);", // IID832 + "__ esarq(rax, r15, 4, true);", // IID833 + "__ esarq(rcx, rcx, 4, true);", // IID834 + "__ eshlq(rdx, r26, 4, false);", // IID835 + "__ eshlq(rax, r26, 4, false);", // IID836 + "__ eshlq(r8, r8, 4, false);", // IID837 + "__ eshlq(rcx, rcx, 1, true);", // IID838 + "__ eshlq(rax, rcx, 1, true);", // IID839 + "__ eshlq(r13, r13, 2, true);", // IID840 + "__ eshrq(r14, r27, 2, false);", // IID841 + "__ eshrq(rax, r11, 2, false);", // IID842 + "__ eshrq(r9, r9, 16, false);", // IID843 + "__ eshrq(rdx, r31, 2, true);", // IID844 + "__ eshrq(rax, r14, 2, true);", // IID845 + "__ eshrq(r12, r12, 8, true);", // IID846 + "__ esubq(r10, r28, 1, false);", // IID847 + "__ esubq(rax, r8, 1, false);", // IID848 + "__ esubq(rcx, rcx, 16777216, false);", // IID849 + "__ esubq(rdx, rbx, 16777216, true);", // IID850 + "__ esubq(rax, r18, 16777216, true);", // IID851 + "__ esubq(r27, r27, 65536, true);", // IID852 + "__ exorq(r30, rcx, 4096, false);", // IID853 + "__ exorq(rax, r21, 4096, false);", // IID854 + "__ exorq(rcx, rcx, 16777216, false);", // IID855 + "__ exorq(r21, r12, 1, true);", // IID856 + "__ exorq(rax, rdx, 1, true);", // IID857 + "__ exorq(rbx, rbx, 16777216, true);", // IID858 + "__ eorq_imm32(r11, rdx, 65536, false);", // IID859 + "__ eorq_imm32(rax, r14, 65536, false);", // IID860 + "__ eorq_imm32(r14, r14, 262144, false);", // IID861 + "__ eorq_imm32(r25, r29, 262144, false);", // IID862 + "__ eorq_imm32(rax, r21, 262144, false);", // IID863 + "__ eorq_imm32(r11, r11, 16777216, false);", // IID864 + "__ esubq_imm32(r29, r19, 67108864, false);", // IID865 + "__ esubq_imm32(rax, r11, 67108864, false);", // IID866 + "__ esubq_imm32(r18, r18, 67108864, false);", // IID867 + "__ esubq_imm32(r28, r23, 4194304, true);", // IID868 + "__ esubq_imm32(rax, r21, 4194304, true);", // IID869 + "__ esubq_imm32(r16, r16, 16777216, true);", // IID870 + "__ eaddq(r8, r25, Address(r26, r8, (Address::ScaleFactor)1, +0x10633def), false);", // IID871 + "__ eaddq(r13, r13, Address(r18, r16, (Address::ScaleFactor)1, -0x74204508), false);", // IID872 + "__ eaddq(r17, r26, Address(r12, +0x23a80abf), true);", // IID873 + "__ eaddq(r9, r9, Address(r29, r19, (Address::ScaleFactor)0, -0x29e9e52), true);", // IID874 + "__ eandq(r9, r28, Address(rcx, r25, (Address::ScaleFactor)2, +0x4261ffaa), false);", // IID875 + "__ eandq(r27, r27, Address(rdx, r28, (Address::ScaleFactor)0, -0x26bdc9c1), false);", // IID876 + "__ eandq(r14, r11, Address(r16, +0x63ba0ddf), true);", // IID877 + "__ eandq(r8, r8, Address(r22, r25, (Address::ScaleFactor)1, -0x43b6ab44), true);", // IID878 + "__ eorq(r19, rcx, Address(r27, rcx, (Address::ScaleFactor)2, -0x7f687fc6), false);", // IID879 + "__ eorq(r19, r19, Address(rbx, r26, (Address::ScaleFactor)1, -0x486db7ea), false);", // IID880 + "__ eorq(r30, r10, Address(r14, r18, (Address::ScaleFactor)3, +0x14884884), true);", // IID881 + "__ eorq(r27, r27, Address(r29, +0x20337180), true);", // IID882 + "__ eimulq(rcx, r21, Address(r21, rbx, (Address::ScaleFactor)0, -0x3303888e), false);", // IID883 + "__ eimulq(rdx, rdx, Address(r28, r9, (Address::ScaleFactor)3, -0x7ad8f741), false);", // IID884 + "__ eimulq(r8, r29, Address(r17, r12, (Address::ScaleFactor)0, +0x6e85396a), true);", // IID885 + "__ eimulq(r16, r16, Address(r19, r10, (Address::ScaleFactor)3, -0x49599300), true);", // IID886 + "__ esubq(r20, r17, Address(r13, r22, (Address::ScaleFactor)0, +0x1d219a4f), false);", // IID887 + "__ esubq(r25, r25, Address(r21, r21, (Address::ScaleFactor)3, -0x6868a8c7), false);", // IID888 + "__ esubq(r20, r24, Address(rbx, r20, (Address::ScaleFactor)2, +0x32c59da6), true);", // IID889 + "__ esubq(r8, r8, Address(r12, r17, (Address::ScaleFactor)0, -0x26be2dcf), true);", // IID890 + "__ exorq(rdx, r19, Address(r9, +0x7d903b91), false);", // IID891 + "__ exorq(r28, r28, Address(r29, r27, (Address::ScaleFactor)2, +0x53091f6f), false);", // IID892 + "__ exorq(r17, r16, Address(r27, +0x7c6e9207), true);", // IID893 + "__ exorq(r15, r15, Address(r13, r24, (Address::ScaleFactor)3, -0x75c87960), true);", // IID894 + "__ eaddq(r16, rbx, r18, false);", // IID895 + "__ eaddq(r24, r24, r18, false);", // IID896 + "__ eaddq(r9, r15, r9, false);", // IID897 + "__ eaddq(r19, r26, r13, true);", // IID898 + "__ eaddq(r28, r28, r22, true);", // IID899 + "__ eaddq(r22, r11, r22, true);", // IID900 + "__ eadcxq(rcx, r12, r13);", // IID901 + "__ eadcxq(r30, r30, r12);", // IID902 + "__ eadoxq(r28, r14, r18);", // IID903 + "__ eadoxq(r30, r30, r19);", // IID904 + "__ eandq(r20, r14, r14, false);", // IID905 + "__ eandq(r17, r17, r23, false);", // IID906 + "__ eandq(r17, r14, r17, false);", // IID907 + "__ eandq(r19, r20, r15, true);", // IID908 + "__ eandq(rbx, rbx, r13, true);", // IID909 + "__ eandq(r22, r30, r22, true);", // IID910 + "__ eimulq(r17, r24, rcx, false);", // IID911 + "__ eimulq(r21, r21, r8, false);", // IID912 + "__ eimulq(r29, r21, r29, false);", // IID913 + "__ eimulq(r27, r13, r23, true);", // IID914 + "__ eimulq(r26, r26, r8, true);", // IID915 + "__ eimulq(r22, r13, r22, true);", // IID916 + "__ eorq(r11, rdx, r29, false);", // IID917 + "__ eorq(rdx, rdx, r31, false);", // IID918 + "__ eorq(r10, r29, r10, false);", // IID919 + "__ eorq(r27, r28, rcx, true);", // IID920 + "__ eorq(r25, r25, r9, true);", // IID921 + "__ eorq(rcx, r8, rcx, true);", // IID922 + "__ esubq(rcx, r10, r16, false);", // IID923 + "__ esubq(r17, r17, rcx, false);", // IID924 + "__ esubq(r13, r21, r24, true);", // IID925 + "__ esubq(r31, r31, r28, true);", // IID926 + "__ exorq(r23, r28, r23, false);", // IID927 + "__ exorq(r10, r10, r11, false);", // IID928 + "__ exorq(r19, r18, r19, false);", // IID929 + "__ exorq(r31, r9, rdx, true);", // IID930 + "__ exorq(r13, r13, r9, true);", // IID931 + "__ exorq(rcx, r10, rcx, true);", // IID932 + "__ eshldq(r12, r24, r22, 8, false);", // IID933 + "__ eshldq(r25, r25, r25, 8, false);", // IID934 + "__ eshldq(r21, r20, r15, 8, true);", // IID935 + "__ eshldq(r21, r21, r10, 8, true);", // IID936 + "__ eshrdq(r18, r18, r8, 2, false);", // IID937 + "__ eshrdq(r26, r26, r29, 8, false);", // IID938 + "__ eshrdq(r29, r26, r19, 2, true);", // IID939 + "__ eshrdq(r12, r12, rcx, 4, true);", // IID940 + "__ ecmovq (Assembler::Condition::overflow, r21, r22, r23);", // IID941 + "__ ecmovq (Assembler::Condition::overflow, r9, r9, r13);", // IID942 + "__ ecmovq (Assembler::Condition::noOverflow, rcx, r23, r24);", // IID943 + "__ ecmovq (Assembler::Condition::noOverflow, r28, r28, rdx);", // IID944 + "__ ecmovq (Assembler::Condition::below, r14, r31, r23);", // IID945 + "__ ecmovq (Assembler::Condition::below, r30, r30, r23);", // IID946 + "__ ecmovq (Assembler::Condition::aboveEqual, r10, r29, r22);", // IID947 + "__ ecmovq (Assembler::Condition::aboveEqual, rbx, rbx, r26);", // IID948 + "__ ecmovq (Assembler::Condition::zero, r23, r21, r13);", // IID949 + "__ ecmovq (Assembler::Condition::zero, r10, r10, r20);", // IID950 + "__ ecmovq (Assembler::Condition::notZero, rbx, r9, r29);", // IID951 + "__ ecmovq (Assembler::Condition::notZero, r16, r16, r30);", // IID952 + "__ ecmovq (Assembler::Condition::belowEqual, r13, rcx, r29);", // IID953 + "__ ecmovq (Assembler::Condition::belowEqual, r31, r31, r13);", // IID954 + "__ ecmovq (Assembler::Condition::above, r27, r9, r30);", // IID955 + "__ ecmovq (Assembler::Condition::above, r26, r26, r20);", // IID956 + "__ ecmovq (Assembler::Condition::negative, r8, r12, r22);", // IID957 + "__ ecmovq (Assembler::Condition::negative, r31, r31, r17);", // IID958 + "__ ecmovq (Assembler::Condition::positive, r29, rcx, r25);", // IID959 + "__ ecmovq (Assembler::Condition::positive, r22, r22, r14);", // IID960 + "__ ecmovq (Assembler::Condition::parity, rcx, r27, r9);", // IID961 + "__ ecmovq (Assembler::Condition::parity, r22, r22, r11);", // IID962 + "__ ecmovq (Assembler::Condition::noParity, r14, r19, r24);", // IID963 + "__ ecmovq (Assembler::Condition::noParity, r24, r24, r17);", // IID964 + "__ ecmovq (Assembler::Condition::less, r17, r19, r30);", // IID965 + "__ ecmovq (Assembler::Condition::less, r19, r19, r14);", // IID966 + "__ ecmovq (Assembler::Condition::greaterEqual, r25, r11, r29);", // IID967 + "__ ecmovq (Assembler::Condition::greaterEqual, r12, r12, r26);", // IID968 + "__ ecmovq (Assembler::Condition::lessEqual, r11, rbx, r10);", // IID969 + "__ ecmovq (Assembler::Condition::lessEqual, rdx, rdx, r22);", // IID970 + "__ ecmovq (Assembler::Condition::greater, r14, r15, r23);", // IID971 + "__ ecmovq (Assembler::Condition::greater, r8, r8, r24);", // IID972 + "__ ecmovq (Assembler::Condition::overflow, rbx, r31, Address(r10, r8, (Address::ScaleFactor)3, -0x313f60e0));", // IID973 + "__ ecmovq (Assembler::Condition::overflow, r23, r23, Address(rcx, r24, (Address::ScaleFactor)2, +0x17f41d9c));", // IID974 + "__ ecmovq (Assembler::Condition::noOverflow, r31, r11, Address(r16, +0x2c018942));", // IID975 + "__ ecmovq (Assembler::Condition::noOverflow, r11, r11, Address(r16, r20, (Address::ScaleFactor)3, +0x674b6a55));", // IID976 + "__ ecmovq (Assembler::Condition::below, r9, r13, Address(r9, rcx, (Address::ScaleFactor)0, +0x394a11df));", // IID977 + "__ ecmovq (Assembler::Condition::below, r30, r30, Address(rdx, r22, (Address::ScaleFactor)1, -0x6c362b88));", // IID978 + "__ ecmovq (Assembler::Condition::aboveEqual, r13, rcx, Address(r24, rcx, (Address::ScaleFactor)3, +0x46500b66));", // IID979 + "__ ecmovq (Assembler::Condition::aboveEqual, r24, r24, Address(r18, r25, (Address::ScaleFactor)1, +0x53283b7c));", // IID980 + "__ ecmovq (Assembler::Condition::zero, r23, r25, Address(r15, r9, (Address::ScaleFactor)0, -0x5f03031e));", // IID981 + "__ ecmovq (Assembler::Condition::zero, r25, r25, Address(r28, r16, (Address::ScaleFactor)1, -0x53cef514));", // IID982 + "__ ecmovq (Assembler::Condition::notZero, rbx, r25, Address(r24, r25, (Address::ScaleFactor)2, -0x66caac87));", // IID983 + "__ ecmovq (Assembler::Condition::notZero, r16, r16, Address(r27, r30, (Address::ScaleFactor)3, +0x797f455d));", // IID984 + "__ ecmovq (Assembler::Condition::belowEqual, r25, r30, Address(r18, r18, (Address::ScaleFactor)1, +0x1c9daacd));", // IID985 + "__ ecmovq (Assembler::Condition::belowEqual, r22, r22, Address(rcx, r25, (Address::ScaleFactor)1, -0x3dcbfaa9));", // IID986 + "__ ecmovq (Assembler::Condition::above, r24, r26, Address(r25, +0x747060b5));", // IID987 + "__ ecmovq (Assembler::Condition::above, r8, r8, Address(r24, r20, (Address::ScaleFactor)3, +0x47d285f6));", // IID988 + "__ ecmovq (Assembler::Condition::negative, r12, r16, Address(r13, r10, (Address::ScaleFactor)2, +0x34e5b214));", // IID989 + "__ ecmovq (Assembler::Condition::negative, rdx, rdx, Address(r15, r19, (Address::ScaleFactor)0, -0x405138b1));", // IID990 + "__ ecmovq (Assembler::Condition::positive, r18, r21, Address(rbx, r13, (Address::ScaleFactor)2, +0x51b19197));", // IID991 + "__ ecmovq (Assembler::Condition::positive, r24, r24, Address(r11, r31, (Address::ScaleFactor)3, +0x3e01520a));", // IID992 + "__ ecmovq (Assembler::Condition::parity, r29, r26, Address(r10, r25, (Address::ScaleFactor)3, -0x5f7c3872));", // IID993 + "__ ecmovq (Assembler::Condition::parity, r11, r11, Address(r22, r10, (Address::ScaleFactor)3, -0x68731453));", // IID994 + "__ ecmovq (Assembler::Condition::noParity, r20, r15, Address(r9, r25, (Address::ScaleFactor)0, +0x4a37edaa));", // IID995 + "__ ecmovq (Assembler::Condition::noParity, r31, r31, Address(r9, r20, (Address::ScaleFactor)0, +0x4f999f86));", // IID996 + "__ ecmovq (Assembler::Condition::less, r18, r23, Address(r9, r27, (Address::ScaleFactor)0, -0x3410441d));", // IID997 + "__ ecmovq (Assembler::Condition::less, r16, r16, Address(r24, r10, (Address::ScaleFactor)3, +0x52ed66ee));", // IID998 + "__ ecmovq (Assembler::Condition::greaterEqual, r11, r18, Address(rcx, +0x1de09163));", // IID999 + "__ ecmovq (Assembler::Condition::greaterEqual, r14, r14, Address(r24, r23, (Address::ScaleFactor)1, +0x5df3b4da));", // IID1000 + "__ ecmovq (Assembler::Condition::lessEqual, r15, r14, Address(r30, r20, (Address::ScaleFactor)1, +0x5c9ab976));", // IID1001 + "__ ecmovq (Assembler::Condition::lessEqual, r26, r26, Address(r18, r27, (Address::ScaleFactor)2, -0xd8c329));", // IID1002 + "__ ecmovq (Assembler::Condition::greater, r29, r9, Address(r30, r20, (Address::ScaleFactor)3, -0x37a9cf8d));", // IID1003 + "__ ecmovq (Assembler::Condition::greater, r20, r20, Address(r8, rbx, (Address::ScaleFactor)1, +0x1bdc7def));", // IID1004 #endif // _LP64 }; // END Generated code -- do not edit diff --git a/test/hotspot/gtest/x86/x86-asmtest.py b/test/hotspot/gtest/x86/x86-asmtest.py index 7081c64e604..714b7aaea40 100644 --- a/test/hotspot/gtest/x86/x86-asmtest.py +++ b/test/hotspot/gtest/x86/x86-asmtest.py @@ -92,6 +92,8 @@ 'r31': {64: 'r31', 32: 'r31d', 16: 'r31w', 8: 'r31b'}, } +commutative_instrs = ['imul', 'add', 'and', 'xor', 'or'] + class Operand(object): def generate(self): return self @@ -400,6 +402,15 @@ def __init__(self, name, aname, width, no_flag, reg1, mem_base, mem_idx, reg2): self.mem = Address().generate(mem_base, mem_idx, width) self.reg2 = Register().generate(reg2, width) self.generate_operands(self.reg1, self.mem, self.reg2) + self.demote = True + + def astr(self): + if self.demote: + ops = [op.cstr() for op in self.operands] + # imul does not support RegMemReg + if self._aname in commutative_instrs[1:] and ops[0] == ops[2] and (not self.no_flag): + return f'{self._aname} ' + ', '.join([op.astr() for op in self.operands[:2]]) + return super().astr() class RegRegImmNddInstruction(NFInstruction): def __init__(self, name, aname, width, no_flag, reg1, reg2, imm): @@ -448,6 +459,9 @@ def astr(self): ops = [op.cstr() for op in self.operands] if ops[0] == ops[1] and (not self.no_flag): return hdr + f'{self._aname} ' + ', '.join([op.astr() for op in self.operands[1:]]) + if self._aname in commutative_instrs and ops[0] == ops[2] and (not self.no_flag): + return hdr + f'{self._aname} ' + ', '.join([op.astr() for op in self.operands[:2]]) + return hdr + super().astr() class RegRegRegImmNddInstruction(NFInstruction): @@ -574,6 +588,18 @@ def generate(RegOp, ops, print_lp64_flag=True, full_set=False): lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_reg2, test_reg3) instr = RegOp(*op, reg1=test_reg1, reg2=test_reg2, reg3=test_reg3) print_instruction(instr, lp64_flag, print_lp64_flag) + + demote = True if TEST_DEMOTION else False + commute = True if op[1] in commutative_instrs else False + if RegOp in [RegRegRegNddInstruction] and demote and commute : + for i in range(len(test_regs) if full_set else 1): + test_reg1 = test_regs[i] if full_set else random.choice(test_regs) + test_reg2 = test_regs[(i + 2) % len(test_regs)] if full_set else random.choice(test_regs) + test_reg3 = test_reg1 + + lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_reg2, test_reg3) + instr = RegOp(*op, reg1=test_reg1, reg2=test_reg2, reg3=test_reg3) + print_instruction(instr, lp64_flag, print_lp64_flag) elif RegOp in [MemRegInstruction, RegMemInstruction, MoveRegMemInstruction, CmpxchgInstruction, CondRegMemInstruction, RegMemNddInstruction]: if full_set: @@ -699,7 +725,7 @@ def generate(RegOp, ops, print_lp64_flag=True, full_set=False): print_instruction(instr, lp64_flag, print_lp64_flag) elif RegOp in [RegMemRegNddInstruction, RegRegMemNddInstruction, CondRegRegMemInstruction]: - demote_options = [False] if TEST_DEMOTION and RegOp not in [RegMemRegNddInstruction] else [False, True] + demote_options = [False, True] for demote in demote_options: for i in range(len(test_regs) if full_set else 1): test_reg1 = test_regs[i] if full_set else random.choice(test_regs) @@ -1023,6 +1049,8 @@ def print_with_ifdef(ifdef_flags, items, item_formatter, width): RegMemRegNddInstruction: [ ('eaddl', 'add', 32, False), ('eaddl', 'add', 32, True), + ('eandl', 'and', 32, False), + ('eandl', 'and', 32, True), ('eorl', 'or', 32, False), ('eorl', 'or', 32, True), ('eorb', 'or', 8, False), diff --git a/test/hotspot/jtreg/ProblemList-Xcomp.txt b/test/hotspot/jtreg/ProblemList-Xcomp.txt index 6df68c1ed62..393a33d3eae 100644 --- a/test/hotspot/jtreg/ProblemList-Xcomp.txt +++ b/test/hotspot/jtreg/ProblemList-Xcomp.txt @@ -52,6 +52,4 @@ vmTestbase/nsk/jvmti/scenarios/capability/CM03/cm03t001/TestDescription.java 829 vmTestbase/nsk/stress/thread/thread006.java 8321476 linux-all -compiler/cha/TypeProfileFinalMethod.java 8341039 generic-all - gc/arguments/TestNewSizeFlags.java 8299116 macosx-aarch64 diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 72d9ff039f0..26198afba6c 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -66,6 +66,7 @@ compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/NativeCallTest.java 8 compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleDebugInfoTest.java 8331704 linux-riscv64 compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java 8331704 linux-riscv64 compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/VirtualObjectDebugInfoTest.java 8331704 linux-riscv64 +compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInvalidationReasonTest.java 8360168 linux-riscv64 compiler/floatingpoint/TestSubnormalFloat.java 8317810 generic-i586 compiler/floatingpoint/TestSubnormalDouble.java 8317810 generic-i586 @@ -98,6 +99,7 @@ gc/shenandoah/TestEvilSyncBug.java#generational 8345501 generic-all # :hotspot_runtime +runtime/cds/DeterministicDump.java 8363986 macosx-x64,macosx-aarch64 runtime/jni/terminatedThread/TestTerminatedThread.java 8317789 aix-ppc64 runtime/Monitor/SyncOnValueBasedClassTest.java 8340995 linux-s390x runtime/os/TestTracePageSizes.java#no-options 8267460 linux-aarch64 @@ -182,3 +184,13 @@ vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn001/forceEa vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi005/TestDescription.java 8076494 windows-x64 vmTestbase/nsk/monitoring/ThreadMXBean/findMonitorDeadlockedThreads/find006/TestDescription.java 8310144 macosx-aarch64 + +# Mechanically added: +runtime/Thread/TestThreadDumpMonitorContention.java 8361370 windows-x64 +runtime/Thread/StopAtExit.java 8365835 linux-x64 +runtime/Thread/SetPriorityAtExit.java 8365835 linux-x64 +runtime/Thread/SuspendAtExit.java 8365835 linux-x64 +runtime/Thread/SetNameAtExit.java 8365835 linux-x64 +runtime/8176717/TestInheritFD.java 8347001 linux-x64 +vmTestbase/nsk/jdi/stress/serial/mixed002/TestDescription.java 8291514 macosx-aarch64 +serviceability/jvmti/RedefineClasses/ClassVersionAfterRedefine.java 8369953 linux-aarch64,linux-x64,macosx-aarch64,windows-x64 diff --git a/test/hotspot/jtreg/TEST.ROOT b/test/hotspot/jtreg/TEST.ROOT index 59dd48e5af7..f5b6922e7e1 100644 --- a/test/hotspot/jtreg/TEST.ROOT +++ b/test/hotspot/jtreg/TEST.ROOT @@ -79,6 +79,8 @@ requires.properties= \ vm.rtm.cpu \ vm.rtm.compiler \ vm.cds \ + vm.cds.default.archive.available \ + vm.cds.nocoops.archive.available \ vm.cds.custom.loaders \ vm.cds.supports.aot.class.linking \ vm.cds.supports.aot.code.caching \ @@ -91,6 +93,8 @@ requires.properties= \ vm.compiler1.enabled \ vm.compiler2.enabled \ vm.musl \ + vm.asan \ + vm.ubsan \ vm.flagless \ container.support \ systemd.support \ @@ -100,7 +104,7 @@ requires.properties= \ jdk.static # Minimum jtreg version -requiredVersion=7.5.1+1 +requiredVersion=8+2 # Path to libraries in the topmost test directory. This is needed so @library # does not need ../../../ notation to reach them diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index 2fa0862a186..246399d7438 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -417,6 +417,7 @@ hotspot_appcds_dynamic = \ -runtime/cds/appcds/aotClassLinking \ -runtime/cds/appcds/aotCode \ -runtime/cds/appcds/aotFlags \ + -runtime/cds/appcds/aotProfile \ -runtime/cds/appcds/applications \ -runtime/cds/appcds/cacheObject \ -runtime/cds/appcds/complexURI \ @@ -511,14 +512,17 @@ hotspot_cds_epsilongc = \ runtime/cds/appcds/jigsaw \ runtime/cds/appcds/loaderConstraints -# Run CDS tests with -XX:+AOTClassLinking. This should include most CDS tests, except for +# Run "old" CDS tests with -XX:+AOTClassLinking. This should include most CDS tests, except for # those that rely on redefining classes that are already archived. +# Note that appcds/aotXXX directories are excluded -- those tests already specifically +# test AOT class linking, so there's no need to run them again with -XX:+AOTClassLinking. hotspot_aot_classlinking = \ runtime/cds \ -runtime/cds/appcds/aotCache \ -runtime/cds/appcds/aotClassLinking \ -runtime/cds/appcds/aotCode \ -runtime/cds/appcds/aotFlags \ + -runtime/cds/appcds/aotProfile \ -runtime/cds/appcds/BadBSM.java \ -runtime/cds/appcds/cacheObject/ArchivedIntegerCacheTest.java \ -runtime/cds/appcds/cacheObject/ArchivedModuleCompareTest.java \ diff --git a/test/hotspot/jtreg/applications/jcstress/README b/test/hotspot/jtreg/applications/jcstress/README index 2aaf1210f9b..b85b4ddbbe3 100644 --- a/test/hotspot/jtreg/applications/jcstress/README +++ b/test/hotspot/jtreg/applications/jcstress/README @@ -1,4 +1,4 @@ -Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. +Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. This code is free software; you can redistribute it and/or modify it @@ -24,10 +24,13 @@ The tests located under this directory run tests from the Java Concurrency Stress test suite[1] (a.k.a. jcstress). This suite aims to verify the correctness of concurrency support in the JDK. -All the tests are run through the test driver class -- JcstressRunner, which -downloads the specified build of org.openjdk.jcstress:jcstress-tests-all, +All the tests are run through the test driver class -- JcstressRunner, spawns a new JVM to run one jcstress test and checks that it finishes -successfully. +successfully. These tests require a build of org.openjdk.jcstress:jcstress-tests-all. +If this artifact could not be found automatically, you can build it using jcstress +guide[1], and then pass the JAR location with JDK option such as +-Djdk.test.lib.artifacts.jcstress-tests-all=jcstress-tests-all.jar, +either with explicit -javaoption: or TEST_VM_OPTS test variable. When the used version of org.openjdk.jcstress:jcstress-tests-all needs to be changed, one should make corresponding changes to the artifact description in diff --git a/test/hotspot/jtreg/compiler/arraycopy/TestIllegalArrayCopyBeforeInfiniteLoop.java b/test/hotspot/jtreg/compiler/arraycopy/TestIllegalArrayCopyBeforeInfiniteLoop.java index 0b3572d6afa..af166571909 100644 --- a/test/hotspot/jtreg/compiler/arraycopy/TestIllegalArrayCopyBeforeInfiniteLoop.java +++ b/test/hotspot/jtreg/compiler/arraycopy/TestIllegalArrayCopyBeforeInfiniteLoop.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/arraycopy/TestNegArrayLengthAsIndex1.java b/test/hotspot/jtreg/compiler/arraycopy/TestNegArrayLengthAsIndex1.java index 2f35a11e948..b7da2119bd3 100644 --- a/test/hotspot/jtreg/compiler/arraycopy/TestNegArrayLengthAsIndex1.java +++ b/test/hotspot/jtreg/compiler/arraycopy/TestNegArrayLengthAsIndex1.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/arraycopy/TestNegArrayLengthAsIndex2.java b/test/hotspot/jtreg/compiler/arraycopy/TestNegArrayLengthAsIndex2.java index da8f0936cae..b101254d189 100644 --- a/test/hotspot/jtreg/compiler/arraycopy/TestNegArrayLengthAsIndex2.java +++ b/test/hotspot/jtreg/compiler/arraycopy/TestNegArrayLengthAsIndex2.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/arraycopy/TestNegativeArrayCopyAfterLoop.java b/test/hotspot/jtreg/compiler/arraycopy/TestNegativeArrayCopyAfterLoop.java index e28cfb871f7..901ff78347d 100644 --- a/test/hotspot/jtreg/compiler/arraycopy/TestNegativeArrayCopyAfterLoop.java +++ b/test/hotspot/jtreg/compiler/arraycopy/TestNegativeArrayCopyAfterLoop.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/c1/TestRangeCheckEliminated.java b/test/hotspot/jtreg/compiler/c1/TestRangeCheckEliminated.java index 9da8a5390da..0f5b8860195 100644 --- a/test/hotspot/jtreg/compiler/c1/TestRangeCheckEliminated.java +++ b/test/hotspot/jtreg/compiler/c1/TestRangeCheckEliminated.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, Tencent. All rights reserved. * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * diff --git a/test/hotspot/jtreg/compiler/c2/Test7046096.java b/test/hotspot/jtreg/compiler/c2/Test7046096.java index 46eb935e2d0..fb73bba4373 100644 --- a/test/hotspot/jtreg/compiler/c2/Test7046096.java +++ b/test/hotspot/jtreg/compiler/c2/Test7046096.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 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 @@ -30,6 +30,18 @@ * compiler.c2.Test7046096 */ + +/* + * @test id=stringConcatInline + * @bug 7046096 8357822 + * @summary The same test with an updated compile directive that produces + * StringBuilder-backed string concatenations. + * + * @compile -XDstringConcat=inline Test7046096.java + * @run main/othervm -Xbatch compiler.c2.Test7046096 + */ + + package compiler.c2; public class Test7046096 { diff --git a/test/hotspot/jtreg/compiler/c2/Test7179138_2.java b/test/hotspot/jtreg/compiler/c2/Test7179138_2.java index 4e89f6aced0..5f96ea942ef 100644 --- a/test/hotspot/jtreg/compiler/c2/Test7179138_2.java +++ b/test/hotspot/jtreg/compiler/c2/Test7179138_2.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * Copyright 2012 Skip Balk. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -32,6 +33,18 @@ * @author Skip Balk */ + +/* + * @test id=stringConcatInline + * @bug 7179138 + * @summary The same test with an updated compile directive that produces + * StringBuilder-backed string concatenations. + * + * @compile -XDstringConcat=inline Test7179138_2.java + * @run main/othervm -Xbatch -XX:-TieredCompilation compiler.c2.Test7179138_2 + */ + + package compiler.c2; public class Test7179138_2 { diff --git a/test/hotspot/jtreg/compiler/c2/TestBit.java b/test/hotspot/jtreg/compiler/c2/TestBit.java index a3c9421a3f9..01769470d78 100644 --- a/test/hotspot/jtreg/compiler/c2/TestBit.java +++ b/test/hotspot/jtreg/compiler/c2/TestBit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, 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 @@ -33,7 +33,7 @@ * @library /test/lib / * * @requires vm.flagless - * @requires os.arch=="aarch64" | os.arch=="amd64" | os.arch == "ppc64le" | os.arch == "riscv64" + * @requires os.arch == "aarch64" | os.arch == "amd64" | os.arch == "x86_64" | os.arch == "ppc64" | os.arch == "ppc64le" | os.arch == "riscv64" * @requires vm.debug == true & vm.compiler2.enabled * * @run driver compiler.c2.TestBit diff --git a/test/hotspot/jtreg/compiler/c2/TestDuplicateSimpleLoopBackedge.java b/test/hotspot/jtreg/compiler/c2/TestDuplicateSimpleLoopBackedge.java index 0b102b4c9fd..414a351e53f 100644 --- a/test/hotspot/jtreg/compiler/c2/TestDuplicateSimpleLoopBackedge.java +++ b/test/hotspot/jtreg/compiler/c2/TestDuplicateSimpleLoopBackedge.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (c) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/c2/TestMergeStores.java b/test/hotspot/jtreg/compiler/c2/TestMergeStores.java index 2e2b2b6661f..22920eda828 100644 --- a/test/hotspot/jtreg/compiler/c2/TestMergeStores.java +++ b/test/hotspot/jtreg/compiler/c2/TestMergeStores.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -611,7 +611,7 @@ static Object[] test1R(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test1a(byte[] a) { a[0] = (byte)0xbe; @@ -626,7 +626,7 @@ static Object[] test1a(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test1b(byte[] a) { // Add custom null check, to ensure the unsafe access always recognizes its type as an array store @@ -636,7 +636,7 @@ static Object[] test1b(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test1c(byte[] a) { storeLongLE(a, 0, 0xdeadbeefbaadbabeL); @@ -644,7 +644,7 @@ static Object[] test1c(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test1d(byte[] a) { storeIntLE(a, 0, 0xbaadbabe); @@ -653,7 +653,7 @@ static Object[] test1d(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test1e(byte[] a) { storeShortLE(a, 0, (short)0xbabe); @@ -664,7 +664,7 @@ static Object[] test1e(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test1f(byte[] a) { UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 0, (byte)0xbe); @@ -680,8 +680,8 @@ static Object[] test1f(byte[] a) { @Test // Do not optimize these, just to be sure we do not mess with store ordering. - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "8"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test1g(byte[] a) { UNSAFE.putByteRelease(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 0, (byte)0xbe); @@ -697,8 +697,8 @@ static Object[] test1g(byte[] a) { @Test // Do not optimize these, just to be sure we do not mess with store ordering. - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "8"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test1h(byte[] a) { UNSAFE.putByteVolatile(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 0, (byte)0xbe); @@ -714,8 +714,8 @@ static Object[] test1h(byte[] a) { @Test // Do not optimize these, just to be sure we do not mess with store ordering. - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "8"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test1i(byte[] a) { UNSAFE.putByteOpaque(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 0, (byte)0xbe); @@ -743,13 +743,13 @@ static Object[] test2R(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"little-endian", "true"}) - @IR(counts = { IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", + @IR(counts = { IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", IRNode.REVERSE_BYTES_L, "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) @@ -766,7 +766,7 @@ static Object[] test2a(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test2b(byte[] a, int offset, long v) { // Add custom null check, to ensure the unsafe access always recognizes its type as an array store @@ -776,13 +776,13 @@ static Object[] test2b(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"little-endian", "true"}) - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", IRNode.REVERSE_BYTES_L, "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) @@ -823,14 +823,14 @@ static Object[] test2RBE(byte[] a, int offset, long v) { } @Test - @IR(counts = { IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", + @IR(counts = { IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", IRNode.REVERSE_BYTES_L, "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatformAnd = {"little-endian", "true", "riscv64", "false"}) // Exclude riscv64 where ReverseBytes is only conditionally supported - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test2aBE(byte[] a, int offset, long v) { @@ -846,7 +846,7 @@ static Object[] test2aBE(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test2bBE(byte[] a, int offset, long v) { // Add custom null check, to ensure the unsafe access always recognizes its type as an array store @@ -856,14 +856,14 @@ static Object[] test2bBE(byte[] a, int offset, long v) { } @Test - @IR(counts = { IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", + @IR(counts = { IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", IRNode.REVERSE_BYTES_L, "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatformAnd = {"little-endian", "true", "riscv64", "false"}) // Exclude riscv64 where ReverseBytes is only conditionally supported - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test2cBE(byte[] a, int offset, long v) { @@ -903,16 +903,16 @@ static Object[] test3R(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"little-endian", "true"}) - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", IRNode.REVERSE_BYTES_I, "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) @@ -942,14 +942,14 @@ static Object[] test3RBE(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", IRNode.REVERSE_BYTES_I, "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatformAnd = {"little-endian", "true", "riscv64", "false"}) // Exclude riscv64 where ReverseBytes is only conditionally supported - @IR(counts = {IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2"}, + @IR(counts = {IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test3aBE(byte[] a, int offset, long v) { @@ -987,16 +987,16 @@ static Object[] test4R(byte[] a, int offset, long v1, int v2, short v3, byte v4) } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "4", // 3 (+ 1 for uncommon trap) - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "4", // 3 (+ 1 for uncommon trap) + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "3", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"little-endian", "true"}) - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "4", // Unmerged stores: offset + (2,3,16) , and 1 for uncommon trap - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3", // 1([+0,+1]) for platform order and 2([+4,+5], [+14,+15]) for reverse order - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2", // 1([+6,+9]) for platform order and 1([+10,+13]) for reverse order - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "4", // Unmerged stores: offset + (2,3,16) , and 1 for uncommon trap + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "3", // 1([+0,+1]) for platform order and 2([+4,+5], [+14,+15]) for reverse order + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2", // 1([+6,+9]) for platform order and 1([+10,+13]) for reverse order + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", IRNode.REVERSE_BYTES_I, "1", IRNode.REVERSE_BYTES_S, "2"}, applyIf = {"UseUnalignedAccesses", "true"}, @@ -1045,18 +1045,18 @@ static Object[] test4RBE(byte[] a, int offset, long v1, int v2, short v3, byte v } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "4", // Unmerged stores: offset + (2,3,16) , and 1 for uncommon trap - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3", // 1([+0,+1]) for platform order and 2([+4,+5], [+14,+15]) for reverse order - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2", // 1([+6,+9]) for platform order and 1([+10,+13]) for reverse order - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "4", // Unmerged stores: offset + (2,3,16) , and 1 for uncommon trap + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "3", // 1([+0,+1]) for platform order and 2([+4,+5], [+14,+15]) for reverse order + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2", // 1([+6,+9]) for platform order and 1([+10,+13]) for reverse order + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", IRNode.REVERSE_BYTES_I, "1", IRNode.REVERSE_BYTES_S, "2"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatformAnd = {"little-endian", "true", "riscv64", "false"}) // Exclude riscv64 where ReverseBytes is only conditionally supported - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "4", // 3 (+ 1 for uncommon trap) - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "4", // 3 (+ 1 for uncommon trap) + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "3", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test4aBE(byte[] a, int offset, long v1, int v2, short v3, byte v4) { @@ -1101,10 +1101,10 @@ static Object[] test5R(byte[] a, int offset) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test5a(byte[] a, int offset) { a[offset + 0] = (byte)0x01; @@ -1139,10 +1139,10 @@ static Object[] test6R(byte[] a, byte[] b, int offset1, int offset2) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "8", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}) static Object[] test6a(byte[] a, byte[] b, int offset1, int offset2) { a[offset1 + 1] = (byte)0x02; a[offset1 + 3] = (byte)0x04; @@ -1164,10 +1164,10 @@ static Object[] test7R(byte[] a, int offset1, int v1) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "3", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}) static Object[] test7a(byte[] a, int offset1, int v1) { a[offset1 + 1] = (byte)(v1 >> 8); a[offset1 + 2] = (byte)(v1 >> 16); @@ -1184,10 +1184,10 @@ static Object[] test7RBE(byte[] a, int offset1, int v1) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "3", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}) static Object[] test7aBE(byte[] a, int offset1, int v1) { a[offset1 + 1] = (byte)(v1 >> 24); a[offset1 + 2] = (byte)(v1 >> 16); @@ -1211,10 +1211,10 @@ static Object[] test10R(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", // no merge - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "8", // no merge + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}) static Object[] test10a(byte[] a) { // We have 11 summands: 10x zero variable + 1x array base. // Parsing only allows 10 summands -> does not merge the stores. @@ -1232,10 +1232,10 @@ static Object[] test10a(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // 1 left in uncommon trap path of RangeCheck - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // all merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // 1 left in uncommon trap path of RangeCheck + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, // all merged applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test10b(byte[] a) { int zero = zero0 + zero1 + zero2 + zero3 + zero4 @@ -1254,10 +1254,10 @@ static Object[] test10b(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // 1 left in uncommon trap path of RangeCheck - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // all merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // 1 left in uncommon trap path of RangeCheck + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, // all merged applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test10c(byte[] a) { int zero = 7 * zero0 + 7 * zero1 + 7 * zero2 + 7 * zero3 + 7 * zero4 @@ -1277,10 +1277,10 @@ static Object[] test10c(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // all merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, // all merged applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test10d(byte[] a) { // Summand is subtracted from itself -> scale = 0 -> should be removed from list. @@ -1296,10 +1296,10 @@ static Object[] test10d(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // all merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, // all merged applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test10e(byte[] a) { // Summand is subtracted from itself -> scale = 0 -> should be removed from list. Thus equal to if not present at all. @@ -1315,10 +1315,10 @@ static Object[] test10e(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", // no merge - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "8", // no merge + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}) static Object[] test10f(byte[] a) { int big = 1 << 29; // Adding up the scales overflows -> no merge. @@ -1355,10 +1355,10 @@ static Object[] test100R(short[] a, int offset) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_I_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_L_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_I_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_L_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "3"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test100a(short[] a, int offset) { a[offset + 0] = (short)0x0100; // stays unchanged -> both used for RC and Return path @@ -1399,10 +1399,10 @@ static Object[] test101R(short[] a, int offset) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // only for RC - IRNode.STORE_I_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_L_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // only for RC + IRNode.STORE_I_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_L_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "3"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test101a(short[] a, int offset) { a[offset + 0] = (short)0x0100; // I plus kept unchanged for RC @@ -1445,16 +1445,16 @@ static Object[] test102R(short[] a, int offset, long v1, int v2, short v3) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "4", // 3 (+1 that goes into RC) - IRNode.STORE_I_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3", - IRNode.STORE_L_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "4", // 3 (+1 that goes into RC) + IRNode.STORE_I_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "3", + IRNode.STORE_L_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"little-endian", "true"}) - @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "12", - IRNode.STORE_I_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // Stores of constants can be merged - IRNode.STORE_L_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "12", + IRNode.STORE_I_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // Stores of constants can be merged + IRNode.STORE_L_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test102a(short[] a, int offset, long v1, int v2, short v3) { @@ -1501,16 +1501,16 @@ static Object[] test102RBE(short[] a, int offset, long v1, int v2, short v3) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "12", - IRNode.STORE_I_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // Stores of constants can be merged - IRNode.STORE_L_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "12", + IRNode.STORE_I_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // Stores of constants can be merged + IRNode.STORE_L_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"little-endian", "true"}) - @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "4", // 3 (+1 that goes into RC) - IRNode.STORE_I_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3", - IRNode.STORE_L_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "4", // 3 (+1 that goes into RC) + IRNode.STORE_I_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "3", + IRNode.STORE_L_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test102aBE(short[] a, int offset, long v1, int v2, short v3) { @@ -1555,10 +1555,10 @@ static Object[] test200R(int[] a, int offset) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "7"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_L_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "7"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test200a(int[] a, int offset) { a[offset + 0] = 0x01001236; // stays unchanged -> both used for RC and Return path @@ -1599,10 +1599,10 @@ static Object[] test201R(int[] a, int offset) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // only for RC - IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "7"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // only for RC + IRNode.STORE_L_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "7"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test201a(int[] a, int offset) { a[offset + 0] = 0x01001236; // L and also kept unchanged for RC @@ -1645,16 +1645,16 @@ static Object[] test202R(int[] a, int offset, long v1, int v2) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "6", // 5 (+1 that goes into RC) - IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "6"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "6", // 5 (+1 that goes into RC) + IRNode.STORE_L_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "6"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"little-endian", "true"}) - @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "10", - IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "4"}, // Stores of constants can be merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "10", + IRNode.STORE_L_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "4"}, // Stores of constants can be merged applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test202a(int[] a, int offset, long v1, int v2) { @@ -1701,16 +1701,16 @@ static Object[] test202RBE(int[] a, int offset, long v1, int v2) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "10", - IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "4"}, // Stores of constants can be merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "10", + IRNode.STORE_L_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "4"}, // Stores of constants can be merged applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"little-endian", "true"}) - @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "6", // 5 (+1 that goes into RC) - IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "6"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "6", // 5 (+1 that goes into RC) + IRNode.STORE_L_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "6"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test202aBE(int[] a, int offset, long v1, int v2) { @@ -1745,7 +1745,7 @@ static Object[] test300R(int[] a) { } @Test - @IR(counts = {IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test300a(int[] a) { a[2] = 42; @@ -1771,10 +1771,10 @@ static Object[] test400R(int[] a) { @Test // All constants are known, and AddI can be converted to AddL safely, hence the stores can be merged. - @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // all merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, // all merged applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test400a(int[] a) { UNSAFE.putByte(a, UNSAFE.ARRAY_INT_BASE_OFFSET + 0, (byte)0xbe); @@ -1818,16 +1818,16 @@ static Object[] test500R(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // for RangeCheck trap - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // expect merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // for RangeCheck trap + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, // expect merged applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"little-endian", "true"}) - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // for RangeCheck trap - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // expect merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // for RangeCheck trap + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // expect merged IRNode.REVERSE_BYTES_L, "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) @@ -1855,10 +1855,10 @@ static Object[] test500a(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", // No optimization because of too many RangeChecks - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "8", // No optimization because of too many RangeChecks + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}) static Object[] test501a(byte[] a, int offset, long v) { int idx = 0; try { @@ -1883,10 +1883,10 @@ static Object[] test501a(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", // No optimization because of too many RangeChecks - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "8", // No optimization because of too many RangeChecks + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}) static Object[] test502a(byte[] a, int offset, long v) { int idx = 0; try { @@ -1940,17 +1940,17 @@ static Object[] test500RBE(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // for RangeCheck trap - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // expect merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // for RangeCheck trap + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // expect merged IRNode.REVERSE_BYTES_L, "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatformAnd = {"little-endian", "true", "riscv64", "false"}) // Exclude riscv64 where ReverseBytes is only conditionally supported - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // for RangeCheck trap - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // expect merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // for RangeCheck trap + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, // expect merged applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test500aBE(byte[] a, int offset, long v) { @@ -1977,17 +1977,17 @@ static Object[] test500aBE(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "7", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "7", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", IRNode.REVERSE_BYTES_S, "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatformAnd = {"little-endian", "true", "riscv64", "false"}) // Exclude riscv64 where ReverseBytes is only conditionally supported - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "7", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "7", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test501aBE(byte[] a, int offset, long v) { @@ -2014,17 +2014,17 @@ static Object[] test501aBE(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "7", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "7", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", IRNode.REVERSE_BYTES_S, "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatformAnd = {"little-endian", "true", "riscv64", "false"}) // Exclude riscv64 where ReverseBytes is only conditionally supported - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "7", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "7", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test502aBE(byte[] a, int offset, long v) { @@ -2073,10 +2073,10 @@ static Object[] test600R(byte[] aB, int[] aI, int i) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // all merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, // all merged applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test600a(byte[] aB, int[] aI, int i) { Object a = null; @@ -2123,15 +2123,15 @@ static Object[] test601R(byte[] aB, int[] aI, int i, int offset1) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", // nothing merged - IRNode.STORE_C_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "8", // nothing merged + IRNode.STORE_C_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}, applyIfPlatform = {"64-bit", "true"}) - @IR(counts = {IRNode.STORE_B_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // all merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, // all merged applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"32-bit", "true"}) static Object[] test601a(byte[] aB, int[] aI, int i, int offset1) { @@ -2165,10 +2165,10 @@ static Object[] test700R(int[] a, long v1) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2", - IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2", + IRNode.STORE_L_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}) static Object[] test700a(int[] a, long v1) { // Negative shift: cannot optimize a[0] = (int)(v1 >> -1); @@ -2188,10 +2188,10 @@ static Object[] test800R(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "6", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "6", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}) static Object[] test800a(byte[] a, int offset, long v) { // Merge attempts begin at the lowest store in the Memory chain. // Candidates are found following the chain. The list is trimmed to a @@ -2217,17 +2217,17 @@ static Object[] test800RBE(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", IRNode.REVERSE_BYTES_I, "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatformAnd = {"little-endian", "true", "riscv64", "false"}) // Exclude riscv64 where ReverseBytes is only conditionally supported - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test800aBE(byte[] a, int offset, long v) { diff --git a/test/hotspot/jtreg/compiler/c2/TestMergeStoresAndAllocationElimination.java b/test/hotspot/jtreg/compiler/c2/TestMergeStoresAndAllocationElimination.java new file mode 100644 index 00000000000..605f65eb00c --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestMergeStoresAndAllocationElimination.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.c2; + +/* + * @test + * @bug 8370405 + * @summary Test case where we had escape analysis tell us that we can possibly eliminate + * the array allocation, then MergeStores introduces a mismatched store, which + * the actual elimination does not verify for. That led to wrong results. + * @run main/othervm -XX:CompileCommand=compileonly,compiler.c2.TestMergeStoresAndAllocationElimination::test + * -XX:CompileCommand=exclude,compiler.c2.TestMergeStoresAndAllocationElimination::dontinline + * -XX:-TieredCompilation -Xbatch + * -XX:+IgnoreUnrecognizedVMOptions -XX:-CICompileOSR + * compiler.c2.TestMergeStoresAndAllocationElimination + * @run main compiler.c2.TestMergeStoresAndAllocationElimination + */ + +public class TestMergeStoresAndAllocationElimination { + static void dontinline() {} + + static int test(boolean flag) { + int[] arr = new int[4]; + // The values below will be caputured as "raw stores" in the Initialize + // of the array allocation above. + // These stores are for cosmetics only, we set the "1" bits so that it is + // simple to track where values are coming from. + arr[0] = 0x0001_0000; + arr[1] = 0x0010_0000; + arr[2] = 0x0000_0100; + arr[3] = 0x0100_0000; + // So far, the result should be: + // 0x421_0300 + + // The call below prevents further assignments from being captured into + // the Initialize above. + dontinline(); + // The follwoing stores are eventually optimized by MergeStores, and create + // a mismatched StoreL. + arr[0] = 0x0000_0001; + arr[1] = 0x0000_0010; + // Now, the result should be: + // 0x400_0321 + + // We create an uncommon trap because of an "unstable if". + // If Escape Analysis were to work, it would try to capture the values + // from the StoreL above. But because it is mismatched, it should fail. + // What happened before that verification: we would take the ConL, and + // insert it in a list of ConI. That meant that we eventually applied + // that value wrong if the deopt was taken (flag = true). + // + // What happened when the deopt got the wrong values: It got these values: + // [0]=68719476737 = 0x10_0000_0001 -> long value, not correct + // [1]=1048576 = 0x10_0000 -> this entry is not updated! + // [2]=256 = 0x100 + // [3]=16777216 = 0x100_0000 + // + // This is serialized as a long and 3 ints, and that looks like 5 ints. + // This creates an array of 5 elements (and not 4): + // [0] = 0x1 + // [1] = 0x10 + // [2] = 0x10_0000 -> this entry is "inserted" + // [3] = 0x100 + // [4] = 0x100_0000 + // + // This creates the wrong state: + // 0x30_0421 + // And we can actually read that the arr.length is 5, below. + if (flag) { System.out.println("unstable if: " + arr.length); } + + // Delay the allocation elimination until after loop opts, so that it + // happens after MergeStores. Without this, we would immediately + // eliminate the allocation during Escape Analysis, and then MergeStores + // would not find the stores that would be removed with the allocation. + for (int i = 0; i < 10_000; i++) { + arr[3] = 0x0000_1000; + } + // Coming from the correct value, we should have transition of state: + // 0x400_0321 -> 0x4321 + // But coming from the bad (rematerialized) state, we transition: + // 0x30_0421 -> 0x30_4021 + + // Tag each entry with an index number + // We expect: 0x4321 + return 1 * arr[0] + 2 * arr[1] + 3 * arr[2] + 4 * arr[3]; + } + + public static void main(String[] args) { + // Capture interpreter result. + int gold = test(false); + // Repeat until we get compilation. + for (int i = 0; i < 10_000; i++) { + test(false); + } + // Capture compiled results. + int res0 = test(false); + int res1 = test(true); + if (res0 != gold || res1 != gold) { + throw new RuntimeException("Unexpected result: " + Integer.toHexString(res0) + " and " + Integer.toHexString(res1) + ", should be: " + Integer.toHexString(gold)); + } + } +} diff --git a/test/hotspot/jtreg/compiler/c2/cr6865031/Test.java b/test/hotspot/jtreg/compiler/c2/cr6865031/Test.java index af23628577b..beb41943183 100644 --- a/test/hotspot/jtreg/compiler/c2/cr6865031/Test.java +++ b/test/hotspot/jtreg/compiler/c2/cr6865031/Test.java @@ -1,6 +1,6 @@ /* * Copyright 2009 Goldman Sachs International. All Rights Reserved. - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeIntIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeIntIdealizationTests.java index e3651129daa..f5225e8173c 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeIntIdealizationTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeIntIdealizationTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ * @summary Test that Ideal transformations of RotateLeftNode* are being performed as expected. * @library /test/lib / * @run driver compiler.c2.irTests.RotateLeftNodeIntIdealizationTests - * @requires os.arch == "x86_64" | os.arch == "aarch64" | (os.arch == "riscv64" & vm.cpu.features ~= ".*zbb.*") + * @requires os.arch == "amd64" | os.arch == "x86_64" | os.arch == "aarch64" | (os.arch == "riscv64" & vm.cpu.features ~= ".*zbb.*") */ public class RotateLeftNodeIntIdealizationTests { diff --git a/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeLongIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeLongIdealizationTests.java index 190f08d348c..b28d2f6dc8b 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeLongIdealizationTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeLongIdealizationTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ * @summary Test that Ideal transformations of RotateLeftNode* are being performed as expected. * @library /test/lib / * @run driver compiler.c2.irTests.RotateLeftNodeLongIdealizationTests - * @requires os.arch == "x86_64" | os.arch == "aarch64" | (os.arch == "riscv64" & vm.cpu.features ~= ".*zbb.*") + * @requires os.arch == "amd64" | os.arch == "x86_64" | os.arch == "aarch64" | (os.arch == "riscv64" & vm.cpu.features ~= ".*zbb.*") */ public class RotateLeftNodeLongIdealizationTests { diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestAutoVectorization2DArray.java b/test/hotspot/jtreg/compiler/c2/irTests/TestAutoVectorization2DArray.java index ac622e3bcc3..5b1d6f51bb3 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestAutoVectorization2DArray.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestAutoVectorization2DArray.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestIfMinMax.java b/test/hotspot/jtreg/compiler/c2/irTests/TestIfMinMax.java index bb0a1200a7f..fdc0a83fb8b 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestIfMinMax.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestIfMinMax.java @@ -296,7 +296,11 @@ public void checkTestMinIntReduction(Object[] vals) { @Test @IR(applyIf = { "SuperWordReductions", "true" }, - applyIfCPUFeatureOr = { "avx512", "true", "rvv", "true" }, + applyIfCPUFeature = { "avx512", "true" }, + counts = { IRNode.MAX_REDUCTION_V, "> 0" }) + @IR(applyIfPlatform = {"riscv64", "true"}, + applyIfAnd = { "SuperWordReductions", "true", "MaxVectorSize", ">=32" }, + applyIfCPUFeature = { "rvv", "true" }, counts = { IRNode.MAX_REDUCTION_V, "> 0" }) @Arguments(setup = "setupLongArrays") public Object[] testMaxLongReduction(long[] a, long[] b) { @@ -331,7 +335,11 @@ public void checkTestMaxLongReduction(Object[] vals) { @Test @IR(applyIf = { "SuperWordReductions", "true" }, - applyIfCPUFeatureOr = { "avx512", "true", "rvv", "true" }, + applyIfCPUFeature = { "avx512", "true" }, + counts = { IRNode.MIN_REDUCTION_V, "> 0" }) + @IR(applyIfPlatform = {"riscv64", "true"}, + applyIfAnd = { "SuperWordReductions", "true", "MaxVectorSize", ">=32" }, + applyIfCPUFeature = { "rvv", "true" }, counts = { IRNode.MIN_REDUCTION_V, "> 0" }) @Arguments(setup = "setupLongArrays") public Object[] testMinLongReduction(long[] a, long[] b) { diff --git a/test/hotspot/jtreg/compiler/c2/irTests/stringopts/TestArrayCopySelect.java b/test/hotspot/jtreg/compiler/c2/irTests/stringopts/TestArrayCopySelect.java new file mode 100644 index 00000000000..4743f61ac39 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/irTests/stringopts/TestArrayCopySelect.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2025, Institute of Software, Chinese Academy of Sciences. + * All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.c2.irTests.stringopts; + +import compiler.lib.ir_framework.*; + +/** + * @test + * @bug 8359270 + * @requires vm.debug == true & vm.compiler2.enabled + * @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="riscv64" | os.arch=="aarch64" + * @summary C2: alignment check should consider base offset when emitting arraycopy runtime call. + * @library /test/lib / + * @run driver compiler.c2.irTests.stringopts.TestArrayCopySelect + */ + +public class TestArrayCopySelect { + + public static final String input_strU = "\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28"; + public static final char[] input_arrU = new char[] {'\u0f21', '\u0f22', '\u0f23', '\u0f24', + '\u0f25', '\u0f26', '\u0f27', '\u0f28'}; + + public static String output_strU; + public static char[] output_arrU; + + public static void main(String[] args) { + TestFramework.runWithFlags("-XX:-UseCompactObjectHeaders", + "-XX:-CompactStrings", + "-XX:CompileCommand=inline,java.lang.StringBuilder::toString", + "-XX:CompileCommand=inline,java.lang.StringUTF16::getChars", + "-XX:CompileCommand=inline,java.lang.StringUTF16::toBytes"); + + TestFramework.runWithFlags("-XX:+UseCompactObjectHeaders", + "-XX:-CompactStrings", + "-XX:CompileCommand=inline,java.lang.StringBuilder::toString", + "-XX:CompileCommand=inline,java.lang.StringUTF16::getChars", + "-XX:CompileCommand=inline,java.lang.StringUTF16::toBytes"); + } + + @Test + @Warmup(10000) + @IR(applyIf = {"UseCompactObjectHeaders", "false"}, + counts = {IRNode.CALL_OF, "arrayof_jshort_disjoint_arraycopy", ">0"}) + static void testSBToStringAligned() { + // Exercise the StringBuilder.toString API + StringBuilder sb = new StringBuilder(input_strU); + output_strU = sb.append(input_strU).toString(); + } + + @Test + @Warmup(10000) + @IR(applyIf = {"UseCompactObjectHeaders", "true"}, + counts = {IRNode.CALL_OF, "arrayof_jshort_disjoint_arraycopy", "0"}) + static void testSBToStringUnAligned() { + // Exercise the StringBuilder.toString API + StringBuilder sb = new StringBuilder(input_strU); + output_strU = sb.append(input_strU).toString(); + } + + @Test + @Warmup(10000) + @IR(applyIf = {"UseCompactObjectHeaders", "false"}, + counts = {IRNode.CALL_OF, "arrayof_jshort_disjoint_arraycopy", ">0"}) + static void testStrUGetCharsAligned() { + // Exercise the StringUTF16.getChars API + output_arrU = input_strU.toCharArray(); + } + + @Test + @Warmup(10000) + @IR(applyIf = {"UseCompactObjectHeaders", "true"}, + counts = {IRNode.CALL_OF, "arrayof_jshort_disjoint_arraycopy", "0"}) + static void testStrUGetCharsUnAligned() { + // Exercise the StringUTF16.getChars API + output_arrU = input_strU.toCharArray(); + } + + @Test + @Warmup(10000) + @IR(applyIf = {"UseCompactObjectHeaders", "false"}, + counts = {IRNode.CALL_OF, "arrayof_jshort_disjoint_arraycopy", ">0"}) + static void testStrUtoBytesAligned() { + // Exercise the StringUTF16.toBytes API + output_strU = String.valueOf(input_arrU); + } + + @Test + @Warmup(10000) + @IR(applyIf = {"UseCompactObjectHeaders", "true"}, + counts = {IRNode.CALL_OF, "arrayof_jshort_disjoint_arraycopy", "0"}) + static void testStrUtoBytesUnAligned() { + // Exercise the StringUTF16.toBytes API + output_strU = String.valueOf(input_arrU); + } + +} diff --git a/test/hotspot/jtreg/compiler/cha/TypeProfileFinalMethod.java b/test/hotspot/jtreg/compiler/cha/TypeProfileFinalMethod.java index a81ba53af52..8958a195653 100644 --- a/test/hotspot/jtreg/compiler/cha/TypeProfileFinalMethod.java +++ b/test/hotspot/jtreg/compiler/cha/TypeProfileFinalMethod.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -25,7 +25,7 @@ /* * @test * @summary test c1 to record type profile with CHA optimization - * @requires vm.flavor == "server" & (vm.opt.TieredStopAtLevel == null | vm.opt.TieredStopAtLevel == 4) + * @requires vm.flavor == "server" & vm.flagless * @library /test/lib * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox @@ -48,6 +48,7 @@ public static void main(String[] args) throws Exception { "-Xbatch", "-XX:-UseOnStackReplacement", "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", "-XX:Tier3InvocationThreshold=200", "-XX:Tier4InvocationThreshold=5000", + "-XX:CompileCommand=CompileOnly," + Launcher.class.getName() + "::test*", Launcher.class.getName()); OutputAnalyzer output = ProcessTools.executeProcess(pb); System.out.println("debug output"); @@ -61,7 +62,7 @@ public static void main(String[] args) throws Exception { while (matcher.find()) { matchCnt++; } - Asserts.assertEquals(matchCnt, 2); // inline Child1::m() twice + Asserts.assertEquals(2, matchCnt); // inline Child1::m() twice } static class Launcher { @@ -86,23 +87,23 @@ public static void main(String[] args) throws Exception { static void addCompilerDirectives() { WhiteBox WB = WhiteBox.getWhiteBox(); - // do not inline getInstance() for test1() and test2() + // Directive for test1 String directive = "[{ match: [\"" + Launcher.class.getName() + "::test1\"]," + - "inline:[\"-" + Launcher.class.getName()+"::getInstance()\"] }]"; + // Do not inline getInstance + "inline:[\"-" + Launcher.class.getName()+"::getInstance\"] }]"; WB.addCompilerDirective(directive); + // Directive for test2 directive = "[{ match: [\"" + Launcher.class.getName() + "::test2\"]," + - "inline:[\"-" + Launcher.class.getName()+"::getInstance()\"] }]"; - WB.addCompilerDirective(directive); - - // do not inline test1() for test2() in c1 compilation - directive = "[{ match: [\"" + Launcher.class.getName() + "::test2\"]," + - "c1: { inline:[\"-" + Launcher.class.getName()+"::test1()\"] } }]"; - WB.addCompilerDirective(directive); - - // print inline tree for checking - directive = "[{ match: [\"" + Launcher.class.getName() + "::test2\"]," + - "c2: { PrintInlining: true } }]"; + // Do not inline getInstance + "inline:[\"-" + Launcher.class.getName()+"::getInstance\"]," + + // Do not inline test1 in C1 compilation + "c1: { inline:[\"-" + Launcher.class.getName()+"::test1\"] }," + + // Make sure to inline test1 in C2 compilation + "c2: { inline:[\"+" + Launcher.class.getName()+"::test1\"]," + + // Print the inline tree for checking + " PrintInlining:true }" + + "}]"; WB.addCompilerDirective(directive); } diff --git a/test/hotspot/jtreg/compiler/compilercontrol/TestConflictInlineCommands.java b/test/hotspot/jtreg/compiler/compilercontrol/TestConflictInlineCommands.java index 9c12ea6b8a7..c7e20157e7e 100644 --- a/test/hotspot/jtreg/compiler/compilercontrol/TestConflictInlineCommands.java +++ b/test/hotspot/jtreg/compiler/compilercontrol/TestConflictInlineCommands.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/debug/TraceIterativeGVN.java b/test/hotspot/jtreg/compiler/debug/TraceIterativeGVN.java index 59d3de0d58e..8e6169f07dc 100644 --- a/test/hotspot/jtreg/compiler/debug/TraceIterativeGVN.java +++ b/test/hotspot/jtreg/compiler/debug/TraceIterativeGVN.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/escapeAnalysis/TestRematerializeObjects.java b/test/hotspot/jtreg/compiler/escapeAnalysis/TestRematerializeObjects.java new file mode 100644 index 00000000000..d2fdf47b060 --- /dev/null +++ b/test/hotspot/jtreg/compiler/escapeAnalysis/TestRematerializeObjects.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test id=yEA + * @bug 8370405 + * @summary Test elimination of array allocation, and the rematerialization. + * @library /test/lib / + * @run driver compiler.escapeAnalysis.TestRematerializeObjects yEA + */ + +/* + * @test id=nEA + * @library /test/lib / + * @run driver compiler.escapeAnalysis.TestRematerializeObjects nEA + */ + +package compiler.escapeAnalysis; + +import jdk.test.lib.Utils; + +import compiler.lib.ir_framework.*; +import compiler.lib.verify.*; + +public class TestRematerializeObjects { + + public static void main(String[] args) { + TestFramework framework = new TestFramework(TestRematerializeObjects.class); + switch (args[0]) { + case "yEA" -> { framework.addFlags("-XX:+EliminateAllocations"); } + case "nEA" -> { framework.addFlags("-XX:-EliminateAllocations"); } + default -> { throw new RuntimeException("Test argument not recognized: " + args[0]); } + }; + framework.start(); + } + + @DontInline + static void dontinline() {} + + @Run(test = "test1", mode = RunMode.STANDALONE) + public void runTest1() { + // Capture interpreter result. + int gold = test1(false); + // Repeat until we get compilation. + for (int i = 0; i < 10_000; i++) { + test1(false); + } + // Capture compiled results. + int res0 = test1(false); + int res1 = test1(true); + if (res0 != gold || res1 != gold) { + throw new RuntimeException("Unexpected result: " + Integer.toHexString(res0) + " and " + + Integer.toHexString(res1) + ", should be: " + Integer.toHexString(gold)); + } + } + + @Test + @IR(counts = {IRNode.ALLOC_ARRAY, "1", + IRNode.UNSTABLE_IF_TRAP, "1", + IRNode.STORE_L_OF_CLASS, "int\\[int:4\\]", "1", + IRNode.SAFEPOINT_SCALAROBJECT_OF, "fields@\\[0..3\\]", "0"}, + applyIfAnd = {"EliminateAllocations", "false", "UseUnalignedAccesses", "true"}) + @IR(counts = {IRNode.ALLOC_ARRAY, "0", + IRNode.UNSTABLE_IF_TRAP, "1", + IRNode.STORE_L_OF_CLASS, "int\\[int:4\\]", "0", + IRNode.SAFEPOINT_SCALAROBJECT_OF, "fields@\\[0..3\\]", "2"}, + applyIfAnd = {"EliminateAllocations", "true", "UseUnalignedAccesses", "true"}) + static int test1(boolean flag) { + int[] arr = new int[4]; + arr[0] = 0x0001_0000; // these slip into Initialize + arr[1] = 0x0010_0000; + arr[2] = 0x0000_0100; + arr[3] = 0x0100_0000; + dontinline(); + arr[0] = 0x0000_0001; // MergeStores -> StoreL + arr[1] = 0x0000_0010; + if (flag) { + // unstable if -> deopt -> rematerialized array (if was eliminated) + System.out.println("unstable if: " + arr.length); + } + arr[3] = 0x0000_1000; + return 1 * arr[0] + 2 * arr[1] + 3 * arr[2] + 4 * arr[3]; + } + + @Run(test = "test2", mode = RunMode.STANDALONE) + public void runTest2() { + // Capture interpreter result. + int gold = test2(false); + // Repeat until we get compilation. + for (int i = 0; i < 10_000; i++) { + test2(false); + } + // Capture compiled results. + int res0 = test2(false); + int res1 = test2(true); + if (res0 != gold || res1 != gold) { + throw new RuntimeException("Unexpected result: " + Integer.toHexString(res0) + " and " + + Integer.toHexString(res1) + ", should be: " + Integer.toHexString(gold)); + } + } + + @Test + @IR(counts = {IRNode.ALLOC_ARRAY, "1", + IRNode.UNSTABLE_IF_TRAP, "1", + IRNode.STORE_I_OF_CLASS, "short\\[int:4\\]", "1", + IRNode.SAFEPOINT_SCALAROBJECT_OF, "fields@\\[0..3\\]", "0"}, + applyIfAnd = {"EliminateAllocations", "false", "UseUnalignedAccesses", "true"}) + @IR(counts = {IRNode.ALLOC_ARRAY, "0", + IRNode.UNSTABLE_IF_TRAP, "1", + IRNode.STORE_I_OF_CLASS, "short\\[int:4\\]", "0", + IRNode.SAFEPOINT_SCALAROBJECT_OF, "fields@\\[0..3\\]", "2"}, + applyIfAnd = {"EliminateAllocations", "true", "UseUnalignedAccesses", "true"}) + static int test2(boolean flag) { + short[] arr = new short[4]; + arr[0] = 1; + arr[1] = 2; + arr[2] = 4; + arr[3] = 8; + dontinline(); + // Seems we detect that this is a short value passed into the short field. + arr[0] = 16; + arr[1] = 32; + if (flag) { + // unstable if -> deopt -> rematerialized array (if was eliminated) + System.out.println("unstable if: " + arr.length); + } + arr[3] = 64; + return 0x1 * arr[0] + 0x100 * arr[1] + 0x1_0000 * arr[2] + 0x100_0000 * arr[3]; + } + + @Run(test = "test3", mode = RunMode.STANDALONE) + public void runTest3() { + // Capture interpreter result. + int gold = test3(false, 42); + // Repeat until we get compilation. + for (int i = 0; i < 10_000; i++) { + test3(false, 42); + } + // Capture compiled results. + int res0 = test3(false, 42); + int res1 = test3(true, 42); + if (res0 != gold || res1 != gold) { + throw new RuntimeException("Unexpected result: " + Integer.toHexString(res0) + " and " + + Integer.toHexString(res1) + ", should be: " + Integer.toHexString(gold)); + } + } + + @Test + @IR(counts = {IRNode.ALLOC_ARRAY, "1", + IRNode.UNSTABLE_IF_TRAP, "1", + IRNode.SAFEPOINT_SCALAROBJECT_OF, "fields@\\[0..3\\]", "0"}, + applyIf = {"EliminateAllocations", "false"}) + @IR(counts = {IRNode.ALLOC_ARRAY, "0", + IRNode.UNSTABLE_IF_TRAP, "1", + IRNode.SAFEPOINT_SCALAROBJECT_OF, "fields@\\[0..3\\]", "2"}, + applyIf = {"EliminateAllocations", "true"}) + static int test3(boolean flag, int x) { + short[] arr = new short[4]; + arr[0] = 1; + arr[1] = 2; + arr[2] = 4; + arr[3] = 8; + dontinline(); + // Here, we don't get ConI, but instead AddI, which means we are + // serializing an int value, for a short slot. + arr[0] = (short)(x + 1); + arr[1] = (short)(x + 2); + if (flag) { + // unstable if -> deopt -> rematerialized array (if was eliminated) + System.out.println("unstable if: " + arr.length); + } + arr[3] = 64; + return 0x1 * arr[0] + 0x100 * arr[1] + 0x1_0000 * arr[2] + 0x100_0000 * arr[3]; + } +} diff --git a/test/hotspot/jtreg/compiler/floatingpoint/TestSubNodeFloatDoubleNegation.java b/test/hotspot/jtreg/compiler/floatingpoint/TestSubNodeFloatDoubleNegation.java index 4c7092ec654..d96e64baa36 100644 --- a/test/hotspot/jtreg/compiler/floatingpoint/TestSubNodeFloatDoubleNegation.java +++ b/test/hotspot/jtreg/compiler/floatingpoint/TestSubNodeFloatDoubleNegation.java @@ -38,7 +38,13 @@ public class TestSubNodeFloatDoubleNegation { public static void main(String[] args) { - TestFramework.runWithFlags("--add-modules=jdk.incubator.vector", "-XX:CompileCommand=inline,jdk.incubator.vector.Float16::*"); + // Disable inlining for java.lang.Float::float16ToFloat and java.lang.Float::floatToFloat16. + // Otherwise, they could be inlined into testHalfFloat on platforms where there is no support + // for fp16, which causes unexpected IR graph. + TestFramework.runWithFlags("--add-modules=jdk.incubator.vector", + "-XX:CompileCommand=inline,jdk.incubator.vector.Float16::*", + "-XX:CompileCommand=dontinline,java.lang.Float::float16ToFloat", + "-XX:CompileCommand=dontinline,java.lang.Float::floatToFloat16"); } @Run(test = { "testHalfFloat", "testFloat", "testDouble" }) diff --git a/test/hotspot/jtreg/compiler/gcbarriers/TestG1BarrierGeneration.java b/test/hotspot/jtreg/compiler/gcbarriers/TestG1BarrierGeneration.java index a9df0019ab1..b50827e6d3e 100644 --- a/test/hotspot/jtreg/compiler/gcbarriers/TestG1BarrierGeneration.java +++ b/test/hotspot/jtreg/compiler/gcbarriers/TestG1BarrierGeneration.java @@ -880,6 +880,16 @@ public void runAtomicTests() { Asserts.assertEquals(oldVal, oldVal2); Asserts.assertEquals(o.f, newVal); } + { + Outer o = new Outer(); + Object oldVal = new Object(); + o.f = oldVal; + Object cmpVal = new Object(); + Object newVal = new Object(); + Object oldVal2 = testCompareAndExchange(o, cmpVal, newVal); + Asserts.assertEquals(oldVal2, oldVal); + Asserts.assertEquals(o.f, oldVal); + } { Outer o = new Outer(); Object oldVal = new Object(); @@ -889,6 +899,16 @@ public void runAtomicTests() { Asserts.assertTrue(b); Asserts.assertEquals(o.f, newVal); } + { + Outer o = new Outer(); + Object oldVal = new Object(); + o.f = oldVal; + Object cmpVal = new Object(); + Object newVal = new Object(); + boolean b = testCompareAndSwap(o, cmpVal, newVal); + Asserts.assertFalse(b); + Asserts.assertEquals(o.f, oldVal); + } { Outer o = new Outer(); Object oldVal = new Object(); diff --git a/test/hotspot/jtreg/compiler/intrinsics/float16/Binary16ConversionNaN_2.java b/test/hotspot/jtreg/compiler/intrinsics/float16/Binary16ConversionNaN_2.java new file mode 100644 index 00000000000..b1170227542 --- /dev/null +++ b/test/hotspot/jtreg/compiler/intrinsics/float16/Binary16ConversionNaN_2.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, Rivos Inc. All rights reserved. + * 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 8365206 + * @summary Verify NaN sign and significand bits are preserved across conversions, + * float -> float16 -> float + * @requires (os.arch == "riscv64" & vm.cpu.features ~= ".*zfh.*") + * @requires vm.compiler1.enabled & vm.compiler2.enabled + * @requires vm.compMode != "Xcomp" + * @library /test/lib / + * + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -Xmixed -XX:-BackgroundCompilation -XX:-UseOnStackReplacement + * -XX:CompileThresholdScaling=1000.0 Binary16ConversionNaN_2 + */ + +/* + * The behavior tested below is an implementation property not + * required by the specification. It would be acceptable for this + * information to not be preserved (as long as a NaN is returned) if, + * say, a intrinsified version using native hardware instructions + * behaved differently. + * + * If that is the case, this test should be modified to disable + * intrinsics or to otherwise not run on platforms with an differently + * behaving intrinsic. + */ + +import compiler.whitebox.CompilerWhiteBoxTest; +import jdk.test.whitebox.WhiteBox; +import java.lang.reflect.Method; +import java.util.Random; + +public class Binary16ConversionNaN_2 { + + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + + /* + * Put all 16-bit NaN values through a conversion loop and make + * sure the significand, sign, and exponent are all preserved. + */ + public static void main(String... argv) throws NoSuchMethodException { + int errors = 0; + final int NAN_EXPONENT = 0x7f80_0000; + final int SIGN_BIT = 0x8000_0000; + + // First, run with Interpreter only to collect "gold" data. + // Glags -Xmixed -XX:CompileThresholdScaling=1000.0 are used + // to prevent compilation during this phase. + float[] pVal = new float[1024]; + float[] pRes = new float[1024]; + float[] nVal = new float[1024]; + float[] nRes = new float[1024]; + + Random rand = new Random(); + + // A NaN has a nonzero significand + for (int i = 1; i <= 0x3ff; i++) { + int shift = rand.nextInt(13+1); + int binaryNaN = (NAN_EXPONENT | (i << shift)); + assert isNaN(binaryNaN); + // the payloads of non-canonical NaNs are preserved. + float f1 = Float.intBitsToFloat(binaryNaN); + float f2 = testRoundTrip(f1); + errors += verify(f1, f2); + pVal[i] = f1; + pRes[i] = f2; + + int binaryNegNaN = (SIGN_BIT | binaryNaN); + float f3 = Float.intBitsToFloat(binaryNegNaN); + float f4 = testRoundTrip(f3); + errors += verify(f3, f4); + nVal[i] = f3; + nRes[i] = f4; + } + if (errors > 0) { // Exit if Interpreter failed + throw new RuntimeException(errors + " errors"); + } + + Method test_method = Binary16ConversionNaN_2.class.getDeclaredMethod("testRoundTrip", float.class); + + // Compile with C1 and compare results + WHITE_BOX.enqueueMethodForCompilation(test_method, CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE); + if (!WHITE_BOX.isMethodCompiled(test_method)) { + throw new RuntimeException("test is not compiled by C1"); + } + for (int i = 1; i <= 0x3ff; i++) { + float f1 = testRoundTrip(pVal[i]); + errors += verifyCompiler(pRes[i], f1, "C1"); + float f2 = testRoundTrip(nVal[i]); + errors += verifyCompiler(nRes[i], f2, "C1"); + } + + WHITE_BOX.deoptimizeMethod(test_method); + + // Compile with C2 and compare results + WHITE_BOX.enqueueMethodForCompilation(test_method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION); + if (!WHITE_BOX.isMethodCompiled(test_method)) { + throw new RuntimeException("test is not compiled by C2"); + } + for (int i = 1; i <= 0x3ff; i++) { + float f1 = testRoundTrip(pVal[i]); + errors += verifyCompiler(pRes[i], f1, "C2"); + float f2 = testRoundTrip(nVal[i]); + errors += verifyCompiler(nRes[i], f2, "C2"); + } + + if (errors > 0) { + throw new RuntimeException(errors + " errors"); + } + } + + private static boolean isNaN(int binary) { + return ((binary & 0x7f80_0000) == 0x7f80_0000) // Max exponent and... + && ((binary & 0x007f_ffff) != 0 ); // significand nonzero. + } + + private static float testRoundTrip(float f) { + short s = Float.floatToFloat16(f); + return Float.float16ToFloat(s); + } + + private static int verify(float f1, float f2) { + int errors = 0; + int i1 = Float.floatToRawIntBits(f1); + int i2 = Float.floatToRawIntBits(f2); + assert Float.isNaN(f1); + if (!Float.isNaN(f2) || + ((i1 & 0x8000_0000) != (i2 & 0x8000_0000))) { + errors++; + System.out.println("Roundtrip failure on NaN value " + + Integer.toHexString(i1) + + "\t got back " + Integer.toHexString(i2)); + } + return errors; + } + + private static int verifyCompiler(float f1, float f2, String name) { + int errors = 0; + int i1 = Float.floatToRawIntBits(f1); + int i2 = Float.floatToRawIntBits(f2); + assert Float.isNaN(f1); + if (!Float.isNaN(f2) || + ((i1 & 0x8000_0000) != (i2 & 0x8000_0000))) { + errors++; + System.out.println("Roundtrip failure on NaN value " + + Integer.toHexString(i1) + + "\t got back " + Integer.toHexString(i2) + + "\t from " + name + " code"); + } + return errors; + } +} diff --git a/test/hotspot/jtreg/compiler/intrinsics/math/TestPow0Dot5Opt.java b/test/hotspot/jtreg/compiler/intrinsics/math/TestPow0Dot5Opt.java index a0560870d2a..9854eb8c386 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/math/TestPow0Dot5Opt.java +++ b/test/hotspot/jtreg/compiler/intrinsics/math/TestPow0Dot5Opt.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/intrinsics/math/TestPow2Opt.java b/test/hotspot/jtreg/compiler/intrinsics/math/TestPow2Opt.java index 2bf48407a36..db05baf9683 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/math/TestPow2Opt.java +++ b/test/hotspot/jtreg/compiler/intrinsics/math/TestPow2Opt.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/DigestOptionsBase.java b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/DigestOptionsBase.java index 2d4d4353868..22b3bba854c 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/DigestOptionsBase.java +++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/DigestOptionsBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -120,7 +120,7 @@ public static BooleanSupplier getPredicateForOption(String optionName) { case DigestOptionsBase.USE_SHA256_INTRINSICS_OPTION: return IntrinsicPredicates.SHA256_INSTRUCTION_AVAILABLE; case DigestOptionsBase.USE_SHA512_INTRINSICS_OPTION: - return IntrinsicPredicates.SHA512_INSTRUCTION_AVAILABLE; + return IntrinsicPredicates.isSHA512IntrinsicAvailable(); case DigestOptionsBase.USE_SHA3_INTRINSICS_OPTION: return IntrinsicPredicates.SHA3_INSTRUCTION_AVAILABLE; default: diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA3IntrinsicsOptionOnSupportedCPU.java b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA3IntrinsicsOptionOnSupportedCPU.java index 3706f3abfd8..d3c0a4a8da7 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA3IntrinsicsOptionOnSupportedCPU.java +++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA3IntrinsicsOptionOnSupportedCPU.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2020, Huawei Technologies Co., Ltd. All rights reserved. - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA3IntrinsicsOptionOnUnsupportedCPU.java b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA3IntrinsicsOptionOnUnsupportedCPU.java index 633ceb1d9ab..c0045ae2922 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA3IntrinsicsOptionOnUnsupportedCPU.java +++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA3IntrinsicsOptionOnUnsupportedCPU.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2020, Huawei Technologies Co., Ltd. All rights reserved. - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnSupportedCPU.java b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnSupportedCPU.java index e349c22e383..7913a25d939 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnSupportedCPU.java +++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnSupportedCPU.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 8035968 * @summary Verify UseSHA512Intrinsics option processing on supported CPU. - * @requires os.arch!="x86" & os.arch!="i386" * @library /test/lib / * @requires vm.flagless * diff --git a/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java b/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java index 4285000e27f..4c8e63d0a42 100644 --- a/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java +++ b/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java @@ -229,8 +229,8 @@ public static void reprofile(HotSpotResolvedJavaMethod method) { CTVM.reprofile((HotSpotResolvedJavaMethodImpl)method); } - public static void invalidateHotSpotNmethod(HotSpotNmethod nmethodMirror, boolean deoptimize) { - CTVM.invalidateHotSpotNmethod(nmethodMirror, deoptimize); + public static void invalidateHotSpotNmethod(HotSpotNmethod nmethodMirror, boolean deoptimize, int invalidationReason) { + CTVM.invalidateHotSpotNmethod(nmethodMirror, deoptimize, invalidationReason); } public static long[] collectCounters() { diff --git a/test/hotspot/jtreg/compiler/jvmci/errors/TestInvalidTieredStopAtLevel.java b/test/hotspot/jtreg/compiler/jvmci/errors/TestInvalidTieredStopAtLevel.java index 3527dd891d6..0a00987f3d8 100644 --- a/test/hotspot/jtreg/compiler/jvmci/errors/TestInvalidTieredStopAtLevel.java +++ b/test/hotspot/jtreg/compiler/jvmci/errors/TestInvalidTieredStopAtLevel.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2020, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInvalidationReasonTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInvalidationReasonTest.java new file mode 100644 index 00000000000..624a2290509 --- /dev/null +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInvalidationReasonTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @requires vm.jvmci + * @requires vm.simpleArch == "x64" | vm.simpleArch == "aarch64" | vm.simpleArch == "riscv64" + * @library /test/lib / + * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot + * jdk.internal.vm.ci/jdk.vm.ci.meta + * jdk.internal.vm.ci/jdk.vm.ci.code + * jdk.internal.vm.ci/jdk.vm.ci.code.site + * jdk.internal.vm.ci/jdk.vm.ci.runtime + * jdk.internal.vm.ci/jdk.vm.ci.aarch64 + * jdk.internal.vm.ci/jdk.vm.ci.amd64 + * jdk.internal.vm.ci/jdk.vm.ci.riscv64 + * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java aarch64/AArch64TestAssembler.java riscv64/RISCV64TestAssembler.java + * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:-UseJVMCICompiler jdk.vm.ci.code.test.CodeInvalidationReasonTest + */ + +package jdk.vm.ci.code.test; + +import jdk.test.lib.Asserts; +import jdk.vm.ci.code.Register; +import jdk.vm.ci.hotspot.HotSpotNmethod; + +import org.junit.Test; + +import java.lang.reflect.Method; + +/** + * Test if setting HotSpotNmethod invalidation reason around works. + */ +public class CodeInvalidationReasonTest extends CodeInstallationTest { + + public static int add(int a, int b) { + return a + b; + } + + private static void compileAdd(TestAssembler asm) { + Register arg0 = asm.emitIntArg0(); + Register arg1 = asm.emitIntArg1(); + Register ret = asm.emitIntAdd(arg0, arg1); + asm.emitIntRet(ret); + } + + @Test + public void test() { + Method method = getMethod("add", int.class, int.class); + + HotSpotNmethod nmethod = test(CodeInvalidationReasonTest::compileAdd, method, 5, 7); + Asserts.assertEquals(-1 /* since it was not invalidated yet. */, nmethod.getInvalidationReason()); + + nmethod.invalidate(true, config.NMETHOD_INVALIDATION_REASON_JVMCI_INVALIDATE); + Asserts.assertEquals(config.NMETHOD_INVALIDATION_REASON_JVMCI_INVALIDATE, nmethod.getInvalidationReason()); + } +} diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java index c9c88024d99..4c76aea7a40 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,13 +71,13 @@ public void test() { Asserts.assertNotEquals(nmethod.getStart(), 0L); // Make nmethod non-entrant but still alive - nmethod.invalidate(false); + nmethod.invalidate(false, config.NMETHOD_INVALIDATION_REASON_JVMCI_INVALIDATE); Asserts.assertFalse(nmethod.isValid(), "code is valid, i = " + nmethod); Asserts.assertTrue(nmethod.isAlive(), "code is not alive, i = " + nmethod); Asserts.assertEquals(nmethod.getStart(), 0L); // Deoptimize the nmethod and cut the link to it from the HotSpotNmethod - nmethod.invalidate(true); + nmethod.invalidate(true, config.NMETHOD_INVALIDATION_REASON_JVMCI_INVALIDATE); Asserts.assertFalse(nmethod.isValid(), "code is valid, i = " + nmethod); Asserts.assertFalse(nmethod.isAlive(), "code is alive, i = " + nmethod); Asserts.assertEquals(nmethod.getStart(), 0L); diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java index db30229d34f..a26872b96ae 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,6 +55,8 @@ public TestHotSpotVMConfig(HotSpotVMConfigStore config, Architecture arch) { public final int maxOopMapStackOffset = getFieldValue("CompilerToVM::Data::_max_oop_map_stack_offset", Integer.class, "int"); public final int heapWordSize = getConstant("HeapWordSize", Integer.class); + public final int NMETHOD_INVALIDATION_REASON_JVMCI_INVALIDATE = getConstant("nmethod::InvalidationReason::JVMCI_INVALIDATE", Integer.class); + public final boolean ropProtection; private Boolean initNmethodEntryBarrierConcurrentPatch(Architecture arch) { @@ -65,7 +67,7 @@ private Boolean initNmethodEntryBarrierConcurrentPatch(Architecture arch) { // There currently only 2 variants in use that differ only by the presence of a // dmb instruction int stw = getConstant("NMethodPatchingType::stw_instruction_and_data_patch", Integer.class); - int conc = getConstant("NMethodPatchingType::conc_data_patch", Integer.class); + int conc = getConstant("NMethodPatchingType::conc_instruction_and_data_patch", Integer.class); if (patchingType == stw) { patchConcurrent = false; } else if (patchingType == conc) { diff --git a/test/hotspot/jtreg/compiler/lib/compile_framework/Compile.java b/test/hotspot/jtreg/compiler/lib/compile_framework/Compile.java index 7fde22cd207..e7f9b949a6d 100644 --- a/test/hotspot/jtreg/compiler/lib/compile_framework/Compile.java +++ b/test/hotspot/jtreg/compiler/lib/compile_framework/Compile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,7 @@ */ class Compile { private static final int COMPILE_TIMEOUT = 60; + private static final float timeoutFactor = Float.parseFloat(System.getProperty("test.timeout.factor", "1.0")); private static final String JAVA_PATH = JDKToolFinder.getJDKTool("java"); private static final String JAVAC_PATH = JDKToolFinder.getJDKTool("javac"); @@ -182,7 +183,8 @@ private static void executeCompileCommand(List command) { int exitCode; try { Process process = builder.start(); - boolean exited = process.waitFor(COMPILE_TIMEOUT, TimeUnit.SECONDS); + long timeout = COMPILE_TIMEOUT * (long)timeoutFactor; + boolean exited = process.waitFor(timeout, TimeUnit.SECONDS); if (!exited) { process.destroyForcibly(); System.out.println("Timeout: compile command: " + String.join(" ", command)); diff --git a/test/hotspot/jtreg/compiler/lib/generators/UniformDoubleGenerator.java b/test/hotspot/jtreg/compiler/lib/generators/UniformDoubleGenerator.java index d160bf319d8..b5729aeec7d 100644 --- a/test/hotspot/jtreg/compiler/lib/generators/UniformDoubleGenerator.java +++ b/test/hotspot/jtreg/compiler/lib/generators/UniformDoubleGenerator.java @@ -35,6 +35,9 @@ final class UniformDoubleGenerator extends UniformIntersectionRestrictableGenera */ public UniformDoubleGenerator(Generators g, double lo, double hi) { super(g, lo, hi); + if (Double.compare(lo, hi) >= 0) { + throw new EmptyGeneratorException(); + } } @Override diff --git a/test/hotspot/jtreg/compiler/lib/generators/UniformFloatGenerator.java b/test/hotspot/jtreg/compiler/lib/generators/UniformFloatGenerator.java index 1b72ad5adc9..4405b120619 100644 --- a/test/hotspot/jtreg/compiler/lib/generators/UniformFloatGenerator.java +++ b/test/hotspot/jtreg/compiler/lib/generators/UniformFloatGenerator.java @@ -35,6 +35,9 @@ final class UniformFloatGenerator extends UniformIntersectionRestrictableGenerat */ public UniformFloatGenerator(Generators g, float lo, float hi) { super(g, lo, hi); + if (Float.compare(lo, hi) >= 0) { + throw new EmptyGeneratorException(); + } } @Override diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index f53bb45bd43..030a70e2e6c 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -102,8 +102,6 @@ public class IRNode { private static final String START = "(\\d+(\\s){2}("; private static final String MID = ".*)+(\\s){2}===.*"; private static final String END = ")"; - private static final String STORE_OF_CLASS_POSTFIX = "(:|\\+)\\S* \\*" + END; - private static final String LOAD_OF_CLASS_POSTFIX = "(:|\\+)\\S* \\*" + END; public static final String IS_REPLACED = "#IS_REPLACED#"; // Is replaced by an additional user-defined string. @@ -1820,6 +1818,11 @@ public class IRNode { optoOnly(SCOPE_OBJECT, regex); } + public static final String SAFEPOINT_SCALAROBJECT_OF = COMPOSITE_PREFIX + "SAFEPOINT_SCALAROBJECT_OF" + POSTFIX; + static { + safepointScalarobjectOfNodes(SAFEPOINT_SCALAROBJECT_OF, "SafePointScalarObject"); + } + public static final String SIGNUM_VD = VECTOR_PREFIX + "SIGNUM_VD" + POSTFIX; static { vectorNode(SIGNUM_VD, "SignumVD", TYPE_DOUBLE); @@ -2938,13 +2941,30 @@ private static void parsePredicateNodes(String irNodePlaceholder, String label) CompilePhase.AFTER_LOOP_OPTS)); } + // Typename in load/store have the structure: + // @fully/qualified/package/name/to/TheClass+12 * + // And variation: + // - after @, we can have "stable:" or other labels, with optional space after ':' + // - the class can actually be a subclass, with $ separator (and it must be ok to give only the deepest one + // - after the class name, we can have a comma-separated list of implemented interfaces enclosed in parentheses + // - before the offset, we can have something like ":NotNull", either way, seeing "+" or ":" means the end of the type + // Worst case, it can be something like: + // @bla: bli:a/b/c$d$e (f/g,h/i/j):NotNull+24 * + private static final String LOAD_STORE_PREFIX = "@(\\w+: ?)*[\\w/\\$]*\\b"; + private static final String LOAD_STORE_SUFFIX = "( \\([^\\)]+\\))?(:|\\+)\\S* \\*"; + private static void loadOfNodes(String irNodePlaceholder, String irNodeRegex) { - String regex = START + irNodeRegex + MID + "@\\S*" + IS_REPLACED + LOAD_OF_CLASS_POSTFIX; + String regex = START + irNodeRegex + MID + LOAD_STORE_PREFIX + IS_REPLACED + LOAD_STORE_SUFFIX + END; beforeMatching(irNodePlaceholder, regex); } private static void storeOfNodes(String irNodePlaceholder, String irNodeRegex) { - String regex = START + irNodeRegex + MID + "@\\S*" + IS_REPLACED + STORE_OF_CLASS_POSTFIX; + String regex = START + irNodeRegex + MID + LOAD_STORE_PREFIX + IS_REPLACED + LOAD_STORE_SUFFIX + END; + beforeMatching(irNodePlaceholder, regex); + } + + private static void safepointScalarobjectOfNodes(String irNodePlaceholder, String irNodeRegex) { + String regex = START + irNodeRegex + MID + ".*" + IS_REPLACED + ".*" + END; beforeMatching(irNodePlaceholder, regex); } diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/checkattribute/parsing/RawIRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/checkattribute/parsing/RawIRNode.java index bf3021a6868..b86ae47e186 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/checkattribute/parsing/RawIRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/checkattribute/parsing/RawIRNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, 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 @@ -30,6 +30,8 @@ import compiler.lib.ir_framework.driver.irmatching.parser.VMInfo; import compiler.lib.ir_framework.driver.SuccessOnlyConstraintException; +import java.util.regex.Matcher; + /** * This class represents a "raw IR node" as read from a check attribute. It has a node part that either represents an * {@link IRNode} placeholder string or a user defined regex. In the former case, we could additionally have a user @@ -62,7 +64,7 @@ public String regex(CompilePhase compilePhase, VMInfo vmInfo, Comparison.Bound b if (IRNode.isVectorIRNode(node)) { nodeRegex = regexForVectorIRNode(nodeRegex, vmInfo, bound); } else if (userPostfix.isValid()) { - nodeRegex = nodeRegex.replaceAll(IRNode.IS_REPLACED, userPostfix.value()); + nodeRegex = nodeRegex.replaceAll(IRNode.IS_REPLACED, Matcher.quoteReplacement(userPostfix.value())); } } return nodeRegex; diff --git a/test/hotspot/jtreg/compiler/loopopts/LoopReductionHasControlOrBadInput.java b/test/hotspot/jtreg/compiler/loopopts/LoopReductionHasControlOrBadInput.java new file mode 100644 index 00000000000..b30939412f0 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/LoopReductionHasControlOrBadInput.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8350576 + * @summary Optimization bails out and hits an assert: + * assert(false) failed: reduction has ctrl or bad vector_input + * @run main/othervm -Xbatch -XX:-TieredCompilation + * -XX:CompileCommand=compileonly,compiler.loopopts.LoopReductionHasControlOrBadInput::* + * compiler.loopopts.LoopReductionHasControlOrBadInput + * @run main compiler.loopopts.LoopReductionHasControlOrBadInput + * + */ + +package compiler.loopopts; + +public class LoopReductionHasControlOrBadInput { + static long lFld; + static long lArr[] = new long[400]; + + static void test() { + int i = 1; + do { + long x = -1; + lArr[i] = i; + lFld += i | x; + } while (++i < 355); + } + + public static void main(String[] strArr) { + for (int i = 0; i < 100; i++) { + test(); + } + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/TestLoopEndNodeEliminate.java b/test/hotspot/jtreg/compiler/loopopts/TestLoopEndNodeEliminate.java index a4683db4f70..e3b5bdff12f 100644 --- a/test/hotspot/jtreg/compiler/loopopts/TestLoopEndNodeEliminate.java +++ b/test/hotspot/jtreg/compiler/loopopts/TestLoopEndNodeEliminate.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/loopopts/TestLoopPredicateDep.java b/test/hotspot/jtreg/compiler/loopopts/TestLoopPredicateDep.java index ca651a20750..bb945342c0d 100644 --- a/test/hotspot/jtreg/compiler/loopopts/TestLoopPredicateDep.java +++ b/test/hotspot/jtreg/compiler/loopopts/TestLoopPredicateDep.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/loopopts/TestSkeletonPredicateNegation.java b/test/hotspot/jtreg/compiler/loopopts/TestSkeletonPredicateNegation.java index 38a82139553..eae00ca3522 100644 --- a/test/hotspot/jtreg/compiler/loopopts/TestSkeletonPredicateNegation.java +++ b/test/hotspot/jtreg/compiler/loopopts/TestSkeletonPredicateNegation.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, Tencent. All rights reserved. * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * diff --git a/test/hotspot/jtreg/compiler/loopopts/TestValidTypeInOverflowProtection.java b/test/hotspot/jtreg/compiler/loopopts/TestValidTypeInOverflowProtection.java new file mode 100644 index 00000000000..39f72b04139 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestValidTypeInOverflowProtection.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8373525 + * @summary Test for the check of a valid type (long) for the input variable of overflow protection + * @run main/othervm -Xbatch -XX:-TieredCompilation -XX:CompileCommand=compileonly,compiler.loopopts.TestValidTypeInOverflowProtection::test + * ${test.main.class} + * @run main ${test.main.class} + */ + +package compiler.loopopts; + +import java.util.Vector; + +class TestVector extends Vector { + TestVector(int initialCapacity) { + super(initialCapacity); + } + + Object getElementData() { + return elementData; + } +} + +public class TestValidTypeInOverflowProtection { + int cntr; + int mode; + int value = 533; + int one = 1; + + public static void main(String[] args) { + TestValidTypeInOverflowProtection test = new TestValidTypeInOverflowProtection(); + for (int i = 0; i < 1000; i++) { + test.test(); + } + } + + TestVector nextVector() { + if (cntr == one) { + return null; + } + TestVector vect = new TestVector(value); + if (mode == 2) { + int cap = vect.capacity(); + for (int i = 0; i < cap; i++) { + vect.addElement(new Object()); + } + } + if (++mode == 3) { + mode = cntr++; + } + return vect; + } + + String test() { + cntr = 0; + TestVector vect = nextVector(); + while (vect != null) { + Object backup_array = new Object[vect.size()]; + System.arraycopy(vect.getElementData(), 0, backup_array, 0, vect.size()); + int old_size = vect.size(); + int old_cap = vect.capacity(); + vect.setSize(vect.capacity() + 1); + for (int i = old_size; i < old_cap; i++) { + if (vect.elementAt(i) != null) { + } + } + for (int i = 0; i < new MyInteger(old_size).v; i++) { + } + vect = nextVector(); + } + return null; + } + + class MyInteger { + int v; + + MyInteger(int v) { + int M452 = 4; + int N452 = 8; + for (int i452 = 0; i452 < M452; i452++) { + for (int j452 = 0; j452 < N452; j452++) { + switch (i452) { + case -2: + case 0: + this.v = v; + } + } + } + } + } +} \ No newline at end of file diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/MinMaxRed_Long.java b/test/hotspot/jtreg/compiler/loopopts/superword/MinMaxRed_Long.java index 9c3e2c7bc5d..f1e68fb95fb 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/MinMaxRed_Long.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/MinMaxRed_Long.java @@ -31,16 +31,21 @@ package compiler.loopopts.superword; -import compiler.lib.ir_framework.*; -import jdk.test.lib.Utils; +import compiler.lib.generators.Generator; +import compiler.lib.generators.Generators; +import compiler.lib.ir_framework.IR; +import compiler.lib.ir_framework.IRNode; +import compiler.lib.ir_framework.Run; +import compiler.lib.ir_framework.RunMode; +import compiler.lib.ir_framework.Test; +import compiler.lib.ir_framework.TestFramework; import java.util.Arrays; -import java.util.Random; -import java.util.stream.LongStream; public class MinMaxRed_Long { - private static final Random random = Utils.getRandomInstance(); + private static final int SIZE = 1024; + private static final Generator GEN_LONG = Generators.G.longs(); public static void main(String[] args) throws Exception { TestFramework framework = new TestFramework(); @@ -53,97 +58,41 @@ public static void main(String[] args) throws Exception { @Run(test = {"maxReductionImplement"}, mode = RunMode.STANDALONE) public void runMaxTest() { - runMaxTest(50); - runMaxTest(80); - runMaxTest(100); - } + long[] longs = new long[SIZE]; + Generators.G.fill(GEN_LONG, longs); - private static void runMaxTest(int probability) { - long[] longs = reductionInit(probability); long res = 0; for (int j = 0; j < 2000; j++) { res = maxReductionImplement(longs, res); } - if (res == 11 * Arrays.stream(longs).max().getAsLong()) { + + final long expected = Arrays.stream(longs).map(l -> l * 11).max().getAsLong(); + if (res == expected) { System.out.println("Success"); } else { - throw new AssertionError("Failed"); + throw new AssertionError("Failed, got result " + res + " but expected " + expected); } } @Run(test = {"minReductionImplement"}, mode = RunMode.STANDALONE) public void runMinTest() { - runMinTest(50); - runMinTest(80); - runMinTest(100); - } + long[] longs = new long[SIZE]; + Generators.G.fill(GEN_LONG, longs); - private static void runMinTest(int probability) { - long[] longs = reductionInit(probability); - // Negating the values generated for controlling max branching - // allows same logic to be used for min tests. - longs = negate(longs); long res = 0; for (int j = 0; j < 2000; j++) { res = minReductionImplement(longs, res); } - if (res == 11 * Arrays.stream(longs).min().getAsLong()) { + + final long expected = Arrays.stream(longs).map(l -> l * 11).min().getAsLong(); + if (res == expected) { System.out.println("Success"); } else { - throw new AssertionError("Failed"); + throw new AssertionError("Failed, got result " + res + " but expected " + expected); } } - static long[] negate(long[] nums) { - return LongStream.of(nums).map(l -> -l).toArray(); - } - - public static long[] reductionInit(int probability) { - int aboveCount, abovePercent; - long[] longs = new long[1024]; - - // Generates an array of numbers such that as the array is iterated - // there is P probability of finding a new max value, - // and 100-P probability of not finding a new max value. - // The algorithm loops around if the distribution does not match the probability, - // but it approximates the probability as the array sizes increase. - // The worst case of this algorithm is when the desired array size is 100 - // and the aim is to get 50% of probability, which can only be satisfied - // with 50 elements being a new max. This situation can take 15 rounds. - // As sizes increase, say 10'000 elements, - // the number of elements that have to satisfy 50% increases, - // so the algorithm will stop as an example when 5027 elements are a new max values. - // Also, probability values in the edges will achieve their objective quicker, - // with 0% or 100% probability doing it in a single loop. - // To support the same algorithm for min calculations, - // negating the array elements achieves the same objective. - do { - long max = random.nextLong(10); - longs[0] = max; - - aboveCount = 0; - for (int i = 1; i < longs.length; i++) { - long value; - if (random.nextLong(101) <= probability) { - long increment = random.nextLong(10); - value = max + increment; - aboveCount++; - } else { - // Decrement by at least 1 - long diffToMax = random.nextLong(10) + 1; - value = max - diffToMax; - } - longs[i] = value; - max = Math.max(max, value); - } - - abovePercent = ((aboveCount + 1) * 100) / longs.length; - } while (abovePercent != probability); - - return longs; - } - @Test @IR(applyIfAnd = {"SuperWordReductions", "true", "MaxVectorSize", ">=32"}, applyIfCPUFeatureOr = {"avx512", "true", "asimd" , "true"}, diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/RedTest_long.java b/test/hotspot/jtreg/compiler/loopopts/superword/RedTest_long.java index 10cd32bbbc7..cd8e0aa8b7f 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/RedTest_long.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/RedTest_long.java @@ -140,7 +140,7 @@ public static void reductionInit2( counts = {IRNode.ADD_REDUCTION_VL, ">= 1", IRNode.ADD_REDUCTION_VL, "<= 2"}) // one for main-loop, one for vector-post-loop @IR(applyIfPlatform = {"riscv64", "true"}, applyIfCPUFeature = {"rvv", "true"}, - applyIfAnd = {"SuperWordReductions", "true", "LoopMaxUnroll", ">= 8"}, + applyIfAnd = {"SuperWordReductions", "true", "LoopMaxUnroll", ">= 8", "MaxVectorSize", ">=32"}, counts = {IRNode.ADD_REDUCTION_VL, ">= 1", IRNode.ADD_REDUCTION_VL, "<= 2"}) // one for main-loop, one for vector-post-loop public static long sumReductionImplement( long[] a, @@ -162,7 +162,7 @@ public static long sumReductionImplement( counts = {IRNode.OR_REDUCTION_V, ">= 1", IRNode.OR_REDUCTION_V, "<= 2"}) // one for main-loop, one for vector-post-loop @IR(applyIfPlatform = {"riscv64", "true"}, applyIfCPUFeature = {"rvv", "true"}, - applyIfAnd = {"SuperWordReductions", "true", "LoopMaxUnroll", ">= 8"}, + applyIfAnd = {"SuperWordReductions", "true", "LoopMaxUnroll", ">= 8", "MaxVectorSize", ">=32"}, counts = {IRNode.OR_REDUCTION_V, ">= 1", IRNode.OR_REDUCTION_V, "<= 2"}) // one for main-loop, one for vector-post-loop public static long orReductionImplement( long[] a, @@ -184,7 +184,7 @@ public static long orReductionImplement( counts = {IRNode.AND_REDUCTION_V, ">= 1", IRNode.AND_REDUCTION_V, "<= 2"}) // one for main-loop, one for vector-post-loop @IR(applyIfPlatform = {"riscv64", "true"}, applyIfCPUFeature = {"rvv", "true"}, - applyIfAnd = {"SuperWordReductions", "true", "LoopMaxUnroll", ">= 8"}, + applyIfAnd = {"SuperWordReductions", "true", "LoopMaxUnroll", ">= 8", "MaxVectorSize", ">=32"}, counts = {IRNode.AND_REDUCTION_V, ">= 1", IRNode.AND_REDUCTION_V, "<= 2"}) // one for main-loop, one for vector-post-loop public static long andReductionImplement( long[] a, @@ -206,7 +206,7 @@ public static long andReductionImplement( counts = {IRNode.XOR_REDUCTION_V, ">= 1", IRNode.XOR_REDUCTION_V, "<= 2"}) // one for main-loop, one for vector-post-loop @IR(applyIfPlatform = {"riscv64", "true"}, applyIfCPUFeature = {"rvv", "true"}, - applyIfAnd = {"SuperWordReductions", "true", "LoopMaxUnroll", ">= 8"}, + applyIfAnd = {"SuperWordReductions", "true", "LoopMaxUnroll", ">= 8", "MaxVectorSize", ">=32"}, counts = {IRNode.XOR_REDUCTION_V, ">= 1", IRNode.XOR_REDUCTION_V, "<= 2"}) // one for main-loop, one for vector-post-loop public static long xorReductionImplement( long[] a, @@ -228,7 +228,7 @@ public static long xorReductionImplement( counts = {IRNode.MUL_REDUCTION_VL, ">= 1", IRNode.MUL_REDUCTION_VL, "<= 2"}) // one for main-loop, one for vector-post-loop @IR(applyIfPlatform = {"riscv64", "true"}, applyIfCPUFeature = {"rvv", "true"}, - applyIfAnd = {"SuperWordReductions", "true", "LoopMaxUnroll", ">= 8"}, + applyIfAnd = {"SuperWordReductions", "true", "LoopMaxUnroll", ">= 8", "MaxVectorSize", ">=32"}, counts = {IRNode.MUL_REDUCTION_VL, ">= 1", IRNode.MUL_REDUCTION_VL, "<= 2"}) // one for main-loop, one for vector-post-loop public static long mulReductionImplement( long[] a, diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/SumRed_Long.java b/test/hotspot/jtreg/compiler/loopopts/superword/SumRed_Long.java index e803b33bd4f..64ec0941b22 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/SumRed_Long.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/SumRed_Long.java @@ -98,7 +98,7 @@ public static void sumReductionInit( counts = {IRNode.ADD_REDUCTION_VL, ">= 1", IRNode.ADD_REDUCTION_VL, "<= 2"}) // one for main-loop, one for vector-post-loop @IR(applyIfPlatform = {"riscv64", "true"}, applyIfCPUFeature = {"rvv", "true"}, - applyIfAnd = {"SuperWordReductions", "true", "LoopMaxUnroll", ">= 8"}, + applyIfAnd = {"SuperWordReductions", "true", "LoopMaxUnroll", ">= 8", "MaxVectorSize", ">=32"}, counts = {IRNode.ADD_REDUCTION_VL, ">= 1", IRNode.ADD_REDUCTION_VL, "<= 2"}) // one for main-loop, one for vector-post-loop public static long sumReductionImplement( long[] a, diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java index 97a3c4ed037..322c36c39e1 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java @@ -1063,8 +1063,16 @@ static Object[] test12(byte[] a, byte[] b, byte mask) { IRNode.ADD_VL, IRNode.VECTOR_SIZE + "min(max_int, max_long)", "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfPlatform = {"64-bit", "true"}, - applyIfCPUFeatureOr = {"avx2", "true", "rvv", "true"}) + applyIfCPUFeature = {"avx2", "true"}) // require avx to ensure vectors are larger than what unrolling produces + @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE + "min(max_int, max_long)", "> 0", + IRNode.LOAD_VECTOR_L, IRNode.VECTOR_SIZE + "min(max_int, max_long)", "> 0", + IRNode.ADD_VI, IRNode.VECTOR_SIZE + "min(max_int, max_long)", "> 0", + IRNode.ADD_VL, IRNode.VECTOR_SIZE + "min(max_int, max_long)", "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"riscv64", "true"}, + applyIfCPUFeature = {"rvv", "true"}, + applyIf = {"MaxVectorSize", ">=32"}) static Object[] test13aIL(int[] a, long[] b) { for (int i = 0; i < RANGE; i++) { a[i]++; @@ -1175,8 +1183,16 @@ static Object[] test13aBSIL(byte[] a, short[] b, int[] c, long[] d) { IRNode.ADD_VL, IRNode.VECTOR_SIZE + "min(max_int, max_long)", "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfPlatform = {"64-bit", "true"}, - applyIfCPUFeatureOr = {"avx2", "true", "rvv", "true"}) + applyIfCPUFeature = {"avx2", "true"}) // require avx to ensure vectors are larger than what unrolling produces + @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE + "min(max_int, max_long)", "> 0", + IRNode.LOAD_VECTOR_L, IRNode.VECTOR_SIZE + "min(max_int, max_long)", "> 0", + IRNode.ADD_VI, IRNode.VECTOR_SIZE + "min(max_int, max_long)", "> 0", + IRNode.ADD_VL, IRNode.VECTOR_SIZE + "min(max_int, max_long)", "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"riscv64", "true"}, + applyIfCPUFeature = {"rvv", "true"}, + applyIf = {"MaxVectorSize", ">=32"}) static Object[] test13bIL(int[] a, long[] b) { for (int i = 1; i < RANGE; i++) { a[i]++; diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVectorFuzzer.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVectorFuzzer.java index d75db965ea3..019dad55b65 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVectorFuzzer.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVectorFuzzer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,19 @@ * @key randomness * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions * -XX:LoopUnrollLimit=250 - * -XX:CompileCommand=printcompilation,compiler.loopopts.superword.TestAlignVectorFuzzer::* + * compiler.loopopts.superword.TestAlignVectorFuzzer + */ + +/* + * @test id=CompileOnly + * @bug 8253191 + * @summary Fuzzing loops with different (random) init, limit, stride, scale etc. Do not force alignment. + * @modules java.base/jdk.internal.misc + * @library /test/lib + * @key randomness + * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions + * -XX:LoopUnrollLimit=250 + * -XX:CompileCommand=compileonly,compiler.loopopts.superword.TestAlignVectorFuzzer::* * compiler.loopopts.superword.TestAlignVectorFuzzer */ @@ -44,7 +56,6 @@ * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions * -XX:+AlignVector -XX:+VerifyAlignVector * -XX:LoopUnrollLimit=250 - * -XX:CompileCommand=printcompilation,compiler.loopopts.superword.TestAlignVectorFuzzer::* * compiler.loopopts.superword.TestAlignVectorFuzzer */ @@ -58,7 +69,6 @@ * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions * -XX:+AlignVector -XX:+VerifyAlignVector * -XX:LoopUnrollLimit=250 - * -XX:CompileCommand=printcompilation,compiler.loopopts.superword.TestAlignVectorFuzzer::* * -XX:ObjectAlignmentInBytes=16 * compiler.loopopts.superword.TestAlignVectorFuzzer */ @@ -73,7 +83,6 @@ * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions * -XX:+AlignVector -XX:+VerifyAlignVector * -XX:LoopUnrollLimit=250 - * -XX:CompileCommand=printcompilation,compiler.loopopts.superword.TestAlignVectorFuzzer::* * -XX:-TieredCompilation -Xbatch * compiler.loopopts.superword.TestAlignVectorFuzzer */ diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestGeneralizedReductions.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestGeneralizedReductions.java index 92bc4f17446..6c2f0d825b9 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestGeneralizedReductions.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestGeneralizedReductions.java @@ -81,10 +81,14 @@ private static void initArray(long[] array) { } @Test - @IR(applyIfCPUFeatureOr = {"avx2", "true", "rvv", "true"}, + @IR(applyIfCPUFeature = {"avx2", "true"}, applyIf = {"SuperWordReductions", "true"}, applyIfPlatform = {"64-bit", "true"}, counts = {IRNode.ADD_REDUCTION_VI, ">= 1"}) + @IR(applyIfPlatform = {"riscv64", "true"}, + applyIfCPUFeature = {"rvv", "true"}, + applyIfAnd = {"SuperWordReductions", "true", "MaxVectorSize", ">=32"}, + counts = {IRNode.ADD_REDUCTION_VI, ">= 1"}) private static long testReductionOnGlobalAccumulator(long[] array) { acc = 0; for (int i = 0; i < array.length; i++) { @@ -94,10 +98,14 @@ private static long testReductionOnGlobalAccumulator(long[] array) { } @Test - @IR(applyIfCPUFeatureOr = {"avx2", "true", "rvv", "true"}, + @IR(applyIfCPUFeature = {"avx2", "true"}, applyIf = {"SuperWordReductions", "true"}, applyIfPlatform = {"64-bit", "true"}, counts = {IRNode.ADD_REDUCTION_VI, ">= 1"}) + @IR(applyIfPlatform = {"riscv64", "true"}, + applyIfCPUFeature = {"rvv", "true"}, + applyIfAnd = {"SuperWordReductions", "true", "MaxVectorSize", ">=32"}, + counts = {IRNode.ADD_REDUCTION_VI, ">= 1"}) private static long testReductionOnPartiallyUnrolledLoop(long[] array) { int sum = 0; for (int i = 0; i < array.length / 2; i++) { @@ -108,10 +116,14 @@ private static long testReductionOnPartiallyUnrolledLoop(long[] array) { } @Test - @IR(applyIfCPUFeatureOr = {"avx2", "true", "rvv", "true"}, + @IR(applyIfCPUFeature = {"avx2", "true"}, applyIf = {"SuperWordReductions", "true"}, applyIfPlatform = {"64-bit", "true"}, counts = {IRNode.ADD_REDUCTION_VI, ">= 1"}) + @IR(applyIfPlatform = {"riscv64", "true"}, + applyIfCPUFeature = {"rvv", "true"}, + applyIfAnd = {"SuperWordReductions", "true", "MaxVectorSize", ">=32"}, + counts = {IRNode.ADD_REDUCTION_VI, ">= 1"}) private static long testReductionOnLargePartiallyUnrolledLoop(long[] array) { int sum = 0; for (int i = 0; i < array.length / 8; i++) { @@ -148,13 +160,13 @@ private static long testReductionOnPartiallyUnrolledLoopWithSwappedInputs(long[] @Test @IR(applyIfCPUFeatureOr = {"avx2", "true"}, - applyIfAnd = {"SuperWordReductions", "true","UsePopCountInstruction", "true"}, + applyIfAnd = {"SuperWordReductions", "true", "UsePopCountInstruction", "true"}, applyIfPlatform = {"64-bit", "true"}, counts = {IRNode.ADD_REDUCTION_VI, ">= 1", IRNode.POPCOUNT_VL, ">= 1"}) @IR(applyIfPlatform = {"riscv64", "true"}, applyIfCPUFeatureOr = {"zvbb", "true"}, - applyIfAnd = {"SuperWordReductions", "true","UsePopCountInstruction", "true"}, + applyIfAnd = {"SuperWordReductions", "true", "UsePopCountInstruction", "true", "MaxVectorSize", ">=32"}, counts = {IRNode.ADD_REDUCTION_VI, ">= 1", IRNode.POPCOUNT_VL, ">= 1"}) private static long testMapReductionOnGlobalAccumulator(long[] array) { diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestUnorderedReductionPartialVectorization.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestUnorderedReductionPartialVectorization.java index 0a0f0c3114e..c862704da26 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestUnorderedReductionPartialVectorization.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestUnorderedReductionPartialVectorization.java @@ -66,7 +66,19 @@ public void runTests() throws Exception { IRNode.OR_REDUCTION_V, "> 0",}, applyIfOr = {"AlignVector", "false", "UseCompactObjectHeaders", "false"}, applyIfPlatform = {"64-bit", "true"}, - applyIfCPUFeatureOr = {"avx2", "true", "rvv", "true"}) + applyIfCPUFeature = {"avx2", "true"}) + @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE + "min(max_int, max_long)", "> 0", + IRNode.VECTOR_CAST_I2L, IRNode.VECTOR_SIZE + "min(max_int, max_long)", "> 0", + IRNode.OR_REDUCTION_V, "> 0",}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">=32"}, + applyIfPlatform = {"riscv64", "true"}, + applyIfCPUFeature = {"rvv", "true"}) + @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE + "min(max_int, max_long)", "> 0", + IRNode.VECTOR_CAST_I2L, IRNode.VECTOR_SIZE + "min(max_int, max_long)", "> 0", + IRNode.OR_REDUCTION_V, "> 0",}, + applyIfAnd = {"UseCompactObjectHeaders", "false", "MaxVectorSize", ">=32"}, + applyIfPlatform = {"riscv64", "true"}, + applyIfCPUFeature = {"rvv", "true"}) static long test1(int[] data, long sum) { for (int i = 0; i < data.length; i+=2) { // Mixing int and long ops means we only end up allowing half of the int diff --git a/test/hotspot/jtreg/compiler/loopstripmining/CheckLoopStripMining.java b/test/hotspot/jtreg/compiler/loopstripmining/CheckLoopStripMining.java index 9e8ac6b013a..1091037cdfb 100644 --- a/test/hotspot/jtreg/compiler/loopstripmining/CheckLoopStripMining.java +++ b/test/hotspot/jtreg/compiler/loopstripmining/CheckLoopStripMining.java @@ -42,8 +42,8 @@ public static void main(String args[]) throws Exception { "-XX:+SafepointTimeout", "-XX:+SafepointALot", "-XX:+AbortVMOnSafepointTimeout", - "-XX:SafepointTimeoutDelay=" + Utils.adjustTimeout(300), - "-XX:GuaranteedSafepointInterval=" + Utils.adjustTimeout(300), + "-XX:SafepointTimeoutDelay=" + Utils.adjustTimeout(1200), + "-XX:GuaranteedSafepointInterval=" + Utils.adjustTimeout(1200), "-XX:-TieredCompilation", "-XX:+UseCountedLoopSafepoints", "-XX:LoopStripMiningIter=1000", @@ -58,8 +58,8 @@ public static void main(String args[]) throws Exception { "-XX:+SafepointTimeout", "-XX:+SafepointALot", "-XX:+AbortVMOnSafepointTimeout", - "-XX:SafepointTimeoutDelay=" + Utils.adjustTimeout(300), - "-XX:GuaranteedSafepointInterval=" + Utils.adjustTimeout(300), + "-XX:SafepointTimeoutDelay=" + Utils.adjustTimeout(1200), + "-XX:GuaranteedSafepointInterval=" + Utils.adjustTimeout(1200), "-XX:-TieredCompilation", "-XX:+UseCountedLoopSafepoints", "-XX:LoopStripMiningIter=1000", diff --git a/test/hotspot/jtreg/compiler/oracle/TestInvalidCompileCommand.java b/test/hotspot/jtreg/compiler/oracle/TestInvalidCompileCommand.java index 791b1d042e3..a64e5f2b8bb 100644 --- a/test/hotspot/jtreg/compiler/oracle/TestInvalidCompileCommand.java +++ b/test/hotspot/jtreg/compiler/oracle/TestInvalidCompileCommand.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/print/TestTraceOptoParse.java b/test/hotspot/jtreg/compiler/print/TestTraceOptoParse.java index 65aa6bcb2d0..52a7aba1a7e 100644 --- a/test/hotspot/jtreg/compiler/print/TestTraceOptoParse.java +++ b/test/hotspot/jtreg/compiler/print/TestTraceOptoParse.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (c) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/rangechecks/TestRangeCheckHoistingScaledIV.java b/test/hotspot/jtreg/compiler/rangechecks/TestRangeCheckHoistingScaledIV.java index 4b4026c452a..62fb27ecb0f 100644 --- a/test/hotspot/jtreg/compiler/rangechecks/TestRangeCheckHoistingScaledIV.java +++ b/test/hotspot/jtreg/compiler/rangechecks/TestRangeCheckHoistingScaledIV.java @@ -28,7 +28,8 @@ * @summary Test range check hoisting for some scaled iv at array index * @library /test/lib / * @requires vm.flagless - * @requires vm.debug & vm.compiler2.enabled & (os.simpleArch == "x64" | os.arch == "aarch64" | os.arch == "riscv64") + * @requires vm.debug & vm.compiler2.enabled + * @requires os.simpleArch == "x64" | os.arch == "aarch64" | (os.arch == "riscv64" & vm.cpu.features ~= ".*rvv.*") * @modules jdk.incubator.vector * @run main/othervm compiler.rangechecks.TestRangeCheckHoistingScaledIV */ diff --git a/test/hotspot/jtreg/compiler/regalloc/TestGCMRecalcPressureNodes.java b/test/hotspot/jtreg/compiler/regalloc/TestGCMRecalcPressureNodes.java index fe2fd7e4444..c99bdca2cb1 100644 --- a/test/hotspot/jtreg/compiler/regalloc/TestGCMRecalcPressureNodes.java +++ b/test/hotspot/jtreg/compiler/regalloc/TestGCMRecalcPressureNodes.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, Tencent. All rights reserved. * 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,4 +50,3 @@ public static void main(String[] args) { } } } - diff --git a/test/hotspot/jtreg/compiler/startup/StartupOutput.java b/test/hotspot/jtreg/compiler/startup/StartupOutput.java index 22f2887a266..bb08a2c0a2d 100644 --- a/test/hotspot/jtreg/compiler/startup/StartupOutput.java +++ b/test/hotspot/jtreg/compiler/startup/StartupOutput.java @@ -36,6 +36,7 @@ package compiler.startup; +import jdk.test.lib.Platform; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.Utils; @@ -60,8 +61,11 @@ public static void main(String[] args) throws Exception { throw new Exception("VM crashed with exit code " + exitCode); } - for (int i = 0; i < 200; i++) { - int initialCodeCacheSizeInKb = 800 + rand.nextInt(400); + // On s390x, generated code is ~6x larger in fastdebug and ~1.4x in release builds vs. other archs, + // hence we require slightly more minimum space. + int minInitialSize = 800 + (Platform.isS390x() ? 800 : 0); + for (int i = 0; i < 50; i++) { + int initialCodeCacheSizeInKb = minInitialSize + rand.nextInt(400); int reservedCodeCacheSizeInKb = initialCodeCacheSizeInKb + rand.nextInt(200); pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:InitialCodeCacheSize=" + initialCodeCacheSizeInKb + "K", "-XX:ReservedCodeCacheSize=" + reservedCodeCacheSizeInKb + "k", "-version"); out = new OutputAnalyzer(pb.start()); diff --git a/test/hotspot/jtreg/compiler/unsafe/TestMisalignedUnsafeAccess.java b/test/hotspot/jtreg/compiler/unsafe/TestMisalignedUnsafeAccess.java index 84752a0ccf0..f4b1e3f0a53 100644 --- a/test/hotspot/jtreg/compiler/unsafe/TestMisalignedUnsafeAccess.java +++ b/test/hotspot/jtreg/compiler/unsafe/TestMisalignedUnsafeAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2020, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestIntrinsicBailOut.java b/test/hotspot/jtreg/compiler/vectorapi/TestIntrinsicBailOut.java index 72e1c3aa30f..b6ddadad49b 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/TestIntrinsicBailOut.java +++ b/test/hotspot/jtreg/compiler/vectorapi/TestIntrinsicBailOut.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021, 2022, THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, 2022, Tencent. 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. * diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestVectorErgonomics.java b/test/hotspot/jtreg/compiler/vectorapi/TestVectorErgonomics.java index 4f9f8ca3bd2..0fd586f8d6e 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/TestVectorErgonomics.java +++ b/test/hotspot/jtreg/compiler/vectorapi/TestVectorErgonomics.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestVectorMathLib.java b/test/hotspot/jtreg/compiler/vectorapi/TestVectorMathLib.java new file mode 100644 index 00000000000..af9e7c051f8 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/TestVectorMathLib.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.vectorapi; + +import jdk.incubator.vector.FloatVector; +import jdk.incubator.vector.VectorOperators; +import jdk.incubator.vector.VectorSpecies; + +/* + * @test + * @bug 8367333 + * @requires vm.compiler2.enabled + * @modules jdk.incubator.vector + * @library /test/lib + * + * @run main/othervm -Xbatch -XX:-TieredCompilation + * -XX:+UnlockDiagnosticVMOptions -XX:+StressIncrementalInlining + * -XX:CompileCommand=quiet + * -XX:CompileCommand=compileonly,compiler.vectorapi.TestVectorMathLib::test* + * compiler.vectorapi.TestVectorMathLib + */ + +public class TestVectorMathLib { + private static final VectorSpecies SPECIES = FloatVector.SPECIES_PREFERRED; + + static FloatVector testTAN(FloatVector fv) { + return fv.lanewise(VectorOperators.TAN); + } + static FloatVector testTANH(FloatVector fv) { + return fv.lanewise(VectorOperators.TANH); + } + static FloatVector testSIN(FloatVector fv) { + return fv.lanewise(VectorOperators.SIN); + } + static FloatVector testSINH(FloatVector fv) { + return fv.lanewise(VectorOperators.SINH); + } + static FloatVector testCOS(FloatVector fv) { + return fv.lanewise(VectorOperators.COS); + } + static FloatVector testCOSH(FloatVector fv) { + return fv.lanewise(VectorOperators.COSH); + } + static FloatVector testASIN(FloatVector fv) { + return fv.lanewise(VectorOperators.ASIN); + } + static FloatVector testACOS(FloatVector fv) { + return fv.lanewise(VectorOperators.ACOS); + } + static FloatVector testATAN(FloatVector fv) { + return fv.lanewise(VectorOperators.ATAN); + } + static FloatVector testATAN2(FloatVector fv) { + return fv.lanewise(VectorOperators.ATAN2, fv); + } + static FloatVector testCBRT(FloatVector fv) { + return fv.lanewise(VectorOperators.CBRT); + } + static FloatVector testLOG(FloatVector fv) { + return fv.lanewise(VectorOperators.LOG); + } + static FloatVector testLOG10(FloatVector fv) { + return fv.lanewise(VectorOperators.LOG10); + } + static FloatVector testLOG1P(FloatVector fv) { + return fv.lanewise(VectorOperators.LOG1P); + } + static FloatVector testPOW(FloatVector fv) { + return fv.lanewise(VectorOperators.POW, fv); + } + static FloatVector testEXP(FloatVector fv) { + return fv.lanewise(VectorOperators.EXP); + } + static FloatVector testEXPM1(FloatVector fv) { + return fv.lanewise(VectorOperators.EXPM1); + } + static FloatVector testHYPOT(FloatVector fv) { + return fv.lanewise(VectorOperators.HYPOT, fv); + } + + public static void main(String[] args) { + FloatVector z = FloatVector.zero(SPECIES); + for (int i = 0; i < 20_000; i++) { + z.neg(); // unary + z.add(z); // binary + + testTAN(z); + testTANH(z); + testSIN(z); + testSINH(z); + testCOS(z); + testCOSH(z); + testASIN(z); + testACOS(z); + testATAN(z); + testATAN2(z); + testCBRT(z); + testLOG(z); + testLOG10(z); + testLOG1P(z); + testPOW(z); + testEXP(z); + testEXPM1(z); + testHYPOT(z); + } + + System.out.println("TEST PASSED"); + } +} + diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorReinterpretTest.java b/test/hotspot/jtreg/compiler/vectorapi/VectorReinterpretTest.java index b453311f857..2f9b97b56d7 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorReinterpretTest.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorReinterpretTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/compiler/vectorization/TestFloatConversionsVectorNaN.java b/test/hotspot/jtreg/compiler/vectorization/TestFloatConversionsVectorNaN.java index 6f76defa279..dad6e51f2ec 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestFloatConversionsVectorNaN.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestFloatConversionsVectorNaN.java @@ -23,6 +23,7 @@ /** * @test + * @key randomness * @bug 8320646 * @summary Auto-vectorize Float.floatToFloat16, Float.float16ToFloat APIs, with NaN * @requires vm.compiler2.enabled @@ -37,9 +38,11 @@ package compiler.vectorization; import java.util.HexFormat; +import java.util.Random; import compiler.lib.ir_framework.*; import jdk.test.lib.Asserts; +import jdk.test.lib.Utils; public class TestFloatConversionsVectorNaN { private static final int ARRLEN = 1024; @@ -79,14 +82,16 @@ public void test_float_float16(short[] sout, float[] finp) { @Run(test = {"test_float_float16"}, mode = RunMode.STANDALONE) public void kernel_test_float_float16() { + Random rand = Utils.getRandomInstance(); int errno = 0; finp = new float[ARRLEN]; sout = new short[ARRLEN]; // Setup for (int i = 0; i < ARRLEN; i++) { - if (i%39 == 0) { - int x = 0x7f800000 + ((i/39) << 13); + if (i%3 == 0) { + int shift = rand.nextInt(13+1); + int x = 0x7f800000 + ((i/39) << shift); x = (i%2 == 0) ? x : (x | 0x80000000); finp[i] = Float.intBitsToFloat(x); } else { @@ -128,7 +133,8 @@ public void kernel_test_float_float16() { static int assertEquals(int idx, float f, short expected, short actual) { HexFormat hf = HexFormat.of(); - String msg = "floatToFloat16 wrong result: idx: " + idx + ", \t" + f + + String msg = "floatToFloat16 wrong result: idx: " + idx + + ", \t" + f + ", hex: " + Integer.toHexString(Float.floatToRawIntBits(f)) + ",\t expected: " + hf.toHexDigits(expected) + ",\t actual: " + hf.toHexDigits(actual); if ((expected & 0x7c00) != 0x7c00) { @@ -167,7 +173,7 @@ public void kernel_test_float16_float() { // Setup for (int i = 0; i < ARRLEN; i++) { - if (i%39 == 0) { + if (i%3 == 0) { int x = 0x7c00 + i; x = (i%2 == 0) ? x : (x | 0x8000); sinp[i] = (short)x; diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/BasicIntOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/BasicIntOpTest.java index 9f1e5789056..8b85bfa6327 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/BasicIntOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/BasicIntOpTest.java @@ -141,7 +141,7 @@ public int[] vectorMulSub() { } @Test - @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx2", "true", "rvv", "true"}, + @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx2", "true", "zvbb", "true"}, counts = {IRNode.POPCOUNT_VI, ">0"}) public int[] vectorPopCount() { int[] res = new int[SIZE]; diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/LoopReductionOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/LoopReductionOpTest.java index ac8be6bc0ec..546d99f5cce 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/LoopReductionOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/LoopReductionOpTest.java @@ -177,7 +177,11 @@ public double twoReductionsDifferentSizes2() { @Test @IR(applyIfCPUFeatureOr = {"asimd", "true", "sse2", "true", "rvv", "true"}, counts = {IRNode.STORE_VECTOR, ">0"}) - @IR(applyIfCPUFeatureOr = {"avx2", "true", "rvv", "true"}, + @IR(applyIfCPUFeature = {"avx2", "true"}, + counts = {IRNode.ADD_REDUCTION_V, ">0"}) + @IR(applyIfPlatform = {"riscv64", "true"}, + applyIfCPUFeature = {"rvv", "true"}, + applyIf = {"MaxVectorSize", ">=32" }, counts = {IRNode.ADD_REDUCTION_V, ">0"}) public long reductionWithNonReductionDifferentSizes() { long res = 0L; diff --git a/test/hotspot/jtreg/containers/docker/DockerBasicTest.java b/test/hotspot/jtreg/containers/docker/DockerBasicTest.java index 9233b199532..8e2c0b6a85a 100644 --- a/test/hotspot/jtreg/containers/docker/DockerBasicTest.java +++ b/test/hotspot/jtreg/containers/docker/DockerBasicTest.java @@ -26,6 +26,7 @@ * @test * @summary Basic (sanity) test for JDK-under-test inside a docker image. * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/test/hotspot/jtreg/containers/docker/ShareTmpDir.java b/test/hotspot/jtreg/containers/docker/ShareTmpDir.java index 43cd6ec5152..9a4748563bd 100644 --- a/test/hotspot/jtreg/containers/docker/ShareTmpDir.java +++ b/test/hotspot/jtreg/containers/docker/ShareTmpDir.java @@ -28,6 +28,7 @@ * @key cgroups * @summary Test for hsperfdata file name conflict when two containers share the same /tmp directory * @requires container.support + * @requires !vm.asan * @library /test/lib * @build WaitForFlagFile * @run driver ShareTmpDir diff --git a/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java b/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java index c51bfa1abbb..99220201f66 100644 --- a/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java +++ b/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java @@ -27,6 +27,7 @@ * @key cgroups * @summary Test JVM's CPU resource awareness when running inside docker container * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc * java.base/jdk.internal.platform diff --git a/test/hotspot/jtreg/containers/docker/TestCPUSets.java b/test/hotspot/jtreg/containers/docker/TestCPUSets.java index aabe82e131f..7894172e401 100644 --- a/test/hotspot/jtreg/containers/docker/TestCPUSets.java +++ b/test/hotspot/jtreg/containers/docker/TestCPUSets.java @@ -27,6 +27,7 @@ * @key cgroups * @summary Test JVM's awareness of cpu sets (cpus and mems) * @requires container.support + * @requires !vm.asan * @requires (os.arch != "s390x") * @library /test/lib * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/containers/docker/TestContainerInfo.java b/test/hotspot/jtreg/containers/docker/TestContainerInfo.java index 5db3c2af098..b9b6fb65b75 100644 --- a/test/hotspot/jtreg/containers/docker/TestContainerInfo.java +++ b/test/hotspot/jtreg/containers/docker/TestContainerInfo.java @@ -28,6 +28,7 @@ * @summary Test container info for cgroup v2 * @key cgroups * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/test/hotspot/jtreg/containers/docker/TestJFREvents.java b/test/hotspot/jtreg/containers/docker/TestJFREvents.java index 77c735cde00..c8905f4e49c 100644 --- a/test/hotspot/jtreg/containers/docker/TestJFREvents.java +++ b/test/hotspot/jtreg/containers/docker/TestJFREvents.java @@ -30,6 +30,7 @@ * Also make sure that PIDs are based on value provided by container, * not by the host system. * @requires (container.support & os.maxMemory >= 2g) + * @requires !vm.asan * @modules java.base/jdk.internal.platform * @library /test/lib * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java b/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java index 9f9497d9c63..c0dde368d1e 100644 --- a/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java +++ b/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java @@ -28,6 +28,7 @@ * the reported host ip and host name are correctly reported within * the container. * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java b/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java index b7517254281..efe1fa4ffbc 100644 --- a/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java +++ b/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java @@ -26,6 +26,7 @@ * @test * @summary Test JFR recording controlled via JMX across container boundary. * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc * java.management @@ -76,7 +77,7 @@ public static void main(String[] args) throws Exception { throw new SkippedException("Docker is not supported on this host"); } - if (isPodman() & !Platform.isRoot()) { + if (DockerTestUtils.isPodman() & !Platform.isRoot()) { throw new SkippedException("test cannot be run under rootless podman configuration"); } @@ -221,10 +222,4 @@ static File transferRecording(FlightRecorderMXBean bean, long streamId) throws E } } - static boolean isPodman() { - String[] parts = Container.ENGINE_COMMAND - .toLowerCase() - .split(File.pathSeparator); - return "podman".equals(parts[parts.length - 1]); - } } diff --git a/test/hotspot/jtreg/containers/docker/TestJcmd.java b/test/hotspot/jtreg/containers/docker/TestJcmd.java index 4b604096b00..8c210544bb6 100644 --- a/test/hotspot/jtreg/containers/docker/TestJcmd.java +++ b/test/hotspot/jtreg/containers/docker/TestJcmd.java @@ -57,7 +57,7 @@ public class TestJcmd { private static final String IMAGE_NAME = Common.imageName("jcmd"); private static final int TIME_TO_RUN_CONTAINER_PROCESS = (int) (10 * Utils.TIMEOUT_FACTOR); // seconds private static final String CONTAINER_NAME = "test-container"; - private static final boolean IS_PODMAN = Container.ENGINE_COMMAND.contains("podman"); + private static final boolean IS_PODMAN = DockerTestUtils.isPodman(); private static final String ROOT_UID = "0"; diff --git a/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java b/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java index 9feeda6f4ad..91a07012f00 100644 --- a/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java +++ b/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java @@ -31,6 +31,7 @@ * namespace such as PID namespace, specific sub-directories, IPC and more. * @requires container.support * @requires vm.flagless + * @requires !vm.asan * @modules java.base/jdk.internal.misc * java.management * jdk.jartool/sun.tools.jar diff --git a/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java b/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java index 14227a71068..7b05669085c 100644 --- a/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java +++ b/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java @@ -30,6 +30,7 @@ * @key cgroups * @summary Test container limits updating as they get updated at runtime without restart * @requires container.support + * @requires !vm.asan * @library /test/lib * @build jdk.test.whitebox.WhiteBox LimitUpdateChecker * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar whitebox.jar jdk.test.whitebox.WhiteBox diff --git a/test/hotspot/jtreg/containers/docker/TestMemoryInvisibleParent.java b/test/hotspot/jtreg/containers/docker/TestMemoryInvisibleParent.java new file mode 100644 index 00000000000..68331f26766 --- /dev/null +++ b/test/hotspot/jtreg/containers/docker/TestMemoryInvisibleParent.java @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2025, IBM Corporation. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import jdk.test.lib.Container; +import jdk.test.lib.containers.docker.Common; +import jdk.test.lib.containers.docker.DockerTestUtils; +import jdk.test.lib.containers.docker.ContainerRuntimeVersionTestUtils; +import jdk.test.lib.containers.docker.DockerRunOptions; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.internal.platform.Metrics; + +import java.nio.file.Path; +import java.nio.file.Files; +import java.util.ArrayList; + +import jdk.test.lib.Platform; +import jtreg.SkippedException; + +/* + * @test + * @bug 8370966 + * @requires os.family == "linux" + * @requires !vm.asan + * @modules java.base/jdk.internal.platform + * @library /test/lib + * @run main TestMemoryInvisibleParent + */ +public class TestMemoryInvisibleParent { + private static final String UNLIMITED = "-1"; + private static final String imageName = Common.imageName("invisible-parent"); + + public static void main(String[] args) throws Exception { + Metrics metrics = Metrics.systemMetrics(); + if (metrics == null) { + System.out.println("Cgroup not configured."); + return; + } + if (!DockerTestUtils.canTestDocker()) { + System.out.println("Unable to run docker tests."); + return; + } + + ContainerRuntimeVersionTestUtils.checkContainerVersionSupported(); + + if (DockerTestUtils.isRootless()) { + throw new SkippedException("Test skipped in rootless mode"); + } + if (!Platform.isRoot()) { + throw new SkippedException("Test should be run as root"); + } + DockerTestUtils.buildJdkContainerImage(imageName); + + if ("cgroupv1".equals(metrics.getProvider())) { + try { + testMemoryLimitHiddenParent("104857600", "104857600"); + testMemoryLimitHiddenParent("209715200", "209715200"); + } finally { + DockerTestUtils.removeDockerImage(imageName); + } + } else { + throw new SkippedException("cgroup v1 - only test! This is " + metrics.getProvider()); + } + } + + private static void testMemoryLimitHiddenParent(String valueToSet, String expectedValue) + throws Exception { + + Common.logNewTestCase("Cgroup V1 hidden parent memory limit: " + valueToSet); + + try { + String cgroupParent = setParentWithLimit(valueToSet); + DockerRunOptions opts = new DockerRunOptions(imageName, "/jdk/bin/java", "-version", "-Xlog:os+container=trace"); + opts.appendTestJavaOptions = false; + if (DockerTestUtils.isPodman()) { + // Podman needs to run this test with engine option --cgroup-manager=cgroupfs + opts.addEngineOpts("--cgroup-manager", "cgroupfs"); + } + opts.addDockerOpts("--cgroup-parent=/" + cgroupParent); + Common.run(opts) + .shouldContain("Hierarchical Memory Limit is: " + expectedValue); + } finally { + // Reset the parent memory limit to unlimited (-1) + setParentWithLimit(UNLIMITED); + } + } + + private static String setParentWithLimit(String memLimit) throws Exception { + String cgroupParent = "hidden-parent-" + TestMemoryInvisibleParent.class.getSimpleName() + Runtime.version().feature(); + Path sysFsMemory = Path.of("/", "sys", "fs", "cgroup", "memory"); + Path cgroupParentPath = sysFsMemory.resolve(cgroupParent); + ProcessBuilder pb = new ProcessBuilder("mkdir", "-p", cgroupParentPath.toString()); + OutputAnalyzer out = new OutputAnalyzer(pb.start()) + .shouldHaveExitValue(0); + Path memoryLimitsFile = cgroupParentPath.resolve("memory.limit_in_bytes"); + Files.writeString(memoryLimitsFile, memLimit); + System.out.println("Cgroup parent is: /" + cgroupParentPath.getFileName() + + " at " + sysFsMemory.toString()); + return cgroupParent; + } + +} diff --git a/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java b/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java index f8c8b34135d..3340f9de03c 100644 --- a/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java +++ b/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * 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,6 +32,7 @@ * @test * @key cgroups * @requires os.family == "linux" + * @requires !vm.asan * @modules java.base/jdk.internal.platform * @library /test/lib * @build jdk.test.whitebox.WhiteBox PrintContainerInfo CheckOperatingSystemMXBean diff --git a/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java b/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java index a75f314b53d..3b901765ee9 100644 --- a/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java +++ b/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java @@ -36,6 +36,7 @@ * @test * @bug 8343191 * @requires os.family == "linux" + * @requires !vm.asan * @modules java.base/jdk.internal.platform * @library /test/lib * @build jdk.test.whitebox.WhiteBox @@ -45,19 +46,6 @@ public class TestMemoryWithSubgroups { private static final String imageName = Common.imageName("subgroup"); - static String getEngineInfo(String format) throws Exception { - return DockerTestUtils.execute(Container.ENGINE_COMMAND, "info", "-f", format) - .getStdout(); - } - - static boolean isRootless() throws Exception { - // Docker and Podman have different INFO structures. - // The node path for Podman is .Host.Security.Rootless, that also holds for - // Podman emulating Docker CLI. The node path for Docker is .SecurityOptions. - return (getEngineInfo("{{.Host.Security.Rootless}}").contains("true") || - getEngineInfo("{{.SecurityOptions}}").contains("name=rootless")); - } - public static void main(String[] args) throws Exception { Metrics metrics = Metrics.systemMetrics(); if (metrics == null) { @@ -71,7 +59,7 @@ public static void main(String[] args) throws Exception { ContainerRuntimeVersionTestUtils.checkContainerVersionSupported(); - if (isRootless()) { + if (DockerTestUtils.isRootless()) { throw new SkippedException("Test skipped in rootless mode"); } Common.prepareWhiteBox(); diff --git a/test/hotspot/jtreg/containers/docker/TestMisc.java b/test/hotspot/jtreg/containers/docker/TestMisc.java index a811666999b..a1998cef344 100644 --- a/test/hotspot/jtreg/containers/docker/TestMisc.java +++ b/test/hotspot/jtreg/containers/docker/TestMisc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ * @test * @summary Test miscellanous functionality related to JVM running in docker container * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc * java.management @@ -110,9 +111,11 @@ private static void checkContainerInfo(OutputAnalyzer out) throws Exception { "CPU Shares", "CPU Quota", "CPU Period", + "CPU Usage", "OSContainer::active_processor_count", "Memory Limit", "Memory Soft Limit", + "Memory Throttle Limit", "Memory Usage", "Maximum Memory Usage", "memory_max_usage_in_bytes", diff --git a/test/hotspot/jtreg/containers/docker/TestPids.java b/test/hotspot/jtreg/containers/docker/TestPids.java index 9b65a1b1ee8..62bd70dc61f 100644 --- a/test/hotspot/jtreg/containers/docker/TestPids.java +++ b/test/hotspot/jtreg/containers/docker/TestPids.java @@ -28,6 +28,7 @@ * @key cgroups * @summary Test JVM's awareness of pids controller * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc * java.management @@ -46,7 +47,7 @@ public class TestPids { private static final String imageName = Common.imageName("pids"); - private static final boolean IS_PODMAN = Container.ENGINE_COMMAND.contains("podman"); + private static final boolean IS_PODMAN = DockerTestUtils.isPodman(); private static final int UNLIMITED_PIDS_PODMAN = 0; private static final int UNLIMITED_PIDS_DOCKER = -1; diff --git a/test/hotspot/jtreg/gc/TestAlwaysPreTouchBehavior.java b/test/hotspot/jtreg/gc/TestAlwaysPreTouchBehavior.java index b8197f70384..79b6d420df5 100644 --- a/test/hotspot/jtreg/gc/TestAlwaysPreTouchBehavior.java +++ b/test/hotspot/jtreg/gc/TestAlwaysPreTouchBehavior.java @@ -133,13 +133,8 @@ public class TestAlwaysPreTouchBehavior { // public static void main(String [] args) { - long rss = WhiteBox.getWhiteBox().rss(); - System.out.println("RSS: " + rss); - long available = WhiteBox.getWhiteBox().hostAvailableMemory(); - System.out.println("Host available memory: " + available); - + int maxIter = 20; long heapSize = 256 * 1024 * 1024; - // On Linux, a JVM that runs with 256M pre-committed heap will use about 60MB (release JVM) RSS. Barring // memory pressure that causes us to lose RSS, pretouching should increase RSS to >256MB. So there should be a // clear distinction between non-pretouched and pretouched. @@ -150,12 +145,28 @@ public static void main(String [] args) { // on the side of disregarding true errors than to produce false positives (if pretouching is broken, at least // some of the runs of this test will run on beefy enough machines and show the test as failed). long requiredAvailable = 1024 * 1024 * 1024; - if (rss == 0) { - throw new SkippedException("cannot get RSS?"); - } - if (available > requiredAvailable) { - Asserts.assertGreaterThan(rss, minRequiredRss, "RSS of this process(" + rss + "b) should be bigger " + - "than or equal to heap size(" + heapSize + "b) (available memory: " + available + ")"); + + // RSS values we get are sometimes somewhat delayed or inaccurate + for (int iter=0; iter < maxIter; iter++) { + long rss = WhiteBox.getWhiteBox().rss(); + System.out.println("RSS: " + rss); + long available = WhiteBox.getWhiteBox().hostAvailableMemory(); + System.out.println("Host available memory: " + available); + + if (rss == 0) { + throw new SkippedException("cannot get RSS?"); + } + if (available <= requiredAvailable) { + throw new SkippedException("Available memory on host " + available + " is too small, not larger than required available memory " + requiredAvailable); + } + + if ((rss < minRequiredRss) && iter < maxIter-1) { + System.out.println("We got only an RSS value of " + rss + " but require " + minRequiredRss + ", let's retry!"); + } else { + Asserts.assertGreaterThan(rss, minRequiredRss, "RSS of this process(" + rss + "b) should be bigger " + + "than or equal to heap size(" + heapSize + "b) (available memory: " + available + "). On Linux Kernel < 4.14 RSS can be inaccurate"); + break; + } } } } diff --git a/test/hotspot/jtreg/gc/TestObjectAlignmentCardSize.java b/test/hotspot/jtreg/gc/TestObjectAlignmentCardSize.java index 5fb46a87b51..7abded3673e 100644 --- a/test/hotspot/jtreg/gc/TestObjectAlignmentCardSize.java +++ b/test/hotspot/jtreg/gc/TestObjectAlignmentCardSize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ /* @test TestObjectAlignmentCardSize.java * @summary Test to check correct handling of ObjectAlignmentInBytes and GCCardSizeInBytes combinations * @requires vm.gc != "Z" + * @requires vm.bits == "64" * @library /test/lib * @modules java.base/jdk.internal.misc * @run driver gc.TestObjectAlignmentCardSize diff --git a/test/hotspot/jtreg/gc/TestTransparentHugePagesHeap.java b/test/hotspot/jtreg/gc/TestTransparentHugePagesHeap.java new file mode 100644 index 00000000000..2c2e19b87c4 --- /dev/null +++ b/test/hotspot/jtreg/gc/TestTransparentHugePagesHeap.java @@ -0,0 +1,181 @@ +/* + * 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 id=G1 + * @summary Run tests with G1 + * @library /test/lib + * @build jdk.test.lib.Platform + * @requires os.family == "linux" + * @requires vm.gc.G1 + * @run driver TestTransparentHugePagesHeap G1 +*/ +/* + * @test id=Parallel + * @summary Run tests with Parallel + * @library /test/lib + * @build jdk.test.lib.Platform + * @requires os.family == "linux" + * @requires vm.gc.Parallel + * @run driver TestTransparentHugePagesHeap Parallel +*/ +/* + * @test id=Serial + * @summary Run tests with Serial + * @library /test/lib + * @build jdk.test.lib.Platform + * @requires os.family == "linux" + * @requires vm.gc.Serial + * @run driver TestTransparentHugePagesHeap Serial +*/ + +import java.math.BigInteger; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.Scanner; + +import jdk.test.lib.os.linux.HugePageConfiguration; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.Platform; + +import jtreg.SkippedException; + +// We verify that the heap can be backed by THP by looking at the +// THPeligible field for the heap section in /proc/self/smaps. This +// field indicates if a mapping can use THP. +// THP mode 'always': this field is 1 whenever huge pages can be used +// THP mode 'madvise': this field is 1 if the mapping has been madvised +// as MADV_HUGEPAGE. In the JVM that should happen when the flag +// -XX:+UseTransparentHugePages is specified. +// +// Note: we don't verify if the heap is backed by huge pages because we +// can't know if the underlying system have any available. +public class TestTransparentHugePagesHeap { + + public static void main(String args[]) throws Exception { + // To be able to detect large page use (esp. THP) somewhat reliably, we + // need at least kernel 3.8 to get the "VmFlags" tag in smaps. + // (Note: its still good we started the VM at least since this serves as a nice + // test for all manners of large page options). + if (Platform.getOsVersionMajor() < 3 || + (Platform.getOsVersionMajor() == 3 && Platform.getOsVersionMinor() < 8)) { + throw new SkippedException("Kernel older than 3.8 - skipping this test."); + } + + final HugePageConfiguration hugePageConfiguration = HugePageConfiguration.readFromOS(); + if (!hugePageConfiguration.supportsTHP()) { + throw new SkippedException("THP is turned off"); + } + + OutputAnalyzer oa = ProcessTools.executeTestJava("-XX:+Use" + args[0] + "GC", "-Xmx128m", "-Xms128m", "-Xlog:pagesize:thp-%p.log", "-XX:+UseTransparentHugePages", VerifyTHPEnabledForHeap.class.getName()); + oa.shouldHaveExitValue(0); + } + + class VerifyTHPEnabledForHeap { + + public static void main(String args[]) throws Exception { + // Extract the heap start from pagesize logging + BigInteger heapStart = extractHeapStartFromLog(); + + Path smaps = makeSmapsCopy(); + + final Pattern addressRangePattern = Pattern.compile("([0-9a-f]*?)-([0-9a-f]*?) .*"); + final Pattern thpEligiblePattern = Pattern.compile("THPeligible:\\s+(\\d)\\s*"); + + Scanner smapsFile = new Scanner(smaps); + while (smapsFile.hasNextLine()) { + Matcher addressRangeMatcher = addressRangePattern.matcher(smapsFile.nextLine()); + if (!addressRangeMatcher.matches()) { + continue; + } + + // Found an address range line in the smaps file + + BigInteger addressStart = new BigInteger(addressRangeMatcher.group(1), 16); + BigInteger addressEnd = new BigInteger(addressRangeMatcher.group(2), 16); + + // Linux sometimes merges adjacent VMAs so we can't search for a range that + // exactly matches the heap range. Instead we look for the first range that + // contains the start of the heap and verify that that range is THP eligible. + + if (addressStart.compareTo(heapStart) > 0 || heapStart.compareTo(addressEnd) >= 0) { + continue; + } + + // Found a range that contains the start of the heap, verify that it is THP eligible. + + while (smapsFile.hasNextLine()) { + Matcher m = thpEligiblePattern.matcher(smapsFile.nextLine()); + if (!m.matches()) { + continue; + } + + // Found the THPeligible line + + if (m.group(1).equals("1")) { + // Success - THPeligible is 1, heap can be backed by huge pages + return; + } + + throw new RuntimeException("The address range 0x" + addressStart.toString(16) + + "-0x" + addressEnd.toString(16) + + " that contains the heap start" + heapStart + + " is not THPeligible"); + } + + throw new RuntimeException("Couldn't find THPeligible in the smaps file"); + } + + throw new RuntimeException("Could not find an address range containing the heap start " + heapStart + " in the smaps file"); + } + + private static BigInteger extractHeapStartFromLog() throws Exception { + // [0.041s][info][pagesize] Heap: min=128M max=128M base=0x0000ffff5c600000 size=128M page_size=2M + final Pattern heapAddress = Pattern.compile(".* Heap: .*base=0x([0-9A-Fa-f]*).*"); + + Scanner logFile = new Scanner(Paths.get("thp-" + ProcessHandle.current().pid() + ".log")); + while (logFile.hasNextLine()) { + String line = logFile.nextLine(); + + Matcher m = heapAddress.matcher(line); + if (m.matches()) { + return new BigInteger(m.group(1), 16); + } + } + + throw new RuntimeException("Failed to find heap start"); + } + + private static Path makeSmapsCopy() throws Exception { + Path src = Paths.get("/proc/self/smaps"); + Path dest = Paths.get("smaps-copy-" + ProcessHandle.current().pid() + ".txt"); + Files.copy(src, dest, StandardCopyOption.REPLACE_EXISTING); + return dest; + } + } +} diff --git a/test/hotspot/jtreg/gc/TestUseGCOverheadLimit.java b/test/hotspot/jtreg/gc/TestUseGCOverheadLimit.java new file mode 100644 index 00000000000..8f1d541d385 --- /dev/null +++ b/test/hotspot/jtreg/gc/TestUseGCOverheadLimit.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package gc; + +/* + * @test id=Parallel + * @requires vm.gc.Parallel & false + * @requires !vm.debug + * @summary Verifies that the UseGCOverheadLimit functionality works in Parallel GC. + * @library /test/lib + * @run driver gc.TestUseGCOverheadLimit Parallel + */ + +/* + * @test id=G1 + * @requires vm.gc.G1 + * @requires !vm.debug + * @summary Verifies that the UseGCOverheadLimit functionality works in G1 GC. + * @library /test/lib + * @run driver gc.TestUseGCOverheadLimit G1 + */ + +import java.util.Arrays; +import java.util.stream.Stream; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class TestUseGCOverheadLimit { + public static void main(String args[]) throws Exception { + String[] parallelArgs = { + "-XX:+UseParallelGC", + "-XX:NewSize=122m", + "-XX:SurvivorRatio=99", + "-XX:GCHeapFreeLimit=10" + }; + String[] g1Args = { + "-XX:+UseG1GC", + "-XX:GCHeapFreeLimit=5" + }; + + String[] selectedArgs = args[0].equals("G1") ? g1Args : parallelArgs; + + final String[] commonArgs = { + "-XX:-UseCompactObjectHeaders", // Object sizes are calculated such that the heap is tight. + "-XX:ParallelGCThreads=1", // Make GCs take longer. + "-XX:+UseGCOverheadLimit", + "-Xlog:gc=debug", + "-XX:GCTimeLimit=80", // Ease the CPU requirement. + "-Xmx128m", + Allocating.class.getName() + }; + + String[] vmArgs = Stream.concat(Arrays.stream(selectedArgs), Arrays.stream(commonArgs)).toArray(String[]::new); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava(vmArgs); + output.shouldNotHaveExitValue(0); + + System.out.println(output.getStdout()); + + output.stdoutShouldContain("GC Overhead Limit exceeded too often (5)."); + } + + static class Allocating { + public static void main(String[] args) { + Object[] cache = new Object[1024 * 1024 * 2]; + + // Allocate random objects, keeping around data, causing garbage + // collections. + for (int i = 0; i < 1024* 1024 * 30; i++) { + Object[] obj = new Object[10]; + cache[i % cache.length] = obj; + } + + System.out.println(cache); + } + } +} diff --git a/test/hotspot/jtreg/gc/arguments/TestG1CompressedOops.java b/test/hotspot/jtreg/gc/arguments/TestG1CompressedOops.java index 5a705ffe8ed..3aec113990c 100644 --- a/test/hotspot/jtreg/gc/arguments/TestG1CompressedOops.java +++ b/test/hotspot/jtreg/gc/arguments/TestG1CompressedOops.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * Copyright (C) 2025 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2025, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/gc/arguments/TestParallelGCErgo.java b/test/hotspot/jtreg/gc/arguments/TestParallelGCErgo.java index 63c51c25149..b9e5629d875 100644 --- a/test/hotspot/jtreg/gc/arguments/TestParallelGCErgo.java +++ b/test/hotspot/jtreg/gc/arguments/TestParallelGCErgo.java @@ -27,7 +27,7 @@ * @test TestParallelGCErgo * @bug 8272364 * @requires vm.gc.Parallel - * @requires vm.opt.UseLargePages == null | !vm.opt.UseLargePages + * @requires !vm.opt.final.UseLargePages * @summary Verify ParallelGC minimum young and old ergonomics are setup correctly * @modules java.base/jdk.internal.misc * @library /test/lib diff --git a/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsFlagsWithUlimit.java b/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsFlagsWithUlimit.java index 40d83739ef5..40f607bf8a1 100644 --- a/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsFlagsWithUlimit.java +++ b/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsFlagsWithUlimit.java @@ -31,6 +31,8 @@ * @library /test/lib * @library / * @requires vm.bits == "64" + * @comment ulimit clashes with the memory requirements of ASAN + * @requires !vm.asan * @requires os.family == "linux" * @requires vm.gc != "Z" * @requires vm.opt.UseCompressedOops == null diff --git a/test/hotspot/jtreg/gc/g1/TestCodeCacheUnloadDuringConcCycle.java b/test/hotspot/jtreg/gc/g1/TestCodeCacheUnloadDuringConcCycle.java new file mode 100644 index 00000000000..e36ccace9dc --- /dev/null +++ b/test/hotspot/jtreg/gc/g1/TestCodeCacheUnloadDuringConcCycle.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package gc.g1; + +/* + * @test TestCodeCacheUnloadDuringConcCycle + * @bug 8350621 + * @summary Test to make sure that code cache unloading does not hang when receiving + * a request to unload code cache during concurrent mark. + * We do that by triggering a code cache gc request (by triggering compilations) + * during concurrent mark, and verify that after the concurrent cycle additional code + * cache gc requests start more concurrent cycles. + * @requires vm.gc.G1 + * @library /test/lib /testlibrary / + * @modules java.base/jdk.internal.misc + * java.management + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xmx20M -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. gc.g1.TestCodeCacheUnloadDuringConcCycle + */ + +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryPoolMXBean; +import java.lang.management.MemoryUsage; +import java.lang.reflect.Field; + +import java.net.URL; +import java.net.URLClassLoader; + +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import jdk.test.lib.Asserts; +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jdk.test.whitebox.WhiteBox; + +public class TestCodeCacheUnloadDuringConcCycle { + public static final String AFTER_FIRST_CYCLE_MARKER = "Marker for this test"; + + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + + private static OutputAnalyzer runTest(String concPhase) throws Exception { + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UseG1GC", + "-Xmx20M", + "-XX:+UnlockDiagnosticVMOptions", + "-Xbootclasspath/a:.", + "-Xlog:gc=trace,codecache", + "-XX:+WhiteBoxAPI", + "-XX:ReservedCodeCacheSize=" + (Platform.is32bit() ? "4M" : "8M"), + "-XX:StartAggressiveSweepingAt=50", + "-XX:CompileCommand=compileonly,gc.g1.SomeClass::*", + "-XX:CompileCommand=compileonly,gc.g1.Foo*::*", + TestCodeCacheUnloadDuringConcCycleRunner.class.getName(), + concPhase); + return output; + } + + private static void runAndCheckTest(String test) throws Exception { + OutputAnalyzer output; + + output = runTest(test); + output.shouldHaveExitValue(0); + System.out.println(output.getStdout()); + + String[] parts = output.getStdout().split(AFTER_FIRST_CYCLE_MARKER); + + // Either "Threshold" or "Aggressive" CodeCache GC are fine for the test. + final String codecacheGCStart = "Pause Young (Concurrent Start) (CodeCache GC "; + + boolean success = parts.length == 2 && parts[1].indexOf(codecacheGCStart) != -1; + Asserts.assertTrue(success, "Could not find a CodeCache GC Threshold GC after finishing the concurrent cycle"); + } + + private static void allTests() throws Exception { + runAndCheckTest(WB.BEFORE_MARKING_COMPLETED); + runAndCheckTest(WB.G1_BEFORE_REBUILD_COMPLETED); + runAndCheckTest(WB.G1_BEFORE_CLEANUP_COMPLETED); + } + + public static void main(String[] args) throws Exception { + allTests(); + } +} + +class TestCodeCacheUnloadDuringConcCycleRunner { + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + + private static void refClass(Class clazz) throws Exception { + Field name = clazz.getDeclaredField("NAME"); + name.setAccessible(true); + name.get(null); + } + + private static class MyClassLoader extends URLClassLoader { + public MyClassLoader(URL url) { + super(new URL[]{url}, null); + } + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + try { + return super.loadClass(name, resolve); + } catch (ClassNotFoundException e) { + return Class.forName(name, resolve, TestCodeCacheUnloadDuringConcCycleRunner.class.getClassLoader()); + } + } + } + + private static void triggerCodeCacheGC() throws Exception { + URL url = TestCodeCacheUnloadDuringConcCycleRunner.class.getProtectionDomain().getCodeSource().getLocation(); + + try { + int i = 0; + do { + ClassLoader cl = new MyClassLoader(url); + refClass(cl.loadClass("gc.g1.SomeClass")); + + if (i % 20 == 0) { + System.out.println("Compiled " + i + " classes"); + } + i++; + } while (i < 200); + System.out.println("Compilation done, compiled " + i + " classes"); + } catch (Throwable t) { + } + } + + public static void main(String[] args) throws Exception { + System.out.println("Running to breakpoint: " + args[0]); + try { + WB.concurrentGCAcquireControl(); + WB.concurrentGCRunTo(args[0]); + + System.out.println("Try to trigger code cache GC"); + + triggerCodeCacheGC(); + + WB.concurrentGCRunToIdle(); + } finally { + // Make sure that the marker we use to find the expected log message is printed + // before we release whitebox control, i.e. before the expected garbage collection + // can start. + System.out.println(TestCodeCacheUnloadDuringConcCycle.AFTER_FIRST_CYCLE_MARKER); + WB.concurrentGCReleaseControl(); + } + Thread.sleep(1000); + triggerCodeCacheGC(); + } +} + +abstract class Foo { + public abstract int foo(); +} + +class Foo1 extends Foo { + private int a; + public int foo() { return a; } +} + +class Foo2 extends Foo { + private int a; + public int foo() { return a; } +} + +class Foo3 extends Foo { + private int a; + public int foo() { return a; } +} + +class Foo4 extends Foo { + private int a; + public int foo() { return a; } +} + +class SomeClass { + static final String NAME = "name"; + + static { + int res =0; + Foo[] foos = new Foo[] { new Foo1(), new Foo2(), new Foo3(), new Foo4() }; + for (int i = 0; i < 100000; i++) { + res = foos[i % foos.length].foo(); + } + } +} diff --git a/test/hotspot/jtreg/gc/g1/plab/TestPLABEvacuationFailure.java b/test/hotspot/jtreg/gc/g1/plab/TestPLABEvacuationFailure.java index f5b61e470b0..67a3f510c21 100644 --- a/test/hotspot/jtreg/gc/g1/plab/TestPLABEvacuationFailure.java +++ b/test/hotspot/jtreg/gc/g1/plab/TestPLABEvacuationFailure.java @@ -99,7 +99,6 @@ private static void runTest(int wastePct, int plabSize, int parGCThreads, int he // Set up test GC and PLAB options List testOptions = new ArrayList<>(); Collections.addAll(testOptions, COMMON_OPTIONS); - Collections.addAll(testOptions, Utils.getTestJavaOpts()); Collections.addAll(testOptions, "-XX:ParallelGCThreads=" + parGCThreads, "-XX:ParallelGCBufferWastePct=" + wastePct, diff --git a/test/hotspot/jtreg/gc/g1/plab/lib/PLABUtils.java b/test/hotspot/jtreg/gc/g1/plab/lib/PLABUtils.java index 21a70c5fe05..c9d76d9da42 100644 --- a/test/hotspot/jtreg/gc/g1/plab/lib/PLABUtils.java +++ b/test/hotspot/jtreg/gc/g1/plab/lib/PLABUtils.java @@ -72,14 +72,12 @@ public static List prepareOptions(List options) { if (options == null) { throw new IllegalArgumentException("Options cannot be null"); } - List executionOtions = new ArrayList<>( - Arrays.asList(Utils.getTestJavaOpts()) - ); - Collections.addAll(executionOtions, WB_DIAGNOSTIC_OPTIONS); - Collections.addAll(executionOtions, G1_PLAB_LOGGING_OPTIONS); - Collections.addAll(executionOtions, GC_TUNE_OPTIONS); - executionOtions.addAll(options); - return executionOtions; + List executionOptions = new ArrayList<>(); + Collections.addAll(executionOptions, WB_DIAGNOSTIC_OPTIONS); + Collections.addAll(executionOptions, G1_PLAB_LOGGING_OPTIONS); + Collections.addAll(executionOptions, GC_TUNE_OPTIONS); + executionOptions.addAll(options); + return executionOptions; } /** diff --git a/test/hotspot/jtreg/gc/shenandoah/TestDynamicSoftMaxHeapSize.java b/test/hotspot/jtreg/gc/shenandoah/TestDynamicSoftMaxHeapSize.java index a3dded8d09a..7ca9c7f46d6 100644 --- a/test/hotspot/jtreg/gc/shenandoah/TestDynamicSoftMaxHeapSize.java +++ b/test/hotspot/jtreg/gc/shenandoah/TestDynamicSoftMaxHeapSize.java @@ -23,105 +23,175 @@ * */ -/* - * @test id=passive +/** + * @test id=satb-adaptive * @requires vm.gc.Shenandoah * @library /test/lib * - * @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions - * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive + * @run main/othervm -Xms100m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -Xlog:gc=info -Dtarget=10000 + * -XX:ShenandoahGCMode=satb * -XX:+ShenandoahDegeneratedGC - * -Dtarget=10000 + * -XX:ShenandoahGCHeuristics=adaptive * TestDynamicSoftMaxHeapSize * - * @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions - * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive - * -XX:-ShenandoahDegeneratedGC - * -Dtarget=10000 - * TestDynamicSoftMaxHeapSize */ -/* - * @test id=aggressive +/** + * @test id=satb-aggressive * @requires vm.gc.Shenandoah * @library /test/lib * - * @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions - * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive - * -Dtarget=1000 + * @run main/othervm -Xms100m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -Xlog:gc=info -Dtarget=10000 + * -XX:ShenandoahGCMode=satb + * -XX:+ShenandoahDegeneratedGC + * -XX:ShenandoahGCHeuristics=aggressive * TestDynamicSoftMaxHeapSize + * */ -/* - * @test id=adaptive +/** + * @test id=satb-compact * @requires vm.gc.Shenandoah * @library /test/lib * - * @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions - * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive - * -Dtarget=10000 + * @run main/othervm -Xms100m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -Xlog:gc=info -Dtarget=10000 + * -XX:ShenandoahGCMode=satb + * -XX:+ShenandoahDegeneratedGC + * -XX:ShenandoahGCHeuristics=compact * TestDynamicSoftMaxHeapSize + * */ -/* - * @test id=generational +/** + * @test id=satb-static * @requires vm.gc.Shenandoah * @library /test/lib * - * @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions - * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive -XX:ShenandoahGCMode=generational - * -Dtarget=10000 + * @run main/othervm -Xms100m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -Xlog:gc=info -Dtarget=10000 + * -XX:ShenandoahGCMode=satb + * -XX:+ShenandoahDegeneratedGC + * -XX:ShenandoahGCHeuristics=static * TestDynamicSoftMaxHeapSize + * */ -/* - * @test id=static +/** + * @test id=passive * @requires vm.gc.Shenandoah * @library /test/lib * * @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions - * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=static + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive + * -XX:+ShenandoahDegeneratedGC + * -Dtarget=10000 + * TestDynamicSoftMaxHeapSize + * + * @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive + * -XX:-ShenandoahDegeneratedGC * -Dtarget=10000 * TestDynamicSoftMaxHeapSize */ -/* - * @test id=compact +/** + * @test id=generational * @requires vm.gc.Shenandoah * @library /test/lib * - * @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions - * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact - * -Dtarget=1000 - * TestDynamicSoftMaxHeapSize + * @run main/othervm -Xms100m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -Xlog:gc=info -Dtarget=10000 + * -XX:ShenandoahGCMode=generational + * -XX:ShenandoahGCHeuristics=adaptive + * TestDynamicSoftMaxHeapSize + * */ -import java.util.Random; +/** + * @test id=generational-softMaxHeapSizeValidation + * @requires vm.gc.Shenandoah + * @library /test/lib + * + * @run main/othervm -DvalidateSoftMaxHeap=true + * TestDynamicSoftMaxHeapSize + * -Xms100m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -Xlog:gc=info -Dtarget=10000 -DverifySoftMaxHeapValue=true + * -XX:ShenandoahGCMode=generational + * -XX:ShenandoahGCHeuristics=adaptive + */ import jdk.test.lib.Utils; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.dcmd.PidJcmdExecutor; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; + public class TestDynamicSoftMaxHeapSize { + static final int K = 1024; + static final int XMS_MB = 100; + static final int XMX_MB = 512; + + public static void main(String[] args) throws Exception { + if ("true".equals(System.getProperty("validateSoftMaxHeap"))) { + List flagArgs = new ArrayList<>(Arrays.asList(args)); - static final long TARGET_MB = Long.getLong("target", 10_000); // 10 Gb allocation - static final long STRIDE = 10_000_000; + int softMaxInMb = Utils.getRandomInstance().nextInt(XMS_MB, XMX_MB); + flagArgs.add("-DsoftMaxCapacity=" + softMaxInMb * K * K); + flagArgs.add("-Dtest.jdk=" + System.getProperty("test.jdk")); + flagArgs.add("-Dcompile.jdk=" + System.getProperty("compile.jdk")); - static volatile Object sink; + flagArgs.add(SoftMaxWithExpectationTest.class.getName()); - public static void main(String[] args) throws Exception { - long count = TARGET_MB * 1024 * 1024 / 16; - Random r = Utils.getRandomInstance(); - PidJcmdExecutor jcmd = new PidJcmdExecutor(); - - for (long c = 0; c < count; c += STRIDE) { - // Sizes specifically include heaps below Xms and above Xmx to test saturation code. - jcmd.execute("VM.set_flag SoftMaxHeapSize " + r.nextInt(768*1024*1024), true); - for (long s = 0; s < STRIDE; s++) { - sink = new Object(); + ProcessBuilder genShenPbValidateFlag = ProcessTools.createLimitedTestJavaProcessBuilder(flagArgs); + OutputAnalyzer output = new OutputAnalyzer(genShenPbValidateFlag.start()); + output.shouldHaveExitValue(0); + output.shouldContain(String.format("Soft Max Heap Size: %dM -> %dM", XMX_MB, softMaxInMb)); // By default, the soft max heap size is Xmx + } else { + SoftMaxSetFlagOnlyTest.test(); + } + } + + public static class SoftMaxSetFlagOnlyTest { + static final long TARGET_MB = Long.getLong("target", 10_000); // 10 Gb allocation + static final long STRIDE = 10_000_000; + + static volatile Object sink; + + public static void test() throws Exception { + long count = TARGET_MB * 1024 * 1024 / 16; + Random r = Utils.getRandomInstance(); + PidJcmdExecutor jcmd = new PidJcmdExecutor(); + + for (long c = 0; c < count; c += STRIDE) { + // Sizes specifically include heaps below Xms and above Xmx to test saturation code. + jcmd.execute("VM.set_flag SoftMaxHeapSize " + r.nextInt(768*1024*1024), true); + for (long s = 0; s < STRIDE; s++) { + sink = new Object(); + } + Thread.sleep(1); } - Thread.sleep(1); } } + public static class SoftMaxWithExpectationTest { + static final long TOTAL = 100_000_000; + + static volatile Object sink; + + public static void main(String[] args) throws Exception { + int expectedSoftMaxHeapSize = Integer.getInteger("softMaxCapacity", 0); + PidJcmdExecutor jcmd = new PidJcmdExecutor(); + jcmd.execute("VM.set_flag SoftMaxHeapSize " + expectedSoftMaxHeapSize, false); + + for (long s = 0; s < TOTAL; s++) { + sink = new Object(); + } + } + } } diff --git a/test/hotspot/jtreg/gc/shenandoah/compiler/TestClone.java b/test/hotspot/jtreg/gc/shenandoah/compiler/TestClone.java index 2e98c72ee17..0775e5baadd 100644 --- a/test/hotspot/jtreg/gc/shenandoah/compiler/TestClone.java +++ b/test/hotspot/jtreg/gc/shenandoah/compiler/TestClone.java @@ -357,6 +357,7 @@ * -XX:TieredStopAtLevel=4 * TestClone */ + public class TestClone { public static void main(String[] args) throws Exception { diff --git a/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java b/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java index f799c0bac21..96440ba15ae 100644 --- a/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java +++ b/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Red Hat, Inc. All rights reserved. + * Copyright (c) 2021, 2025, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @summary guarantee(loc != NULL) failed: missing saved register with native invoke * * @requires vm.flavor == "server" - * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" | os.arch == "ppc64le" + * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" | os.arch == "ppc64" | os.arch == "ppc64le" * @requires vm.gc.Shenandoah * * @run main/othervm --enable-native-access=ALL-UNNAMED -XX:+UnlockDiagnosticVMOptions diff --git a/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java b/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java index 840ceffc4fe..a72baddc5dc 100644 --- a/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java +++ b/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java @@ -25,6 +25,7 @@ /* * @test id=generational * @summary Test that growth of old-gen triggers old-gen marking + * @key intermittent * @requires vm.gc.Shenandoah * @library /test/lib * @run driver TestOldGrowthTriggers diff --git a/test/hotspot/jtreg/gc/z/TestCommitFailure.java b/test/hotspot/jtreg/gc/z/TestCommitFailure.java new file mode 100644 index 00000000000..c7c8dc12add --- /dev/null +++ b/test/hotspot/jtreg/gc/z/TestCommitFailure.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package gc.z; + +/* + * @test id=Normal + * @requires vm.gc.Z & vm.debug + * @summary Test ZGC graceful failure when a commit fails + * @library / /test/lib + * @run driver gc.z.TestCommitFailure + */ + +/* + * @test id=ZFakeNUMA + * @requires vm.gc.Z & vm.debug + * @library / /test/lib + * @summary Test ZGC graceful failure when a commit fails (with ZFakeNUMA) + * @run driver gc.z.TestCommitFailure -XX:ZFakeNUMA=16 + */ + +import jdk.test.lib.process.ProcessTools; + +import static gc.testlibrary.Allocation.blackHole; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class TestCommitFailure { + static final int K = 1024; + static final int M = 1024 * K; + + static final int XMS = 128 * M; + static final int XMX = 512 * M; + + static class Test { + static final int LARGE_ALLOC = 256 * M; + static final int SMALL_GARBAGE = 256 * M; + static final int SMALL_LIVE = 128 * M; + + // Allocates at least totalLive bytes of objects and add them to list. + static void allocLive(List list, int totalLive) { + final int largePageAllocationSize = 6 * M; + for (int live = 0; live < totalLive; live += largePageAllocationSize) { + list.add(new byte[largePageAllocationSize - K]); + } + } + + // Allocates at least totalGarbage bytes of garbage large pages. + static void allocGarbage(int totalGarbage) { + final int largePageAllocationSize = 6 * M; + for (int garbage = 0; garbage < totalGarbage; garbage += largePageAllocationSize) { + blackHole(new byte[largePageAllocationSize - K]); + } + } + + public static void main(String[] args) { + final var list = new ArrayList(); + try { + // Fill heap with small live objects + allocLive(list, SMALL_LIVE); + // Fill with small garbage objects + allocGarbage(SMALL_GARBAGE); + // Allocate large objects where commit fails until an OOME is thrown + while (true) { + list.add(new byte[LARGE_ALLOC - K]); + } + } catch (OutOfMemoryError oome) {} + blackHole(list); + } + } + + public static void main(String[] args) throws Exception { + final int xmxInM = XMX / M; + final int xmsInM = XMS / M; + final var arguments = new ArrayList(Arrays.asList(args)); + arguments.addAll(List.of( + "-XX:+UseZGC", + "-Xlog:gc+init", + "-XX:ZFailLargerCommits=" + XMS, + "-Xms" + xmsInM + "M", + "-Xmx" + xmxInM + "M", + Test.class.getName())); + + ProcessTools.executeTestJava(arguments) + .outputTo(System.out) + .errorTo(System.out) + .shouldHaveExitValue(0); + } +} diff --git a/test/hotspot/jtreg/gc/z/TestUncommit.java b/test/hotspot/jtreg/gc/z/TestUncommit.java index 0ba4c55f22a..afb736501dd 100644 --- a/test/hotspot/jtreg/gc/z/TestUncommit.java +++ b/test/hotspot/jtreg/gc/z/TestUncommit.java @@ -108,7 +108,16 @@ private static void test(int objectSize) throws Exception { throw new Exception("Uncommitted too fast"); } + // In typical conditions (system not over-provisioned or slow), + // uncommitting is expected to complete within 3 * ZUncommitDelay after + // the last commit. To accommodate less ideal environments, only + // durations exceeding 5 * ZUncommitDelay are flagged as errors. + if (actualDelay > delay * 3) { + log(" *** Uncommit slower than expected. ***"); + } + + if (actualDelay > delay * 5) { throw new Exception("Uncommitted too slow"); } diff --git a/test/hotspot/jtreg/gtest/GTestWrapper.java b/test/hotspot/jtreg/gtest/GTestWrapper.java index 50998c2748a..1bd9734e48c 100644 --- a/test/hotspot/jtreg/gtest/GTestWrapper.java +++ b/test/hotspot/jtreg/gtest/GTestWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, 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 @@ -82,6 +82,7 @@ public static void main(String[] args) throws Throwable { command.add(execPath.toAbsolutePath().toString()); command.add("-jdk"); command.add(Utils.TEST_JDK); + command.add("-Xmx200m"); command.add("--gtest_output=xml:" + resultFile); command.add("--gtest_catch_exceptions=0"); for (String a : args) { diff --git a/test/hotspot/jtreg/runtime/ClassInitErrors/TestStackOverflowDuringInit.java b/test/hotspot/jtreg/runtime/ClassInitErrors/TestStackOverflowDuringInit.java index 180dc539795..3fee5ab131f 100644 --- a/test/hotspot/jtreg/runtime/ClassInitErrors/TestStackOverflowDuringInit.java +++ b/test/hotspot/jtreg/runtime/ClassInitErrors/TestStackOverflowDuringInit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,16 +29,25 @@ * cause, even if we can't create the ExceptionInInitializerError * @comment This test could easily be perturbed so don't allow flag settings. * @requires vm.flagless + * @library /test/lib * @comment Run with the smallest stack possible to limit the execution time. * This is the smallest stack that is supported by all platforms. - * @run main/othervm -Xss384K -Xint TestStackOverflowDuringInit + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestStackOverflowDuringInit */ import java.io.ByteArrayOutputStream; import java.io.PrintStream; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jdk.test.whitebox.WhiteBox; public class TestStackOverflowDuringInit { + static String expected = "java.lang.NoClassDefFoundError: Could not initialize class TestStackOverflowDuringInit$LongCache"; + static String cause = "Caused by: java.lang.StackOverflowError"; + // The setup for this is somewhat intricate. We need to trigger a // StackOverflowError during execution of the static initializer // for a class, but we need there to be insufficient stack left @@ -88,34 +97,47 @@ static void recurse() { } } - public static void main(String[] args) throws Exception { - String expected = "java.lang.NoClassDefFoundError: Could not initialize class TestStackOverflowDuringInit$LongCache"; - String cause = "Caused by: java.lang.StackOverflowError"; + static class Launcher { + public static void main(String[] args) throws Exception { - // Pre-load, but not initialize, LongCache, else we will - // hit SOE during class loading. - System.out.println("Pre-loading ..."); - Class c = Class.forName("TestStackOverflowDuringInit$LongCache", - false, - TestStackOverflowDuringInit.class.getClassLoader()); - try { - recurse(); - } catch (Throwable ex) { - // ex.printStackTrace(); - verify_stack(ex, expected, cause); + // Pre-load, but not initialize, LongCache, else we will + // hit SOE during class loading. + System.out.println("Pre-loading ..."); + Class c = Class.forName("TestStackOverflowDuringInit$LongCache", + false, + TestStackOverflowDuringInit.class.getClassLoader()); + try { + recurse(); + } catch (Throwable ex) { + // ex.printStackTrace(); + verify_stack(ex, expected, cause); + } } - } - private static void verify_stack(Throwable e, String expected, String cause) throws Exception { - ByteArrayOutputStream byteOS = new ByteArrayOutputStream(); - try (PrintStream printStream = new PrintStream(byteOS)) { - e.printStackTrace(printStream); - } - String stackTrace = byteOS.toString("ASCII"); - System.out.println(stackTrace); - if (!stackTrace.contains(expected) || - (cause != null && !stackTrace.contains(cause))) { - throw new RuntimeException(expected + " and/or " + cause + " missing from stacktrace"); + private static void verify_stack(Throwable e, String expected, String cause) throws Exception { + ByteArrayOutputStream byteOS = new ByteArrayOutputStream(); + try (PrintStream printStream = new PrintStream(byteOS)) { + e.printStackTrace(printStream); + } + String stackTrace = byteOS.toString("ASCII"); + System.out.println(stackTrace); + if (!stackTrace.contains(expected) || + (cause != null && !stackTrace.contains(cause))) { + throw new RuntimeException(expected + " and/or " + cause + " missing from stacktrace"); + } } } + + public static void main(String[] args) throws Exception { + WhiteBox wb = WhiteBox.getWhiteBox(); + long minimumJavaStackSize = wb.getMinimumJavaStackSize(); + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-Xss" + Long.toString(minimumJavaStackSize), "-Xint", + Launcher.class.getName()); + + OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + analyzer.shouldHaveExitValue(0); + analyzer.shouldContain(expected); + analyzer.shouldContain(cause); + } } diff --git a/test/hotspot/jtreg/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOption.java b/test/hotspot/jtreg/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOption.java index 78a508343d6..d87ca25fc3c 100644 --- a/test/hotspot/jtreg/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOption.java +++ b/test/hotspot/jtreg/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOption.java @@ -116,7 +116,7 @@ static JVMOption createVMOption(String type, String name) { default: throw new Error("Expected only \"int\", \"intx\", \"size_t\", " + "\"uint\", \"uintx\", \"uint64_t\", or \"double\" " - + "option types! Got " + type + " type!"); + + "option types! Got " + type + " type for option " + name + "!"); } return parameter; diff --git a/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java b/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java index 622573fa709..35e4b9ef233 100644 --- a/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java +++ b/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java @@ -28,6 +28,7 @@ * @requires vm.bits == 64 & !vm.graal.enabled & vm.debug == true * @requires vm.flagless * @requires vm.cds + * @requires vm.cds.default.archive.available * @requires (os.family != "windows") & (os.family != "aix") * @library /test/lib * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/runtime/CompressedOops/UseCompressedOops.java b/test/hotspot/jtreg/runtime/CompressedOops/UseCompressedOops.java index 3d118bf73b1..e5e2a23c565 100644 --- a/test/hotspot/jtreg/runtime/CompressedOops/UseCompressedOops.java +++ b/test/hotspot/jtreg/runtime/CompressedOops/UseCompressedOops.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, 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 @@ -30,6 +30,8 @@ * @modules java.base/jdk.internal.misc * java.management * @build jdk.test.whitebox.WhiteBox + * @comment Asan changes memory layout and we get a different coops mode + * @requires !vm.asan * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm/timeout=480 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. UseCompressedOops */ diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/CreateCoredumpOnCrash.java b/test/hotspot/jtreg/runtime/ErrorHandling/CreateCoredumpOnCrash.java index 76ea10d77cb..2fb42e230a5 100644 --- a/test/hotspot/jtreg/runtime/ErrorHandling/CreateCoredumpOnCrash.java +++ b/test/hotspot/jtreg/runtime/ErrorHandling/CreateCoredumpOnCrash.java @@ -30,6 +30,7 @@ * jdk.internal.jvmstat/sun.jvmstat.monitor * @run driver CreateCoredumpOnCrash * @requires vm.flagless + * @requires !vm.asan */ import jdk.test.lib.process.ProcessTools; diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/PrintVMInfoAtExitTest.java b/test/hotspot/jtreg/runtime/ErrorHandling/PrintVMInfoAtExitTest.java index 2b9393e3d35..5e535bab626 100644 --- a/test/hotspot/jtreg/runtime/ErrorHandling/PrintVMInfoAtExitTest.java +++ b/test/hotspot/jtreg/runtime/ErrorHandling/PrintVMInfoAtExitTest.java @@ -27,14 +27,18 @@ * @test * @summary Test PrintVMInfoAtExit * @library /test/lib + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @modules java.base/jdk.internal.misc * @requires vm.flagless * @requires vm.bits == "64" - * @run driver PrintVMInfoAtExitTest + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI PrintVMInfoAtExitTest */ import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; +import jdk.test.whitebox.WhiteBox; + public class PrintVMInfoAtExitTest { @@ -53,7 +57,14 @@ public static void main(String[] args) throws Exception { output_detail.shouldContain("-- S U M M A R Y --"); output_detail.shouldContain("Command Line: -Xmx64M -Xms64M -XX:-CreateCoredumpOnCrash -XX:+UnlockDiagnosticVMOptions -XX:+PrintVMInfoAtExit -XX:NativeMemoryTracking=summary -XX:CompressedClassSpaceSize=256m"); output_detail.shouldContain("Native Memory Tracking:"); - output_detail.shouldContain("Java Heap (reserved=65536KB, committed=65536KB)"); + WhiteBox wb = WhiteBox.getWhiteBox(); + if (wb.isAsanEnabled()) { + // the reserved value can be influenced by asan + output_detail.shouldContain("Java Heap (reserved="); + output_detail.shouldContain(", committed=65536KB)"); + } else { + output_detail.shouldContain("Java Heap (reserved=65536KB, committed=65536KB)"); + } } } diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/TestCrashOnOutOfMemoryError.java b/test/hotspot/jtreg/runtime/ErrorHandling/TestCrashOnOutOfMemoryError.java index 0be39d22ebe..26d1f726feb 100644 --- a/test/hotspot/jtreg/runtime/ErrorHandling/TestCrashOnOutOfMemoryError.java +++ b/test/hotspot/jtreg/runtime/ErrorHandling/TestCrashOnOutOfMemoryError.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,8 +72,8 @@ public static void main(String[] args) throws Exception { # # JRE version: OpenJDK Runtime Environment (9.0) (build 1.9.0-internal-debug-cheleswer_2015_10_20_14_32-b00) # Java VM: OpenJDK 64-Bit Server VM (1.9.0-internal-debug-cheleswer_2015_10_20_14_32-b00, mixed mode, tiered, compressed oops, serial gc, linux-amd64) - # Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport %p %s %c %P" (or dumping to - /home/cheleswer/Desktop/core.6212) + # Core dump will be written. Default location: Determined by the following: + "/usr/share/apport/apport %p %s %c %P" (alternatively, falling back to /home/cheleswer/Desktop/core.6212) # # An error report file with more information is saved as: # /home/cheleswer/Desktop/hs_err_pid6212.log diff --git a/test/hotspot/jtreg/runtime/NMT/CheckForProperDetailStackTrace.java b/test/hotspot/jtreg/runtime/NMT/CheckForProperDetailStackTrace.java index 398d6b523ad..28af0692721 100644 --- a/test/hotspot/jtreg/runtime/NMT/CheckForProperDetailStackTrace.java +++ b/test/hotspot/jtreg/runtime/NMT/CheckForProperDetailStackTrace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,11 +26,14 @@ * @bug 8133747 8218458 * @summary Running with NMT detail should produce expected stack traces. * @library /test/lib + * @library / * @modules java.base/jdk.internal.misc * java.management * @requires vm.debug + * @build jdk.test.whitebox.WhiteBox * @compile ../modules/CompilerUtils.java - * @run driver CheckForProperDetailStackTrace + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI CheckForProperDetailStackTrace */ import jdk.test.lib.Platform; @@ -40,6 +43,7 @@ import java.nio.file.Paths; import java.util.regex.Matcher; import java.util.regex.Pattern; +import jdk.test.whitebox.WhiteBox; /** * We are checking for details that should be seen with NMT detail enabled. @@ -59,7 +63,10 @@ public class CheckForProperDetailStackTrace { private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); private static final Path MODS_DIR = Paths.get(TEST_CLASSES, "mods"); - private static final boolean expectSourceInformation = Platform.isLinux() || Platform.isWindows(); + // Windows has source information only in full pdbs, not in stripped pdbs + private static boolean expectSourceInformation = Platform.isLinux() || Platform.isWindows(); + + static WhiteBox wb = WhiteBox.getWhiteBox(); /* The stack trace we look for by default. Note that :: has been replaced by .* to make sure it matches even if the symbol is not unmangled. @@ -138,6 +145,10 @@ public static void main(String args[]) throws Exception { throw new RuntimeException("Expected stack trace missing from output"); } + if (wb.hasExternalSymbolsStripped()) { + expectSourceInformation = false; + } + System.out.println("Looking for source information:"); if (expectSourceInformation) { if (!stackTraceMatches(".*moduleEntry.cpp.*", output)) { diff --git a/test/hotspot/jtreg/runtime/NMT/CommandLineDetail.java b/test/hotspot/jtreg/runtime/NMT/CommandLineDetail.java index 57f2302db30..a7561c7792e 100644 --- a/test/hotspot/jtreg/runtime/NMT/CommandLineDetail.java +++ b/test/hotspot/jtreg/runtime/NMT/CommandLineDetail.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,13 +35,14 @@ public class CommandLineDetail { - public static void main(String args[]) throws Exception { - - ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( - "-XX:NativeMemoryTracking=detail", - "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldNotContain("error"); - output.shouldHaveExitValue(0); - } + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( + "-Xlog:nmt=warning", + "-XX:NativeMemoryTracking=detail", + "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("NMT initialization failed"); + output.shouldNotContain("Could not create the Java Virtual Machine."); + output.shouldHaveExitValue(0); + } } diff --git a/test/hotspot/jtreg/runtime/NMT/CommandLineSummary.java b/test/hotspot/jtreg/runtime/NMT/CommandLineSummary.java index 02b37a40ef4..381fe3eba34 100644 --- a/test/hotspot/jtreg/runtime/NMT/CommandLineSummary.java +++ b/test/hotspot/jtreg/runtime/NMT/CommandLineSummary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,13 +35,14 @@ public class CommandLineSummary { - public static void main(String args[]) throws Exception { - - ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( - "-XX:NativeMemoryTracking=summary", - "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldNotContain("error"); - output.shouldHaveExitValue(0); - } + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( + "-Xlog:nmt=warning", + "-XX:NativeMemoryTracking=summary", + "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("NMT initialization failed"); + output.shouldNotContain("Could not create the Java Virtual Machine."); + output.shouldHaveExitValue(0); + } } diff --git a/test/hotspot/jtreg/runtime/Thread/AsyncExceptionOnMonitorEnter.java b/test/hotspot/jtreg/runtime/Thread/AsyncExceptionOnMonitorEnter.java index 30cd98fa239..8446ffb20fe 100644 --- a/test/hotspot/jtreg/runtime/Thread/AsyncExceptionOnMonitorEnter.java +++ b/test/hotspot/jtreg/runtime/Thread/AsyncExceptionOnMonitorEnter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ * @bug 8283044 * @summary Stress delivery of asynchronous exceptions while target is at monitorenter * @library /test/hotspot/jtreg/testlibrary - * @run main/othervm AsyncExceptionOnMonitorEnter 0 + * @run main/othervm/native AsyncExceptionOnMonitorEnter 0 * @run main/othervm/native -agentlib:AsyncExceptionOnMonitorEnter AsyncExceptionOnMonitorEnter 1 */ diff --git a/test/hotspot/jtreg/runtime/Thread/AsyncExceptionTest.java b/test/hotspot/jtreg/runtime/Thread/AsyncExceptionTest.java index c7d0d1a27f0..52fc4ca1d56 100644 --- a/test/hotspot/jtreg/runtime/Thread/AsyncExceptionTest.java +++ b/test/hotspot/jtreg/runtime/Thread/AsyncExceptionTest.java @@ -27,13 +27,14 @@ * @requires vm.compiler1.enabled | vm.compiler2.enabled * @summary Stress delivery of asynchronous exceptions. * @library /test/hotspot/jtreg/testlibrary - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+StressCompiledExceptionHandlers + * @run main/othervm/native + * -XX:+IgnoreUnrecognizedVMOptions -XX:+StressCompiledExceptionHandlers * -Xcomp -XX:TieredStopAtLevel=3 * -XX:CompileCommand=dontinline,AsyncExceptionTest::internalRun2 * -XX:CompileCommand=compileonly,AsyncExceptionTest::internalRun1 * -XX:CompileCommand=compileonly,AsyncExceptionTest::internalRun2 * AsyncExceptionTest - * @run main/othervm -Xcomp + * @run main/othervm/native -Xcomp * -XX:CompileCommand=dontinline,AsyncExceptionTest::internalRun2 * -XX:CompileCommand=compileonly,AsyncExceptionTest::internalRun1 * -XX:CompileCommand=compileonly,AsyncExceptionTest::internalRun2 diff --git a/test/hotspot/jtreg/runtime/Thread/TestBreakSignalThreadDump.java b/test/hotspot/jtreg/runtime/Thread/TestBreakSignalThreadDump.java index b985e15bd17..3cb4be1b004 100644 --- a/test/hotspot/jtreg/runtime/Thread/TestBreakSignalThreadDump.java +++ b/test/hotspot/jtreg/runtime/Thread/TestBreakSignalThreadDump.java @@ -28,7 +28,7 @@ * @summary Check that Ctrl-\ or Ctrl-Break (on Windows) causes HotSpot VM to print a full thread dump. * @library /vmTestbase * /test/lib - * @run driver TestBreakSignalThreadDump + * @run main/native TestBreakSignalThreadDump */ /* @@ -38,9 +38,11 @@ * @requires os.family != "windows" & os.family != "aix" * @comment TODO: Decide libjsig support on static JDK with 8351367 * @requires !jdk.static + * @comment loading of the jsig lib does currently not work well with ASAN lib + * @requires !vm.asan * @library /vmTestbase * /test/lib - * @run driver TestBreakSignalThreadDump load_libjsig + * @run main/native TestBreakSignalThreadDump load_libjsig */ import java.nio.file.Files; diff --git a/test/hotspot/jtreg/runtime/Thread/ThreadCountLimit.java b/test/hotspot/jtreg/runtime/Thread/ThreadCountLimit.java index 20d93cbfdbe..6ef7977ef8c 100644 --- a/test/hotspot/jtreg/runtime/Thread/ThreadCountLimit.java +++ b/test/hotspot/jtreg/runtime/Thread/ThreadCountLimit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -73,14 +73,27 @@ public static void main(String[] args) throws Exception { if (Platform.isLinux()) { // On Linux this test sometimes hits the limit for the maximum number of memory mappings, // which leads to various other failure modes. Run this test with a limit on how many - // threads the process is allowed to create, so we hit that limit first. - - final String ULIMIT_CMD = "ulimit -u 4096"; + // threads the process is allowed to create, so we hit that limit first. What we want is + // for another "limit" processes to be available, but ulimit doesn't work that way and + // if there are already many running processes we could fail to even start the JVM properly. + // So we loop increasing the limit until we get a successful run. This is not foolproof. + int pLimit = 4096; + final String ULIMIT_CMD = "ulimit -u "; ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(ThreadCountLimit.class.getName()); String javaCmd = ProcessTools.getCommandLine(pb); - // Relaunch the test with args.length > 0, and the ulimit set - ProcessTools.executeCommand("bash", "-c", ULIMIT_CMD + " && " + javaCmd + " dummy") - .shouldHaveExitValue(0); + for (int i = 1; i <= 10; i++) { + // Relaunch the test with args.length > 0, and the ulimit set + String cmd = ULIMIT_CMD + Integer.toString(pLimit * i) + " && " + javaCmd + " dummy"; + System.out.println("Trying: bash -c " + cmd); + OutputAnalyzer oa = ProcessTools.executeCommand("bash", "-c", cmd); + int exitValue = oa.getExitValue(); + switch (exitValue) { + case 0: System.out.println("Success!"); return; + case 1: System.out.println("Retry ..."); continue; + default: oa.shouldHaveExitValue(0); // generate error report + } + } + throw new Error("Failed to perform a successful run!"); } else { // Not Linux so run directly. test(); diff --git a/test/hotspot/jtreg/runtime/Thread/TooSmallStackSize.java b/test/hotspot/jtreg/runtime/Thread/TooSmallStackSize.java index 09db906b151..6fd1da6f2ae 100644 --- a/test/hotspot/jtreg/runtime/Thread/TooSmallStackSize.java +++ b/test/hotspot/jtreg/runtime/Thread/TooSmallStackSize.java @@ -28,6 +28,7 @@ * VMThreadStackSize values should result in an error message that shows * the minimum stack size value for each thread type. * @library /test/lib + * @requires vm.flagless * @modules java.base/jdk.internal.misc * java.management * @run driver TooSmallStackSize diff --git a/test/hotspot/jtreg/runtime/XCheckJniJsig/XCheckJSig.java b/test/hotspot/jtreg/runtime/XCheckJniJsig/XCheckJSig.java index a8010506d96..6dbe42cebb0 100644 --- a/test/hotspot/jtreg/runtime/XCheckJniJsig/XCheckJSig.java +++ b/test/hotspot/jtreg/runtime/XCheckJniJsig/XCheckJSig.java @@ -29,6 +29,8 @@ * @modules java.base/jdk.internal.misc * java.management * @requires os.family == "linux" | os.family == "mac" + * @comment loading of the jsig lib does currently not work well with ASAN lib + * @requires !vm.asan * @comment TODO: Decide libjsig support on static JDK with 8351367 * @requires !jdk.static * @run driver XCheckJSig diff --git a/test/hotspot/jtreg/runtime/cds/TestDefaultArchiveLoading.java b/test/hotspot/jtreg/runtime/cds/TestDefaultArchiveLoading.java index d90618b51f2..4bca1ed4581 100644 --- a/test/hotspot/jtreg/runtime/cds/TestDefaultArchiveLoading.java +++ b/test/hotspot/jtreg/runtime/cds/TestDefaultArchiveLoading.java @@ -26,6 +26,7 @@ * @test id=nocoops_nocoh * @summary Test Loading of default archives in all configurations * @requires vm.cds + * @requires vm.cds.default.archive.available * @requires vm.cds.write.archived.java.heap * @requires vm.bits == 64 * @library /test/lib @@ -38,6 +39,7 @@ * @test id=nocoops_coh * @summary Test Loading of default archives in all configurations (requires --enable-cds-archive-coh) * @requires vm.cds + * @requires vm.cds.default.archive.available * @requires vm.cds.write.archived.java.heap * @requires vm.bits == 64 * @library /test/lib @@ -50,6 +52,7 @@ * @test id=coops_nocoh * @summary Test Loading of default archives in all configurations * @requires vm.cds + * @requires vm.cds.default.archive.available * @requires vm.cds.write.archived.java.heap * @requires vm.bits == 64 * @library /test/lib @@ -62,6 +65,7 @@ * @test id=coops_coh * @summary Test Loading of default archives in all configurations (requires --enable-cds-archive-coh) * @requires vm.cds + * @requires vm.cds.default.archive.available * @requires vm.cds.write.archived.java.heap * @requires vm.bits == 64 * @library /test/lib @@ -90,8 +94,8 @@ private static Path archivePath(String archiveSuffix) { "server", archiveName(archiveSuffix)); } - private static boolean isCOHArchiveAvailable(char coops, char coh, - String archiveSuffix) throws Exception { + private static boolean isArchiveAvailable(char coops, char coh, + String archiveSuffix) throws Exception { Path archive= archivePath(archiveSuffix); return Files.exists(archive); } @@ -109,12 +113,16 @@ public static void main(String[] args) throws Exception { case "nocoops_nocoh": coh = coops = '-'; archiveSuffix = "_nocoops"; + if (!isArchiveAvailable(coops, coh, archiveSuffix)) { + throw new SkippedException("Skipping test due to " + + archivePath(archiveSuffix).toString() + " not available"); + } break; case "nocoops_coh": coops = '-'; coh = '+'; archiveSuffix = "_nocoops_coh"; - if (!isCOHArchiveAvailable(coops, coh, archiveSuffix)) { + if (!isArchiveAvailable(coops, coh, archiveSuffix)) { throw new SkippedException("Skipping test due to " + archivePath(archiveSuffix).toString() + " not available"); } @@ -123,11 +131,15 @@ public static void main(String[] args) throws Exception { coops = '+'; coh = '-'; archiveSuffix = ""; + if (!isArchiveAvailable(coops, coh, archiveSuffix)) { + throw new SkippedException("Skipping test due to " + + archivePath(archiveSuffix).toString() + " not available"); + } break; case "coops_coh": coh = coops = '+'; archiveSuffix = "_coh"; - if (!isCOHArchiveAvailable(coops, coh, archiveSuffix)) { + if (!isArchiveAvailable(coops, coh, archiveSuffix)) { throw new SkippedException("Skipping test due to " + archivePath(archiveSuffix).toString() + " not available"); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/ArchiveRelocationTest.java b/test/hotspot/jtreg/runtime/cds/appcds/ArchiveRelocationTest.java index 21a43fcf9cb..b433458a059 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/ArchiveRelocationTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/ArchiveRelocationTest.java @@ -67,6 +67,8 @@ static void test(boolean run_reloc) throws Exception { String logArg = "-Xlog:cds=debug,cds+reloc=debug,aot+heap"; String unlockArg = "-XX:+UnlockDiagnosticVMOptions"; String nmtArg = "-XX:NativeMemoryTracking=detail"; + String relocMsg1 = "ArchiveRelocationMode == 1: always map archive(s) at an alternative address"; + String relocMsg2 = "Try to map archive(s) at an alternative address"; OutputAnalyzer out = TestCommon.dump(appJar, TestCommon.list(mainClass), @@ -76,8 +78,10 @@ static void test(boolean run_reloc) throws Exception { TestCommon.run("-cp", appJar, unlockArg, runRelocArg, logArg, mainClass) .assertNormalExit(output -> { if (run_reloc) { - output.shouldContain("ArchiveRelocationMode == 1: always map archive(s) at an alternative address") - .shouldContain("Try to map archive(s) at an alternative address"); + if (!output.contains(relocMsg1) && !output.contains(relocMsg2)) { + throw new RuntimeException("Relocation messages \"" + relocMsg1 + + "\" and \"" + relocMsg2 + "\" are missing from the output"); + } } else { output.shouldContain("ArchiveRelocationMode: 0"); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/FillerObjectLoadTest.java b/test/hotspot/jtreg/runtime/cds/appcds/FillerObjectLoadTest.java index 79d377ca876..8538155375c 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/FillerObjectLoadTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/FillerObjectLoadTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithUseImplMethodHandle.java b/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithUseImplMethodHandle.java index 0c747168945..6b7a4f68bbf 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithUseImplMethodHandle.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithUseImplMethodHandle.java @@ -28,8 +28,6 @@ * @summary CDS cannot archive lambda proxy with useImplMethodHandle * @requires vm.cds * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/test-classes * @build pkg1.BaseWithProtectedMethod * @build pkg2.Child diff --git a/test/hotspot/jtreg/runtime/cds/appcds/LotsOfSyntheticClasses.java b/test/hotspot/jtreg/runtime/cds/appcds/LotsOfSyntheticClasses.java index 6267c6bdf33..3c3db7d0397 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/LotsOfSyntheticClasses.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/LotsOfSyntheticClasses.java @@ -120,9 +120,9 @@ public static void main(String[] args) throws Exception { OutputAnalyzer output = TestCommon.createArchive( APP_JAR.toString(), listAppClasses(), - MAIN_CLASS_NAME, // Verification for lots of classes slows down the test. "-XX:+IgnoreUnrecognizedVMOptions", + "-XX:+UnlockDiagnosticVMOptions", "-XX:-VerifyDependencies", "-XX:-VerifyBeforeExit" ); @@ -134,6 +134,7 @@ public static void main(String[] args) throws Exception { TestCommon.run( // Verification for lots of classes slows down the test. "-XX:+IgnoreUnrecognizedVMOptions", + "-XX:+UnlockDiagnosticVMOptions", "-XX:-VerifyDependencies", "-XX:-VerifyBeforeExit", "-cp", APP_JAR.toString(), diff --git a/test/hotspot/jtreg/runtime/cds/appcds/SignedJar.java b/test/hotspot/jtreg/runtime/cds/appcds/SignedJar.java index 1ad28f99408..9e6cb58bb7f 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/SignedJar.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/SignedJar.java @@ -50,8 +50,8 @@ public static void main(String[] args) throws Exception { String skipMsg = "Skipping Hello: Signed JAR"; String lambdaInArchive = "klasses.*=.*app.*Hello[$][$]Lambda.*hidden"; - String loadFromJar = ".class,load. Hello source: file:.*signed_hello.jar"; - String lambdaLoadFromHello = ".class.load. Hello[$][$]Lambda.*/0x.*source.*Hello"; + String loadFromJar = ".class,load\s*. Hello source: file:.*signed_hello.jar"; + String lambdaLoadFromHello = ".class.load\s*. Hello[$][$]Lambda.*/0x.*source.*Hello"; for (String mainArg : mainArgs) { output = TestCommon.dump(signedJar, TestCommon.list(mainClass), diff --git a/test/hotspot/jtreg/runtime/cds/appcds/TestCommon.java b/test/hotspot/jtreg/runtime/cds/appcds/TestCommon.java index 4f2822a5970..5d1e3831d86 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/TestCommon.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/TestCommon.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, 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 @@ -427,8 +427,6 @@ public static OutputAnalyzer runWithArchive(CDSOptions opts) cmd.add(opts.appJar); } - CDSTestUtils.addVerifyArchivedFields(cmd); - for (String s : opts.suffix) cmd.add(s); if (RUN_WITH_JFR) { diff --git a/test/hotspot/jtreg/runtime/cds/appcds/TestDumpClassListSource.java b/test/hotspot/jtreg/runtime/cds/appcds/TestDumpClassListSource.java index 28e92ac3700..1650cddee3f 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/TestDumpClassListSource.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/TestDumpClassListSource.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, 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 @@ -28,6 +28,7 @@ * @summary test dynamic dump meanwhile output loaded class list * @bug 8279009 8275084 * @requires vm.cds + * @requires vm.cds.default.archive.available * @requires vm.cds.custom.loaders * @requires vm.flagless * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds diff --git a/test/hotspot/jtreg/runtime/cds/appcds/TestParallelGCWithCDS.java b/test/hotspot/jtreg/runtime/cds/appcds/TestParallelGCWithCDS.java index 4ed2ce4446d..be7e69b076c 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/TestParallelGCWithCDS.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/TestParallelGCWithCDS.java @@ -121,34 +121,23 @@ static void test(boolean dumpWithParallel, boolean execWithParallel, boolean use out.shouldNotContain(errMsg); out.shouldHaveExitValue(0); - int n = 2; if (!dumpWithParallel && execWithParallel) { // We dumped with G1, so we have an archived heap. At exec time, try to load them into // a small ParallelGC heap that may be too small. - String[] sizes = { - "4m", // usually this will success load the archived heap - "2m", // usually this will fail to load the archived heap, but app can launch - // or fail with "GC triggered before VM initialization completed" - "1m" // usually this will cause VM launch to fail with "Too small maximum heap" - }; - for (String sz : sizes) { - String xmx = "-Xmx" + sz; - System.out.println("=======\n" + n + ". Exec with " + execGC + " " + xmx); - out = TestCommon.exec(helloJar, - execGC, - small1, - small2, - xmx, - coops, - "-Xlog:cds", - "Hello"); - if (out.getExitValue() == 0) { - out.shouldContain(HELLO); - out.shouldNotContain(errMsg); - } else { - out.shouldNotHaveFatalError(); - } - n++; + System.out.println("2. Exec with " + execGC); + out = TestCommon.exec(helloJar, + execGC, + small1, + small2, + "-Xmx4m", + coops, + "-Xlog:cds", + "Hello"); + if (out.getExitValue() == 0) { + out.shouldContain(HELLO); + out.shouldNotContain(errMsg); + } else { + out.shouldNotHaveFatalError(); } } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/TransformInterfaceOfLambda.java b/test/hotspot/jtreg/runtime/cds/appcds/TransformInterfaceOfLambda.java index 8bbc713fa6f..88620fc039f 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/TransformInterfaceOfLambda.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/TransformInterfaceOfLambda.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ * @summary Transforming an interface of an archived lambda proxy class should not * crash the VM. The lambda proxy class should be regenerated during runtime. * @requires vm.cds + * @requires vm.cds.default.archive.available * @requires vm.jvmti * @requires vm.flagless * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTCacheSupportForCustomLoaders.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTCacheSupportForCustomLoaders.java index ae00477e67b..9461957ef2c 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTCacheSupportForCustomLoaders.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTCacheSupportForCustomLoaders.java @@ -27,8 +27,6 @@ * @summary Test AOT cache support for array classes in custom class loaders. * @bug 8353298 8356838 * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes * @build ReturnIntegerAsString * @build AOTCacheSupportForCustomLoaders diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTLoggingTag.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTLoggingTag.java index 5499063ebbd..896df7ca496 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTLoggingTag.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTLoggingTag.java @@ -34,7 +34,6 @@ * @run driver AOTLoggingTag */ -import java.io.File; import jdk.test.lib.cds.CDSTestUtils; import jdk.test.lib.helpers.ClassFileInstaller; import jdk.test.lib.process.OutputAnalyzer; @@ -59,7 +58,7 @@ public static void main(String[] args) throws Exception { "-cp", appJar, helloClass); out = CDSTestUtils.executeAndLog(pb, "train"); - out.shouldContain("[info][aot] Writing binary AOTConfiguration file:"); + out.shouldContain("[aot] Writing binary AOTConfiguration file:"); out.shouldHaveExitValue(0); //---------------------------------------------------------------------- @@ -71,7 +70,7 @@ public static void main(String[] args) throws Exception { "-Xlog:aot", "-cp", appJar); out = CDSTestUtils.executeAndLog(pb, "asm"); - out.shouldContain("[info][aot] Opened AOT configuration file hello.aotconfig"); + out.shouldContain("[aot] Opened AOT configuration file hello.aotconfig"); out.shouldHaveExitValue(0); //---------------------------------------------------------------------- @@ -81,7 +80,7 @@ public static void main(String[] args) throws Exception { "-Xlog:aot", "-cp", appJar, helloClass); out = CDSTestUtils.executeAndLog(pb, "prod"); - out.shouldContain("[info][aot] Opened AOT cache hello.aot"); + out.shouldContain("[aot] Opened AOT cache hello.aot"); out.shouldHaveExitValue(0); //---------------------------------------------------------------------- @@ -92,7 +91,7 @@ public static void main(String[] args) throws Exception { "-cp", appJar, helloClass); out = CDSTestUtils.executeAndLog(pb, "prod"); out.shouldNotContain("No tag set matches selection: aot+heap"); - out.shouldContain("[info][aot,heap] resolve subgraph java.lang.Integer$IntegerCache"); + out.shouldContain("[aot,heap] resolve subgraph java.lang.Integer$IntegerCache"); out.shouldHaveExitValue(0); //---------------------------------------------------------------------- @@ -102,7 +101,7 @@ public static void main(String[] args) throws Exception { "-XX:AOTMode=on", "-cp", appJar, helloClass); out = CDSTestUtils.executeAndLog(pb, "prod"); - out.shouldContain("[error][aot] An error has occurred while processing the AOT cache. Run with -Xlog:aot for details."); + out.shouldContain("[aot] An error has occurred while processing the AOT cache. Run with -Xlog:aot for details."); out.shouldNotHaveExitValue(0); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/CloseSystemOut.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/CloseSystemOut.java new file mode 100644 index 00000000000..1f4111ecfb1 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/CloseSystemOut.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @summary AOT configuration should not be corrupted even if the app closes System.out in the training run + * @bug 8371944 + * @library /test/jdk/lib/testlibrary /test/lib + * @build CloseSystemOut + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar CloseSystemOutApp + * @run driver CloseSystemOut + */ + +import java.io.PrintWriter; +import jdk.test.lib.cds.CDSAppTester; +import jdk.test.lib.helpers.ClassFileInstaller; +import jdk.test.lib.process.OutputAnalyzer; + +public class CloseSystemOut { + static final String appJar = ClassFileInstaller.getJarPath("app.jar"); + static final String mainClass = "CloseSystemOutApp"; + + public static void main(String[] args) throws Exception { + Tester tester = new Tester(); + tester.run(new String[] {"AOT", "--two-step-training"} ); + } + + static class Tester extends CDSAppTester { + public Tester() { + super(mainClass); + } + + @Override + public String classpath(RunMode runMode) { + return appJar; + } + + @Override + public String[] appCommandLine(RunMode runMode) { + return new String[] {mainClass}; + } + + @Override + public void checkExecution(OutputAnalyzer out, RunMode runMode) { + if (runMode != RunMode.ASSEMBLY) { + out.shouldContain("Hello Confused World"); + } + } + } +} + +class CloseSystemOutApp { + public static void main(String args[]) { + // Naive code that ends up closing System.out/err when we + // leave the "try" block + try (var err = new PrintWriter(System.err); + var out = new PrintWriter(System.out)) { + out.println("Hello Confused World"); + } + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/ExcludedClasses.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/ExcludedClasses.java index 4f2ff4f0f76..f50a2d1f905 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/ExcludedClasses.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/ExcludedClasses.java @@ -26,8 +26,6 @@ * @test * @summary Test how various AOT optimizations handle classes that are excluded from the AOT cache. * @requires vm.cds.write.archived.java.heap - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/jdk/lib/testlibrary /test/lib * /test/hotspot/jtreg/runtime/cds/appcds/aotCache/test-classes * @build ExcludedClasses CustyWithLoop @@ -36,6 +34,8 @@ * TestApp$Foo * TestApp$Foo$Bar * TestApp$Foo$ShouldBeExcluded + * TestApp$Foo$ShouldBeExcludedChild + * TestApp$Foo$Taz * TestApp$MyInvocationHandler * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar cust.jar * CustyWithLoop @@ -63,7 +63,7 @@ public class ExcludedClasses { public static void main(String[] args) throws Exception { Tester tester = new Tester(); - tester.runAOTWorkflow(); + tester.runAOTWorkflow("AOT", "--two-step-training"); } static class Tester extends CDSAppTester { @@ -79,7 +79,11 @@ public String classpath(RunMode runMode) { @Override public String[] vmArgs(RunMode runMode) { return new String[] { - "-Xlog:cds+resolve=trace", + "-Xlog:aot=debug", + "-Xlog:aot+class=debug", + "-Xlog:aot+resolve=trace", + "-Xlog:aot+verification=trace", + "-Xlog:class+load", }; } @@ -92,8 +96,13 @@ public String[] appCommandLine(RunMode runMode) { @Override public void checkExecution(OutputAnalyzer out, RunMode runMode) { - if (isDumping(runMode)) { - out.shouldNotMatch("cds,resolve.*archived field.*TestApp.Foo => TestApp.Foo.ShouldBeExcluded.f:I"); + if (runMode == RunMode.ASSEMBLY) { + out.shouldNotMatch("aot,resolve.*archived field.*TestApp.Foo => TestApp.Foo.ShouldBeExcluded.f:I"); + } else if (runMode == RunMode.PRODUCTION) { + out.shouldContain("check_verification_constraint: TestApp$Foo$Taz: TestApp$Foo$ShouldBeExcludedChild must be subclass of TestApp$Foo$ShouldBeExcluded"); + out.shouldContain("jdk.jfr.Event source: jrt:/jdk.jfr"); + out.shouldMatch("TestApp[$]Foo[$]ShouldBeExcluded source: .*/app.jar"); + out.shouldMatch("TestApp[$]Foo[$]ShouldBeExcludedChild source: .*/app.jar"); } } } @@ -104,8 +113,8 @@ class TestApp { static volatile Object custArrayInstance; public static void main(String args[]) throws Exception { - // In new workflow, classes from custom loaders are passed from the preimage - // to the final image. See ClassPrelinker::record_unregistered_klasses(). + // In AOT workflow, classes from custom loaders are passed from the preimage + // to the final image. See FinalImageRecipes::record_all_classes(). custInstance = initFromCustomLoader(); custArrayInstance = Array.newInstance(custInstance.getClass(), 0); System.out.println(custArrayInstance); @@ -159,6 +168,7 @@ static int hotSpot() { lambdaHotSpot(); s.hotSpot2(); b.hotSpot3(); + Taz.hotSpot4(); // In JDK mainline, generated proxy classes are excluded from the AOT cache. // In Leyden/premain, generated proxy classes included. The following code should @@ -167,7 +177,7 @@ static int hotSpot() { counter += i.intValue(); if (custInstance != null) { - // Classes loaded by custom loaders are included included in the AOT cache + // Classes loaded by custom loaders are included in the AOT cache // but their array classes are excluded. counter += custInstance.equals(null) ? 1 : 2; } @@ -218,6 +228,16 @@ void hotSpot2() { f(); } } + int func() { + return 1; + } + } + + static class ShouldBeExcludedChild extends ShouldBeExcluded { + @Override + int func() { + return 2; + } } static class Bar { @@ -236,6 +256,29 @@ void hotSpot3() { } } } + + static class Taz { + static ShouldBeExcluded m() { + // When verifying this method, we need to check the constraint that + // ShouldBeExcluded must be a supertype of ShouldBeExcludedChild. This information + // is checked by SystemDictionaryShared::check_verification_constraints() when the Taz + // class is linked during the production run. + // + // Because ShouldBeExcluded is excluded from the AOT archive, it must be loaded + // dynamically from app.jar inside SystemDictionaryShared::check_verification_constraints(). + // This must happen after the app class loader has been fully restored from the AOT cache. + return new ShouldBeExcludedChild(); + } + static void hotSpot4() { + long start = System.currentTimeMillis(); + while (System.currentTimeMillis() - start < 20) { + for (int i = 0; i < 50000; i++) { + counter += i; + } + f(); + } + } + } } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/HelloAOTCache.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/HelloAOTCache.java index 007e51004ec..f3326ac1ed6 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/HelloAOTCache.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/HelloAOTCache.java @@ -27,8 +27,6 @@ * @test * @summary Sanity test for AOTCache * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/lib * @build HelloAOTCache * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar HelloAOTCacheApp diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/JNIDefineClass.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/JNIDefineClass.java new file mode 100644 index 00000000000..58c2cb42681 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/JNIDefineClass.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary classes defined with JNI DefineClass should be excluded from the AOT config file and AOT cache. + * @bug 8368182 + * @requires vm.cds + * @requires vm.cds.supports.aot.class.linking + * @library /test/lib + * @build JNIDefineClass + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar + * JNIDefineClassApp ExcludedDummy ExcludedDummy2 + * @run main/native JNIDefineClass + */ + +import java.io.InputStream; +import jdk.test.lib.cds.CDSAppTester; +import jdk.test.lib.helpers.ClassFileInstaller; +import jdk.test.lib.process.OutputAnalyzer; + +public class JNIDefineClass { + static final String appJar = ClassFileInstaller.getJarPath("app.jar"); + static final String mainClass = "JNIDefineClassApp"; + + public static void main(String[] args) throws Exception { + Tester tester = new Tester(); + tester.run(new String[] {"AOT", "--two-step-training"} ); + } + + static class Tester extends CDSAppTester { + public Tester() { + super(mainClass); + } + + @Override + public String classpath(RunMode runMode) { + return appJar; + } + + @Override + public String[] vmArgs(RunMode runMode) { + return new String[] { + "--enable-native-access=ALL-UNNAMED", + "-Xlog:aot,aot+class=debug", + "-Djava.library.path=" + System.getProperty("java.library.path"), + }; + } + + @Override + public String[] appCommandLine(RunMode runMode) { + return new String[] {mainClass}; + } + + @Override + public void checkExecution(OutputAnalyzer out, RunMode runMode) { + if (runMode.isApplicationExecuted()) { + out.shouldContain("@@loader = null"); + out.shouldContain("@@name = ExcludedDummy"); + + out.shouldMatch("@@loader2 = .*AppClassLoader"); + out.shouldContain("@@name2 = ExcludedDummy2"); + } + if (runMode == RunMode.TRAINING) { + out.shouldContain("Skipping ExcludedDummy: Unsupported location"); + } + + // Must not have a log like this + /// [0.378s][debug ][aot,class] klasses[ 65] = 0x0000000800160490 boot ExcludedDummy + /// [0.378s][debug ][aot,class] klasses[ 66] = 0x0000000800160490 app ExcludedDummy2 + out.shouldNotContain("aot,class.* klasses.*ExcludedDummy"); + out.shouldNotContain("aot,class.* klasses.*ExcludedDummy2"); + } + } +} + +class JNIDefineClassApp { + + static native Class nativeDefineClass(String name, ClassLoader ldr, byte[] class_bytes); + + static { + System.loadLibrary("JNIDefineClassApp"); + } + + public static void main(java.lang.String[] unused) throws Exception { + ClassLoader appLoader = JNIDefineClassApp.class.getClassLoader(); + + try (InputStream in = appLoader.getResourceAsStream("ExcludedDummy.class")) { + byte[] b = in.readAllBytes(); + System.out.println(b.length); + Class c = nativeDefineClass("ExcludedDummy", null, b); + System.out.println("@@loader = " + c.getClassLoader()); + System.out.println("@@name = " + c.getName()); + } + + try (InputStream in = appLoader.getResourceAsStream("ExcludedDummy2.class")) { + byte[] b = in.readAllBytes(); + System.out.println(b.length); + Class c = nativeDefineClass("ExcludedDummy2", appLoader, b); + System.out.println("@@loader2 = " + c.getClassLoader()); + System.out.println("@@name2 = " + c.getName()); + } + + System.out.println("TEST PASSED"); + } +} + +// This class is loaded into the bootstrap loader using JNI DefineClass() with a null code source, +// so it should be excluded from the AOT configuration (and hence excluded from AOT cache) +class ExcludedDummy { + +} + +// This class is loaded into the app loader using JNI DefineClass() with a null code source, +// so it should be excluded from the AOT configuration (and hence excluded from AOT cache) +class ExcludedDummy2 { + +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/JavaAgent.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/JavaAgent.java index 7965be8d00a..070f6df9834 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/JavaAgent.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/JavaAgent.java @@ -28,8 +28,6 @@ * @summary -javaagent should be allowed in AOT workflow. However, classes transformed/redefined by agents will not * be cached. * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes * @build JavaAgent JavaAgentTransformer Util * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar JavaAgentApp JavaAgentApp$ShouldBeTransformed diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/ManagementAgent.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/ManagementAgent.java index abbdd3551b7..c558d293b2a 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/ManagementAgent.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/ManagementAgent.java @@ -28,8 +28,6 @@ * @bug 8352187 * @summary ManagementAgent will not be started during AOT cache creation. * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/lib * @build HelloAOTCache * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar HelloAOTCacheApp diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/PackageInfoClass.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/PackageInfoClass.java index 0fff74236f1..014524afde6 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/PackageInfoClass.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/PackageInfoClass.java @@ -27,8 +27,6 @@ * @summary AOT cache handling for package-info class loaded by jdk/internal/loader/ClassLoaders$BootClassLoader * @bug 8354558 * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/lib /test/jdk/java/lang/Package/bootclasspath/boot * @build PackageInfoClass foo.Foo foo.MyAnnotation foo.package-info * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar boot.jar foo.Foo foo.package-info foo.MyAnnotation diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/SpecialCacheNames.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/SpecialCacheNames.java index 89aa9e441a4..e9d9c70a358 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/SpecialCacheNames.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/SpecialCacheNames.java @@ -27,8 +27,6 @@ * @summary Use special characters in the name of the cache file specified by -XX:AOTCacheOutput * Make sure these characters are passed to the child JVM process that assembles the cache. * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/lib * @build SpecialCacheNames * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar MyTestApp diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/VerifierFailOver.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/VerifierFailOver.java index 18caa08c117..50b47e4424d 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/VerifierFailOver.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/VerifierFailOver.java @@ -26,8 +26,6 @@ * @test * @summary Sanity test for AOTCache * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/lib * @build VerifierFailOver_Helper * @build VerifierFailOver diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/libJNIDefineClassApp.c b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/libJNIDefineClassApp.c new file mode 100644 index 00000000000..ec3ed3bc8f6 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/libJNIDefineClassApp.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include + +JNIEXPORT jclass JNICALL +Java_JNIDefineClassApp_nativeDefineClass(JNIEnv* env, jclass clazz /*unused*/, + jstring className, jobject classLoader, jbyteArray bytecode) { + const char* classNameChar = (*env)->GetStringUTFChars(env, className, NULL); + jbyte* arrayContent = (*env)->GetByteArrayElements(env, bytecode, NULL); + jsize bytecodeLength = (*env)->GetArrayLength(env, bytecode); + jclass returnValue = (*env)->DefineClass(env, classNameChar, classLoader, arrayContent, bytecodeLength); + (*env)->ReleaseByteArrayElements(env, bytecode, arrayContent, JNI_ABORT); + (*env)->ReleaseStringUTFChars(env, className, classNameChar); + return returnValue; +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AOTCacheWithZGC.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AOTCacheWithZGC.java index 96f08004fb2..a7c7362b845 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AOTCacheWithZGC.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AOTCacheWithZGC.java @@ -28,8 +28,6 @@ * @bug 8352775 * @requires vm.cds * @requires vm.gc.Z - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/lib * @build AOTCacheWithZGC * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar AOTCacheWithZGCApp diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AOTLoaderConstraintsTest.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AOTLoaderConstraintsTest.java index 63be2038907..f82cf2737fb 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AOTLoaderConstraintsTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AOTLoaderConstraintsTest.java @@ -26,8 +26,6 @@ * @test Make sure loader constraints are passed from AOT preimage to final image. * @bug 8348426 * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/jdk/lib/testlibrary /test/lib * @build AOTLoaderConstraintsTest BootClass * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar boot.jar BootClass diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddExports.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddExports.java index 2a63a4837c2..fc3e945cf9d 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddExports.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddExports.java @@ -28,8 +28,6 @@ * @bug 8352437 * @requires vm.cds * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds * @run driver AddExports */ diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddOpens.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddOpens.java index 5ae8c4a6bb8..d3626d30c7e 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddOpens.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddOpens.java @@ -26,8 +26,6 @@ * @test * @requires vm.cds * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds * @run driver AddOpens * @summary sanity test the --add-opens option diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddReads.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddReads.java index c1dbc602755..5c9364aa079 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddReads.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddReads.java @@ -27,8 +27,6 @@ * @bug 8354083 * @requires vm.cds * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds * @run driver AddReads * @summary sanity test the --add-reads option diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java index 90fd0f33bab..0f7707edae3 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java @@ -29,8 +29,6 @@ /* * @test id=static * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes * @build InitiatingLoaderTester BadOldClassA BadOldClassB * @build jdk.test.whitebox.WhiteBox BulkLoaderTest SimpleCusty @@ -45,8 +43,6 @@ /* * @test id=dynamic * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes * @build InitiatingLoaderTester BadOldClassA BadOldClassB * @build jdk.test.whitebox.WhiteBox BulkLoaderTest SimpleCusty @@ -61,8 +57,6 @@ /* * @test id=aot * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes * @build jdk.test.whitebox.WhiteBox InitiatingLoaderTester BadOldClassA BadOldClassB * @build BulkLoaderTest SimpleCusty @@ -78,6 +72,7 @@ import java.lang.StackWalker.StackFrame; import java.net.URL; import java.net.URLClassLoader; +import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -318,12 +313,15 @@ static void checkCustomLoader() throws Exception { } } + static ArrayList savedLoaders = new ArrayList<>(); + static Object initFromCustomLoader() throws Exception { String path = "cust.jar"; URL url = new File(path).toURI().toURL(); URL[] urls = new URL[] {url}; URLClassLoader urlClassLoader = new URLClassLoader("MyLoader", urls, null); + savedLoaders.add(urlClassLoader); Class c = Class.forName("SimpleCusty", true, urlClassLoader); return c.newInstance(); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/FakeCodeLocation.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/FakeCodeLocation.java index 1ffc904963a..5da2e2754e8 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/FakeCodeLocation.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/FakeCodeLocation.java @@ -26,8 +26,6 @@ * @test Do not cache classes that are loaded from a fake location. * @bug 8352001 * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/jdk/lib/testlibrary /test/lib * @build FakeCodeLocation * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar FakeCodeLocationApp diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/GeneratedInternedString.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/GeneratedInternedString.java index dcb1c59c09f..0ee59bf5afd 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/GeneratedInternedString.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/GeneratedInternedString.java @@ -28,8 +28,6 @@ * @requires vm.cds.write.archived.java.heap * @requires vm.cds.supports.aot.class.linking * @requires vm.debug - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/cds/appcds * @build GeneratedInternedString * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar GeneratedInternedStringApp diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/LambdaInExcludedClass.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/LambdaInExcludedClass.java index 9ed2524bff1..c91e999c40f 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/LambdaInExcludedClass.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/LambdaInExcludedClass.java @@ -27,8 +27,6 @@ * @bug 8349888 * @requires vm.cds.supports.aot.class.linking * @requires vm.gc.Epsilon - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/jdk/lib/testlibrary /test/lib * @build LambdaInExcludedClass * @run driver jdk.test.lib.helpers.ClassFileInstaller LambdaInExcludedClassApp diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/MethodHandleTest.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/MethodHandleTest.java index f7a26a39db1..972dc287af5 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/MethodHandleTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/MethodHandleTest.java @@ -27,8 +27,6 @@ * @requires vm.cds.write.archived.java.heap * @requires vm.cds.supports.aot.class.linking * @requires vm.debug - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/cds/appcds * @build MethodHandleTest * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar mh.jar diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/NonFinalStaticWithInitVal.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/NonFinalStaticWithInitVal.java index ba21f5f98fb..17ff399d23c 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/NonFinalStaticWithInitVal.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/NonFinalStaticWithInitVal.java @@ -27,8 +27,6 @@ * @summary Handling of non-final static string that has an initial value * @bug 8356125 * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/lib * @build NonFinalStaticWithInitVal_Helper * @build NonFinalStaticWithInitVal diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/StringConcatStress.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/StringConcatStress.java index 3786c294791..81bf28010b1 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/StringConcatStress.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/StringConcatStress.java @@ -34,8 +34,6 @@ /* * @test id=aot * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/lib * @build StringConcatStress * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar StringConcatStressApp diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/TestSetupAOTTest.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/TestSetupAOTTest.java index f88af3caed5..118b4c6af1d 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/TestSetupAOTTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/TestSetupAOTTest.java @@ -28,8 +28,6 @@ * is used for running HotSpot tests in the "AOT mode" * (E.g., make test JTREG=AOT_JDK=true TEST=open/test/hotspot/jtreg/runtime/invokedynamic) * @requires vm.cds - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/lib /test/setup_aot * @build TestSetupAOTTest JavacBenchApp TestSetupAOT * @run driver jdk.test.lib.helpers.ClassFileInstaller diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/TrainingRun.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/TrainingRun.java index fd896fd6958..df466151f98 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/TrainingRun.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/TrainingRun.java @@ -27,8 +27,6 @@ * @summary -XX:AOTMode=record should not interfere with app execution: (1) thread creation; (2) exit code * @bug 8351327 * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/jdk/lib/testlibrary /test/lib * @build TrainingRun * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar MyTestApp diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/WeakReferenceTest.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/WeakReferenceTest.java index ae5cd5b3429..3b33d63b0d2 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/WeakReferenceTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/WeakReferenceTest.java @@ -27,8 +27,6 @@ * @requires vm.cds.write.archived.java.heap * @requires vm.cds.supports.aot.class.linking * @requires vm.debug - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/cds/appcds * @build WeakReferenceTest * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar weakref.jar diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotFlags/AOTFlags.java b/test/hotspot/jtreg/runtime/cds/appcds/aotFlags/AOTFlags.java index 44957f5d2ed..6db81351e6b 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotFlags/AOTFlags.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotFlags/AOTFlags.java @@ -257,6 +257,16 @@ static void positiveTests() throws Exception { out.shouldContain("AOTCache creation is complete: hello.aot"); out.shouldMatch("Picked up JAVA_TOOL_OPTIONS:.* -Dmy.prop=My' 'string' '-Xshare:off' 'here"); out.shouldHaveExitValue(0); + + // Training run with -XX:+PrintTieredEvents (see JDK-8362530). + printTestCase("Training run with -XX:+PrintTieredEvents"); + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:AOTMode=record", + "-XX:+PrintTieredEvents", + "-XX:AOTConfiguration=" + aotConfigFile, + "-cp", appJar, helloClass); + out = CDSTestUtils.executeAndLog(pb, "train-with-tiered-events"); + out.shouldHaveExitValue(0); } static void negativeTests() throws Exception { @@ -484,6 +494,7 @@ static void negativeTests() throws Exception { testEmptyValue("AOTCache"); testEmptyValue("AOTConfiguration"); testEmptyValue("AOTMode"); + testEmptyValue("AOTCacheOutput"); } static void testEmptyValue(String option) throws Exception { diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotProfile/AOTProfileFlags.java b/test/hotspot/jtreg/runtime/cds/appcds/aotProfile/AOTProfileFlags.java index e2285a59600..fe9c7e7bbb7 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotProfile/AOTProfileFlags.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotProfile/AOTProfileFlags.java @@ -26,8 +26,6 @@ * @test * @summary Sanity test of combinations of the diagnostic flags [+-]AOTRecordTraining and [+-]AOTReplayTraining * @requires vm.cds - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @requires vm.cds.supports.aot.class.linking * @requires vm.flagless * @library /test/lib /test/setup_aot /test/hotspot/jtreg/runtime/cds/appcds/test-classes diff --git a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchiveHeapTestClass.java b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchiveHeapTestClass.java index 819db99a549..fed56937f2f 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchiveHeapTestClass.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchiveHeapTestClass.java @@ -28,8 +28,6 @@ * @summary Test for the -XX:ArchiveHeapTestClass flag * @requires vm.debug == true & vm.cds.write.archived.java.heap * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @modules java.logging * @library /test/jdk/lib/testlibrary /test/lib * /test/hotspot/jtreg/runtime/cds/appcds diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java index 4806f571dc6..6c46fd07550 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java @@ -27,6 +27,7 @@ * @summary Test -XX:+AutoCreateSharedArchive on a copied JDK without default shared archive * @bug 8261455 * @requires vm.cds + * @requires vm.cds.default.archive.available * @requires vm.flagless * @comment This test doesn't work on Windows because it depends on symlinks * @requires os.family != "windows" diff --git a/test/hotspot/jtreg/runtime/cds/appcds/loaderConstraints/DynamicLoaderConstraintsTest.java b/test/hotspot/jtreg/runtime/cds/appcds/loaderConstraints/DynamicLoaderConstraintsTest.java index 91293531611..1d83fb9efa6 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/loaderConstraints/DynamicLoaderConstraintsTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/loaderConstraints/DynamicLoaderConstraintsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,6 +55,7 @@ /** * @test id=custom-cl-zgc * @requires vm.cds.custom.loaders + * @requires vm.cds.nocoops.archive.available * @requires vm.gc.Z * @summary Test dumptime_table entries are removed with zgc eager class unloading * @bug 8274935 diff --git a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesAsCollectorTest.java b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesAsCollectorTest.java index ba7c0def86a..1061207f764 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesAsCollectorTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesAsCollectorTest.java @@ -28,8 +28,6 @@ * @summary Run the MethodHandlesAsCollectorTest.java test in CDSAppTester::AOT workflow. * @requires vm.cds & vm.compMode != "Xcomp" * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @comment Some of the tests run excessively slowly with -Xcomp. The original * tests aren't executed with -Xcomp in the CI pipeline, so let's exclude * the generated tests from -Xcomp execution as well. diff --git a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesCastFailureTest.java b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesCastFailureTest.java index 3f5008ca8c3..3349d146e10 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesCastFailureTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesCastFailureTest.java @@ -28,8 +28,6 @@ * @summary Run the MethodHandlesCastFailureTest.java test in CDSAppTester::AOT workflow. * @requires vm.cds & vm.compMode != "Xcomp" * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @comment Some of the tests run excessively slowly with -Xcomp. The original * tests aren't executed with -Xcomp in the CI pipeline, so let's exclude * the generated tests from -Xcomp execution as well. diff --git a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesGeneralTest.java b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesGeneralTest.java index 70f02b9a3d7..bba3f367505 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesGeneralTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesGeneralTest.java @@ -28,8 +28,6 @@ * @summary Run the MethodHandlesGeneralTest.java test in CDSAppTester::AOT workflow. * @requires vm.cds & vm.compMode != "Xcomp" * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @comment Some of the tests run excessively slowly with -Xcomp. The original * tests aren't executed with -Xcomp in the CI pipeline, so let's exclude * the generated tests from -Xcomp execution as well. diff --git a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesInvokersTest.java b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesInvokersTest.java index 7de76f5e99a..9ce57a9c66b 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesInvokersTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesInvokersTest.java @@ -28,8 +28,6 @@ * @summary Run the MethodHandlesInvokersTest.java test in CDSAppTester::AOT workflow. * @requires vm.cds & vm.compMode != "Xcomp" * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @comment Some of the tests run excessively slowly with -Xcomp. The original * tests aren't executed with -Xcomp in the CI pipeline, so let's exclude * the generated tests from -Xcomp execution as well. diff --git a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesPermuteArgumentsTest.java b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesPermuteArgumentsTest.java index 1e4bfebce9d..8f75eff0dc7 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesPermuteArgumentsTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesPermuteArgumentsTest.java @@ -28,8 +28,6 @@ * @summary Run the MethodHandlesPermuteArgumentsTest.java test in CDSAppTester::AOT workflow. * @requires vm.cds & vm.compMode != "Xcomp" * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @comment Some of the tests run excessively slowly with -Xcomp. The original * tests aren't executed with -Xcomp in the CI pipeline, so let's exclude * the generated tests from -Xcomp execution as well. diff --git a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesSpreadArgumentsTest.java b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesSpreadArgumentsTest.java index 19755121282..8b431232825 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesSpreadArgumentsTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesSpreadArgumentsTest.java @@ -28,8 +28,6 @@ * @summary Run the MethodHandlesSpreadArgumentsTest.java test in CDSAppTester::AOT workflow. * @requires vm.cds & vm.compMode != "Xcomp" * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @comment Some of the tests run excessively slowly with -Xcomp. The original * tests aren't executed with -Xcomp in the CI pipeline, so let's exclude * the generated tests from -Xcomp execution as well. diff --git a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedLambdas.java b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedLambdas.java index e187f408fb4..ecfaa265923 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedLambdas.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedLambdas.java @@ -28,8 +28,6 @@ * @bug 8340836 * @requires vm.cds * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes/ * @build AOTLinkedLambdas * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar diff --git a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedVarHandles.java b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedVarHandles.java index e262c55beea..4586b94b519 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedVarHandles.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedVarHandles.java @@ -28,8 +28,6 @@ * @bug 8343245 * @requires vm.cds * @requires vm.cds.supports.aot.class.linking - * @comment work around JDK-8345635 - * @requires !vm.jvmci.enabled * @library /test/lib * @build AOTLinkedVarHandles * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar diff --git a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/InternSharedString.java b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/InternSharedString.java index 615aa1c7e7c..ed8e582b213 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/InternSharedString.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/InternSharedString.java @@ -27,8 +27,6 @@ * @summary Test shared strings together with string intern operation * @requires vm.cds.write.archived.java.heap * @requires vm.gc == null - * @comment CDS archive heap mapping is not supported with large pages - * @requires vm.opt.UseLargePages == null | !vm.opt.UseLargePages * @library /test/hotspot/jtreg/runtime/cds/appcds /test/lib * @compile InternStringTest.java * @build jdk.test.whitebox.WhiteBox diff --git a/test/hotspot/jtreg/runtime/exceptionMsgs/IllegalAccessError/IAE78_A.java b/test/hotspot/jtreg/runtime/exceptionMsgs/IllegalAccessError/IAE78_A.java index e0491b4b89f..0684ad1aacc 100644 --- a/test/hotspot/jtreg/runtime/exceptionMsgs/IllegalAccessError/IAE78_A.java +++ b/test/hotspot/jtreg/runtime/exceptionMsgs/IllegalAccessError/IAE78_A.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 by SAP AG, Walldorf, Germany. + * Copyright (c) 2018, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/runtime/exceptionMsgs/IllegalAccessError/IAE_Loader2.java b/test/hotspot/jtreg/runtime/exceptionMsgs/IllegalAccessError/IAE_Loader2.java index 373ee584679..d13e5e5d3c1 100644 --- a/test/hotspot/jtreg/runtime/exceptionMsgs/IllegalAccessError/IAE_Loader2.java +++ b/test/hotspot/jtreg/runtime/exceptionMsgs/IllegalAccessError/IAE_Loader2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 by SAP AG, Walldorf, Germany. + * Copyright (c) 2018, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/runtime/execstack/Test.java b/test/hotspot/jtreg/runtime/execstack/Test.java index 67891a523aa..22063a56dd5 100644 --- a/test/hotspot/jtreg/runtime/execstack/Test.java +++ b/test/hotspot/jtreg/runtime/execstack/Test.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011 SAP AG. All Rights Reserved. + * Copyright (c) 2011, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/runtime/execstack/TestMT.java b/test/hotspot/jtreg/runtime/execstack/TestMT.java index 0be1a461c0a..282b09f9a35 100644 --- a/test/hotspot/jtreg/runtime/execstack/TestMT.java +++ b/test/hotspot/jtreg/runtime/execstack/TestMT.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011 SAP AG. All Rights Reserved. + * Copyright (c) 2011, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/runtime/execstack/libtest-rw.c b/test/hotspot/jtreg/runtime/execstack/libtest-rw.c index 7ad4b95d25e..52e1e8328a1 100644 --- a/test/hotspot/jtreg/runtime/execstack/libtest-rw.c +++ b/test/hotspot/jtreg/runtime/execstack/libtest-rw.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011 SAP AG. All Rights Reserved. + * Copyright (c) 2011, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/runtime/execstack/libtest-rwx.c b/test/hotspot/jtreg/runtime/execstack/libtest-rwx.c index bce4f853106..e0d8e424809 100644 --- a/test/hotspot/jtreg/runtime/execstack/libtest-rwx.c +++ b/test/hotspot/jtreg/runtime/execstack/libtest-rwx.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011 SAP AG. All Rights Reserved. + * Copyright (c) 2011, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/hotspot/jtreg/runtime/handshake/HandshakeTimeoutTest.java b/test/hotspot/jtreg/runtime/handshake/HandshakeTimeoutTest.java index a1a5ff68c31..7f1ee4be711 100644 --- a/test/hotspot/jtreg/runtime/handshake/HandshakeTimeoutTest.java +++ b/test/hotspot/jtreg/runtime/handshake/HandshakeTimeoutTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ * @library /testlibrary /test/lib * @build HandshakeTimeoutTest * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run driver HandshakeTimeoutTest + * @run driver/timeout=480 HandshakeTimeoutTest */ public class HandshakeTimeoutTest { diff --git a/test/hotspot/jtreg/runtime/jni/checked/TestCharArrayReleasing.java b/test/hotspot/jtreg/runtime/jni/checked/TestCharArrayReleasing.java index 7cb427cebbb..c26fb2bea4c 100644 --- a/test/hotspot/jtreg/runtime/jni/checked/TestCharArrayReleasing.java +++ b/test/hotspot/jtreg/runtime/jni/checked/TestCharArrayReleasing.java @@ -25,6 +25,8 @@ * @test * @bug 8357601 * @requires vm.flagless + * @comment The check of the array allocated with raw malloc triggers ASAN as we peek into the malloc header space. + * @requires !vm.asan * @library /test/lib * @run main/othervm/native TestCharArrayReleasing 0 0 * @run main/othervm/native TestCharArrayReleasing 1 0 diff --git a/test/hotspot/jtreg/runtime/jni/checked/TestLargeUTF8Length.java b/test/hotspot/jtreg/runtime/jni/checked/TestLargeUTF8Length.java index 9186a7ea381..27ec125317b 100644 --- a/test/hotspot/jtreg/runtime/jni/checked/TestLargeUTF8Length.java +++ b/test/hotspot/jtreg/runtime/jni/checked/TestLargeUTF8Length.java @@ -25,6 +25,7 @@ * @bug 8328877 * @summary Test warning for GetStringUTFLength and functionality of GetStringUTFLengthAsLong * @requires vm.bits == 64 + * @requires os.maxMemory > 15g * @library /test/lib * @modules java.management * @run main/native TestLargeUTF8Length launch @@ -44,9 +45,14 @@ public class TestLargeUTF8Length { static native void checkUTF8Length(String s, long utf8Length); static void test() { - int length = Integer.MAX_VALUE/2 + 1; - char character = (char)0XD1; // N with tilde - long utf8Length = 2L * length; + // We want a string whose UTF-8 length is > Integer.MAX_VALUE, but + // whose "natural" length is < Integer.MAX_VALUE/2 so it can be + // created regardless of whether compact-strings are enabled or not. + // So we use a character that encodes as 3-bytes in UTF-8. + // U+08A0 : e0 a2 a0 : ARABIC LETTER BEH WITH SMALL V BELOW + char character = '\u08A0'; + int length = Integer.MAX_VALUE/2 - 1; + long utf8Length = 3L * length; char[] chrs = new char[length]; Arrays.fill(chrs, character); String s = new String(chrs); diff --git a/test/hotspot/jtreg/runtime/logging/StressAsyncUL.java b/test/hotspot/jtreg/runtime/logging/StressAsyncUL.java index e14cad6cc65..61c38fe782b 100644 --- a/test/hotspot/jtreg/runtime/logging/StressAsyncUL.java +++ b/test/hotspot/jtreg/runtime/logging/StressAsyncUL.java @@ -45,12 +45,12 @@ static void analyze_output(boolean stalling_mode, String... args) throws Excepti } } public static void main(String[] args) throws Exception { - analyze_output(false, "-Xlog:async:drop", "-Xlog:all=trace", InnerClass.class.getName()); - analyze_output(true, "-Xlog:async:stall", "-Xlog:all=trace", InnerClass.class.getName()); + analyze_output(false, "-Xlog:async:drop", "-Xlog:all=debug", InnerClass.class.getName()); + analyze_output(true, "-Xlog:async:stall", "-Xlog:all=debug", InnerClass.class.getName()); // Stress test with a very small buffer. Note: Any valid buffer size must be able to hold a flush token. // Therefore the size of the buffer cannot be zero. - analyze_output(false, "-Xlog:async:drop", "-Xlog:all=trace", "-XX:AsyncLogBufferSize=192", InnerClass.class.getName()); - analyze_output(true, "-Xlog:async:stall", "-Xlog:all=trace", "-XX:AsyncLogBufferSize=192", InnerClass.class.getName()); + analyze_output(false, "-Xlog:async:drop", "-Xlog:all=debug", "-XX:AsyncLogBufferSize=192", InnerClass.class.getName()); + analyze_output(true, "-Xlog:async:stall", "-Xlog:all=debug", "-XX:AsyncLogBufferSize=192", InnerClass.class.getName()); } public static class InnerClass { diff --git a/test/hotspot/jtreg/runtime/os/TestHugePageDecisionsAtVMStartup.java b/test/hotspot/jtreg/runtime/os/TestHugePageDecisionsAtVMStartup.java index 2def134b9d3..7c0dfb2f3bb 100644 --- a/test/hotspot/jtreg/runtime/os/TestHugePageDecisionsAtVMStartup.java +++ b/test/hotspot/jtreg/runtime/os/TestHugePageDecisionsAtVMStartup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2023, 2024, Red Hat Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -56,6 +56,7 @@ import jdk.test.lib.os.linux.HugePageConfiguration; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; +import jtreg.SkippedException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -123,6 +124,9 @@ static void testOutput(boolean useLP, boolean useTHP, OutputAnalyzer out, HugePa out.shouldContain(warningNoTHP); } else if (useLP && !useTHP && configuration.supportsExplicitHugePages() && haveUsableExplicitHugePages) { + if (configuration.getExplicitAvailableHugePageNumber() == 0) { + throw new SkippedException("No usable explicit hugepages configured on the system, skipping test"); + } out.shouldContain("[info][pagesize] Using the default large page size: " + buildSizeString(configuration.getExplicitDefaultHugePageSize())); out.shouldContain("[info][pagesize] UseLargePages=1, UseTransparentHugePages=0"); out.shouldContain("[info][pagesize] Large page support enabled"); diff --git a/test/hotspot/jtreg/runtime/signal/SigTestDriver.java b/test/hotspot/jtreg/runtime/signal/SigTestDriver.java index 4a62a1e9cca..9a139baf68d 100644 --- a/test/hotspot/jtreg/runtime/signal/SigTestDriver.java +++ b/test/hotspot/jtreg/runtime/signal/SigTestDriver.java @@ -53,15 +53,9 @@ public static void main(String[] args) { switch (signame) { case "SIGWAITING": case "SIGKILL": - case "SIGSTOP": { - throw new SkippedException("signals SIGWAITING, SIGKILL and SIGSTOP can't be tested"); - } + case "SIGSTOP": case "SIGUSR2": { - if (Platform.isLinux()) { - throw new SkippedException("SIGUSR2 can't be tested on Linux"); - } else if (Platform.isOSX()) { - throw new SkippedException("SIGUSR2 can't be tested on OS X"); - } + throw new SkippedException("signals SIGWAITING, SIGKILL, SIGSTOP and SIGUSR2 can't be tested"); } } diff --git a/test/hotspot/jtreg/runtime/verifier/CFLH/TestVerify.java b/test/hotspot/jtreg/runtime/verifier/CFLH/TestVerify.java index 214751863ea..33cb881e537 100644 --- a/test/hotspot/jtreg/runtime/verifier/CFLH/TestVerify.java +++ b/test/hotspot/jtreg/runtime/verifier/CFLH/TestVerify.java @@ -39,7 +39,6 @@ */ import java.lang.invoke.MethodHandles; -import java.time.Duration; import java.lang.classfile.ClassFile; import java.lang.classfile.ClassTransform; import java.lang.classfile.MethodTransform; @@ -61,7 +60,7 @@ public class TestVerify { - private static final String CLASS_TO_BREAK = "java.time.Duration"; + private static final String CLASS_TO_BREAK = "java.util.Date"; private static final String INTERNAL_CLASS_TO_BREAK = CLASS_TO_BREAK.replace('.', '/'); private static final boolean DEBUG = false; @@ -91,7 +90,7 @@ public byte[] transform(Module module, ClassLoader loader, String className, Cla } builder.with(element); }); - var classTransform = ClassTransform.transformingMethods(mm -> mm.methodName().stringValue().equals("getSeconds"), methodTransform); + var classTransform = ClassTransform.transformingMethods(mm -> mm.methodName().equalsString("parse"), methodTransform); byte[] bytes; try { @@ -164,7 +163,7 @@ public static void main(String argv[]) throws Exception { } else { // Load the class instrumented with CFLH for the VerifyError. inst.addTransformer(new BadTransformer()); - System.out.println("1 hour is " + Duration.ofHours(1).getSeconds() + " seconds"); + Class cls = Class.forName(CLASS_TO_BREAK); } throw new RuntimeException("Failed: Did not throw VerifyError"); } catch (VerifyError e) { diff --git a/test/hotspot/jtreg/serviceability/AsyncGetCallTrace/MyPackage/ASGCTBaseTest.java b/test/hotspot/jtreg/serviceability/AsyncGetCallTrace/MyPackage/ASGCTBaseTest.java index 5c41565db8d..e22c1b59394 100644 --- a/test/hotspot/jtreg/serviceability/AsyncGetCallTrace/MyPackage/ASGCTBaseTest.java +++ b/test/hotspot/jtreg/serviceability/AsyncGetCallTrace/MyPackage/ASGCTBaseTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, Google and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -29,7 +29,7 @@ * @summary Verifies that AsyncGetCallTrace is call-able and provides sane information. * @compile ASGCTBaseTest.java * @requires os.family == "linux" - * @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" | os.arch=="arm" | os.arch=="aarch64" | os.arch=="ppc64" | os.arch=="s390" | os.arch=="riscv64" + * @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" | os.arch=="arm" | os.arch=="aarch64" | os.arch=="ppc64" | os.arch=="ppc64le" | os.arch=="s390" | os.arch=="riscv64" * @requires vm.jvmti * @run main/othervm/native -agentlib:AsyncGetCallTraceTest MyPackage.ASGCTBaseTest */ diff --git a/test/hotspot/jtreg/serviceability/HeapDump/UnmountedVThreadNativeMethodAtTop.java b/test/hotspot/jtreg/serviceability/HeapDump/UnmountedVThreadNativeMethodAtTop.java index bb08be91dac..7980b5ae28d 100644 --- a/test/hotspot/jtreg/serviceability/HeapDump/UnmountedVThreadNativeMethodAtTop.java +++ b/test/hotspot/jtreg/serviceability/HeapDump/UnmountedVThreadNativeMethodAtTop.java @@ -27,7 +27,9 @@ * @requires vm.continuations * @modules jdk.management * @library /test/lib - * @run junit/othervm --enable-native-access=ALL-UNNAMED UnmountedVThreadNativeMethodAtTop + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run junit/othervm/native -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI --enable-native-access=ALL-UNNAMED UnmountedVThreadNativeMethodAtTop */ import java.lang.management.ManagementFactory; @@ -45,9 +47,12 @@ import jdk.test.lib.hprof.model.Snapshot; import jdk.test.lib.hprof.model.ThreadObject; import jdk.test.lib.hprof.parser.Reader; +import jdk.test.whitebox.WhiteBox; public class UnmountedVThreadNativeMethodAtTop { + static WhiteBox wb = WhiteBox.getWhiteBox(); + boolean done; /** @@ -56,7 +61,7 @@ public class UnmountedVThreadNativeMethodAtTop { */ @BeforeEach void doGC() { - System.gc(); + wb.fullGC(); } /** diff --git a/test/hotspot/jtreg/serviceability/attach/EarlyDynamicLoad/EarlyDynamicLoad.java b/test/hotspot/jtreg/serviceability/attach/EarlyDynamicLoad/EarlyDynamicLoad.java new file mode 100644 index 00000000000..01ea18296e5 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/attach/EarlyDynamicLoad/EarlyDynamicLoad.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.tools.attach.VirtualMachine; +import com.sun.tools.attach.AgentLoadException; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.AfterAll; + +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.concurrent.TimeUnit; +import jdk.test.lib.dcmd.PidJcmdExecutor; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.Utils; + +/* + * @test EarlyDynamicLoad + * @summary Test that dynamic attach fails gracefully when the JVM is not in live phase. + * @requires vm.jvmti + * @library /test/lib + * @run junit EarlyDynamicLoad + */ +public class EarlyDynamicLoad { + private static final String EXPECTED_MESSAGE = "Dynamic agent loading is only permitted in the live phase"; + + private static Process child; + + @BeforeAll + static void startAndWaitChild() throws Exception { + child = ProcessTools.createTestJavaProcessBuilder( + "-XX:+StartAttachListener", + "-agentpath:" + Utils.TEST_NATIVE_PATH + File.separator + System.mapLibraryName("EarlyDynamicLoad"), + "--version").start(); + + // Wait until the process enters VMStartCallback + try (InputStream is = child.getInputStream()) { + is.read(); + } + } + + @AfterAll + static void stopChild() throws Exception { + try (OutputStream os = child.getOutputStream()) { + os.write(0); + } + + if (!child.waitFor(5, TimeUnit.SECONDS)) { + child.destroyForcibly(); + throw new AssertionError("Timed out while waiting child process to complete"); + } + + OutputAnalyzer analyzer = new OutputAnalyzer(child); + analyzer.shouldHaveExitValue(0); + } + + @Test + public void virtualMachine() throws Exception { + try { + VirtualMachine vm = VirtualMachine.attach(String.valueOf(child.pid())); + vm.loadAgent("some.jar"); + vm.detach(); + throw new AssertionError("Should have failed with AgentLoadException"); + } catch(AgentLoadException exception) { + if (!exception.getMessage().contains(EXPECTED_MESSAGE)) { + throw new AssertionError("Unexpected error message", exception); + } + } + } + + @Test + public void jcmd() throws Exception { + PidJcmdExecutor executor = new PidJcmdExecutor(String.valueOf(child.pid())); + OutputAnalyzer out = executor.execute("JVMTI.agent_load some.jar"); + + out.shouldHaveExitValue(0); + out.stdoutShouldContain(EXPECTED_MESSAGE); + } +} diff --git a/test/hotspot/jtreg/serviceability/attach/EarlyDynamicLoad/libEarlyDynamicLoad.cpp b/test/hotspot/jtreg/serviceability/attach/EarlyDynamicLoad/libEarlyDynamicLoad.cpp new file mode 100644 index 00000000000..3991926306e --- /dev/null +++ b/test/hotspot/jtreg/serviceability/attach/EarlyDynamicLoad/libEarlyDynamicLoad.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include +#include + +extern "C" { + +static void JNICALL VMStartCallback(jvmtiEnv* jvmti, JNIEnv* env) { + putchar('1'); + fflush(stdout); + getchar(); +} + +JNIEXPORT int Agent_OnLoad(JavaVM* vm, char* options, void* reserved) { + jvmtiEnv* jvmti; + if (vm->GetEnv((void**) &jvmti, JVMTI_VERSION_1_0) != JVMTI_ERROR_NONE) { + fprintf(stderr, "JVMTI error occurred during GetEnv\n"); + return JNI_ERR; + } + + jvmtiEventCallbacks callbacks; + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.VMStart = VMStartCallback; + + if (jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks)) != JVMTI_ERROR_NONE) { + fprintf(stderr, "JVMTI error occurred during SetEventCallbacks\n"); + return JNI_ERR; + } + if (jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_START, nullptr) != JVMTI_ERROR_NONE) { + fprintf(stderr, "JVMTI error occurred during SetEventNotificationMode\n"); + return JNI_ERR; + } + + return JNI_OK; +} + +} diff --git a/test/hotspot/jtreg/serviceability/attach/RemovingUnixDomainSocketTest.java b/test/hotspot/jtreg/serviceability/attach/RemovingUnixDomainSocketTest.java index 3e15b24b5d4..22083ee1334 100644 --- a/test/hotspot/jtreg/serviceability/attach/RemovingUnixDomainSocketTest.java +++ b/test/hotspot/jtreg/serviceability/attach/RemovingUnixDomainSocketTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,7 +67,7 @@ private static void runJCmd(long pid) throws InterruptedException, IOException { "jcmd exitValue = " + out.getExitValue()); out.shouldHaveExitValue(0); - out.stderrShouldBeEmptyIgnoreDeprecatedWarnings(); + out.stderrShouldBeEmptyIgnoreVMWarnings(); } public static void main(String... args) throws Exception { diff --git a/test/hotspot/jtreg/serviceability/dcmd/vm/SystemDumpMapTest.java b/test/hotspot/jtreg/serviceability/dcmd/vm/SystemDumpMapTest.java index 1911862b361..8b8ed0b53ab 100644 --- a/test/hotspot/jtreg/serviceability/dcmd/vm/SystemDumpMapTest.java +++ b/test/hotspot/jtreg/serviceability/dcmd/vm/SystemDumpMapTest.java @@ -36,6 +36,8 @@ * @summary Test of diagnostic command System.map * @library /test/lib * @requires (os.family == "linux" | os.family == "windows" | os.family == "mac") + * @comment ASAN changes the memory map dump slightly, but the test has rather strict requirements + * @requires !vm.asan * @requires os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*") * @modules java.base/jdk.internal.misc * java.compiler diff --git a/test/hotspot/jtreg/serviceability/dcmd/vm/SystemMapTest.java b/test/hotspot/jtreg/serviceability/dcmd/vm/SystemMapTest.java index 283dd4bae72..dcc451d41be 100644 --- a/test/hotspot/jtreg/serviceability/dcmd/vm/SystemMapTest.java +++ b/test/hotspot/jtreg/serviceability/dcmd/vm/SystemMapTest.java @@ -32,6 +32,8 @@ * @summary Test of diagnostic command System.map * @library /test/lib * @requires (vm.gc != "Z") & (os.family == "linux" | os.family == "windows" | os.family == "mac") + * @comment ASAN changes the memory map dump slightly, but the test has rather strict requirements + * @requires !vm.asan * @modules java.base/jdk.internal.misc * java.compiler * java.management @@ -47,6 +49,8 @@ * @summary Test of diagnostic command System.map using ZGC * @library /test/lib * @requires vm.gc.Z & (os.family == "linux" | os.family == "windows" | os.family == "mac") + * @comment ASAN changes the memory map dump slightly, but the test has rather strict requirements + * @requires !vm.asan * @modules java.base/jdk.internal.misc * java.compiler * java.management diff --git a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/ClassVersionAfterRedefine.java b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/ClassVersionAfterRedefine.java index cc601147714..7e571f7703b 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/ClassVersionAfterRedefine.java +++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/ClassVersionAfterRedefine.java @@ -32,68 +32,27 @@ * @run main/othervm -javaagent:redefineagent.jar ClassVersionAfterRedefine */ -import java.io.InputStream; import java.lang.reflect.Method; import static jdk.test.lib.Asserts.assertTrue; public class ClassVersionAfterRedefine extends ClassLoader { - private static String myName = ClassVersionAfterRedefine.class.getName(); - - private static byte[] getBytecodes(String name) throws Exception { - InputStream is = ClassVersionAfterRedefine.class.getResourceAsStream(name + ".class"); - byte[] buf = is.readAllBytes(); - System.out.println("sizeof(" + name + ".class) == " + buf.length); - return buf; - } - - private static int getStringIndex(String needle, byte[] buf) { - return getStringIndex(needle, buf, 0); - } - - private static int getStringIndex(String needle, byte[] buf, int offset) { - outer: - for (int i = offset; i < buf.length - offset - needle.length(); i++) { - for (int j = 0; j < needle.length(); j++) { - if (buf[i + j] != (byte)needle.charAt(j)) continue outer; - } - return i; - } - return 0; - } - - private static void replaceString(byte[] buf, String name, int index) { - for (int i = index; i < index + name.length(); i++) { - buf[i] = (byte)name.charAt(i - index); - } - } - - private static void replaceAllStrings(byte[] buf, String oldString, String newString) throws Exception { - assertTrue(oldString.length() == newString.length(), "must have same length"); - int index = -1; - while ((index = getStringIndex(oldString, buf, index + 1)) != 0) { - replaceString(buf, newString, index); - } - } - public static void main(String[] s) throws Exception { - byte[] buf = getBytecodes("TestClassOld"); - // Poor man's renaming of class "TestClassOld" to "TestClassXXX" - replaceAllStrings(buf, "TestClassOld", "TestClassXXX"); ClassVersionAfterRedefine cvar = new ClassVersionAfterRedefine(); + + byte[] buf = RedefineClassHelper.replaceClassName(cvar, "TestClassOld", "TestClassXXX"); Class old = cvar.defineClass(null, buf, 0, buf.length); Method foo = old.getMethod("foo"); Object result = foo.invoke(null); assertTrue("java-lang-String".equals(result)); System.out.println(old.getSimpleName() + ".foo() = " + result); - buf = getBytecodes("TestClassNew"); // Rename class "TestClassNew" to "TestClassXXX" so we can use it for // redefining the original version of "TestClassXXX" (i.e. "TestClassOld"). - replaceAllStrings(buf, "TestClassNew", "TestClassXXX"); - // Now redine the original version of "TestClassXXX" (i.e. "TestClassOld"). + buf = RedefineClassHelper.replaceClassName(cvar, "TestClassNew", "TestClassXXX"); + // Now redefine the original version of "TestClassXXX" (i.e. "TestClassOld"). RedefineClassHelper.redefineClass(old, buf); result = foo.invoke(null); assertTrue("java.lang.String".equals(result)); diff --git a/test/hotspot/jtreg/serviceability/jvmti/VMEvent/libVMEventTest.c b/test/hotspot/jtreg/serviceability/jvmti/VMEvent/libVMEventTest.c index 56f285aee41..2f532384fa6 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/VMEvent/libVMEventTest.c +++ b/test/hotspot/jtreg/serviceability/jvmti/VMEvent/libVMEventTest.c @@ -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. * Copyright (c) 2018, Google and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -47,12 +47,36 @@ extern "C" { #endif +// JVMTI_ERROR_WRONG_PHASE guard +static jrawMonitorID event_mon = NULL; +static int is_vm_dead = 0; + +void lock(jvmtiEnv *jvmti, JNIEnv *jni) { + jvmtiError err = (*jvmti)->RawMonitorEnter(jvmti, event_mon); + if (err != JVMTI_ERROR_NONE) { + JNI_ENV_PTR(jni)->FatalError(JNI_ENV_ARGS2(jni, "RawMonitorEnter failed")); + } +} + +void unlock(jvmtiEnv *jvmti, JNIEnv *jni) { + jvmtiError err = (*jvmti)->RawMonitorExit(jvmti, event_mon); + if (err != JVMTI_ERROR_NONE) { + JNI_ENV_PTR(jni)->FatalError(JNI_ENV_ARGS2(jni, "RawMonitorExit failed")); + } +} + extern JNIEXPORT void JNICALL VMObjectAlloc(jvmtiEnv *jvmti, JNIEnv* jni, jthread thread, jobject object, jclass klass, jlong size) { + lock(jvmti, jni); + if (is_vm_dead) { + unlock(jvmti, jni); + return; + } + char *signature = NULL; jvmtiError error = (*jvmti)->GetClassSignature(jvmti, klass, &signature, NULL); @@ -78,25 +102,40 @@ extern JNIEXPORT void JNICALL VMObjectAlloc(jvmtiEnv *jvmti, JNI_ENV_ARGS2(jni, "Failed during the CallObjectMethod call")); } } + unlock(jvmti, jni); } extern JNIEXPORT void JNICALL OnVMInit(jvmtiEnv *jvmti, JNIEnv *jni, jthread thread) { (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_OBJECT_ALLOC, NULL); } +extern JNIEXPORT void JNICALL OnVMDeath(jvmtiEnv *jvmti, JNIEnv *jni) { + lock(jvmti, jni); + is_vm_dead = 1; + unlock(jvmti, jni); +} + extern JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) { jvmtiEnv *jvmti; jvmtiEventCallbacks callbacks; jvmtiCapabilities caps; + jvmtiError err; if ((*jvm)->GetEnv(jvm, (void **) (&jvmti), JVMTI_VERSION) != JNI_OK) { return JNI_ERR; } + err = (*jvmti)->CreateRawMonitor(jvmti, "Event Monitor", &event_mon); + if (err != JVMTI_ERROR_NONE) { + printf("CreateRawMonitor failed: %d\n", err); + return JNI_ERR; + } + memset(&callbacks, 0, sizeof(callbacks)); callbacks.VMObjectAlloc = &VMObjectAlloc; callbacks.VMInit = &OnVMInit; + callbacks.VMDeath = &OnVMDeath; memset(&caps, 0, sizeof(caps)); caps.can_generate_vm_object_alloc_events = 1; @@ -104,6 +143,7 @@ extern JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(jvmtiEventCallbacks)); (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL); + (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, NULL); return 0; } diff --git a/test/hotspot/jtreg/serviceability/jvmti/thread/GetCurrentContendedMonitor/contmon01/contmon01.java b/test/hotspot/jtreg/serviceability/jvmti/thread/GetCurrentContendedMonitor/contmon01/contmon01.java index 5bc4d4fd2b2..a4912c7e6d2 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/thread/GetCurrentContendedMonitor/contmon01/contmon01.java +++ b/test/hotspot/jtreg/serviceability/jvmti/thread/GetCurrentContendedMonitor/contmon01/contmon01.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -154,9 +154,9 @@ public void run() { System.out.println("check #2 done"); System.out.println("notifying main thread"); + System.out.println("thread is going to loop while is true ..."); contmon01.startingBarrier = false; - System.out.println("thread is going to loop while is true ..."); int i = 0; int n = 1000; while (flag) { diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackXcompStress.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackXcompStress.java index 7e06cb3af95..0a930485b6d 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackXcompStress.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackXcompStress.java @@ -75,7 +75,7 @@ private static void runJstackInLoop(LingeredApp app) throws Exception { System.err.println(out.getStderr()); } - out.stderrShouldBeEmptyIgnoreDeprecatedWarnings(); + out.stderrShouldBeEmptyIgnoreVMWarnings(); out.stdoutShouldNotContain("Error occurred during stack walking:"); out.stdoutShouldContain(LingeredAppWithRecComputation.THREAD_NAME); List stdoutList = Arrays.asList(out.getStdout().split("\\R")); diff --git a/test/hotspot/jtreg/serviceability/sa/JhsdbThreadInfoTest.java b/test/hotspot/jtreg/serviceability/sa/JhsdbThreadInfoTest.java index 798de679d7c..75942f7113a 100644 --- a/test/hotspot/jtreg/serviceability/sa/JhsdbThreadInfoTest.java +++ b/test/hotspot/jtreg/serviceability/sa/JhsdbThreadInfoTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,7 +70,7 @@ public static void main(String[] args) throws Exception { out.shouldNotContain(" prio=0 "); out.shouldNotContain(" java.lang.Thread.State: UNKNOWN"); - out.stderrShouldBeEmptyIgnoreDeprecatedWarnings(); + out.stderrShouldBeEmptyIgnoreVMWarnings(); System.out.println("Test Completed"); } catch (Exception ex) { diff --git a/test/hotspot/jtreg/serviceability/sa/LingeredAppWithVirtualThread.java b/test/hotspot/jtreg/serviceability/sa/LingeredAppWithVirtualThread.java new file mode 100644 index 00000000000..ca98506e133 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/sa/LingeredAppWithVirtualThread.java @@ -0,0 +1,87 @@ + +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, NTT DATA + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.invoke.MethodHandle; +import java.lang.foreign.Arena; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.Linker; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SymbolLookup; +import java.lang.foreign.ValueLayout; +import java.util.concurrent.CountDownLatch; + +import jdk.test.lib.apps.LingeredApp; + +public class LingeredAppWithVirtualThread extends LingeredApp implements Runnable { + + private static final String THREAD_NAME = "target thread"; + + private static final MethodHandle hndSleep; + + private static final int sleepArg; + + private static final CountDownLatch signal = new CountDownLatch(1); + + static { + MemorySegment func; + if (System.getProperty("os.name").startsWith("Windows")) { + func = SymbolLookup.libraryLookup("Kernel32", Arena.global()) + .findOrThrow("Sleep"); + sleepArg = 3600_000; // 1h in milliseconds + } else { + func = Linker.nativeLinker() + .defaultLookup() + .findOrThrow("sleep"); + sleepArg = 3600; // 1h in seconds + } + + var desc = FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.JAVA_INT); + hndSleep = Linker.nativeLinker().downcallHandle(func, desc); + } + + @Override + public void run() { + Thread.yield(); + signal.countDown(); + try { + hndSleep.invoke(sleepArg); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + + public static void main(String[] args) { + try { + Thread.ofVirtual() + .name(THREAD_NAME) + .start(new LingeredAppWithVirtualThread()); + + signal.await(); + LingeredApp.main(args); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLock.java b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLock.java index 8d5c95721d5..ac536523815 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLock.java +++ b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,7 +68,7 @@ public static void main (String... args) throws Exception { out.shouldMatch("^\\s+- locked <0x[0-9a-f]+> \\(a java\\.lang\\.Class for int\\)$"); out.shouldMatch("^\\s+- waiting on (<0x[0-9a-f]+> \\(a java\\.lang\\.Object\\)|)$"); - out.stderrShouldBeEmptyIgnoreDeprecatedWarnings(); + out.stderrShouldBeEmptyIgnoreVMWarnings(); System.out.println("Test Completed"); } finally { diff --git a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackWithVirtualThread.java b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackWithVirtualThread.java new file mode 100644 index 00000000000..39b6e1ed609 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackWithVirtualThread.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, NTT DATA + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import jdk.test.lib.JDKToolLauncher; +import jdk.test.lib.SA.SATestUtils; +import jdk.test.lib.Utils; +import jdk.test.lib.apps.LingeredApp; +import jdk.test.lib.process.OutputAnalyzer; + +/** + * @test + * @bug 8369505 + * @requires vm.hasSA + * @library /test/lib + * @run driver TestJhsdbJstackWithVirtualThread + */ +public class TestJhsdbJstackWithVirtualThread { + + private static void runJstack(LingeredApp app) throws Exception { + JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb"); + launcher.addVMArgs(Utils.getFilteredTestJavaOpts("-showversion")); + launcher.addToolArg("jstack"); + launcher.addToolArg("--pid"); + launcher.addToolArg(Long.toString(app.getPid())); + + ProcessBuilder pb = SATestUtils.createProcessBuilder(launcher); + Process jhsdb = pb.start(); + OutputAnalyzer out = new OutputAnalyzer(jhsdb); + + jhsdb.waitFor(); + + System.out.println(out.getStdout()); + System.err.println(out.getStderr()); + + out.stderrShouldBeEmptyIgnoreVMWarnings(); + out.shouldNotContain("must have non-zero frame size"); + } + + public static void main(String... args) throws Exception { + SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work. + LingeredApp app = null; + + try { + app = new LingeredAppWithVirtualThread(); + LingeredApp.startApp(app); + System.out.println("Started LingeredApp with pid " + app.getPid()); + runJstack(app); + System.out.println("Test Completed"); + } catch (Throwable e) { + e.printStackTrace(); + throw e; + } finally { + LingeredApp.stopApp(app); + } + } +} diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/GarbageProducerTest.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/GarbageProducerTest.java index dfe1a8f12dc..933f2b86ff5 100644 --- a/test/hotspot/jtreg/serviceability/tmtools/jstat/GarbageProducerTest.java +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/GarbageProducerTest.java @@ -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 @@ -25,6 +25,7 @@ import utils.GarbageProducer; import common.TmTool; import utils.JstatResults; +import utils.JstatGcCauseTool; /** * Base class for jstat testing which uses GarbageProducer to allocate garbage. @@ -36,19 +37,19 @@ public class GarbageProducerTest { private final static float TARGET_MEMORY_USAGE = 0.7f; private final static float MEASUREMENT_TOLERANCE = 0.05f; private final GarbageProducer garbageProducer; - private final TmTool jstatTool; + private final JstatGcCauseTool jstatTool; - public GarbageProducerTest(TmTool tool) { + public GarbageProducerTest(JstatGcCauseTool tool) { garbageProducer = new GarbageProducer(TARGET_MEMORY_USAGE); // We will be running jstat tool jstatTool = tool; } public void run() throws Exception { - // Run once and get the results asserting that they are reasonable - JstatResults measurement1 = jstatTool.measure(); - measurement1.assertConsistency(); - // Eat metaspace and heap then run the tool again and get the results asserting that they are reasonable + // Run once and get the results asserting that they are reasonable + JstatResults measurement1 = jstatTool.measureAndAssertConsistency(); + + // Eat metaspace and heap then run the tool again and get the results, asserting that they are reasonable System.gc(); garbageProducer.allocateMetaspaceAndHeap(); // Collect garbage. Also update VM statistics diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/GcNewTest.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/GcNewTest.java index abe80074770..52bc41c3fe3 100644 --- a/test/hotspot/jtreg/serviceability/tmtools/jstat/GcNewTest.java +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/GcNewTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, 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 @@ -44,15 +44,13 @@ public static void main(String[] args) throws Exception { JstatGcNewTool jstatGcTool = new JstatGcNewTool(ProcessHandle.current().pid()); // Run once and get the results asserting that they are reasonable - JstatGcNewResults measurement1 = jstatGcTool.measure(); - measurement1.assertConsistency(); + JstatGcNewResults measurement1 = jstatGcTool.measureAndAssertConsistency(); GcProvoker gcProvoker = new GcProvoker(); // Provoke GC and run the tool again gcProvoker.provokeGc(); - JstatGcNewResults measurement2 = jstatGcTool.measure(); - measurement2.assertConsistency(); + JstatGcNewResults measurement2 = jstatGcTool.measureAndAssertConsistency(); // Assert the increase in GC events and time between the measurements assertThat(measurement2.getFloatValue("YGC") > measurement1.getFloatValue("YGC"), "YGC didn't increase between measurements 1 and 2"); @@ -60,8 +58,7 @@ public static void main(String[] args) throws Exception { // Provoke GC and run the tool again gcProvoker.provokeGc(); - JstatGcNewResults measurement3 = jstatGcTool.measure(); - measurement3.assertConsistency(); + JstatGcNewResults measurement3 = jstatGcTool.measureAndAssertConsistency(); // Assert the increase in GC events and time between the measurements assertThat(measurement3.getFloatValue("YGC") > measurement2.getFloatValue("YGC"), "YGC didn't increase between measurements 1 and 2"); diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/GcTest01.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/GcTest01.java index 74ac7132109..6d062d4fee5 100644 --- a/test/hotspot/jtreg/serviceability/tmtools/jstat/GcTest01.java +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/GcTest01.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, 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 @@ -47,17 +47,15 @@ public static void main(String[] args) throws Exception { // We will be running "jstat -gc" tool JstatGcTool jstatGcTool = new JstatGcTool(ProcessHandle.current().pid()); - // Run once and get the results asserting that they are reasonable - JstatGcResults measurement1 = jstatGcTool.measure(); - measurement1.assertConsistency(); + // Run once and get the results asserting that they are reasonable + JstatGcResults measurement1 = jstatGcTool.measureAndAssertConsistency(); GcProvoker gcProvoker = new GcProvoker(); // Provoke GC then run the tool again and get the results // asserting that they are reasonable gcProvoker.provokeGc(); - JstatGcResults measurement2 = jstatGcTool.measure(); - measurement2.assertConsistency(); + JstatGcResults measurement2 = jstatGcTool.measureAndAssertConsistency(); // Assert the increase in GC events and time between the measurements JstatResults.assertGCEventsIncreased(measurement1, measurement2); @@ -66,13 +64,10 @@ public static void main(String[] args) throws Exception { // Provoke GC again and get the results // asserting that they are reasonable gcProvoker.provokeGc(); - JstatGcResults measurement3 = jstatGcTool.measure(); - measurement3.assertConsistency(); + JstatGcResults measurement3 = jstatGcTool.measureAndAssertConsistency(); // Assert the increase in GC events and time between the measurements JstatResults.assertGCEventsIncreased(measurement2, measurement3); JstatResults.assertGCTimeIncreased(measurement2, measurement3); - } - } diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/GcTest02.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/GcTest02.java index 0a3102625d6..c223a09ba45 100644 --- a/test/hotspot/jtreg/serviceability/tmtools/jstat/GcTest02.java +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/GcTest02.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, 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 @@ -42,6 +42,6 @@ public class GcTest02 { public static void main(String[] args) throws Exception { - new GarbageProducerTest(new JstatGcTool(ProcessHandle.current().pid())).run(); + new GarbageProducerTest(new JstatGcCauseTool(ProcessHandle.current().pid())).run(); } } diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCapacityTool.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCapacityTool.java index 74cffa150ce..0fb24bbd109 100644 --- a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCapacityTool.java +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCapacityTool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 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 @@ -28,10 +28,9 @@ * This tool executes "jstat -gccapacity " and returns the results as * JstatGcCapacityoolResults */ -public class JstatGcCapacityTool extends TmTool { +public class JstatGcCapacityTool extends JstatTool { public JstatGcCapacityTool(long pid) { super(JstatGcCapacityResults.class, "jstat", "-gccapacity " + pid); } - } diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCauseTool.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCauseTool.java index c0dd36d8abb..65bea8d36bd 100644 --- a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCauseTool.java +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCauseTool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 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 @@ -28,10 +28,9 @@ * This tool executes "jstat -gc " and returns the results as * JstatGcToolResults */ -public class JstatGcCauseTool extends TmTool { +public class JstatGcCauseTool extends JstatTool { public JstatGcCauseTool(long pid) { super(JstatGcCauseResults.class, "jstat", "-gc " + pid); } - } diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcNewTool.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcNewTool.java index ed3f20a6c20..7bea437cb28 100644 --- a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcNewTool.java +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcNewTool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 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 @@ -28,10 +28,9 @@ * This tool executes "jstat -gcnew " and returns the results as * JstatGcNewResults */ -public class JstatGcNewTool extends TmTool { +public class JstatGcNewTool extends JstatTool { public JstatGcNewTool(long pid) { super(JstatGcNewResults.class, "jstat", "-gcnew " + pid); } - } diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcTool.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcTool.java index e046768a46f..f4f86038906 100644 --- a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcTool.java +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcTool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 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 @@ -28,10 +28,9 @@ * This tool executes "jstat -gc " and returns the results as * JstatGcToolResults */ -public class JstatGcTool extends TmTool { +public class JstatGcTool extends JstatTool { public JstatGcTool(long pid) { super(JstatGcResults.class, "jstat", "-gc " + pid); } - } diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatResults.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatResults.java index 97368d89b3a..01425d4c5b6 100644 --- a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatResults.java +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatResults.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, 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 @@ -31,7 +31,7 @@ * Results of running the jstat tool Concrete subclasses will detail the jstat * tool options */ -abstract public class JstatResults extends ToolResults { +public abstract class JstatResults extends ToolResults { private static final float FLOAT_COMPARISON_TOLERANCE = 0.0011f; @@ -181,5 +181,5 @@ public static boolean checkFloatIsSum(float sum, float... floats) { return Math.abs(sum) <= FLOAT_COMPARISON_TOLERANCE; } - abstract public void assertConsistency(); + public abstract void assertConsistency(); } diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatTool.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatTool.java new file mode 100644 index 00000000000..404581b1ae7 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatTool.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package utils; + +import common.TmTool; + +/** + * Common base class for Jstat tools. + */ +public class JstatTool extends TmTool { + + private static final int TRIES = 3; + + public JstatTool(Class resultsClz, String toolName, String otherArgs) { + super(resultsClz, toolName, otherArgs); + } + + /** + * Measure, and call assertConsistency() on the results, + * tolerating a set number of failures to account for inconsistencies in PerfData. + */ + public T measureAndAssertConsistency() throws Exception { + T results = null; + for (int i = 1; i <= TRIES; i++) { + try { + results = measure(); + results.assertConsistency(); + } catch (RuntimeException e) { + System.out.println("Attempt " + i + ": " + e); + if (i == TRIES) { + System.out.println("Too many failures."); + throw(e); + } + // Will retry. + } + } + return results; + } +} diff --git a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java index b8f2919e594..0ff9cae8169 100644 --- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java +++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java @@ -28,7 +28,9 @@ import jdk.internal.reflect.ConstantPool; import jdk.test.whitebox.WhiteBox; +import java.lang.reflect.Constructor; import java.lang.reflect.Executable; +import java.lang.reflect.Method; import java.util.Arrays; import java.util.Objects; import java.util.concurrent.Executor; @@ -79,26 +81,53 @@ public static void compileClass(Class aClass, long id, Executor executor) { preloadClasses(aClass.getName(), id, constantPool); } - // Make sure the class is initialized. - UNSAFE.ensureClassInitialized(aClass); + // Attempt to initialize the class. If initialization is not possible + // due to NCDFE, accept this, and try compile anyway. + try { + UNSAFE.ensureClassInitialized(aClass); + } catch (NoClassDefFoundError e) { + CompileTheWorld.OUT.printf("[%d]\t%s\tNOTE unable to init class : %s%n", + id, aClass.getName(), e); + } compileClinit(aClass, id); + // Getting constructor/methods with unresolvable signatures would fail with NCDFE. + // Try to get as much as possible, and compile everything else. + // TODO: Would be good to have a Whitebox method that returns the subset of resolvable + // constructors/methods without throwing NCDFE. This would extend the testing scope. + Constructor[] constructors = new Constructor[0]; + Method[] methods = new Method[0]; + + try { + constructors = aClass.getDeclaredConstructors(); + } catch (NoClassDefFoundError e) { + CompileTheWorld.OUT.printf("[%d]\t%s\tNOTE unable to get constructors : %s%n", + id, aClass.getName(), e); + } + + try { + methods = aClass.getDeclaredMethods(); + } catch (NoClassDefFoundError e) { + CompileTheWorld.OUT.printf("[%d]\t%s\tNOTE unable to get methods : %s%n", + id, aClass.getName(), e); + } + // Populate profile for all methods to expand the scope of // compiler optimizations. Do this before compilations start. - for (Executable e : aClass.getDeclaredConstructors()) { + for (Executable e : constructors) { WHITE_BOX.markMethodProfiled(e); } - for (Executable e : aClass.getDeclaredMethods()) { + for (Executable e : methods) { WHITE_BOX.markMethodProfiled(e); } // Now schedule the compilations. long methodCount = 0; - for (Executable e : aClass.getDeclaredConstructors()) { + for (Executable e : constructors) { ++methodCount; executor.execute(new CompileMethodCommand(id, e)); } - for (Executable e : aClass.getDeclaredMethods()) { + for (Executable e : methods) { ++methodCount; executor.execute(new CompileMethodCommand(id, e)); } @@ -127,9 +156,12 @@ private static void preloadClasses(String className, long id, if (constantPool.getTagAt(i) == ConstantPool.Tag.CLASS) { constantPool.getClassAt(i); } + } catch (NoClassDefFoundError e) { + CompileTheWorld.OUT.printf("[%d]\t%s\tNOTE unable to preload : %s%n", + id, className, e); } catch (Throwable t) { - CompileTheWorld.OUT.println(String.format("[%d]\t%s\tWARNING preloading failed : %s", - id, className, t)); + CompileTheWorld.OUT.printf("[%d]\t%s\tWARNING preloading failed : %s%n", + id, className, t); t.printStackTrace(CompileTheWorld.ERR); } } @@ -170,17 +202,22 @@ public CompileMethodCommand(long classId, Executable method) { @Override public final void run() { + // Make sure method is not compiled at any level before starting + // progressive compilations. No deopt in-between tiers is needed, + // as long as we increase the compilation levels one by one. + WHITE_BOX.deoptimizeMethod(method); + int compLevel = Utils.INITIAL_COMP_LEVEL; if (Utils.TIERED_COMPILATION) { for (int i = compLevel; i <= Utils.TIERED_STOP_AT_LEVEL; ++i) { - WHITE_BOX.deoptimizeMethod(method); compileAtLevel(i); } } else { compileAtLevel(compLevel); } - // Make the method eligible for sweeping sooner + // Ditch all the compiled versions of the code, make the method + // eligible for sweeping sooner. WHITE_BOX.deoptimizeMethod(method); } diff --git a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java index 573b70faabe..1d93520c110 100644 --- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java +++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java @@ -292,6 +292,8 @@ private String[] cmd(long classStart, long classStop) { "--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED", "--add-exports", "java.base/jdk.internal.reflect=ALL-UNNAMED", "--add-exports", "java.base/jdk.internal.access=ALL-UNNAMED", + // Graphics clinits may run, force headless mode + "-Djava.awt.headless=true", // enable diagnostic logging "-XX:+LogCompilation", // use phase specific log, hs_err and ciReplay files @@ -308,6 +310,8 @@ private String[] cmd(long classStart, long classStop) { // Do not pay extra stack trace generation cost for normally thrown exceptions "-XX:-StackTraceInThrowable", "-XX:+IgnoreUnrecognizedVMOptions", + // Do not pay extra for verifying inline caches during nmethod cleanups + "-XX:-VerifyInlineCaches", // Do not pay extra zapping cost for explicit GC invocations "-XX:-ZapUnusedHeapArea", // Stress* are c2-specific stress flags, so IgnoreUnrecognizedVMOptions is needed diff --git a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java index 5e36cf0f7f9..a31098a055c 100644 --- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java +++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java @@ -245,9 +245,12 @@ protected final void processClass(String name, Executor executor) { CompileTheWorld.OUT.println(String.format("[%d]\t%s", id, name)); aClass = entry.loader().loadClass(name); Compiler.compileClass(aClass, id, executor); + } catch (NoClassDefFoundError e) { + CompileTheWorld.OUT.printf("[%d]\t%s\tNOTE unable to load/compile, skipped: %s%n", + id, name, e); } catch (Throwable e) { - CompileTheWorld.OUT.println(String.format("[%d]\t%s\tWARNING skipped: %s", - id, name, e)); + CompileTheWorld.OUT.printf("[%d]\t%s\tWARNING skipped: %s%n", + id, name, e); e.printStackTrace(CompileTheWorld.ERR); } } diff --git a/test/hotspot/jtreg/testlibrary_tests/generators/tests/TestGenerators.java b/test/hotspot/jtreg/testlibrary_tests/generators/tests/TestGenerators.java index 8ad0c17ba98..f949f99c035 100644 --- a/test/hotspot/jtreg/testlibrary_tests/generators/tests/TestGenerators.java +++ b/test/hotspot/jtreg/testlibrary_tests/generators/tests/TestGenerators.java @@ -391,13 +391,13 @@ static void testEmptyGenerators() { Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformDoubles(1, 0)); Asserts.assertNotNull(G.uniformDoubles(0, 1)); - Asserts.assertNotNull(G.uniformDoubles(0, 0)); + Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformDoubles(0, 0)); Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformDoubles(0, 1).restricted(1.1d, 2.4d)); Asserts.assertNotNull(G.uniformDoubles(0, 1).restricted(0.9d, 2.4d)); Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformFloats(1, 0)); Asserts.assertNotNull(G.uniformFloats(0, 1)); - Asserts.assertNotNull(G.uniformFloats(0, 0)); + Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformFloats(0, 0)); Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformFloats(0, 1).restricted(1.1f, 2.4f)); Asserts.assertNotNull(G.uniformFloats(0, 1).restricted(0.9f, 2.4f)); @@ -592,8 +592,13 @@ static void testFuzzy() { var floatBoundGen = G.uniformFloats(); for (int j = 0; j < 500; j++) { - float a = floatBoundGen.next(), b = floatBoundGen.next(); - float lo = Math.min(a, b), hi = Math.max(a, b); + float lo = 1, hi = 0; + // Failure of a single round is very rare, repeated failure even rarer. + while (lo >= hi) { + float a = floatBoundGen.next(), b = floatBoundGen.next(); + lo = Math.min(a, b); + hi = Math.max(a, b); + } var gb = G.uniformFloats(lo, hi); for (int i = 0; i < 10_000; i++) { float x = gb.next(); @@ -604,8 +609,13 @@ static void testFuzzy() { var doubleBoundGen = G.uniformDoubles(); for (int j = 0; j < 500; j++) { - double a = doubleBoundGen.next(), b = doubleBoundGen.next(); - double lo = Math.min(a, b), hi = Math.max(a, b); + double lo = 1, hi = 0; + // Failure of a single round is very rare, repeated failure even rarer. + while (lo >= hi) { + double a = doubleBoundGen.next(), b = doubleBoundGen.next(); + lo = Math.min(a, b); + hi = Math.max(a, b); + } var gb = G.uniformDoubles(lo, hi); for (int i = 0; i < 10_000; i++) { double x = gb.next(); diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestBadFormat.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestBadFormat.java index ac8867f3985..a33aacd924e 100644 --- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestBadFormat.java +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestBadFormat.java @@ -1124,8 +1124,8 @@ public void wrongCountString() {} @Test @FailCount(8) - @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0"}) - @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_MAX, "> 0"}) // valid + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0"}, applyIf = {"MaxVectorSize", "> 0"}) // valid, but only if MaxVectorSize > 0, otherwise, a violation is reported + @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_MAX, "> 0"}, applyIf = {"MaxVectorSize", "> 0"}) // valid, but only if MaxVectorSize > 0, otherwise, a violation is reported @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_ANY, "> 0"}) // valid @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE + "", "> 0"}) @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE + "xxx", "> 0"}) diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRMatching.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRMatching.java index 69690ae8e60..c7f8badf83b 100644 --- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRMatching.java +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRMatching.java @@ -125,6 +125,12 @@ public static void main(String[] args) { GoodFailOnConstraint.create(AllocInstance.class, "allocInstance()", 10) ); + runCheck( + BadFailOnConstraint.create(AllocInstance.class, "allocNested()", 1), + BadFailOnConstraint.create(AllocInstance.class, "allocNested()", 2), + BadFailOnConstraint.create(AllocInstance.class, "allocNested()", 3) + ); + runCheck(BadFailOnConstraint.create(AllocArray.class, "allocArray()", 1), BadFailOnConstraint.create(AllocArray.class, "allocArray()", 2), GoodFailOnConstraint.create(AllocArray.class, "allocArray()", 3), @@ -963,6 +969,13 @@ class AllocInstance { public void allocInstance() { myClass = new MyClass(); } + + static class Nested {} + @Test + @IR(failOn = {IRNode.ALLOC_OF, "Nested"}) + @IR(failOn = {IRNode.ALLOC_OF, "AllocInstance\\$Nested"}) + @IR(failOn = {IRNode.ALLOC_OF, "AllocInst\\w+\\$Nested"}) + public Nested allocNested() { return new Nested(); } } class AllocArray { diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java index a2d98d00502..fe21dce73b5 100644 --- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java @@ -60,6 +60,7 @@ public class TestPhaseIRMatching { public static void main(String[] args) { run(Basics.class); run(NoCompilationOutput.class); + run(LoadStore.class); } private static void run(Class testClass) { @@ -549,3 +550,239 @@ public static List sort(Set failures) { .thenComparing(Failure::constraintId)).collect(Collectors.toList()); } } + +// Test load and store regexes +class LoadStore { + int i; + float f; + interface I1 {} + static class Base implements I1 { + int i; + } + interface I2 {} + static class Derived extends Base implements I2 { + long l; + } + Base base = new Base(); + Derived derived = new Derived(); + + static class SingleNest { + static class DoubleNest { + int i; + } + } + + SingleNest.DoubleNest doubleNest = new SingleNest.DoubleNest(); + + + @Test + @IR(failOn = {IRNode.LOAD_OF_CLASS, ".*", IRNode.STORE_OF_CLASS, ".*"}) + public void triviallyFailBoth() { + } + + @Test + @IR(counts = { + IRNode.LOAD_OF_CLASS, "LoadS[a-z]+", "1", + IRNode.LOAD_OF_CLASS, "Load.tore", "1", + IRNode.LOAD_OF_CLASS, "LoadStore", "1", + IRNode.LOAD_OF_CLASS, "/LoadStore", "1", + IRNode.LOAD_OF_CLASS, "tests/LoadStore", "1", + IRNode.LOAD_OF_CLASS, "/tests/LoadStore", "1", + IRNode.LOAD_OF_CLASS, "ir_framework/tests/LoadStore", "1", + IRNode.LOAD_OF_CLASS, "(?<=[@: ])ir_framework/tests/LoadStore", "1", // To assert it's the whole qualification + IRNode.LOAD_OF_CLASS, "(?<=[@: ])[\\w\\$/]*tests[\\w\\$/]*", "1", + }, + failOn = { + IRNode.LOAD_OF_CLASS, "oadStore", + IRNode.LOAD_OF_CLASS, "LoadStor", + IRNode.LOAD_OF_CLASS, "/ir_framework/tests/LoadStore", + IRNode.LOAD_OF_CLASS, "(?<=[@: ])[\\w\\$]*tests[\\w\\$]*", + } + ) + // @ir_framework/tests/LoadStore+12 * + public float simpleLoad() { + return f; + } + + @Test + @IR(counts = { + IRNode.STORE_OF_CLASS, "LoadS[a-z]+", "1", + IRNode.STORE_OF_CLASS, "Load.tore", "1", + IRNode.STORE_OF_CLASS, "LoadStore", "1", + IRNode.STORE_OF_CLASS, "/LoadStore", "1", + IRNode.STORE_OF_CLASS, "tests/LoadStore", "1", + IRNode.STORE_OF_CLASS, "/tests/LoadStore", "1", + IRNode.STORE_OF_CLASS, "ir_framework/tests/LoadStore", "1", + IRNode.STORE_OF_CLASS, "(?<=[@: ])ir_framework/tests/LoadStore", "1", + IRNode.STORE_OF_CLASS, "(?<=[@: ])[\\w\\$/]*tests[\\w\\$/]*", "1", + }, + failOn = { + IRNode.STORE_OF_CLASS, "oadStore", + IRNode.STORE_OF_CLASS, "LoadStor", + IRNode.STORE_OF_CLASS, "/ir_framework/tests/LoadStore", + IRNode.STORE_OF_CLASS, "(?<=[@: ])[\\w\\$]*tests[\\w\\$]*", + } + ) + // @ir_framework/tests/LoadStore+12 * + public void simpleStore() { + i = 1; + } + + @Test + @IR(counts = { + IRNode.LOAD_I_OF_CLASS, "Base", "1", + IRNode.LOAD_I_OF_CLASS, "\\$Base", "1", + IRNode.LOAD_I_OF_CLASS, "LoadS[a-z]+\\$Base", "1", + IRNode.LOAD_I_OF_CLASS, "Load.tore\\$Base", "1", + IRNode.LOAD_I_OF_CLASS, "LoadStore\\$Base", "1", + IRNode.LOAD_I_OF_CLASS, "/LoadStore\\$Base", "1", + IRNode.LOAD_I_OF_CLASS, "tests/LoadStore\\$Base", "1", + IRNode.LOAD_I_OF_CLASS, "/tests/LoadStore\\$Base", "1", + IRNode.LOAD_I_OF_CLASS, "ir_framework/tests/LoadStore\\$Base", "1", + IRNode.LOAD_I_OF_CLASS, "(?<=[@: ])ir_framework/tests/LoadStore\\$Base", "1", + IRNode.LOAD_I_OF_CLASS, "(?<=[@: ])[\\w\\$/]*tests[\\w\\$/]*", "1", + }, + failOn = { + IRNode.LOAD_I_OF_CLASS, "/Base", + IRNode.LOAD_I_OF_CLASS, "oadStore\\$Base", + IRNode.LOAD_I_OF_CLASS, "LoadStore\\$Bas", + IRNode.LOAD_I_OF_CLASS, "LoadStore", + IRNode.LOAD_I_OF_CLASS, "/ir_framework/tests/LoadStore\\$Base", + IRNode.LOAD_I_OF_CLASS, "(?<=[@: ])[\\w\\$]*tests[\\w\\$]*", + } + ) + // @ir_framework/tests/LoadStore$Base (ir_framework/tests/LoadStore$I1)+12 * + public int loadWithInterface() { + return base.i; + } + + @Test + @IR(counts = { + IRNode.STORE_I_OF_CLASS, "Base", "1", + IRNode.STORE_I_OF_CLASS, "\\$Base", "1", + IRNode.STORE_I_OF_CLASS, "LoadS[a-z]+\\$Base", "1", + IRNode.STORE_I_OF_CLASS, "Load.tore\\$Base", "1", + IRNode.STORE_I_OF_CLASS, "LoadStore\\$Base", "1", + IRNode.STORE_I_OF_CLASS, "/LoadStore\\$Base", "1", + IRNode.STORE_I_OF_CLASS, "tests/LoadStore\\$Base", "1", + IRNode.STORE_I_OF_CLASS, "/tests/LoadStore\\$Base", "1", + IRNode.STORE_I_OF_CLASS, "ir_framework/tests/LoadStore\\$Base", "1", + IRNode.STORE_I_OF_CLASS, "(?<=[@: ])ir_framework/tests/LoadStore\\$Base", "1", + IRNode.STORE_I_OF_CLASS, "(?<=[@: ])[\\w\\$/]*tests[\\w\\$/]*", "1", + }, + failOn = { + IRNode.STORE_I_OF_CLASS, "/Base", + IRNode.STORE_I_OF_CLASS, "oadStore\\$Base", + IRNode.STORE_I_OF_CLASS, "LoadStore\\$Bas", + IRNode.STORE_I_OF_CLASS, "LoadStore", + IRNode.STORE_I_OF_CLASS, "/ir_framework/tests/LoadStore\\$Base", + IRNode.STORE_I_OF_CLASS, "(?<=[@: ])[\\w\\$]*tests[\\w\\$]*", + } + ) + // @ir_framework/tests/LoadStore$Base (ir_framework/tests/LoadStore$I1)+12 * + public void storeWithInterface() { + base.i = 1; + } + + @Test + @IR(counts = { + IRNode.LOAD_L_OF_CLASS, "Derived", "1", + IRNode.LOAD_L_OF_CLASS, "\\$Derived", "1", + IRNode.LOAD_L_OF_CLASS, "LoadS[a-z]+\\$Derived", "1", + IRNode.LOAD_L_OF_CLASS, "Load.tore\\$Derived", "1", + IRNode.LOAD_L_OF_CLASS, "LoadStore\\$Derived", "1", + IRNode.LOAD_L_OF_CLASS, "/LoadStore\\$Derived", "1", + IRNode.LOAD_L_OF_CLASS, "tests/LoadStore\\$Derived", "1", + IRNode.LOAD_L_OF_CLASS, "/tests/LoadStore\\$Derived", "1", + IRNode.LOAD_L_OF_CLASS, "ir_framework/tests/LoadStore\\$Derived", "1", + IRNode.LOAD_L_OF_CLASS, "(?<=[@: ])ir_framework/tests/LoadStore\\$Derived", "1", + IRNode.LOAD_L_OF_CLASS, "(?<=[@: ])[\\w\\$/]*tests[\\w\\$/]*", "1", + }, + failOn = { + IRNode.LOAD_L_OF_CLASS, "/Derived", + IRNode.LOAD_L_OF_CLASS, "oadStore\\$Derived", + IRNode.LOAD_L_OF_CLASS, "LoadStore\\$Derive", + IRNode.LOAD_L_OF_CLASS, "LoadStore", + IRNode.LOAD_L_OF_CLASS, "/ir_framework/tests/LoadStore\\$Derived", + IRNode.LOAD_L_OF_CLASS, "(?<=[@: ])[\\w\\$]*tests[\\w\\$]*", + } + ) + // @ir_framework/tests/LoadStore$Derived (ir_framework/tests/LoadStore$I1,ir_framework/tests/LoadStore$I2)+24 * + public long loadWithInterfaces() { + return derived.l; + } + + @Test + @IR(counts = { + IRNode.STORE_L_OF_CLASS, "Derived", "1", + IRNode.STORE_L_OF_CLASS, "\\$Derived", "1", + IRNode.STORE_L_OF_CLASS, "LoadS[a-z]+\\$Derived", "1", + IRNode.STORE_L_OF_CLASS, "Load.tore\\$Derived", "1", + IRNode.STORE_L_OF_CLASS, "LoadStore\\$Derived", "1", + IRNode.STORE_L_OF_CLASS, "/LoadStore\\$Derived", "1", + IRNode.STORE_L_OF_CLASS, "tests/LoadStore\\$Derived", "1", + IRNode.STORE_L_OF_CLASS, "/tests/LoadStore\\$Derived", "1", + IRNode.STORE_L_OF_CLASS, "ir_framework/tests/LoadStore\\$Derived", "1", + IRNode.STORE_L_OF_CLASS, "(?<=[@: ])ir_framework/tests/LoadStore\\$Derived", "1", + IRNode.STORE_L_OF_CLASS, "(?<=[@: ])[\\w\\$/]*tests[\\w\\$/]*", "1", + }, + failOn = { + IRNode.STORE_L_OF_CLASS, "/Derived", + IRNode.STORE_L_OF_CLASS, "oadStore\\$Derived", + IRNode.STORE_L_OF_CLASS, "LoadStore\\$Derive", + IRNode.STORE_L_OF_CLASS, "LoadStore", + IRNode.STORE_L_OF_CLASS, "/ir_framework/tests/LoadStore\\$Derived", + IRNode.STORE_L_OF_CLASS, "(?<=[@: ])[\\w\\$]*tests[\\w\\$]*", + } + ) + // @ir_framework/tests/LoadStore$Derived (ir_framework/tests/LoadStore$I1,ir_framework/tests/LoadStore$I2)+24 * + public void storeWithInterfaces() { + derived.l = 1; + } + + @Test + @IR(counts = { + IRNode.LOAD_I_OF_CLASS, "DoubleNest", "1", + IRNode.LOAD_I_OF_CLASS, "\\$DoubleNest", "1", + IRNode.LOAD_I_OF_CLASS, "SingleNest\\$DoubleNest", "1", + IRNode.LOAD_I_OF_CLASS, "\\$SingleNest\\$DoubleNest", "1", + IRNode.LOAD_I_OF_CLASS, "LoadStore\\$SingleNest\\$DoubleNest", "1", + IRNode.LOAD_I_OF_CLASS, "/LoadStore\\$SingleNest\\$DoubleNest", "1", + IRNode.LOAD_I_OF_CLASS, "tests/LoadStore\\$SingleNest\\$DoubleNest", "1", + IRNode.LOAD_I_OF_CLASS, "/tests/LoadStore\\$SingleNest\\$DoubleNest", "1", + IRNode.LOAD_I_OF_CLASS, "ir_framework/tests/LoadStore\\$SingleNest\\$DoubleNest", "1", + }, + failOn = { + IRNode.LOAD_I_OF_CLASS, "SingleNest", + IRNode.LOAD_I_OF_CLASS, "LoadStore", + IRNode.LOAD_I_OF_CLASS, "LoadStore\\$SingleNest", + } + ) + // @ir_framework/tests/LoadStore$SingleNest$DoubleNest+12 * + public int loadDoubleNested() { + return doubleNest.i; + } + + @Test + @IR(counts = { + IRNode.STORE_I_OF_CLASS, "DoubleNest", "1", + IRNode.STORE_I_OF_CLASS, "\\$DoubleNest", "1", + IRNode.STORE_I_OF_CLASS, "SingleNest\\$DoubleNest", "1", + IRNode.STORE_I_OF_CLASS, "\\$SingleNest\\$DoubleNest", "1", + IRNode.STORE_I_OF_CLASS, "LoadStore\\$SingleNest\\$DoubleNest", "1", + IRNode.STORE_I_OF_CLASS, "/LoadStore\\$SingleNest\\$DoubleNest", "1", + IRNode.STORE_I_OF_CLASS, "tests/LoadStore\\$SingleNest\\$DoubleNest", "1", + IRNode.STORE_I_OF_CLASS, "/tests/LoadStore\\$SingleNest\\$DoubleNest", "1", + IRNode.STORE_I_OF_CLASS, "ir_framework/tests/LoadStore\\$SingleNest\\$DoubleNest", "1", + }, + failOn = { + IRNode.STORE_I_OF_CLASS, "SingleNest", + IRNode.STORE_I_OF_CLASS, "LoadStore", + IRNode.STORE_I_OF_CLASS, "LoadStore\\$SingleNest", + } + ) + // @ir_framework/tests/LoadStore$SingleNest$DoubleNest+12 * + public void storeDoubleNested() { + doubleNest.i = 1; + } +} \ No newline at end of file diff --git a/test/hotspot/jtreg/vmTestbase/gc/gctests/AllocateWithoutOomTest/AllocateWithoutOomTest.java b/test/hotspot/jtreg/vmTestbase/gc/gctests/AllocateWithoutOomTest/AllocateWithoutOomTest.java index 51307bb996c..a1bd7acedeb 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/gctests/AllocateWithoutOomTest/AllocateWithoutOomTest.java +++ b/test/hotspot/jtreg/vmTestbase/gc/gctests/AllocateWithoutOomTest/AllocateWithoutOomTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ * * @library /vmTestbase * /test/lib - * @run main/othervm + * @run main/othervm/timeout=480 * -XX:-UseGCOverheadLimit * gc.gctests.AllocateWithoutOomTest.AllocateWithoutOomTest */ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/Allocate/alloc001/alloc001.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/Allocate/alloc001/alloc001.java index eafbbf8b05f..e9f4ee7c4f1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/Allocate/alloc001/alloc001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/Allocate/alloc001/alloc001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,6 +43,8 @@ * * @comment Not run on AIX as it does not support ulimit -v * @requires os.family != "aix" + * @comment Do not run with asan enabled because asan has issues with ulimit + * @requires !vm.asan * @run main/native nsk.jvmti.Allocate.alloc001.alloc001 */ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach020/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach020/TestDescription.java index a729aa4d28f..09d54318b60 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach020/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach020/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ * Test scenario: * - during initialization (from function Agent_OnAttach) agent starts auxiliary thread waiting on * raw monitor and enables GarbageCollectionStart and GarbageCollectionFinish events - * - target application provokes garbage collection (calls System.gc()) + * - target application provokes garbage collection (calls WhiteBox.getWhiteBox().fullGC()) * - agent receives event GarbageCollectionStart * - agent receives event GarbageCollectionFinish event and notifies waiting auxiliary thread * - notified auxiliary thread notifies target application that agent finished its work @@ -48,11 +48,13 @@ * /test/lib * @build nsk.share.aod.AODTestRunner * nsk.jvmti.AttachOnDemand.attach020.attach020Target + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm/native * nsk.share.aod.AODTestRunner * -jdk ${test.jdk} * -target nsk.jvmti.AttachOnDemand.attach020.attach020Target - * -javaOpts="-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}" + * -javaOpts="-XX:+UsePerfData ${test.vm.opts} ${test.java.opts} -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI" * -na attach020Agent00 */ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach020/attach020Target.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach020/attach020Target.java index a20cf935bae..3a52a539b82 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach020/attach020Target.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach020/attach020Target.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,14 +22,14 @@ */ package nsk.jvmti.AttachOnDemand.attach020; -import nsk.share.ClassUnloader; import nsk.share.aod.TargetApplicationWaitingAgents; +import jdk.test.whitebox.WhiteBox; public class attach020Target extends TargetApplicationWaitingAgents { protected void targetApplicationActions() { log.display("Provoking garbage collection"); - ClassUnloader.eatMemory(); + WhiteBox.getWhiteBox().fullGC(); } public static void main(String[] args) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/TestDescription.java index 5cf7b39729b..3d8dc2f4e85 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,11 +44,13 @@ * /test/lib * @build nsk.share.aod.AODTestRunner * nsk.jvmti.AttachOnDemand.attach021.attach021Target + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm/native * nsk.share.aod.AODTestRunner * -jdk ${test.jdk} * -target nsk.jvmti.AttachOnDemand.attach021.attach021Target - * -javaOpts="-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}" + * -javaOpts="-XX:+UsePerfData ${test.vm.opts} ${test.java.opts} -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI" * -na attach021Agent00 */ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/attach021Target.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/attach021Target.java index d287616af69..adb2c194189 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/attach021Target.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/attach021Target.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,8 +22,8 @@ */ package nsk.jvmti.AttachOnDemand.attach021; -import nsk.share.ClassUnloader; import nsk.share.aod.TargetApplicationWaitingAgents; +import jdk.test.whitebox.WhiteBox; public class attach021Target extends TargetApplicationWaitingAgents { @@ -51,7 +51,7 @@ protected void targetApplicationActions() throws Throwable { try { if (createTaggedObject()) { log.display("Provoking GC"); - ClassUnloader.eatMemory(); + WhiteBox.getWhiteBox().fullGC(); } } finally { shutdownAgent(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/TestDescription.java index 49b47585749..5875f7a0f50 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,11 +47,13 @@ * /test/lib * @build nsk.share.aod.AODTestRunner * nsk.jvmti.AttachOnDemand.attach022.attach022Target + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm/native * nsk.share.aod.AODTestRunner * -jdk ${test.jdk} * -target nsk.jvmti.AttachOnDemand.attach022.attach022Target - * -javaOpts="-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}" + * -javaOpts="-XX:+UsePerfData ${test.vm.opts} ${test.java.opts} -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI" * -na attach022Agent00 */ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/attach022Target.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/attach022Target.java index eb80c0c2a4c..3324855e622 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/attach022Target.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/attach022Target.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,8 +22,8 @@ */ package nsk.jvmti.AttachOnDemand.attach022; -import nsk.share.ClassUnloader; import nsk.share.aod.TargetApplicationWaitingAgents; +import jdk.test.whitebox.WhiteBox; class ClassForAllocationEventsTest { @@ -47,7 +47,7 @@ protected void targetApplicationActions() throws Throwable { } log.display("Provoking GC"); - ClassUnloader.eatMemory(); + WhiteBox.getWhiteBox().fullGC(); } finally { if (!shutdownAgent(TEST_ALLOCATION_NUMBER)) { setStatusFailed("Error happened during agent work, see error messages for details"); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GarbageCollectionFinish/gcfinish001.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GarbageCollectionFinish/gcfinish001.java index 433ee607d7c..3e25000a2fb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GarbageCollectionFinish/gcfinish001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GarbageCollectionFinish/gcfinish001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ import java.math.*; import nsk.share.*; +import jdk.test.whitebox.WhiteBox; /** * This test exercises the JVMTI event GarbageCollectionFinish. @@ -63,7 +64,7 @@ public static int run(String argv[], PrintStream out) { private int runThis(String argv[], PrintStream out) { try { for (int i=0; iGarbageCollectionStart. @@ -63,13 +64,7 @@ public static int run(String argv[], PrintStream out) { } private int runThis(String argv[], PrintStream out) { - try { - for (int i=0; iGarbageCollectionStart. @@ -61,13 +62,7 @@ public static int run(String argv[], PrintStream out) { } private int runThis(String argv[], PrintStream out) { - try { - for (int i=0; iRawMonitorExit(syncLock); - - if (!NSK_JVMTI_VERIFY(jvmti->DestroyRawMonitor(syncLock))) - nsk_jvmti_setFailStatus(); - } /* ============================================================================= */ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/ClassUnloader.java b/test/hotspot/jtreg/vmTestbase/nsk/share/ClassUnloader.java index 5ea01fb3af4..e3b6693657c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/ClassUnloader.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/ClassUnloader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ package nsk.share; -import java.lang.ref.Cleaner; +import java.lang.ref.PhantomReference; import java.util.*; import nsk.share.gc.gp.*; import nsk.share.test.ExecutionController; @@ -77,19 +77,9 @@ public class ClassUnloader { public static final String INTERNAL_CLASS_LOADER_NAME = "nsk.share.CustomClassLoader"; /** - * Whole amount of time in milliseconds to wait for class loader to be reclaimed. + * Phantom reference to the class loader. */ - private static final int WAIT_TIMEOUT = 15000; - - /** - * Sleep time in milliseconds for the loop waiting for the class loader to be reclaimed. - */ - private static final int WAIT_DELTA = 1000; - - /** - * Has class loader been reclaimed or not. - */ - volatile boolean is_reclaimed = false; + private PhantomReference customClassLoaderPhantomRef = null; /** * Current class loader used for loading classes. @@ -101,6 +91,14 @@ public class ClassUnloader { */ private Vector> classObjects = new Vector>(); + /** + * Has class loader been reclaimed or not. + */ + private boolean isClassLoaderReclaimed() { + return customClassLoaderPhantomRef != null + && customClassLoaderPhantomRef.refersTo(null); + } + /** * Class object of the first class been loaded with current class loader. * To get the rest loaded classes use getLoadedClass(int). @@ -138,8 +136,7 @@ public CustomClassLoader createClassLoader() { customClassLoader = new CustomClassLoader(); classObjects.removeAllElements(); - // Register a Cleaner to inform us when the class loader has been reclaimed. - Cleaner.create().register(customClassLoader, () -> { is_reclaimed = true; } ); + customClassLoaderPhantomRef = new PhantomReference<>(customClassLoader, null); return customClassLoader; } @@ -154,8 +151,7 @@ public void setClassLoader(CustomClassLoader customClassLoader) { this.customClassLoader = customClassLoader; classObjects.removeAllElements(); - // Register a Cleaner to inform us when the class loader has been reclaimed. - Cleaner.create().register(customClassLoader, () -> { is_reclaimed = true; } ); + customClassLoaderPhantomRef = new PhantomReference<>(customClassLoader, null); } /** @@ -244,32 +240,15 @@ public void loadClass(String className, String classDir) throws ClassNotFoundExc */ public boolean unloadClass(ExecutionController stresser) { - is_reclaimed = false; - // free references to class and class loader to be able for collecting by GC - long waitTimeout = (customClassLoader == null) ? 0 : WAIT_TIMEOUT; classObjects.removeAllElements(); customClassLoader = null; // force class unloading by eating memory pool eatMemory(stresser); - // give GC chance to run and wait for receiving reclaim notification - long timeToFinish = System.currentTimeMillis() + waitTimeout; - while (!is_reclaimed && System.currentTimeMillis() < timeToFinish) { - if (!stresser.continueExecution()) { - return false; - } - try { - // suspend thread for a while - Thread.sleep(WAIT_DELTA); - } catch (InterruptedException e) { - throw new Failure("Unexpected InterruptedException while class unloading: " + e); - } - } - // force GC to unload marked class loader and its classes - if (is_reclaimed) { + if (isClassLoaderReclaimed()) { Runtime.getRuntime().gc(); return true; } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/GC.java b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/GC.java index 6b33783306f..15bbc9eb964 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/GC.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/GC.java @@ -48,6 +48,9 @@ protected static class GCTestRunner extends TestRunner { public GCTestRunner(Test test, String[] args) { super(test, args); + // GC tests often run at the brink of OOME, make sure + // LocalRandom is loaded, initialized, and has enough memory. + LocalRandom.init(); } private GCParams getGCParams(String[] args) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java index 44e476d0be7..1735cc1e18d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ /** * This class provides launching of jdb and debuggee in local - * or remote mode according to test command line options. + * mode according to test command line options. */ public class Launcher extends DebugeeBinder { @@ -94,7 +94,7 @@ public Launcher (JdbArgumentHandler argumentHandler, Log log) { } /** - * Defines mode (local or remote) and type of connector (default, launching, + * Defines mode (local) and type of connector (default, launching, * raw launching, attaching or listening) according to options * parsed by JdbArgumentHandler. And then launches jdb * and debuggee in defined mode. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/AbstractDebuggeeTest.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/AbstractDebuggeeTest.java index 0668297d211..86d5d7ecd24 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/AbstractDebuggeeTest.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/AbstractDebuggeeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -149,19 +149,11 @@ public void loadTestClass(String className) { } } - public static final int MAX_UNLOAD_ATTEMPS = 5; - public void unloadTestClass(String className, boolean expectedUnloadingResult) { ClassUnloader classUnloader = loadedClasses.get(className); - int unloadAttemps = 0; - if (classUnloader != null) { - boolean wasUnloaded = false; - - while (!wasUnloaded && (unloadAttemps++ < MAX_UNLOAD_ATTEMPS)) { - wasUnloaded = classUnloader.unloadClass(); - } + boolean wasUnloaded = classUnloader.unloadClass(); if (wasUnloaded) loadedClasses.remove(className); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/BindServer.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/BindServer.java deleted file mode 100644 index 2ed334e0386..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/BindServer.java +++ /dev/null @@ -1,1847 +0,0 @@ -/* - * 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. - */ - -package nsk.share.jpda; - -import java.io.*; -import java.net.*; -import java.util.*; - -import nsk.share.*; - -/** - * BindServer is an utility to perform JPDA tests - * in remote mode across network. - *

- * This utility should be started on remote host. It listens for connection - * from JPDA tests and launches debuggee VM on this host. - *

- * BindServer works together with Binder used in - * the tests to incapsulate actions required for launching debuggee VM. - * See ProcessBinder and DebugeeArgumentHandler - * to know how run tests in local or remote mode across network or - * on an single host. - *

- * BindServer is started on the debuggee host. - * It recognizes following command line options: - *

    - *
  • -bind.file=filename - configuration file - *
  • -verbose - print verbose messages - *
- *

- * Only required option is -bind.file, which points to the file - * where pairs of particular pathes are presented as they are seen from - * both hosts along with some other BindServer options. - * See execution.html to read more about format of bind-file. - * - * @see DebugeeBinder - * @see DebugeeArgumentHandler - */ -public final class BindServer { - - /** Version of BindServer implementation. */ - public static final long VERSION = 2; - - /** Timeout in milliseconds used for waiting for inner threads. */ - private static long THREAD_TIMEOUT = DebugeeBinder.THREAD_TIMEOUT; // milliseconds - - private static int PASSED = 0; - private static int FAILED = 2; - private static int JCK_BASE = 95; - - private static int TRACE_LEVEL_PACKETS = 10; - private static int TRACE_LEVEL_THREADS = 20; - private static int TRACE_LEVEL_ACTIONS = 30; - private static int TRACE_LEVEL_SOCKETS = 40; - private static int TRACE_LEVEL_IO = 50; - - private static String pathSeparator = System.getProperty("path.separator"); - private static String fileSeparator = System.getProperty("file.separator"); - - private static char pathSeparatorChar = pathSeparator.charAt(0); - private static char fileSeparatorChar = fileSeparator.charAt(0); - - private static Log log = null; - private static Log.Logger logger = null; - private static ArgumentHandler argHandler = null; - - private static String pathConvertions[][] = null; - - - private int totalRequests = 0; - private int acceptedRequests = 0; - private int unauthorizedRequests = 0; - private int busyRequests = 0; - - /** - * Start BindServer utility from command line. - * This method invokes run() and redirects output - * to System.err. - * - * @param argv list of command line arguments - */ - public static void main (String argv[]) { - System.exit(run(argv,System.err) + JCK_BASE); - } - - /** - * Start BindServer utility from JCK-compatible - * environment. - * - * @param argv list of command line arguments - * @param out outpur stream for log messages - * - * @return FAILED if error occured - * PASSED oterwise - */ - public static int run(String argv[], PrintStream out) { - return new BindServer().runIt(argv, out); - } - /** - * Perform execution of BindServer. - * This method handles command line arguments, starts seperate - * thread for listening connection from test on remote host, - * and waits for command "exit" from a user. - * Finally it closes all conections and prints connections - * statiscs. - * - * @param argv list of command line arguments - * @param out outpur stream for log messages - * - * @return FAILED if error occured - * PASSED oterwise - */ - private int runIt(String argv[], PrintStream out) { - try { - argHandler = new ArgumentHandler(argv); - } catch (ArgumentHandler.BadOption e) { - out.println("ERROR: " + e.getMessage()); - return FAILED; - } - - if (argHandler.getArguments().length > 0) { - out.println("ERROR: " + "Too many positional arguments in command line"); - return FAILED; - } - - log = new Log(out, argHandler); - logger = new Log.Logger(log, ""); - - logger.trace(TRACE_LEVEL_THREADS, "BindServer: starting main thread"); - - logger.display("Listening to port: " + argHandler.getBindPortNumber()); - logger.display("Authorizing host: " + argHandler.getDebuggerHost()); - - pathConvertions = new String[][] { - { "TESTED_JAVA_HOME", argHandler.getDebuggerJavaHome(), argHandler.getDebugeeJavaHome() }, - { "TESTBASE", argHandler.getDebuggerTestbase(), argHandler.getDebugeeTestbase() }, - { "WORKDIR", argHandler.getDebuggerWorkDir(), argHandler.getDebugeeWorkDir() } - }; - - logger.display("Translating pathes:"); - for (int i = 0; i < pathConvertions.length; i++) { - logger.display(pathConvertions[i][0] + ":" +"\n" - + " " + pathConvertions[i][1] + "\n" - + " =>" + "\n" - + " " + pathConvertions[i][2]); - } - - String windir = argHandler.getDebugeeWinDir(); - if (!(windir == null || windir.equals(""))) { - logger.display("Using WINDIR: \n" - + " " + argHandler.getDebugeeWinDir()); - } - - BufferedReader stdIn = new BufferedReader( - new InputStreamReader(System.in)); - try (ListeningThread listeningThread = new ListeningThread(this)) { - listeningThread.bind(); - listeningThread.start(); - - System.out.println("\n" - + "BindServer started" + "\n" - + "Type \"exit\" to shut down BindServer" - + "\n"); - - for (; ; ) { - try { - String userInput = stdIn.readLine(); - if (userInput == null || userInput.equals("exit") - || userInput.equals("quit")) { - logger.display("Shutting down BindServer"); - stdIn.close(); - stdIn = null; - break; - } else if (userInput.trim().equals("")) { - continue; - } else { - System.out.println("ERROR: Unknown command: " + userInput); - } - } catch (IOException e) { - e.printStackTrace(log.getOutStream()); - throw new Failure("Caught exception while reading console command:\n\t" - + e); - } - } - - printSummary(System.out); - - logger.trace(TRACE_LEVEL_THREADS, "BindServer: exiting main thread"); - } - - return PASSED; - } - - /** - * Print usefull summary statistics about connections occured. - * - * @param out output stream for printing statistics - */ - private void printSummary(PrintStream out) { - out.println("\n" - + "Connections summary:" + "\n" - + " Tolal connections: " + totalRequests + "\n" - + " Accepted authorized: " + acceptedRequests + "\n" - + " Rejected unauthorized " + unauthorizedRequests + "\n" - + " Rejected being busy: " + busyRequests + "\n"); - }; - - /** - * Check if given path starts with the specified prefix taking - * into account difference between slashChar used in path - * and fileSeparatorChar used in prefix. - * - * @param path path to check - * @param prefix prefix to compare with - * @param slashChar file separator used in path - */ - private static boolean checkPathPrefix(String path, String prefix, char slashChar) { - int prefixLength = prefix.length(); - if (prefixLength > path.length()) { - return false; - } - for (int i = 0; i < prefixLength; i++) { - char pathChar = path.charAt(i); - char prefixChar = prefix.charAt(i); - - if (pathChar != prefixChar) { - if ((pathChar == slashChar || pathChar == fileSeparatorChar - || pathChar == '\\' || pathChar == '/') - && (prefixChar == slashChar || prefixChar == fileSeparatorChar - || prefixChar == '\\' || prefixChar == '/')) { - // do nothing - } else { - return false; - } - } - } - return true; - } - - /** - * Convert given path according to list of prefixes from - * pathConvertions table. - * - * @param path path for converting - * @param slash file separator used in path - * @param name path identifier used for error messages - * @param strict force throwing Failure if path is not matched - * - * @return string with the converted path - * - * @throws Failure if path does not matched for translation - */ - private static String convertPath(String path, String slash, String name, boolean strict) { - if (path == null) - return null; - - char slashChar = slash.charAt(0); - - for (int i = 0; i < pathConvertions.length; i++) { - String from = pathConvertions[i][1]; - String to = pathConvertions[i][2]; - if (checkPathPrefix(path, from, slashChar)) { - return (to + path.substring(from.length())).replace(slashChar, fileSeparatorChar); - } - } - if (strict) { - throw new Failure("Path not matched for translation " + name + ":\n\t" + path); - } - return path; - } - - /** - * Convert given list of pathes according to list of prefixes from - * pathConvertions table by invoking convertPath() - * for each path from the list. - * - * @param list list of pathes for converting - * @param slash file separator used in pathes - * @param name path identifier used for error messages - * @param strict force throwing Failure if some path is not matched - * - * @return list of strings with converted pathes - * - * @throws Failure if some path does not matched for translation - * - * @see #convertPath() - */ - private static String[] convertPathes(String[] list, String slash, String name, boolean strict) { - String[] converted = new String[list.length]; - for (int i = 0; i < list.length; i++) { - converted[i] = convertPath(list[i], slash, name, strict); - } - return converted; - } - - /** - * Pause current thread for specified amount of time in milliseconds, - * This method uses Object.wait(long) method as a reliable - * method which prevents whole VM from suspending. - * - * @param millisecs - amount of time in milliseconds - */ - private static void sleeping(int millisecs) { - Object obj = new Object(); - - synchronized(obj) { - try { - obj.wait(millisecs); - } catch (InterruptedException e) { - e.printStackTrace(log.getOutStream()); - new Failure("Thread interrupted while sleeping:\n\t" + e); - } - } - } - - /** - * Wait for given thread finished for specified timeout or - * interrupt this thread if not finished. - * - * @param thr thread to wait for - * @param millisecs timeout in milliseconds - */ - private static void waitInterruptThread(Thread thr, long millisecs) { - if (thr != null) { - String name = thr.getName(); - try { - if (thr.isAlive()) { - logger.trace(TRACE_LEVEL_THREADS, "Waiting for thread: " + name); - thr.join(millisecs); - } - } catch (InterruptedException e) { - e.printStackTrace(log.getOutStream()); - throw new Failure ("Thread interrupted while waiting for another thread:\n\t" - + e); - } finally { - if (thr.isAlive()) { - logger.trace(TRACE_LEVEL_THREADS, "Interrupting not finished thread: " + name); - thr.interrupt(); -/* - logger.display("Stopping not finished thread: " + thr); - thr.stop(); - */ - } - } - } - } - - /** - * Wait for given thread finished for default timeout - * THREAD_TIMEOUT and - * interrupt this thread if not finished. - * - * @param thr thread to wait for - */ - private static void waitInterruptThread(Thread thr) { - waitInterruptThread(thr, THREAD_TIMEOUT); - } - -///////// Thread listening a TCP/IP socket ////////// - - /** - * An inner thread used for listening connection from remote test - * and starting separate serving thread for each accepted connection. - * - * @see ServingThread - */ - private static class ListeningThread extends Thread implements AutoCloseable { - private volatile boolean shouldStop = false; - private volatile boolean closed = false; - - private BindServer owner = null; - private volatile ServingThread servingThread = null; - private volatile int taskCount = 0; - - private ObjectOutputStream socOut = null; - private ObjectInputStream socIn = null; - - private String autorizedHostName = argHandler.getDebuggerHost(); - private InetAddress autorizedInetAddresses[] = null; - private int port = argHandler.getBindPortNumber(); - private Socket socket = null; - private ServerSocket serverSocket = null; - private InetAddress clientInetAddr = null; - private String clientHostName = null; - private SocketConnection connection = null; - - /** - * Make listening thread for given BindServer object - * as an owner and bind it to listening port by invoking method - * bind(). - * - * @see bind() - */ - public ListeningThread(BindServer owner) { - super("ListeningThread"); - this.owner = owner; - try { - autorizedInetAddresses = InetAddress.getAllByName(autorizedHostName); - } catch (UnknownHostException e) { - e.printStackTrace(log.getOutStream()); - throw new Failure("Cannot resolve DEBUGGER_HOST value: " + autorizedHostName); - } - } - - /** - * Bind ServerSocket to the specified port. - */ - public void bind() { - for (int i = 0; !shouldStop && i < DebugeeBinder.CONNECT_TRIES; i++) { - try { - logger.trace(TRACE_LEVEL_SOCKETS, "ListeningThread: binding to server socket ..."); - // length of the queue = 2 - serverSocket = new ServerSocket(port, 2); - // timeout for the ServerSocket.accept() - serverSocket.setSoTimeout(DebugeeBinder.CONNECT_TRY_DELAY); - logger.trace(TRACE_LEVEL_SOCKETS, "ListeningThread: socket bound: " + serverSocket); - logger.display("Bound to listening port"); - return; - } catch (BindException e) { - logger.display("Socket binding try #" + i + " failed:\n\t" + e); - sleeping(DebugeeBinder.CONNECT_TRY_DELAY); - } catch (IOException e) { - e.printStackTrace(log.getOutStream()); - throw new Failure("Caught exception while binding to socket:\n\t" - + e); - } - } - throw new Failure("Unable to bind to socket after " - + DebugeeBinder.CONNECT_TRIES + " tries"); - } - - /** - * Accept socket connection from authorized remote host and - * start separate SrvingThread to handle each connection. - * Connection from unauthorized hosts or connections made while - * current connection is alive are rejected. - * - * @see ServingThread - * @see #llowConnection() - * @see allowServing() - */ - public void run() { - String reply = null; - - logger.trace(TRACE_LEVEL_THREADS, "ListeningThread: started"); - logger.display("Listening for connection from remote host"); - while(!(shouldStop || isInterrupted())) { - try { - try { - logger.trace(TRACE_LEVEL_SOCKETS, "ListeningThread: waiting for connection from test"); - socket = serverSocket.accept(); - logger.trace(TRACE_LEVEL_SOCKETS, "ListeningThread: connection accepted"); - } catch(InterruptedIOException e) { -// logger.trace(TRACE_LEVEL_SOCKETS, "ListeningThread: timeout of waiting for connection from test"); - continue; - } - owner.totalRequests++; - logger.display(""); - clientInetAddr = socket.getInetAddress(); - clientHostName = clientInetAddr.getHostName(); - logger.display("Connection #" + owner.totalRequests - + " requested from host: " + clientHostName); - connection = new SocketConnection(logger, "BindServer"); -// connection.setPingTimeout(DebugeeBinder.PING_TIMEOUT); - connection.setSocket(socket); - socket = null; - if (allowConnection()) { - if (allowServing()) { - owner.acceptedRequests++; - reply = "host authorized: " + clientHostName; - logger.display("Accepting connection #" + owner.acceptedRequests - + ": " + reply); - servingThread = new ServingThread(this, connection); - servingThread.start(); - cleanHostConnection(); - } else { - owner.busyRequests++; - reply = "BindServer is busy"; - logger.complain("Rejecting connection #" + owner.busyRequests - + ": " + reply); - connection.writeObject(new RequestFailed(reply)); - closeHostConnection(); - } - } else { - owner.unauthorizedRequests++; - reply = "host unauthorized: " + clientHostName; - logger.complain("Rejecting connection #" + owner.unauthorizedRequests - + ": " + reply); - connection.writeObject(new RequestFailed(reply)); - closeHostConnection(); - } - } catch (Exception e) { - logger.complain("Caught exception while accepting connection:\n" + e); - e.printStackTrace(log.getOutStream()); - } - } - logger.trace(TRACE_LEVEL_THREADS, "ListeningThread: exiting"); - closeConnection(); - } - - /** - * Check if the connection made is from authorized host. - * - * @return true if connection is allowed because host authorized - * false if connection is rejected because host unauthorized - */ - private boolean allowConnection() { - // check if local host from loopback address - if (autorizedHostName.equals("localhost")) - return clientInetAddr.isLoopbackAddress(); - - // check if equal hostname - if (autorizedHostName.equals(clientHostName)) - return true; - - // check if equal host address - for (int i = 0; i < autorizedInetAddresses.length; i++) { - if (clientInetAddr.equals(autorizedInetAddresses[i])) { - return true; - } - } - return false; - } - - /** - * Check if no current connection exists or it is dead. - * If current connection presents it will be tested by pinging - * remote host and aborted if host sends no reply. If an alive - * connection exists, new connection will be rejected. - * - * @return true if no alive connection exists - * false otherwise - */ - private boolean allowServing() { - if (servingThread == null) { - return true; - } - if (servingThread.done) { - return true; - } - if (!servingThread.isConnectionAlive()) { - logger.display("# WARNING: Previous connection from remote host is dead: aborting connection"); - servingThread.close(); - servingThread = null; - return true; - } - -/* - logger.complain("Previous connection from remote host is alive: starting new connection"); - servingThread = null; - return true; - */ - logger.complain("Previous connection from remote host is alive: reject new connection"); - return false; - } - - /** - * Wait for this thread finished - * for specified timeout or interrupt it. - * - * @param millis timeout in milliseconds - */ - public void waitForThread(long millis) { - shouldStop = true; - waitInterruptThread(this, millis); - } - - /** - * Close socket connection from remote host. - */ - private void closeHostConnection() { - if (connection != null) { - connection.close(); - } - if (socket != null) { - try { - socket.close(); - } catch (IOException e) { - logger.complain("Caught IOException while closing socket:\n\t" - + e); - } - socket = null; - } - } - - /** - * Assign to connection and socket objects - * but do not close them. - */ - private void cleanHostConnection() { - connection = null; - socket = null; - } - - /** - * Close all connections and sockets. - */ - private void closeConnection() { - closeHostConnection(); - if (serverSocket != null) { - try { - serverSocket.close(); - } catch (IOException e) { - logger.complain("Caught IOException while closing ServerSocket:\n\t" - + e); - } - serverSocket = null; - } - } - - /** - * Close thread by closing all connections and waiting - * for thread to finish. - * - * @see #closeConnection() - */ - @Override - public synchronized void close() { - if (closed) { - return; - } - try { - closeHostConnection(); - if (servingThread != null) { - servingThread.close(); - servingThread = null; - } - waitForThread(THREAD_TIMEOUT); - closeConnection(); - closed = true; - logger.trace(TRACE_LEVEL_THREADS, "ListeningThread closed"); - } catch (Throwable e) { - e.printStackTrace(log.getOutStream()); - logger.complain("Caught exception while closing ListeningThread:\n\t" + e); - } - } - - } // ListeningThread - -///////// Thread working with a communication channel ////////// - - /** - * An internal thread for handling each connection from a test - * on remote host. It reads requests from test and starts separate - * LaunchingThread to execute each request. - * - * @see LaunchingThread - */ - private static class ServingThread extends Thread { - private volatile boolean shouldStop = false; - private volatile boolean closed = false; - private volatile boolean done = false; - - private ListeningThread owner = null; - private LaunchingThread launchingThread = null; - - private SocketConnection connection = null; - - /** - * Make serving thread with specified input/output connection streams - * and given Listenerthread as an owner. - * - * @param owner owner of this thread - * @param connection established socket connection with test - */ - public ServingThread(ListeningThread owner, SocketConnection connection) { - super("ServingThread"); - this.owner = owner; - this.connection = connection; - } - - /** - * Read requests from socket connection and start LaunchingThread - * to perform each requested action. - */ - public void run() { - logger.trace(TRACE_LEVEL_THREADS, "ServingThread: starting handling requests from debugger"); - try { - // sending OK(version) - logger.trace(TRACE_LEVEL_ACTIONS, "ServingThread: sending initial OK(VERSION) to debugger"); - connection.writeObject(new OK(VERSION)); - - // receiving TaskID(id) - logger.trace(TRACE_LEVEL_IO, "ServingThread: waiting for TaskID from debugger"); - Object taskID = connection.readObject(); - logger.trace(TRACE_LEVEL_IO, "ServingThread: received TaskID from debugger: " + taskID); - if (taskID instanceof TaskID) { - String id = ((TaskID)taskID).id; - owner.taskCount++; - logger.println("[" + owner.taskCount + "/" + owner.owner.totalRequests + "]: " + id); - } else { - throw new Failure("Unexpected TaskID received form debugger: " + taskID); - } - - // starting launching thread - launchingThread = new LaunchingThread(this, connection); - launchingThread.start(); - - // receiving and handling requests - while(!(shouldStop || isInterrupted())) { - logger.trace(TRACE_LEVEL_IO, "ServingThread: waiting for request from debugger"); - Object request = connection.readObject(); - logger.trace(TRACE_LEVEL_IO, "ServingThread: received request from debugger: " + request); - if (request == null) { - logger.display("Connection closed"); - break; - } else if (request instanceof Disconnect) { - logger.display("Closing connection by request"); - request = null; - break; - } else { - boolean success = false; - long timeToFinish = System.currentTimeMillis() + THREAD_TIMEOUT; - while (System.currentTimeMillis() < timeToFinish) { - if (launchingThread.doneRequest()) { - success = true; - logger.trace(TRACE_LEVEL_ACTIONS, "ServingThread: asking launching thread to handle request: " + request); - launchingThread.handleRequest(request); - break; - } - try { - launchingThread.join(DebugeeBinder.TRY_DELAY); - } catch (InterruptedException e) { - throw new Failure("ServingThread interrupted while waiting for LaunchingThread:\n\t" - + e); - } - } - if (!success) { - logger.complain("Rejecting request because of being busy:\n" + request); - connection.writeObject( - new RequestFailed("Busy with handling previous request")); - } - } - } - } catch (Exception e) { - e.printStackTrace(log.getOutStream()); - logger.complain("Caught exception while handling request:\n\t" + e); - } finally { - logger.trace(TRACE_LEVEL_THREADS, "ServingThread: exiting"); - closeConnection(); - done = true; - } - } - - /** - * Check if present socket connection is alive. - */ - private boolean isConnectionAlive() { - return (connection != null && connection.isConnected()); - } - - /** - * Wait for this thread finished - * for specified timeout or interrupt it. - * - * @param millis timeout in milliseconds - */ - public void waitForThread(long millis) { - shouldStop = true; - waitInterruptThread(this, millis); - } - - /** - * Close socket connection from remote host. - */ - private void closeConnection() { - if (connection != null) { - connection.close(); - } - if (launchingThread != null) { - launchingThread.handleRequest(null); - } - } - - /** - * Close thread closing socket connection and - * waiting for thread finished. - */ - public synchronized void close() { - if (closed) { - return; - } - closeConnection(); - if (launchingThread != null) { - launchingThread.close(); - launchingThread = null; - } - waitForThread(THREAD_TIMEOUT); - closed = true; - logger.trace(TRACE_LEVEL_THREADS, "ServingThread closed"); - } - - } // ServingThread - -///////// Thread serving a particular Binder's request ////////// - - /** - * An internal thread to execute each request from a test on remote host. - * Requests are coming from ServingThread by invoking handleRequest(Object) - * method. - */ - private static class LaunchingThread extends Thread { - private volatile boolean shouldStop = false; - private volatile boolean closed = false; - public volatile boolean done = false; - - private ServingThread owner = null; -// private ProcessWaitingThread waitingThread = null; - private Process process = null; - - private StreamRedirectingThread stdoutRedirectingThread = null; - private StreamRedirectingThread stderrRedirectingThread = null; - - /** Notification about request occurence. */ - private volatile Object notification = new Object(); - /** Request to execute. */ - private volatile Object request = null; - /** Socket stream to send replies to. */ - private SocketConnection connection = null; - - /** - * Make thread for executing requests from a test and - * send reply. - * - * @param owner owner of this thread - * @connection socket connection for sending replies - */ - public LaunchingThread(ServingThread owner, SocketConnection connection) { - super("LaunchingThread"); - this.owner = owner; - this.connection = connection; - } - - /** - * Notify this thread that new request has come. - * - * @param request request to execute - */ - public void handleRequest(Object request) { - synchronized (notification) { - this.request = request; - notification.notifyAll(); - } - } - - /** - * Check if request has been executed. - */ - public boolean doneRequest() { - return done; - } - - /** - * Wait for request notification from ServingThread - * and execute an action according to the request. - * Request null means thread should finish. - */ - public void run() { - logger.trace(TRACE_LEVEL_THREADS, "LaunchingThread: started to handle request"); - done = true; - while (!isInterrupted()) { - // wait for new request notification - logger.trace(TRACE_LEVEL_ACTIONS, "LaunchingThread: waiting for request"); - synchronized (notification) { - try { - notification.wait(); - } catch (InterruptedException e) { - logger.complain("LaunchingThread interrupted while waiting for request:\n\t" - + e); - break; - } - } - - // execute the request - try { - logger.trace(TRACE_LEVEL_ACTIONS, "LaunchingThread: handling request: " + request); - if (request == null) { - break; - } else if (request instanceof LaunchDebugee) { - launchDebugee((LaunchDebugee)request); - } else if (request instanceof WaitForDebugee) { - waitForDebugee((WaitForDebugee)request); - } else if (request instanceof DebugeeExitCode) { - debugeeExitCode((DebugeeExitCode)request); - } else if (request instanceof KillDebugee) { - killDebugee((KillDebugee)request); - } else { - String reason = "Unknown request: " + request; - logger.complain(reason); - sendReply(new RequestFailed(reason)); - } - } catch (Exception e) { - e.printStackTrace(log.getOutStream()); - logger.complain("Caught exception while handling request:\n\t" + e); - } - done = true; - } - done = true; - logger.trace(TRACE_LEVEL_THREADS, "LaunchingThread: exiting"); - closeConnection(); - } - - /** - * Send given reply to remote test. - * - * @param reply reply object to send - */ - public void sendReply(Object reply) throws IOException { - connection.writeObject(reply); - } - - /** - * Send given output line to remote test. - * - * @param reply wrapper object for output line to send - */ - public void sendStreamMessage(RedirectedStream wrapper) throws IOException { - logger.trace(TRACE_LEVEL_ACTIONS, "Sending output line wrapper to debugger: " + wrapper); - if (connection.isConnected()) { - sendReply(wrapper); - } else { - logger.complain("NOT redirected: " + wrapper.line); - } - } - - /** - * Launch two StreamRedirectingThread threads to redirect - * stdin/stderr output of debuggee VM process via BindServer - * connection. - * - * @param process debuggee VM process - */ - private void launchStreamRedirectors(Process process) { - stdoutRedirectingThread = - new StdoutRedirectingThread(this, process.getInputStream(), - DebugeeProcess.DEBUGEE_STDOUT_LOG_PREFIX); - stdoutRedirectingThread.start(); - stderrRedirectingThread = - new StderrRedirectingThread(this, process.getErrorStream(), - DebugeeProcess.DEBUGEE_STDERR_LOG_PREFIX); - stderrRedirectingThread.start(); - } - - /** - * Execute request for launching debuggee. - * - * @param request request to execute - */ - private void launchDebugee(LaunchDebugee request) throws IOException { - logger.trace(TRACE_LEVEL_ACTIONS, "LaunchDebugee: handle request: " + request); - - if (process != null) { - logger.complain("Unable to launch debuggee: process already launched"); - sendReply(new RequestFailed("Debuggee process already launched")); - return; - } - - try { - String[] cmd = request.cmd; - cmd[0] = convertPath(cmd[0], request.slash, "TESTED_JAVA_HOME", true); - for (int i = 1; i < cmd.length; i++) { - cmd[i] = convertPath(cmd[i], request.slash, "JAVA_ARGS", false); - } - String workDir = convertPath(request.workDir, request.slash, "WORKDIR", true); - String[] classPathes = convertPathes(request.classPathes, request.slash, "CLASSPATH", true); - String windir = argHandler.getDebugeeWinDir(); - - boolean win = (!(windir == null || windir.equals(""))); - String[] envp = new String[win ? 3 : 1] ; - envp[0] = "CLASSPATH=" + ArgumentParser.joinArguments(classPathes, "", pathSeparator); - if (win) { - envp[1] = "WINDIR=" + windir; - envp[2] = "SystemRoot=" + windir; - } - - logger.display("Setting environment:\n" - + " " + ArgumentHandler.joinArguments(envp, "", "\n ")); - logger.display("Setting work dir:\n" - + " " + workDir); - logger.display("Launching debuggee:\n" - + " " + ArgumentHandler.joinArguments(cmd, "\"")); - - process = Runtime.getRuntime().exec(cmd, envp, new File(workDir)); - logger.display(" debuggee launched successfully"); - - launchStreamRedirectors(process); - } catch (Exception e) { - if (!(e instanceof Failure)) { - e.printStackTrace(log.getOutStream()); - } - logger.complain("Caught exception while launching debuggee:\n\t" + e); - sendReply(new CaughtException(e)); - return; - } - - sendReply(new OK()); - } - - /** - * Execute request for waiting for debuggee exited. - * - * @param request request to execute - */ - private void waitForDebugee(WaitForDebugee request) throws IOException { - logger.trace(TRACE_LEVEL_ACTIONS, "WaitForDebugee: handle request: " + request); - - if (process == null) { - String reply = "No debuggee process to wait for"; - logger.complain(reply); - sendReply(new RequestFailed(reply)); - return; - } - - logger.display("Waiting for debuggee to exit"); -/* - // because timeout is not supported now - // we do not use separate thread for waiting for process - // and so following lines are commented out - - waitingThread = new ProcessWaitingThread(); - logger.trace(TRACE_LEVEL_ACTIONS, "LaunchingThread: starting thread for waiting for debugee process"); - waitingThread.start(); - try { - waitingThread.join(request.timeout); - if (waitingThread.isAlive()) { - String reply = "Timeout exceeded while waiting for debuggee to exit"; - logger.complain(reply); - waitingThread.interrupt(); - sendReply(socOut, new RequestFailed(reply)); - return; - } - } catch (InterruptedException e) { - e.printStackTrace(log.getOutStream()); - logger.complain("Caught exception while waiting for debuggee:\n\t" + e); - sendReply(new CaughtException(e)); - return; - } - int exitStatus = waitingThread.exitStatus; - waitingThread = null; - */ - int exitStatus; - try { - exitStatus = process.waitFor(); - waitForRedirectors(THREAD_TIMEOUT); - process.destroy(); - } catch (InterruptedException e) { - e.printStackTrace(log.getOutStream()); - logger.complain("Caught exception while waiting for debuggee process to exit:\n\t" - + e); - sendReply(new CaughtException(e)); - return; - } - logger.display(" debuggee exited with exit status: " + exitStatus); - sendReply(new OK(exitStatus)); - } - - /** - * Execute request for returning debuggee exit code. - * - * @param request request to execute - */ - private void debugeeExitCode(DebugeeExitCode request) throws IOException { - logger.trace(TRACE_LEVEL_ACTIONS, "DebugeeExitCode: handle request: " + request); - - if (process == null) { - String reply = "No debuggee process to get exit code for"; - logger.complain(reply); - sendReply(new RequestFailed(reply)); - return; - } - - int exitStatus = 0; - try { - exitStatus = process.exitValue(); - } catch (IllegalThreadStateException e) { - logger.display("# WARNING: Caught exception while getting exit status of debuggee:\n\t" - + e); - sendReply(new CaughtException(e)); - return; - } - logger.trace(TRACE_LEVEL_ACTIONS, "DebugeeExitCode: return debuggee exit status: " + exitStatus); - sendReply(new OK(exitStatus)); - } - - /** - * Execute request for unconditional terminating debuggee process. - * - * @param request request to execute - */ - private void killDebugee(KillDebugee request) throws IOException { - logger.trace(TRACE_LEVEL_ACTIONS, "killDebugee: handle request: " + request); - - if (process == null) { - String reply = "No debuggee process to kill"; - logger.complain(reply); - sendReply(new RequestFailed(reply)); - return; - } - - logger.trace(TRACE_LEVEL_ACTIONS, "killDebugee: killing debuggee process"); - process.destroy(); - - logger.trace(TRACE_LEVEL_ACTIONS, "killDebugee: debuggee process killed"); - sendReply(new OK()); - } - - /** - * Terminate debigee VM process if still alive. - */ - private void terminateDebugeeAtExit() { - if (process != null) { - logger.trace(TRACE_LEVEL_ACTIONS, "Checking that debuggee process has exited correctly"); - try { - int value = process.exitValue(); - } catch (IllegalThreadStateException e) { - logger.complain("Debuggee process has not exited correctly: trying to kill it"); - process.destroy(); - try { - int value = process.exitValue(); - } catch (IllegalThreadStateException ie) { - logger.complain("Debuggee process is alive after killing it"); - } - process = null; - return; - } - logger.trace(TRACE_LEVEL_ACTIONS, "Debuggee process has exited correctly"); - } - } - - /** - * Wait for stream redirecting threads finished - * for specified timeout. - * - * @param millis timeout in milliseconds - */ - private void waitForRedirectors(long millis) { - try { - if (stdoutRedirectingThread != null) { - stdoutRedirectingThread.join(millis); - } - if (stderrRedirectingThread != null) { - stderrRedirectingThread.join(millis); - } - } catch (InterruptedException e) { - e.printStackTrace(log.getOutStream()); - logger.complain("Caught exception while waiting for debuggee process exited:\n\t" - + e); - } - } - - /** - * Wait for this thread finished - * for specified timeout or interrupt it. - * - * @param millis timeout in milliseconds - */ - public void waitForThread(long millis) { - shouldStop = true; - handleRequest(null); - waitInterruptThread(this, millis); - } - - /** - * Close connection with debuggee. - */ - public void closeConnection() { - // no connections to close - } - - /** - * Close thread by closing all connections with debuggee, - * finishing all redirectors and wait for thread finished. - */ - public synchronized void close() { - if (closed) { - return; - } - closeConnection(); - terminateDebugeeAtExit(); - if (stdoutRedirectingThread != null) { - stdoutRedirectingThread.close(); - stdoutRedirectingThread = null; - } - if (stderrRedirectingThread != null) { - stderrRedirectingThread.close(); - stderrRedirectingThread = null; - } - waitForThread(THREAD_TIMEOUT); - closed = true; - logger.trace(TRACE_LEVEL_THREADS, "LaunchingThread closed"); - } - - /** - * An inner thread for waiting for debuggee process exited - * and saving its exit status. (currently not used) - */ -/* - private class ProcessWaitingThread extends Thread { - int exitStatus = 0; - - ProcessWaitingThread() { - super("ProcessWaitingThread"); - } - - public void run() { - logger.trace(TRACE_LEVEL_THREADS, "ProcessWaitingThread: starting waiting for process"); - try { - exitStatus = process.waitFor(); - } catch (InterruptedException e) { - e.printStackTrace(log.getOutStream()); - logger.complain("Caught exception while waiting for debuggee process:\n\t" - + e); - } - logger.trace(TRACE_LEVEL_ACTIONS, "ProcessWaitingThread: process finished with status: " + exitStatus); - logger.trace(TRACE_LEVEL_THREADS, "ProcessWaitingThread: exiting"); - } - - public synchronized void close() { - logger.trace(TRACE_LEVEL_THREADS, "ProcessWaitingThread closed"); - } - - } // ProcessWaitingThread - */ - } // LaunchingThread - -///////// Redirecting threads ///////// - - /** - * An abstract base class for internal threads which redirects stderr/stdout - * output from debuggee process via BindServer connection. - *

- * Two derived classes will redirect stderr or stdout stream - * by enwrapping stream line by DebugeeStderr or - * DebugeeStderr objects. They should implement only one - * abstract method enwrapLine(String) to make the difference. - */ - public static abstract class StreamRedirectingThread extends Thread { - private volatile boolean shouldStop = false; - private volatile boolean closed = false; - - private LaunchingThread owner = null; - - private BufferedReader bin = null; - private String prefix = null; - - /** - * Make a thread to enwrap and redirect lines from specified - * input stream with given prefix. - * - * @param owner owner of this thread - * @param is input stream to redirect lines from - * @param prefix prefix to add to each line - */ - public StreamRedirectingThread(LaunchingThread owner, InputStream is, String prefix) { - super("StreamRedirectingThread"); - this.prefix = prefix; - this.owner = owner; - bin = new BufferedReader(new InputStreamReader(is)); - } - - /** - * Read lines from an input stream, enwrap them, and send to remote - * test via BindServer connection. - */ - public void run() { - logger.trace(TRACE_LEVEL_THREADS, "StreamRedirectingThread: starting redirect output stream"); - try { - String line; - logger.trace(TRACE_LEVEL_IO, "StreamRedirectingThread: waiting for line from debuggee output"); - while(!shouldStop) { - line = bin.readLine(); - if (line == null) - break; - owner.sendStreamMessage(enwrapLine(prefix + line)); - } - } catch (EOFException e) { - logger.display("Debuggee output stream closed by process"); - } catch (IOException e) { - e.printStackTrace(log.getOutStream()); - logger.display("# WARNING: Connection to debuggee output stream aborted:\n\t" + e); - } catch (Exception e) { - e.printStackTrace(log.getOutStream()); - logger.complain("Caught exception while redirecting debuggee output stream:\n\t" - + e); - } - logger.trace(TRACE_LEVEL_THREADS, "StreamRedirectingThread: exiting"); - closeConnection(); - } - - /** - * Envrap output line by the appropriate wrapper. - * @param line line to enwrap - */ - protected abstract RedirectedStream enwrapLine(String line); - - /** - * Wait for this thread finished or interrupt it. - * - * @param millis timeout in milliseconds - */ - public void waitForThread(long millis) { - shouldStop = true; - waitInterruptThread(this, millis); - } - - /** - * Close redirected process output stream. - */ - public void closeConnection() { - if (closed) { - return; - } - if (bin != null) { - try { - bin.close(); - } catch (IOException e) { - e.printStackTrace(log.getOutStream()); - logger.complain("Caught exception while closing debuggee output stream:\n\t" - + e); - } - bin = null; - } - closed = true; - logger.trace(TRACE_LEVEL_THREADS, "StreamRedirectingThread closed"); - } - - /** - * Close thread by waiting redirected stream closed - * and finish the thread. - */ - public synchronized void close() { - if (closed) { - return; - } - waitForThread(THREAD_TIMEOUT); - closeConnection(); - closed = true; - logger.trace(TRACE_LEVEL_THREADS, "StreamRedirectingThread closed"); - } - - } // StreamRedirectingThread - - /** - * Particalar case of StreamRedirectingThread to redirect - * stderr stream by enwrapping lines into DebugeeStderr - * objects. - */ - private static class StderrRedirectingThread extends StreamRedirectingThread { - - /** - * Make a thread to redirect stderr output stream. - */ - StderrRedirectingThread(LaunchingThread owner, InputStream is, String prefix) { - super(owner, is, prefix); - setName("StderrRedirectingThread"); - } - - /** - * Enwrap given line into DebugeeStderr object. - */ - protected RedirectedStream enwrapLine(String line) { - return new DebugeeStderr(line); - } - - } - - /** - * Particalar case of StreamRedirectingThread to redirect - * stdout stream by enwrapping lines into DebugeeStdout - * objects. - */ - private static class StdoutRedirectingThread extends StreamRedirectingThread { - - /** - * Make a thread to redirect stdout output stream. - */ - StdoutRedirectingThread(LaunchingThread owner, InputStream is, String prefix) { - super(owner, is, prefix); - setName("StdoutRedirectingThread"); - } - - /** - * Enwrap given line into DebugeeStdout object. - */ - protected RedirectedStream enwrapLine(String line) { - return new DebugeeStdout(line); - } - - } - -///////// BinderServer's packets ////////// - - /** - * Base serializable object to transmit request or reply - * via BindServer connection. - */ - public static class Packet implements Serializable {} - - ///////// Binder's requests ////////// - - /** - * Base class to represent request to BindServer. - */ - public static abstract class Request extends Packet {} - - /** - * This class implements task identification command. - */ - public static class TaskID extends Request { - public String id; - - public TaskID(String id) { - this.id = id; - } - - public String toString() { - return "TaskID: id=" + id; - } - } - - /** - * This class implements a request for launching a debugee. - */ - public static class LaunchDebugee extends Request { - public String slash; // slash symbol used on debugger host - public String[] cmd; // command line arguments as seen on debugger host - public String workDir; // path to working directory as seen on debugger host - public String[] classPathes; // list of class pathes as seen on debugger host - - public LaunchDebugee(String[] cmd, String slash, String workDir, - String[] pathes, String[] classPathes, - String[] libPathes) { - this.cmd = cmd; - this.slash = slash; - this.workDir = workDir; - this.classPathes = classPathes; - } - - public String toString() { - return "LaunchDebugee:" - + "\n\tcommand=" + ArgumentParser.joinArguments(cmd, "\"") - + "\n\tWORKDIR=" + workDir - + "\n\tCLASSPATH=" + ArgumentParser.joinArguments(classPathes, "", ":") - + "\n\tslash=" + slash; - } - } - - /** - * This class implements a request for waiting for debugee - * termination. - */ - public static class WaitForDebugee extends Request { - public long timeout = 0; // timeout in minutes for waiting - - public WaitForDebugee(long value) { - timeout = value; - } - - public String toString() { - return "WaitForDebugee: timeout=" + timeout; - } - } - - /** - * This class implements a request for exit code of - * debugee process. - */ - public static class DebugeeExitCode extends Request { - public String toString() { - return "SebugeeExitCode"; - } - } - - /** - * This class implements a request for killing debugee process. - */ - public static class KillDebugee extends Request { - public String toString() { - return "KillDebugee"; - } - } - - /** - * This class implements a request to disconnect connection with test. - */ - public static class Disconnect extends Request { - public String toString() { - return "Disconnect"; - } - } - - ///////// BindServer's responses ////////// - - /** - * Base class to represent response from BindServer. - */ - public static abstract class Response extends Packet {} - - /** - * This class implements a response that a previoulsy received - * request has been successfully performed. - */ - public static class OK extends Response { - public long info = BindServer.VERSION; // optional additional info - - public OK() { - } - - public OK(long value) { - info = value; - } - - public String toString() { - return "OK(" + info + ")"; - } - } - - /** - * This class implements a response that the BindServer is - * unable to serve a previoulsy received request. - */ - public static class RequestFailed extends Response { - public String reason; // the short explanation of failure - - public RequestFailed(String reason) { - this.reason = reason; - } - - public String toString() { - return "RequestFailed(" + reason + ")"; - } - } - - /** - * This class implements a response that the BindServer is - * unable to serve a previoulsy received request because of - * caught exception. - */ - public static class CaughtException extends RequestFailed { - public CaughtException(Exception cause) { - super("Caught exception: " + cause); - } - } - - ///////// Wrappers for redirected messages ////////// - - /** - * Base class to represent wrappers for redirected streams. - */ - public static class RedirectedStream extends Packet { - public String line; // line containing line from redirected stream - - public RedirectedStream(String str) { - line = str; - } - - public String toString() { - return "RedirectedStream(" + line + ")"; - } - } - - /** - * This class enwraps redirected line of stdout stream. - */ - public static class DebugeeStdout extends RedirectedStream { - - public DebugeeStdout(String str) { - super(str); - } - - public String toString() { - return "DebugeeStdout(" + line + ")"; - } - } - - /** - * This class enwraps redirected line of stderr stream. - */ - public static class DebugeeStderr extends RedirectedStream { - public DebugeeStderr(String str) { - super(str); - } - - public String toString() { - return "DebugeeStderr(" + line + ")"; - } - } - -/////// ArgumentHandler for BindServer command line ///////// - - /** - * This class is used to parse arguments from command line - * and specified bind-file, - */ - private static class ArgumentHandler extends ArgumentParser { - - protected Properties fileOptions; - - /** - * Make parser object for command line arguments. - * - * @param args list of command line arguments - */ - public ArgumentHandler(String[] args) { - super(args); - } - - /** - * Check if given command line option is aloowed. - * - * @param option option name - * @param value option value - */ - protected boolean checkOption(String option, String value) { - if (option.equals("bind.file")) { - // accept any file name - return true; - } - return super.checkOption(option, value); - } - - /** - * Check if all recignized options are compatible. - */ - protected void checkOptions() { - if (getBindFileName() == null) { - throw new BadOption("Option -bind.file is requred "); - } - super.checkOptions(); - } - - /** - * Check if value of this option points to a existing directory. - * - * @param option option name - * @param dir option value - */ - private void checkDir(String option, String dir) { - File file = new File(dir); - if (!file.exists()) { - throw new BadOption(option + " does not exist: " + dir); - } - if (!file.isAbsolute()) { - throw new BadOption(option + " is not absolute pathname: " + dir); - } - if (!file.isDirectory()) { - throw new BadOption(option + " is not directory: " + dir); - } - } - - /** - * Check if option from bind-file is allowed. - * - * @param option option name - * @param value option value - */ - protected boolean checkAdditionalOption(String option, String value) { - - if (option.equals("DEBUGGER_HOST")) { - // accept any hostname - return true; - } - - if (option.equals("BINDSERVER_PORT")) { - // accept only integer value - try { - int port = Integer.parseInt(value); - } catch (NumberFormatException e) { - throw new Failure("Not integer value of bind-file option " + option - + ": " + value); - } - return true; - } - - if (option.equals("DEBUGGER_TESTED_JAVA_HOME") - || option.equals("DEBUGGER_WORKDIR") - || option.equals("DEBUGGER_TESTBASE")) { - if (value == null || value.equals("")) { - throw new BadOption("Empty value of bind-file option " + option); - } - return true; - } - - if (option.equals("DEBUGGEE_TESTED_JAVA_HOME") - || option.equals("DEBUGGEE_WORKDIR") - || option.equals("DEBUGGEE_TESTBASE")) { - if (value == null || value.equals("")) { - throw new BadOption("Empty value of bind-file option " + option); - } - checkDir(option, value); - return true; - } - - if (option.equals("DEBUGGEE_WINDIR")) { - if (!(value == null || value.equals(""))) { - checkDir(option, value); - } - return true; - } - - return false; - } - - /** - * Check if all recignized options form bind-file are compatible. - */ - protected void checkAdditionalOptions() { - - if (getDebuggerJavaHome() == null) { - throw new BadOption("Option DEBUGGER_JAVA_HOME missed from bind-file"); - } - if (getDebuggerWorkDir() == null) { - throw new BadOption("Option DEBUGGER_WORKDIR missed from bind-file"); - } - if (getDebuggerTestbase() == null) { - throw new BadOption("Option DEBUGGER_TESTBASE missed from bind-file"); - } - - if (getDebugeeJavaHome() == null) { - throw new BadOption("Option DEBUGGEE_JAVA_HOME missed from bind-file"); - } - if (getDebugeeWorkDir() == null) { - throw new BadOption("Option DEBUGGEE_WORKDIR missed from bind-file"); - } - if (getDebugeeTestbase() == null) { - throw new BadOption("Option DEBUGGEE_TESTBASE missed from bind-file"); - } - } - - /** - * Parse options form specified bind-file. - */ - protected void parseAdditionalOptions() { - Enumeration keys = fileOptions.keys(); - while (keys.hasMoreElements()) { - String option = (String)keys.nextElement(); - String value = fileOptions.getProperty(option); - if (! checkAdditionalOption(option, value)) { - throw new BadOption("Unrecognized bind-file option: " + option); - } - } - checkAdditionalOptions(); - } - - /** - * Parse all options from command line and specified bind-file. - */ - protected void parseArguments() { - super.parseArguments(); - String fileName = getBindFileName(); - try { - FileInputStream bindFile = new FileInputStream(fileName); - fileOptions = new Properties(); - fileOptions.load(bindFile); - bindFile.close(); - } catch(FileNotFoundException e) { - throw new BadOption("Unable to open bind-file " + fileName + ": " + e); - } catch(IOException e) { - e.printStackTrace(log.getOutStream()); - throw new Failure("Caught exception while reading bind-file:\n" + e); - } - parseAdditionalOptions(); - } - - /** Return name of specified bind-file. */ - public String getBindFileName() { - return options.getProperty("bind.file"); - } - - /** Return specified debuggee host name . */ - public String getDebuggerHost() { - return fileOptions.getProperty("DEBUGGER_HOST", "localhost"); - } - - /** Return string representation of port number for BindServer connection. */ - public String getBindPort() { - return fileOptions.getProperty("BINDSERVER_PORT", "9000"); - } - - /** Return specified port number for BindServer connection. */ - public int getBindPortNumber() { - try { - return Integer.parseInt(getBindPort()); - } catch (NumberFormatException e) { - throw new Failure("Not integer value of BindServer port"); - } - } - - /** Return specified path to tested JDK used for debuggee VM. */ - public String getDebugeeJavaHome() { - return fileOptions.getProperty("DEBUGGEE_TESTED_JAVA_HOME"); - } - - /** Return specified path to tested JDK used for debugger. */ - public String getDebuggerJavaHome() { - return fileOptions.getProperty("DEBUGGER_TESTED_JAVA_HOME"); - } - - /** Return specified path to working dir from debuggee host. */ - public String getDebugeeWorkDir() { - return fileOptions.getProperty("DEBUGGEE_WORKDIR"); - } - - /** Return specified path to working dir from debugger host. */ - public String getDebuggerWorkDir() { - return fileOptions.getProperty("DEBUGGER_WORKDIR"); - } - - /** Return specified path to testbase dir from debuggee host. */ - public String getDebugeeTestbase() { - return fileOptions.getProperty("DEBUGGEE_TESTBASE"); - } - - /** Return specified path to testbase dir from debugger host. */ - public String getDebuggerTestbase() { - return fileOptions.getProperty("DEBUGGER_TESTBASE"); - } - - /** Return specified path to system directory on Wimdows platform. */ - public String getDebugeeWinDir() { - return fileOptions.getProperty("DEBUGGEE_WINDIR"); - } - - } // ArgumentHandler - -} // BindServer diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeArgumentHandler.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeArgumentHandler.java index 72b8076f927..05d0054928b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeArgumentHandler.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeArgumentHandler.java @@ -67,8 +67,6 @@ * using JVMDI strict mode *

  • -pipe.port=<port> - * port number for internal IOPipe connection - *
  • -bind.port=<port> - - * port number for BindServer connection * *

    * See also list of basic options recognized by @@ -421,47 +419,6 @@ public boolean isDefaultDebugeeJavaHome() { return (java_home == null); } - private boolean bindPortInited = false; - /** - * Return string representation of the port number for BindServer connection, - * specified by -bind.port command line option, or - * "DEFAULT_BIND_PORT" string by default. - * - * @see #getBindPortNumber() - * @see #setRawArguments(String[]) - */ - public String getBindPort() { - String port = options.getProperty("bind.port"); - if (port == null) { - if (!bindPortInited) { - port = findFreePort(); - if (port == null) { - port = DEFAULT_BIND_PORT; - } - options.setProperty("bind.port", port); - bindPortInited = true; - } - } - return port; - } - - /** - * Return port number for BindServer connection, - * specified by -bind.port command line option, or - * "DEFAULT_BIND_PORT" port number by default. - * - * @see #getBindPort() - * @see #setRawArguments(String[]) - */ - public int getBindPortNumber() { - String value = getBindPort(); - try { - return Integer.parseInt(value); - } catch (NumberFormatException e) { - throw new TestBug("Not integer value of \"bind.port\" argument: " + value); - } - } - /** * Return JVMDI strict mode for launching debugee VM, specified by. * -jvmdi.strict command line option, or @@ -683,7 +640,6 @@ protected boolean checkOption(String option, String value) { // option with positive integer port value if (option.equals("transport.port") - || option.equals("bind.port") || option.equals("pipe.port")) { try { int number = Integer.parseInt(value); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeBinder.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeBinder.java index d36c9d9624f..d04fed1bd32 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeBinder.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeBinder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, 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 @@ -52,8 +52,8 @@ * @see DebugeeArgumentHandler * @see DebugeeProcess * @see IOPipe - * @see BindServer * + * @see nsk.share.jdb.Launcher * @see nsk.share.jdi.Binder * @see nsk.share.jdwp.Binder */ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeProcess.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeProcess.java index b875911e973..55ee5366582 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeProcess.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeProcess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, 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 @@ -41,7 +41,7 @@ * This is an abstract class that declares abstract methods to control * debugee VM process. * Derived classes should implement these methods corresponding to the mode - * that the process should be started in (locally, remotely or manually). + * that the process should be started in (locally). *

    * Particular derived classes nsk.share.jdi.Debugee and * nsk.share.jdwp.Debugee provides additional abilities diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/IOPipe.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/IOPipe.java index 74e3a7c3a6d..062b8a4ba4d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/IOPipe.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/IOPipe.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, 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,12 +29,10 @@ /** * This class implements communicational channel between * debugger and debugee used for synchronization and data exchange. - * This channel is based on TCP/IP sockets and works in all - * modes (local, remote and manual). In a remote mode - * connection to BindServer is used for redirecting IOPipe messages. - * In all other modes direct TCP/IP coonnection between two VMs is used. + * This channel is based on TCP/IP sockets. * - * @see BindServer + * @see jpda.DebugeeArgumentHandler + * @see jpda.DebugeeProcess */ public class IOPipe extends SocketIOPipe { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/test/Stresser.java b/test/hotspot/jtreg/vmTestbase/nsk/share/test/Stresser.java index 83e8baa2836..c2851267911 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/test/Stresser.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/test/Stresser.java @@ -58,9 +58,12 @@ public class Stresser implements ExecutionController { private String name; private long maxIterations; private long iterations; + + // In nanoseconds private long startTime; - private long finishTime; private long currentTime; + private long stressTime; + private PrintStream defaultOutput = System.out; /* @@ -179,15 +182,15 @@ public void printStressInfo(PrintStream out) { */ public void printExecutionInfo(PrintStream out) { println(out, "Completed iterations: " + iterations); - println(out, "Execution time: " + (currentTime - startTime) + " seconds"); + println(out, "Execution time: " + (currentTime - startTime) / 1_000_000_000.0 + " seconds"); if (!finished) { println(out, "Execution is not finished yet"); } else if (forceFinish) { println(out, "Execution was forced to finish"); } else if (maxIterations != 0 && iterations >= maxIterations) { println(out, "Execution finished because number of iterations was exceeded: " + iterations + " >= " + maxIterations); - } else if (finishTime != 0 && currentTime >= finishTime) { - println(out, "Execution finished because time was exceeded: " + (currentTime - startTime) + " >= " + (finishTime - startTime)); + } else if (stressTime != 0 && (currentTime - startTime) >= stressTime) { + println(out, "Execution finished because time has exceeded stress time: " + stressTime / 1_000_000_000 + " seconds"); } } @@ -208,13 +211,8 @@ private void println(PrintStream out, String s) { public void start(long stdIterations) { maxIterations = stdIterations * options.getIterationsFactor(); iterations = 0; - long stressTime = options.getTime(); - startTime = System.currentTimeMillis(); - if (stressTime == 0) { - finishTime = 0; - } else { - finishTime = startTime + stressTime * 1000; - } + stressTime = options.getTime() * 1_000_000_000; + startTime = System.nanoTime(); finished = false; forceFinish = false; if (options.isDebugEnabled()) { @@ -232,7 +230,7 @@ public void start(long stdIterations) { * finally {} block. */ public void finish() { - currentTime = System.currentTimeMillis(); + currentTime = System.nanoTime(); finished = true; if (options.isDebugEnabled()) { printExecutionInfo(defaultOutput); @@ -255,10 +253,12 @@ public void forceFinish() { */ public boolean iteration() { ++iterations; + boolean result = continueExecution(); + // Call print at the end to show the most up-to-date info. if (options.isDebugDetailed()) { printExecutionInfo(defaultOutput); } - return continueExecution(); + return result; } /** @@ -267,14 +267,14 @@ public boolean iteration() { * @return true if execution needs to continue */ public boolean continueExecution() { - currentTime = System.currentTimeMillis(); + currentTime = System.nanoTime(); if (startTime == 0) { throw new TestBug("Stresser is not started."); } return !forceFinish && !finished && (maxIterations == 0 || iterations < maxIterations) - && (finishTime == 0 || currentTime < finishTime); + && (stressTime == 0 || (currentTime - startTime) < stressTime); } /** @@ -309,7 +309,7 @@ public long getIterationsLeft() { * @return time */ public long getExecutionTime() { - return System.currentTimeMillis() - startTime; + return (System.nanoTime() - startTime) / 1_000_000; } /** @@ -318,11 +318,11 @@ public long getExecutionTime() { * @return time */ public long getTimeLeft() { - long current = System.currentTimeMillis(); - if (current >= finishTime) { + long elapsedTime = System.nanoTime() - startTime; + if (elapsedTime >= stressTime) { return 0; } else { - return finishTime - current; + return (stressTime - elapsedTime) / 1_000_000; } } diff --git a/test/hotspot/jtreg/vmTestbase/vm/compiler/optimizations/stringconcat/implicit/Implicit01/cs_disabled/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/compiler/optimizations/stringconcat/implicit/Implicit01/cs_disabled/TestDescription.java index 2eddeafa2c9..13bc3b4d640 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/compiler/optimizations/stringconcat/implicit/Implicit01/cs_disabled/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/vm/compiler/optimizations/stringconcat/implicit/Implicit01/cs_disabled/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * 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,3 +33,17 @@ * @run main/othervm -XX:-CompactStrings vm.compiler.optimizations.stringconcat.implicit.Implicit01 */ + +/* + * @test id=stringConcatInline + * + * @summary The same test with an updated compile directive that produces + * StringBuilder-backed string concatenations. + * VM Testbase keywords: [jit, quick] + * + * @library /vmTestbase + * /test/lib + * @compile -XDstringConcat=inline ../../Implicit01.java + * @run main/othervm -XX:-CompactStrings vm.compiler.optimizations.stringconcat.implicit.Implicit01 + */ + diff --git a/test/hotspot/jtreg/vmTestbase/vm/compiler/optimizations/stringconcat/implicit/Implicit01/cs_enabled/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/compiler/optimizations/stringconcat/implicit/Implicit01/cs_enabled/TestDescription.java index 7e7295f5108..87e8bdcbcc7 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/compiler/optimizations/stringconcat/implicit/Implicit01/cs_enabled/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/vm/compiler/optimizations/stringconcat/implicit/Implicit01/cs_enabled/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * 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,3 +33,17 @@ * @run main/othervm -XX:+CompactStrings vm.compiler.optimizations.stringconcat.implicit.Implicit01 */ + +/* + * @test id=stringConcatInline + * + * @summary The same test with an updated compile directive that produces + * StringBuilder-backed string concatenations. + * VM Testbase keywords: [jit, quick] + * + * @library /vmTestbase + * /test/lib + * @compile -XDstringConcat=inline ../../Implicit01.java + * @run main/othervm -XX:+CompactStrings vm.compiler.optimizations.stringconcat.implicit.Implicit01 + */ + diff --git a/test/hotspot/jtreg/vmTestbase/vm/compiler/optimizations/stringconcat/implicit/Merge01/cs_disabled/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/compiler/optimizations/stringconcat/implicit/Merge01/cs_disabled/TestDescription.java index c56a554b1da..cbbe4d97ee4 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/compiler/optimizations/stringconcat/implicit/Merge01/cs_disabled/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/vm/compiler/optimizations/stringconcat/implicit/Merge01/cs_disabled/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * 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,3 +33,17 @@ * @run main/othervm -XX:-CompactStrings vm.compiler.optimizations.stringconcat.implicit.Merge01 */ + +/* + * @test id=stringConcatInline + * + * @summary The same test with an updated compile directive that produces + * StringBuilder-backed string concatenations. + * VM Testbase keywords: [jit, quick] + * + * @library /vmTestbase + * /test/lib + * @compile -XDstringConcat=inline ../../Merge01.java + * @run main/othervm -XX:-CompactStrings vm.compiler.optimizations.stringconcat.implicit.Merge01 + */ + diff --git a/test/hotspot/jtreg/vmTestbase/vm/compiler/optimizations/stringconcat/implicit/Merge01/cs_enabled/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/compiler/optimizations/stringconcat/implicit/Merge01/cs_enabled/TestDescription.java index 3c082fefd25..c6fc8d67de6 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/compiler/optimizations/stringconcat/implicit/Merge01/cs_enabled/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/vm/compiler/optimizations/stringconcat/implicit/Merge01/cs_enabled/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * 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,3 +33,17 @@ * @run main/othervm -XX:+CompactStrings vm.compiler.optimizations.stringconcat.implicit.Merge01 */ + +/* + * @test id=stringConcatInline + * + * @summary The same test with an updated compile directive that produces + * StringBuilder-backed string concatenations. + * VM Testbase keywords: [jit, quick] + * + * @library /vmTestbase + * /test/lib + * @compile -XDstringConcat=inline ../../Merge01.java + * @run main/othervm -XX:+CompactStrings vm.compiler.optimizations.stringconcat.implicit.Merge01 + */ + diff --git a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_InternedStrings_Strings/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_InternedStrings_Strings/TestDescription.java index 4e11e51a894..ad7db17e412 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_InternedStrings_Strings/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_InternedStrings_Strings/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ * * @library /vmTestbase * /test/lib - * @run main/othervm + * @run main/othervm/timeout=480 * -XX:-UseGCOverheadLimit * vm.gc.compact.Compact * -gp interned(randomString) diff --git a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_NonbranchyTree/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_NonbranchyTree/TestDescription.java index b058bb2c84d..be4f9f673b7 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_NonbranchyTree/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_NonbranchyTree/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ * * @library /vmTestbase * /test/lib - * @run main/othervm + * @run main/othervm/timeout=480 * -XX:-UseGCOverheadLimit * vm.gc.compact.Compact * -gp nonbranchyTree(high) diff --git a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_NonbranchyTree_ArrayOf/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_NonbranchyTree_ArrayOf/TestDescription.java index 3beeaa76a84..2ca21ae2ee6 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_NonbranchyTree_ArrayOf/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_NonbranchyTree_ArrayOf/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ * * @library /vmTestbase * /test/lib - * @run main/othervm + * @run main/othervm/timeout=480 * -XX:-UseGCOverheadLimit * vm.gc.compact.Compact * -gp nonbranchyTree(high) diff --git a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_NonbranchyTree_TwoFields/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_NonbranchyTree_TwoFields/TestDescription.java index c1421263a48..01dc687251b 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_NonbranchyTree_TwoFields/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_NonbranchyTree_TwoFields/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ * * @library /vmTestbase * /test/lib - * @run main/othervm + * @run main/othervm/timeout=480 * -XX:-UseGCOverheadLimit * vm.gc.compact.Compact * -gp nonbranchyTree(high) diff --git a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_Strings/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_Strings/TestDescription.java index 207822c666b..9ba96b7e493 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_Strings/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_Strings/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ * * @library /vmTestbase * /test/lib - * @run main/othervm + * @run main/othervm/timeout=480 * -XX:-UseGCOverheadLimit * vm.gc.compact.Compact * -gp randomString diff --git a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_Strings_InternedStrings/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_Strings_InternedStrings/TestDescription.java index 705e47ea68b..30dcfc7502e 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_Strings_InternedStrings/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_Strings_InternedStrings/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ * * @library /vmTestbase * /test/lib - * @run main/othervm + * @run main/othervm/timeout=480 * -XX:-UseGCOverheadLimit * vm.gc.compact.Compact * -gp randomString diff --git a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_Strings_TwoFields/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_Strings_TwoFields/TestDescription.java index 7d5ddc36fcb..8a62d4b07eb 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_Strings_TwoFields/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_Strings_TwoFields/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ * * @library /vmTestbase * /test/lib - * @run main/othervm + * @run main/othervm/timeout=480 * -XX:-UseGCOverheadLimit * vm.gc.compact.Compact * -gp randomString diff --git a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Humongous_NonbranchyTree/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Humongous_NonbranchyTree/TestDescription.java index 38c5b1e6bab..c9c117f0b0e 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Humongous_NonbranchyTree/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Humongous_NonbranchyTree/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ * * @library /vmTestbase * /test/lib - * @run main/othervm + * @run main/othervm/timeout=480 * -XX:-UseGCOverheadLimit * vm.gc.compact.Compact * -gp nonbranchyTree(high) diff --git a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Humongous_Strings/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Humongous_Strings/TestDescription.java index 88d11739141..7d4b6ae3a21 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Humongous_Strings/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Humongous_Strings/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ * * @library /vmTestbase * /test/lib - * @run main/othervm + * @run main/othervm/timeout=480 * -XX:-UseGCOverheadLimit * vm.gc.compact.Compact * -gp randomString diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/indy/func/jvmti/stepBreakPopReturn/stepBreakPopReturn.cpp b/test/hotspot/jtreg/vmTestbase/vm/mlvm/indy/func/jvmti/stepBreakPopReturn/stepBreakPopReturn.cpp index 413450892a5..0f7d1826937 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/indy/func/jvmti/stepBreakPopReturn/stepBreakPopReturn.cpp +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/indy/func/jvmti/stepBreakPopReturn/stepBreakPopReturn.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2024, 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 @@ -89,7 +89,7 @@ MethodEntry(jvmtiEnv *jvmti_env, gIsMethodEntryWorking = JNI_TRUE; if (!gIsBreakpointSet) - NSK_JVMTI_VERIFY(jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_SINGLE_STEP, nullptr)); + NSK_JVMTI_VERIFY(jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_SINGLE_STEP, thread)); } } @@ -116,7 +116,7 @@ SingleStep(jvmtiEnv *jvmti_env, free(locStr); } - NSK_JVMTI_VERIFY(gJvmtiEnv->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_SINGLE_STEP, nullptr)); + NSK_JVMTI_VERIFY(gJvmtiEnv->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_SINGLE_STEP, thread)); if (!gIsDebuggerCompatible) { if (!NSK_JVMTI_VERIFY(jvmti_env->SetBreakpoint(method, location))) diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/jni/nativeAndMH/Test.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/jni/nativeAndMH/Test.java index c8264e8f963..abb771e30e7 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/jni/nativeAndMH/Test.java +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/jni/nativeAndMH/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ * another method handle and so on. * The test verifies that arguments are correctly passed between native methods and MHs. * + * @requires vm.compMode != "Xcomp" * @library /vmTestbase * /test/lib * @@ -62,26 +63,32 @@ public class Test extends MultiThreadedTest { private static final String RETURN_VALUE = "test"; + private static final MethodType MT_calledFromNative = MethodType.methodType( + Object.class, + Object.class, Object.class, int.class, long.class, double.class, float.class); + + private static MethodHandle mh; + static { System.loadLibrary("nativeAndMH"); + try { + mh = MethodHandles.lookup().findStatic( + Test.class, + "calledFromNative", + MT_calledFromNative); + } catch (Exception ex) { + throw new RuntimeException("TEST FAILED - Unable to lookup \"calledFromNative\""); + } } private static native Object native01(Object a1, String a2, Object a3, Object a4, Object a5, Object a6, MethodHandle mh); - private static final MethodType MT_calledFromNative = MethodType.methodType( - Object.class, - Object.class, Object.class, int.class, long.class, double.class, float.class); - private static Object calledFromNative(Object s1, Object s2, int i, long l, double d, float f) { return RETURN_VALUE; } @Override protected boolean runThread(int threadNum) throws Throwable { - MethodHandle mh = MethodHandles.lookup().findStatic( - Test.class, - "calledFromNative", - MT_calledFromNative); Stresser stresser = createStresser(); stresser.start(1); diff --git a/test/jaxp/TEST.ROOT b/test/jaxp/TEST.ROOT index 7a457d87b69..bafa67a700e 100644 --- a/test/jaxp/TEST.ROOT +++ b/test/jaxp/TEST.ROOT @@ -23,7 +23,7 @@ modules=java.xml groups=TEST.groups # Minimum jtreg version -requiredVersion=7.5.1+1 +requiredVersion=8+2 # Path to libraries in the topmost test directory. This is needed so @library # does not need ../../ notation to reach them diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index fb774bbca5b..6418e1dfb36 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -260,7 +260,7 @@ java/awt/FullScreen/DisplayChangeVITest/DisplayChangeVITest.java 8169469,8273617 java/awt/FullScreen/UninitializedDisplayModeChangeTest/UninitializedDisplayModeChangeTest.java 8273617 macosx-all java/awt/print/PrinterJob/PSQuestionMark.java 7003378 generic-all java/awt/print/PrinterJob/GlyphPositions.java 7003378 generic-all -java/awt/Choice/ChoiceMouseWheelTest/ChoiceMouseWheelTest.java 6849371 macosx-all,linux-all +java/awt/Choice/ChoiceMouseWheelTest/ChoiceMouseWheelTest.java 8366852 generic-all java/awt/Component/GetScreenLocTest/GetScreenLocTest.java 4753654 generic-all java/awt/Component/SetEnabledPerformance/SetEnabledPerformance.java 8165863 macosx-all java/awt/Clipboard/PasteNullToTextComponentsTest.java 8234140 macosx-all,windows-all @@ -455,7 +455,6 @@ java/awt/Focus/TranserFocusToWindow/TranserFocusToWindow.java 6848810 macosx-all java/awt/FileDialog/ModalFocus/FileDialogModalFocusTest.java 8194751 linux-all java/awt/image/VolatileImage/BitmaskVolatileImage.java 8133102 linux-all java/awt/SplashScreen/MultiResolutionSplash/unix/UnixMultiResolutionSplashTest.java 8203004 linux-all -java/awt/ScrollPane/ScrollPositionTest.java 8040070 linux-all java/awt/ScrollPane/ScrollPaneEventType.java 8296516 macosx-all java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java 7107528 linux-all,macosx-all java/awt/Mouse/MouseDragEvent/MouseDraggedTest.java 8080676 linux-all @@ -553,8 +552,6 @@ java/io/IO/IO.java 8337935 linux-pp # jdk_management -com/sun/management/OperatingSystemMXBean/GetProcessCpuLoad.java 8030957 aix-all -com/sun/management/OperatingSystemMXBean/GetSystemCpuLoad.java 8030957 aix-all java/lang/management/MemoryMXBean/Pending.java 8158837 generic-all java/lang/management/MemoryMXBean/PendingAllGC.sh 8158837 generic-all @@ -569,7 +566,6 @@ sun/management/jdp/JdpOffTest.java 8308807 aix-ppc6 # jdk_jmx -javax/management/MBeanServer/OldMBeanServerTest.java 8030957 aix-all javax/management/remote/mandatory/connection/BrokenConnectionTest.java 8262312 linux-all @@ -592,14 +588,10 @@ java/net/MulticastSocket/SetLoopbackMode.java 7122846,8308807 java/net/MulticastSocket/SetOutgoingIf.java 8308807 aix-ppc64 java/net/MulticastSocket/Test.java 7145658,8308807 macosx-all,aix-ppc64 -java/net/Socket/asyncClose/Race.java 8317801 aix-ppc64 - ############################################################################ # jdk_nio -java/nio/channels/Channels/SocketChannelStreams.java 8317838 aix-ppc64 - java/nio/channels/DatagramChannel/AdaptorMulticasting.java 8308807,8144003 aix-ppc64,macosx-all java/nio/channels/DatagramChannel/AfterDisconnect.java 8308807 aix-ppc64 java/nio/channels/DatagramChannel/ManySourcesAndTargets.java 8264385 macosx-aarch64 @@ -616,8 +608,6 @@ java/rmi/server/Unreferenced/finiteGCLatency/FiniteGCLatency.java 7140992 generi java/rmi/transport/rapidExportUnexport/RapidExportUnexport.java 7146541 linux-all -java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java 7191877 generic-all - java/rmi/registry/readTest/CodebaseTest.java 8173324 windows-all java/rmi/registry/multipleRegistries/MultipleRegistries.java 8268182 macosx-all @@ -805,7 +795,6 @@ java/awt/event/MouseEvent/SpuriousExitEnter/SpuriousExitEnter_2.java 7131438,802 java/awt/Modal/WsDisabledStyle/CloseBlocker/CloseBlocker.java 7187741 linux-all,macosx-all java/awt/xembed/server/TestXEmbedServerJava.java 8001150,8004031 generic-all java/awt/Modal/PrintDialogsTest/PrintDialogsTest.java 8068378 generic-all -java/awt/event/MouseEvent/AltGraphModifierTest/AltGraphModifierTest.java 8162380 generic-all java/awt/image/VolatileImage/VolatileImageConfigurationTest.java 8171069 macosx-all,linux-all java/awt/Modal/InvisibleParentTest/InvisibleParentTest.java 8172245 linux-all java/awt/Frame/FrameStateTest/FrameStateTest.java 8203920 macosx-all,linux-all @@ -815,6 +804,7 @@ java/awt/font/GlyphVector/TestGlyphVectorLayout.java 8354987 generic-all java/awt/font/TextLayout/TestJustification.java 8250791 macosx-all java/awt/TrayIcon/DragEventSource/DragEventSource.java 8252242 macosx-all java/awt/FileDialog/DefaultFocusOwner/DefaultFocusOwner.java 7187728 macosx-all,linux-all +java/awt/FileDialog/DoubleActionESC.java 8356981 linux-all java/awt/print/PageFormat/Orient.java 8016055 macosx-all java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.java 8024986 macosx-all,linux-all java/awt/TextComponent/CorrectTextComponentSelectionTest.java 8237220 macosx-all @@ -826,7 +816,6 @@ java/awt/Focus/FrameMinimizeTest/FrameMinimizeTest.java 8016266 linux-x64 java/awt/Frame/SizeMinimizedTest.java 8305915 linux-x64 java/awt/PopupMenu/PopupHangTest.java 8340022 windows-all java/awt/Focus/MinimizeNonfocusableWindowTest.java 8024487 windows-all -java/awt/Focus/InactiveFocusRace.java 8023263 linux-all java/awt/List/HandlingKeyEventIfMousePressedTest.java 6848358 macosx-all,windows-all java/awt/List/ListScrollbarCursorTest.java 8066410 generic-all java/awt/Checkbox/CheckboxBoxSizeTest.java 8340870 windows-all @@ -835,3 +824,8 @@ java/awt/Checkbox/CheckboxNullLabelTest.java 8340870 windows-all java/awt/dnd/WinMoveFileToShellTest.java 8341665 windows-all java/awt/Menu/MenuVisibilityTest.java 8161110 macosx-all java/awt/Modal/NativeDialogToFrontBackTest.java 7188049 windows-all,linux-all +java/awt/Cursor/CursorDragTest/ListDragCursor.java 7177297 macosx-all + +# Mechanically added: +javax/sound/midi/Soundbanks/ExtraCharInSoundbank.java 8350613 linux-aarch64,linux-x64 +java/net/CookieHandler/B6644726.java 8366103 linux-aarch64,linux-x64,macosx-aarch64,windows-x64 diff --git a/test/jdk/TEST.ROOT b/test/jdk/TEST.ROOT index 30e2f7cab41..9d12d384399 100644 --- a/test/jdk/TEST.ROOT +++ b/test/jdk/TEST.ROOT @@ -102,6 +102,8 @@ requires.properties= \ vm.cds.write.archived.java.heap \ vm.continuations \ vm.musl \ + vm.asan \ + vm.ubsan \ vm.debug \ vm.hasSA \ vm.hasJFR \ @@ -119,7 +121,7 @@ requires.properties= \ jdk.static # Minimum jtreg version -requiredVersion=7.5.1+1 +requiredVersion=8+2 # Path to libraries in the topmost test directory. This is needed so @library # does not need ../../ notation to reach them diff --git a/test/jdk/build/AbsPathsInImage.java b/test/jdk/build/AbsPathsInImage.java index 7821b60670a..1aa7e59941e 100644 --- a/test/jdk/build/AbsPathsInImage.java +++ b/test/jdk/build/AbsPathsInImage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,8 @@ * @bug 8226346 * @summary Check all output files for absolute path fragments * @requires !vm.debug + * @comment ASAN keeps the 'unwanted' paths in the binaries because of its build options + * @requires !vm.asan * @run main/othervm -Xmx900m AbsPathsInImage */ public class AbsPathsInImage { diff --git a/test/jdk/com/sun/crypto/provider/Cipher/AES/TestGCMSplitBound.java b/test/jdk/com/sun/crypto/provider/Cipher/AES/TestGCMSplitBound.java new file mode 100644 index 00000000000..133e68b344f --- /dev/null +++ b/test/jdk/com/sun/crypto/provider/Cipher/AES/TestGCMSplitBound.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2025, Google LLC. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8371864 + * @run main/othervm/timeout=600 TestGCMSplitBound + * @requires (os.simpleArch == "x64" & (vm.cpu.features ~= ".*avx2.*" | + * vm.cpu.features ~= ".*avx512.*")) + * @summary Test GaloisCounterMode.implGCMCrypt0 AVX512/AVX2 intrinsics. + */ + +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; +import java.time.Duration; +import java.util.Arrays; +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +public class TestGCMSplitBound { + + static final SecureRandom SECURE_RANDOM = newDefaultSecureRandom(); + + private static SecureRandom newDefaultSecureRandom() { + SecureRandom retval = new SecureRandom(); + retval.nextLong(); // force seeding + return retval; + } + + private static byte[] randBytes(int size) { + byte[] rand = new byte[size]; + SECURE_RANDOM.nextBytes(rand); + return rand; + } + + private static final int IV_SIZE_IN_BYTES = 12; + private static final int TAG_SIZE_IN_BYTES = 16; + + private Cipher getCipher(final byte[] key, final byte[] aad, + final byte[] nonce, int mode) + throws Exception { + SecretKey keySpec = new SecretKeySpec(key, "AES"); + AlgorithmParameterSpec params = + new GCMParameterSpec(8 * TAG_SIZE_IN_BYTES, nonce, 0, nonce.length); + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + cipher.init(mode, keySpec, params); + if (aad != null && aad.length != 0) { + cipher.updateAAD(aad); + } + return cipher; + } + + private byte[] gcmEncrypt(final byte[] key, final byte[] plaintext, + final byte[] aad) + throws Exception { + byte[] nonce = randBytes(IV_SIZE_IN_BYTES); + Cipher cipher = getCipher(key, aad, nonce, Cipher.ENCRYPT_MODE); + int outputSize = cipher.getOutputSize(plaintext.length); + int len = IV_SIZE_IN_BYTES + outputSize; + byte[] output = new byte[len]; + System.arraycopy(nonce, 0, output, 0, IV_SIZE_IN_BYTES); + cipher.doFinal(plaintext, 0, plaintext.length, output, + IV_SIZE_IN_BYTES); + return output; + } + + private byte[] gcmDecrypt(final byte[] key, final byte[] ciphertext, + final byte[] aad) + throws Exception { + byte[] nonce = new byte[IV_SIZE_IN_BYTES]; + System.arraycopy(ciphertext, 0, nonce, 0, IV_SIZE_IN_BYTES); + Cipher cipher = getCipher(key, aad, nonce, Cipher.DECRYPT_MODE); + return cipher.doFinal(ciphertext, IV_SIZE_IN_BYTES, + ciphertext.length - IV_SIZE_IN_BYTES); + } + + // x86-64 parallel intrinsic data size + private static final int PARALLEL_LEN = 512; + // max data size for x86-64 intrinsic + private static final int SPLIT_LEN = 1048576; // 1MB + + private void encryptAndDecrypt(byte[] key, byte[] aad, byte[] message, + int messageSize) + throws Exception { + byte[] ciphertext = gcmEncrypt(key, message, aad); + byte[] decrypted = gcmDecrypt(key, ciphertext, aad); + if (ciphertext == null) { + throw new RuntimeException("ciphertext is null"); + } + if (Arrays.compare(decrypted, 0, messageSize, + message, 0, messageSize) != 0) { + throw new RuntimeException( + "Decrypted message is different from the original message"); + } + } + + private void run() throws Exception { + byte[] aad = randBytes(20); + byte[] key = randBytes(16); + // Force JIT. + for (int i = 0; i < 100000; i++) { + byte[] message = randBytes(PARALLEL_LEN); + encryptAndDecrypt(key, aad, message, PARALLEL_LEN); + } + for (int messageSize = SPLIT_LEN - 300; messageSize <= SPLIT_LEN + 300; + messageSize++) { + byte[] message = randBytes(messageSize); + try { + encryptAndDecrypt(key, aad, message, messageSize); + } catch (Exception e) { + throw new RuntimeException("Failed for messageSize " + + Integer.toHexString(messageSize), e); + } + } + } + + public static void main(String[] args) throws Exception { + TestGCMSplitBound test = new TestGCMSplitBound(); + for (int i = 0; i < 3; i++) { + test.run(); + } + } +} diff --git a/test/jdk/com/sun/java/swing/plaf/gtk/4928019/bug4928019.java b/test/jdk/com/sun/java/swing/plaf/gtk/4928019/bug4928019.java index cb90f374d84..7824b030d41 100644 --- a/test/jdk/com/sun/java/swing/plaf/gtk/4928019/bug4928019.java +++ b/test/jdk/com/sun/java/swing/plaf/gtk/4928019/bug4928019.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,25 +26,25 @@ * @bug 4928019 * @key headful * @summary Makes sure all the basic classes can be created with GTK. - * @author Scott Violet + * @requires (os.family != "windows" & os.family != "mac") + * @library /test/lib + * @build jtreg.SkippedException + * @run main bug4928019 */ import javax.swing.*; import javax.swing.plaf.basic.*; +import jtreg.SkippedException; + public class bug4928019 { public static void main(String[] args) throws Throwable { try { UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); - } catch (UnsupportedLookAndFeelException ex) { - System.err.println("GTKLookAndFeel is not supported on this platform." + - " Test is considered passed."); - return; - } catch (ClassNotFoundException ex) { - System.err.println("GTKLookAndFeel class is not found." + - " Test is considered passed."); - return; + } catch (Exception e) { + throw new SkippedException("GTKLookAndFeel isn't supported", e); } + new JButton() { public void updateUI() { setUI(new BasicButtonUI()); diff --git a/test/jdk/com/sun/java/swing/plaf/gtk/Test6635110.java b/test/jdk/com/sun/java/swing/plaf/gtk/Test6635110.java index ddf8363e2ee..eb3e1e7ca62 100644 --- a/test/jdk/com/sun/java/swing/plaf/gtk/Test6635110.java +++ b/test/jdk/com/sun/java/swing/plaf/gtk/Test6635110.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,18 +21,28 @@ * questions. */ -/* @test - @bug 6635110 - @key headful - @summary GTK icons should not throw NPE when called by non-GTK UI - @author Peter Zhelezniakov - @run main Test6635110 +/* + * @test + * @bug 6635110 + * @key headful + * @summary GTK icons should not throw NPE when called by non-GTK UI + * @requires (os.family != "windows" & os.family != "mac") + * @library /test/lib + * @build jtreg.SkippedException + * @run main Test6635110 */ -import javax.swing.*; -import java.awt.*; +import java.awt.Component; import java.awt.image.BufferedImage; -import javax.swing.plaf.basic.*; + +import javax.swing.JMenu; +import javax.swing.JToolBar; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.plaf.basic.BasicMenuUI; +import javax.swing.plaf.basic.BasicToolBarUI; + +import jtreg.SkippedException; public class Test6635110 implements Runnable { @@ -53,7 +63,7 @@ public class Test6635110 implements Runnable { paint(tb); } - void paint(Component c) { + private void paint(Component c) { c.setSize(WIDTH, HEIGHT); c.paint(IMAGE.getGraphics()); } @@ -62,9 +72,9 @@ public static void main(String[] args) throws Exception { try { UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); } catch (Exception e) { - System.out.println("GTKLookAndFeel cannot be set, skipping this test"); - return; + throw new SkippedException("GTKLookAndFeel isn't supported", e); } + SwingUtilities.invokeAndWait(new Test6635110()); } } diff --git a/test/jdk/com/sun/java/swing/plaf/gtk/Test6963870.java b/test/jdk/com/sun/java/swing/plaf/gtk/Test6963870.java index 962a2d1a0af..ea072419a59 100644 --- a/test/jdk/com/sun/java/swing/plaf/gtk/Test6963870.java +++ b/test/jdk/com/sun/java/swing/plaf/gtk/Test6963870.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,23 +21,28 @@ * questions. */ -/* @test - @bug 6963870 - @key headful - @summary Tests that GTKPainter.ListTableFocusBorder.getBorderInsets() - doesn't return null - @author Peter Zhelezniakov - @run main Test6963870 -*/ +/* + * @test + * @bug 6963870 + * @key headful + * @summary Tests that GTKPainter.ListTableFocusBorder.getBorderInsets() + * doesn't return null + * @requires (os.family != "windows" & os.family != "mac") + * @library /test/lib + * @build jtreg.SkippedException + * @run main Test6963870 + */ import java.awt.Insets; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.border.Border; +import jtreg.SkippedException; + public class Test6963870 implements Runnable { - final static String[] UI_NAMES = { + static final String[] UI_NAMES = { "List.focusCellHighlightBorder", "List.focusSelectedCellHighlightBorder", "List.noFocusBorder", @@ -45,6 +50,7 @@ public class Test6963870 implements Runnable { "Table.focusSelectedCellHighlightBorder", }; + @Override public void run() { for (String uiName: UI_NAMES) { test(uiName); @@ -63,11 +69,9 @@ public static void main(String[] args) throws Exception { try { UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); } catch (Exception e) { - System.out.println("GTKLookAndFeel cannot be set, skipping this test"); - return; + throw new SkippedException("GTKLookAndFeel isn't supported", e); } SwingUtilities.invokeAndWait(new Test6963870()); } } - diff --git a/test/jdk/com/sun/jdi/JdbStopInNotificationThreadTest.java b/test/jdk/com/sun/jdi/JdbStopInNotificationThreadTest.java index 98a0d9d98ce..7490d26fe6f 100644 --- a/test/jdk/com/sun/jdi/JdbStopInNotificationThreadTest.java +++ b/test/jdk/com/sun/jdi/JdbStopInNotificationThreadTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -113,9 +113,11 @@ public class JdbStopInNotificationThreadTest extends JdbTest { private static final String DEBUGGEE_CLASS = JdbStopInNotificationThreadTestTarg.class.getName(); private static final String PATTERN1_TEMPLATE = "^Breakpoint hit: \"thread=Notification Thread\", " + "JdbStopInNotificationThreadTestTarg\\$1\\.handleNotification\\(\\), line=%LINE_NUMBER.*\\R%LINE_NUMBER\\s+System\\.out\\.println\\(\"Memory usage low!!!\"\\);.*"; + private static final String[] DEBUGGEE_OPTIONS = {"-Xmx256M"}; private JdbStopInNotificationThreadTest() { - super(DEBUGGEE_CLASS); + super(new LaunchOptions(DEBUGGEE_CLASS) + .addDebuggeeOptions(DEBUGGEE_OPTIONS)); } public static void main(String argv[]) { diff --git a/test/jdk/com/sun/jdi/ThreadMemoryLeakTest.java b/test/jdk/com/sun/jdi/ThreadMemoryLeakTest.java index ef44829f1f7..8ab3589ef7d 100644 --- a/test/jdk/com/sun/jdi/ThreadMemoryLeakTest.java +++ b/test/jdk/com/sun/jdi/ThreadMemoryLeakTest.java @@ -28,7 +28,7 @@ * * @comment Don't allow -Xcomp or -Xint as they impact memory useage and number of iterations. * Require compressed oops because not doing so increases memory usage. - * @requires (vm.compMode == "Xmixed") & vm.opt.final.UseCompressedOops + * @requires (vm.compMode == "Xmixed") & (vm.bits == 32 | vm.opt.final.UseCompressedOops) * @run build TestScaffold VMConnection TargetListener TargetAdapter * @run compile -g ThreadMemoryLeakTest.java * @comment run with -Xmx7m so any leak will quickly produce OOME diff --git a/test/jdk/com/sun/jdi/TwoThreadsTest.java b/test/jdk/com/sun/jdi/TwoThreadsTest.java index e38783f3ea6..e5732ffd8d1 100644 --- a/test/jdk/com/sun/jdi/TwoThreadsTest.java +++ b/test/jdk/com/sun/jdi/TwoThreadsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,6 +55,13 @@ public static void main(String[] args) { t1.start(); t2.start(); + // The threads might be virtual and daemon, so wait until completion. + try { + t1.join(); + t2.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } } diff --git a/test/jdk/com/sun/jndi/ldap/LdapPoolTimeoutTest.java b/test/jdk/com/sun/jndi/ldap/LdapPoolTimeoutTest.java index 123c5120daf..d7d0f9a8392 100644 --- a/test/jdk/com/sun/jndi/ldap/LdapPoolTimeoutTest.java +++ b/test/jdk/com/sun/jndi/ldap/LdapPoolTimeoutTest.java @@ -35,6 +35,8 @@ import javax.naming.Context; import javax.naming.NamingException; import javax.naming.directory.InitialDirContext; + +import java.net.SocketTimeoutException; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; @@ -82,14 +84,10 @@ public void test() throws Exception { env.put(Context.PROVIDER_URL, "ldap://example.com:1234"); try { - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); + // launch a few concurrent connection attempts + for (int i = 0; i < 8; i++) { + futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); + } } finally { executorService.shutdown(); } @@ -109,39 +107,56 @@ public void test() throws Exception { private static void attemptConnect(Hashtable env) throws Exception { try { - LdapTimeoutTest.assertCompletion(CONNECT_MILLIS - 1000, - 2 * CONNECT_MILLIS + TOLERANCE, - () -> new InitialDirContext(env)); - } catch (RuntimeException e) { - final String msg = e.getCause() == null ? e.getMessage() : e.getCause().getMessage(); - // assertCompletion may wrap a CommunicationException in an RTE - if (msg != null && - (msg.contains("Network is unreachable") - || msg.contains("No route to host") - || msg.contains("Connection timed out"))) { - // got the expected exception - System.out.println("Received expected RuntimeException message: " + msg); - } else { - // propagate the unexpected exception - throw e; + final InitialDirContext unexpectedCtx = + LdapTimeoutTest.assertCompletion(CONNECT_MILLIS - 1000, + 2 * CONNECT_MILLIS + TOLERANCE, + () -> new InitialDirContext(env)); + throw new RuntimeException("InitialDirContext construction was expected to fail," + + " but returned " + unexpectedCtx); + } catch (Throwable t) { + final NamingException namingEx = findNamingException(t); + if (namingEx != null) { + // found the NamingException, verify it's the right reason + if (namingEx.getCause() instanceof SocketTimeoutException ste) { + // got the expected exception + System.out.println("Received expected SocketTimeoutException: " + ste); + return; + } + // rely on the exception message to verify the expected exception + final String msg = namingEx.getCause() == null + ? namingEx.getMessage() + : namingEx.getCause().getMessage(); + if (msg != null && + (msg.contains("Network is unreachable") + || msg.contains("No route to host") + || msg.contains("Timed out waiting for lock") + || msg.contains("Connect timed out") + || msg.contains("Timeout exceeded while waiting for a connection"))) { + // got the expected exception + System.out.println("Received expected NamingException with message: " + msg); + return; + } } - } catch (NamingException ex) { - final String msg = ex.getCause() == null ? ex.getMessage() : ex.getCause().getMessage(); - if (msg != null && - (msg.contains("Network is unreachable") - || msg.contains("Timed out waiting for lock") - || msg.contains("Connect timed out") - || msg.contains("Timeout exceeded while waiting for a connection"))) { - // got the expected exception - System.out.println("Received expected NamingException message: " + msg); + // unexpected exception, propagate it + if (t instanceof Exception e) { + throw e; } else { - // propagate the unexpected exception - throw ex; + throw new Exception(t); } - } catch (Throwable t) { - throw new RuntimeException(t); } } + // Find and return the NamingException from the given Throwable. Returns null if none found. + private static NamingException findNamingException(final Throwable t) { + Throwable cause = t; + while (cause != null) { + if (cause instanceof NamingException ne) { + return ne; + } + cause = cause.getCause(); + } + return null; + } + } diff --git a/test/jdk/com/sun/net/httpserver/FileServerHandler.java b/test/jdk/com/sun/net/httpserver/FileServerHandler.java index 849b5fd06de..509adf7bf72 100644 --- a/test/jdk/com/sun/net/httpserver/FileServerHandler.java +++ b/test/jdk/com/sun/net/httpserver/FileServerHandler.java @@ -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 @@ -43,7 +43,6 @@ public FileServerHandler (String docroot) { this.docroot = docroot; } - int invocation = 1; public void handle (HttpExchange t) throws IOException { @@ -87,16 +86,16 @@ public void handle (HttpExchange t) rmap.set ("Content-Type", "text/html"); t.sendResponseHeaders (200, 0); String[] list = f.list(); - OutputStream os = t.getResponseBody(); - PrintStream p = new PrintStream (os); - p.println ("

    Directory listing for: " + path+ "

    "); - p.println ("
      "); - for (int i=0; i"+list[i]+""); + try (final OutputStream os = t.getResponseBody(); + final PrintStream p = new PrintStream (os)) { + p.println("

      Directory listing for: " + path + "

      "); + p.println("
        "); + for (int i = 0; i < list.length; i++) { + p.println("
      • " + list[i] + "
      • "); + } + p.println("


      "); + p.flush(); } - p.println ("


    "); - p.flush(); - p.close(); } else { int clen; if (fixedrequest != null) { @@ -105,10 +104,9 @@ public void handle (HttpExchange t) clen = 0; } t.sendResponseHeaders (200, clen); - OutputStream os = t.getResponseBody(); - FileInputStream fis = new FileInputStream (f); int count = 0; - try { + try (final OutputStream os = t.getResponseBody(); + final FileInputStream fis = new FileInputStream (f)) { byte[] buf = new byte [16 * 1024]; int len; while ((len=fis.read (buf)) != -1) { @@ -118,8 +116,6 @@ public void handle (HttpExchange t) } catch (IOException e) { e.printStackTrace(); } - fis.close(); - os.close(); } } diff --git a/test/jdk/com/sun/net/httpserver/ServerStopTerminationTest.java b/test/jdk/com/sun/net/httpserver/ServerStopTerminationTest.java index 81561160725..e8f365b715b 100644 --- a/test/jdk/com/sun/net/httpserver/ServerStopTerminationTest.java +++ b/test/jdk/com/sun/net/httpserver/ServerStopTerminationTest.java @@ -124,13 +124,16 @@ public void shouldAwaitActiveExchange() throws InterruptedException { // Complete the exchange one second into the future final Duration exchangeDuration = Duration.ofSeconds(1); + // taking start time before entering completeExchange to account for possible + // delays in reaching server.stop(). + final long startTime = System.nanoTime(); completeExchange(exchangeDuration); log("Complete Exchange triggered"); // Time the shutdown sequence - final Duration delayDuration = Duration.ofSeconds(Utils.adjustTimeout(5)); + final Duration delayDuration = Duration.ofSeconds(Utils.adjustTimeout(20)); log("Shutdown triggered with the delay of " + delayDuration.getSeconds()); - final long elapsed = timeShutdown(delayDuration); + final long elapsed = timeShutdown(delayDuration, startTime); log("Shutdown complete"); // The shutdown should take at least as long as the exchange duration @@ -151,31 +154,20 @@ public void shouldAwaitActiveExchange() throws InterruptedException { * @throws InterruptedException if an unexpected interruption occurs */ @Test - public void shouldCompeteAfterDelay() throws InterruptedException { + public void shouldCompleteAfterDelay() throws InterruptedException { // Initiate an exchange startExchange(); // Wait for the server to receive the exchange start.await(); log("Exchange started"); - // Complete the exchange 10 second into the future. - // Runs in parallel, so won't block the server stop - final Duration exchangeDuration = Duration.ofSeconds(Utils.adjustTimeout(10)); - completeExchange(exchangeDuration); - log("Complete Exchange triggered"); - - // Time the shutdown sequence final Duration delayDuration = Duration.ofSeconds(1); log("Shutdown triggered with the delay of " + delayDuration.getSeconds()); final long elapsed = timeShutdown(delayDuration); log("Shutdown complete"); - - - // The shutdown should not await the exchange to complete - if (elapsed >= exchangeDuration.toNanos()) { - fail("HttpServer.stop terminated too late"); - } + complete.countDown(); + log("Exchange completed"); // The shutdown delay should have expired if (elapsed < delayDuration.toNanos()) { @@ -277,7 +269,14 @@ public void shouldAllowRepeatedStop() { */ private long timeShutdown(Duration delayDuration) { final long startTime = System.nanoTime(); + return timeShutdown(delayDuration, startTime); + } + /** + * This allows passing a custom start time + */ + private long timeShutdown(Duration delayDuration, + long startTime) { server.stop((int) delayDuration.toSeconds()); return System.nanoTime() - startTime; } diff --git a/test/jdk/com/sun/net/httpserver/Test12.java b/test/jdk/com/sun/net/httpserver/Test12.java index ab1d9d548e7..2a0ee1fc0a4 100644 --- a/test/jdk/com/sun/net/httpserver/Test12.java +++ b/test/jdk/com/sun/net/httpserver/Test12.java @@ -21,23 +21,12 @@ * questions. */ -/* - * @test - * @bug 6270015 - * @library /test/lib - * @build jdk.test.lib.Asserts - * jdk.test.lib.Utils - * jdk.test.lib.net.SimpleSSLContext - * jdk.test.lib.net.URIBuilder - * @run main/othervm Test12 - * @run main/othervm -Djava.net.preferIPv6Addresses=true Test12 - * @summary Light weight HTTP server - */ - import com.sun.net.httpserver.*; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.*; import java.io.*; import java.net.*; @@ -49,11 +38,19 @@ import static jdk.test.lib.Asserts.assertFileContentsEqual; import static jdk.test.lib.Utils.createTempFileOfSize; -/* basic http/s connectivity test - * Tests: - * - same as Test1, but in parallel +/* + * @test + * @bug 6270015 8359477 + * @summary Light weight HTTP server - basic http/s connectivity test, same as Test1, + * but in parallel + * @library /test/lib + * @build jdk.test.lib.Asserts + * jdk.test.lib.Utils + * jdk.test.lib.net.SimpleSSLContext + * jdk.test.lib.net.URIBuilder + * @run main/othervm Test12 + * @run main/othervm -Djava.net.preferIPv6Addresses=true Test12 */ - public class Test12 extends Test { private static final String TEMP_FILE_PREFIX = @@ -61,14 +58,12 @@ public class Test12 extends Test { static SSLContext ctx; - static boolean fail = false; - public static void main (String[] args) throws Exception { HttpServer s1 = null; HttpsServer s2 = null; - ExecutorService executor=null; Path smallFilePath = createTempFileOfSize(TEMP_FILE_PREFIX, null, 23); Path largeFilePath = createTempFileOfSize(TEMP_FILE_PREFIX, null, 2730088); + final ExecutorService executor = Executors.newCachedThreadPool(); try { System.out.print ("Test12: "); InetAddress loopback = InetAddress.getLoopbackAddress(); @@ -80,7 +75,6 @@ public static void main (String[] args) throws Exception { HttpHandler h = new FileServerHandler(smallFilePath.getParent().toString()); HttpContext c1 = s1.createContext ("/", h); HttpContext c2 = s2.createContext ("/", h); - executor = Executors.newCachedThreadPool(); s1.setExecutor (executor); s2.setExecutor (executor); ctx = new SimpleSSLContext().get(); @@ -90,7 +84,7 @@ public static void main (String[] args) throws Exception { int port = s1.getAddress().getPort(); int httpsport = s2.getAddress().getPort(); - Runner r[] = new Runner[8]; + final Runner[] r = new Runner[8]; r[0] = new Runner (true, "http", port, smallFilePath); r[1] = new Runner (true, "http", port, largeFilePath); r[2] = new Runner (true, "https", httpsport, smallFilePath); @@ -99,95 +93,83 @@ public static void main (String[] args) throws Exception { r[5] = new Runner (false, "http", port, largeFilePath); r[6] = new Runner (false, "https", httpsport, smallFilePath); r[7] = new Runner (false, "https", httpsport, largeFilePath); - start (r); - join (r); - System.out.println ("OK"); + // submit the tasks + final List> futures = new ArrayList<>(); + for (Runner runner : r) { + futures.add(executor.submit(runner)); + } + // wait for the tasks' completion + for (Future f : futures) { + f.get(); + } + System.out.println ("All " + futures.size() + " tasks completed successfully"); } finally { - if (s1 != null) + if (s1 != null) { s1.stop(0); - if (s2 != null) + } + if (s2 != null) { s2.stop(0); - if (executor != null) - executor.shutdown (); + } + executor.close(); + // it's OK to delete these files since the server side handlers + // serving these files have completed (guaranteed by the completion of Executor.close()) + System.out.println("deleting " + smallFilePath); Files.delete(smallFilePath); + System.out.println("deleting " + largeFilePath); Files.delete(largeFilePath); } } - static void start (Runner[] x) { - for (int i=0; i { boolean fixedLen; String protocol; int port; private final Path filePath; - Runner (boolean fixedLen, String protocol, int port, Path filePath) { + Runner(boolean fixedLen, String protocol, int port, Path filePath) { this.fixedLen=fixedLen; this.protocol=protocol; this.port=port; this.filePath = filePath; } - public void run () { - try { - URL url = URIBuilder.newBuilder() - .scheme(protocol) - .loopback() - .port(port) - .path("/" + filePath.getFileName()) - .toURL(); - HttpURLConnection urlc = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY); - if (urlc instanceof HttpsURLConnection) { - HttpsURLConnection urlcs = (HttpsURLConnection) urlc; - urlcs.setHostnameVerifier (new HostnameVerifier () { - public boolean verify (String s, SSLSession s1) { - return true; - } - }); - urlcs.setSSLSocketFactory (ctx.getSocketFactory()); - } - byte [] buf = new byte [4096]; - - if (fixedLen) { - urlc.setRequestProperty ("XFixed", "yes"); - } - InputStream is = urlc.getInputStream(); - File temp = File.createTempFile ("Test1", null); - temp.deleteOnExit(); - OutputStream fout = new BufferedOutputStream (new FileOutputStream(temp)); - int c, count = 0; - while ((c=is.read(buf)) != -1) { - count += c; - fout.write (buf, 0, c); - } - is.close(); - fout.close(); - - if (count != filePath.toFile().length()) { - throw new RuntimeException ("wrong amount of data returned"); - } - assertFileContentsEqual(filePath, temp.toPath()); - temp.delete(); - } catch (Exception e) { - e.printStackTrace(); - fail = true; + @Override + public Void call() throws Exception { + final URL url = URIBuilder.newBuilder() + .scheme(protocol) + .loopback() + .port(port) + .path("/" + filePath.getFileName()) + .toURL(); + final HttpURLConnection urlc = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY); + if (urlc instanceof HttpsURLConnection) { + HttpsURLConnection urlcs = (HttpsURLConnection) urlc; + urlcs.setHostnameVerifier (new HostnameVerifier () { + public boolean verify (String s, SSLSession s1) { + return true; + } + }); + urlcs.setSSLSocketFactory (ctx.getSocketFactory()); } + if (fixedLen) { + urlc.setRequestProperty ("XFixed", "yes"); + } + final Path temp = Files.createTempFile(Path.of("."), "Test12", null); + final long numReceived; + try (InputStream is = urlc.getInputStream(); + OutputStream fout = new BufferedOutputStream(new FileOutputStream(temp.toFile()))) { + numReceived = is.transferTo(fout); + } + System.out.println("received " + numReceived + " response bytes for " + url); + final long expected = filePath.toFile().length(); + if (numReceived != expected) { + throw new RuntimeException ("expected " + expected + " bytes, but received " + + numReceived); + } + assertFileContentsEqual(filePath, temp); + Files.delete(temp); + return null; } } - } diff --git a/test/jdk/com/sun/net/httpserver/Test9.java b/test/jdk/com/sun/net/httpserver/Test9.java index 6f7b1d4f5bc..6051de96596 100644 --- a/test/jdk/com/sun/net/httpserver/Test9.java +++ b/test/jdk/com/sun/net/httpserver/Test9.java @@ -59,7 +59,7 @@ public class Test9 extends Test { HttpServer.class.getPackageName() + '-' + Test9.class.getSimpleName() + '-'; static SSLContext ctx; - static boolean error = false; + static volatile boolean error = false; public static void main (String[] args) throws Exception { HttpServer s1 = null; @@ -67,6 +67,8 @@ public static void main (String[] args) throws Exception { ExecutorService executor=null; Path smallFilePath = createTempFileOfSize(TEMP_FILE_PREFIX, null, 23); Path largeFilePath = createTempFileOfSize(TEMP_FILE_PREFIX, null, 2730088); + smallFilePath.toFile().deleteOnExit(); + largeFilePath.toFile().deleteOnExit(); try { System.out.print ("Test9: "); InetAddress loopback = InetAddress.getLoopbackAddress(); @@ -122,20 +124,16 @@ public static void main (String[] args) throws Exception { s2.stop(0); if (executor != null) executor.shutdown (); - Files.delete(smallFilePath); - Files.delete(largeFilePath); } } - static int foo = 1; - static ClientThread test (boolean fixedLen, String protocol, int port, Path filePath) throws Exception { ClientThread t = new ClientThread (fixedLen, protocol, port, filePath); t.start(); return t; } - static Object fileLock = new Object(); + static final Object fileLock = new Object(); static class ClientThread extends Thread { @@ -203,9 +201,8 @@ public boolean verify (String s, SSLSession s1) { error = true; } assertFileContentsEqual(filePath, temp.toPath()); - temp.delete(); } catch (Exception e) { - e.printStackTrace(); + System.err.println("Error occurred: " + e); error = true; } } diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/CustomFileSystemTest.java b/test/jdk/com/sun/net/httpserver/simpleserver/CustomFileSystemTest.java index d6ec3eb0695..0a46ac1ea8a 100644 --- a/test/jdk/com/sun/net/httpserver/simpleserver/CustomFileSystemTest.java +++ b/test/jdk/com/sun/net/httpserver/simpleserver/CustomFileSystemTest.java @@ -256,63 +256,65 @@ public void testDirectoryWithIndexGET(String id, @Test public void testNotReadableFileGET() throws Exception { - if (!Platform.isWindows()) { // not applicable on Windows - var expectedBody = openHTML + """ -

    File not found

    -

    /aFile.txt

    - """ + closeHTML; - var expectedLength = Integer.toString(expectedBody.getBytes(UTF_8).length); - var root = createDirectoryInCustomFs("testNotReadableFileGET"); - var file = Files.writeString(root.resolve("aFile.txt"), "some text", CREATE); - - file.toFile().setReadable(false, false); - assert !Files.isReadable(file); - - var server = SimpleFileServer.createFileServer(LOOPBACK_ADDR, root, OutputLevel.VERBOSE); - server.start(); - try { - var client = HttpClient.newBuilder().proxy(NO_PROXY).build(); - var request = HttpRequest.newBuilder(uri(server, "aFile.txt")).build(); - var response = client.send(request, BodyHandlers.ofString()); - assertEquals(response.statusCode(), 404); - assertEquals(response.headers().firstValue("content-length").get(), expectedLength); - assertEquals(response.body(), expectedBody); - } finally { - server.stop(0); - file.toFile().setReadable(true, false); - } + if (Platform.isWindows()) { + throw new SkipException("Not applicable on Windows"); + } + var expectedBody = openHTML + """ +

    File not found

    +

    /aFile.txt

    + """ + closeHTML; + var expectedLength = Integer.toString(expectedBody.getBytes(UTF_8).length); + var root = createDirectoryInCustomFs("testNotReadableFileGET"); + var file = Files.writeString(root.resolve("aFile.txt"), "some text", CREATE); + + file.toFile().setReadable(false, false); + assert !Files.isReadable(file); + + var server = SimpleFileServer.createFileServer(LOOPBACK_ADDR, root, OutputLevel.VERBOSE); + server.start(); + try { + var client = HttpClient.newBuilder().proxy(NO_PROXY).build(); + var request = HttpRequest.newBuilder(uri(server, "aFile.txt")).build(); + var response = client.send(request, BodyHandlers.ofString()); + assertEquals(response.statusCode(), 404); + assertEquals(response.headers().firstValue("content-length").get(), expectedLength); + assertEquals(response.body(), expectedBody); + } finally { + server.stop(0); + file.toFile().setReadable(true, false); } } @Test public void testNotReadableSegmentGET() throws Exception { - if (!Platform.isWindows()) { // not applicable on Windows - var expectedBody = openHTML + """ -

    File not found

    -

    /dir/aFile.txt

    - """ + closeHTML; - var expectedLength = Integer.toString(expectedBody.getBytes(UTF_8).length); - var root = createDirectoryInCustomFs("testNotReadableSegmentGET"); - var dir = Files.createDirectory(root.resolve("dir")); - var file = Files.writeString(dir.resolve("aFile.txt"), "some text", CREATE); - - dir.toFile().setReadable(false, false); - assert !Files.isReadable(dir); - assert Files.isReadable(file); - - var server = SimpleFileServer.createFileServer(LOOPBACK_ADDR, root, OutputLevel.VERBOSE); - server.start(); - try { - var client = HttpClient.newBuilder().proxy(NO_PROXY).build(); - var request = HttpRequest.newBuilder(uri(server, "dir/aFile.txt")).build(); - var response = client.send(request, BodyHandlers.ofString()); - assertEquals(response.statusCode(), 404); - assertEquals(response.headers().firstValue("content-length").get(), expectedLength); - assertEquals(response.body(), expectedBody); - } finally { - server.stop(0); - dir.toFile().setReadable(true, false); - } + if (Platform.isWindows()) { + throw new SkipException("Not applicable on Windows"); + } + var expectedBody = openHTML + """ +

    File not found

    +

    /dir/aFile.txt

    + """ + closeHTML; + var expectedLength = Integer.toString(expectedBody.getBytes(UTF_8).length); + var root = createDirectoryInCustomFs("testNotReadableSegmentGET"); + var dir = Files.createDirectory(root.resolve("dir")); + var file = Files.writeString(dir.resolve("aFile.txt"), "some text", CREATE); + + dir.toFile().setReadable(false, false); + assert !Files.isReadable(dir); + assert Files.isReadable(file); + + var server = SimpleFileServer.createFileServer(LOOPBACK_ADDR, root, OutputLevel.VERBOSE); + server.start(); + try { + var client = HttpClient.newBuilder().proxy(NO_PROXY).build(); + var request = HttpRequest.newBuilder(uri(server, "dir/aFile.txt")).build(); + var response = client.send(request, BodyHandlers.ofString()); + assertEquals(response.statusCode(), 404); + assertEquals(response.headers().firstValue("content-length").get(), expectedLength); + assertEquals(response.body(), expectedBody); + } finally { + server.stop(0); + dir.toFile().setReadable(true, false); } } diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/SimpleFileServerTest.java b/test/jdk/com/sun/net/httpserver/simpleserver/SimpleFileServerTest.java index ea1c73b361b..167fcd3b5d3 100644 --- a/test/jdk/com/sun/net/httpserver/simpleserver/SimpleFileServerTest.java +++ b/test/jdk/com/sun/net/httpserver/simpleserver/SimpleFileServerTest.java @@ -309,63 +309,65 @@ public void testDirectoryWithIndexGET(String id, @Test public void testNotReadableFileGET() throws Exception { - if (!Platform.isWindows()) { // not applicable on Windows - var expectedBody = openHTML + """ -

    File not found

    -

    /aFile.txt

    - """ + closeHTML; - var expectedLength = Integer.toString(expectedBody.getBytes(UTF_8).length); - var root = Files.createDirectory(TEST_DIR.resolve("testNotReadableFileGET")); - var file = Files.writeString(root.resolve("aFile.txt"), "some text", CREATE); + if (Platform.isWindows()) { + throw new SkipException("Not applicable on Windows"); + } + var expectedBody = openHTML + """ +

    File not found

    +

    /aFile.txt

    + """ + closeHTML; + var expectedLength = Integer.toString(expectedBody.getBytes(UTF_8).length); + var root = Files.createDirectory(TEST_DIR.resolve("testNotReadableFileGET")); + var file = Files.writeString(root.resolve("aFile.txt"), "some text", CREATE); - file.toFile().setReadable(false, false); - assert !Files.isReadable(file); + file.toFile().setReadable(false, false); + assert !Files.isReadable(file); - var server = SimpleFileServer.createFileServer(LOOPBACK_ADDR, root, OutputLevel.VERBOSE); - server.start(); - try { - var client = HttpClient.newBuilder().proxy(NO_PROXY).build(); - var request = HttpRequest.newBuilder(uri(server, "aFile.txt")).build(); - var response = client.send(request, BodyHandlers.ofString()); - assertEquals(response.statusCode(), 404); - assertEquals(response.headers().firstValue("content-length").get(), expectedLength); - assertEquals(response.body(), expectedBody); - } finally { - server.stop(0); - file.toFile().setReadable(true, false); - } + var server = SimpleFileServer.createFileServer(LOOPBACK_ADDR, root, OutputLevel.VERBOSE); + server.start(); + try { + var client = HttpClient.newBuilder().proxy(NO_PROXY).build(); + var request = HttpRequest.newBuilder(uri(server, "aFile.txt")).build(); + var response = client.send(request, BodyHandlers.ofString()); + assertEquals(response.statusCode(), 404); + assertEquals(response.headers().firstValue("content-length").get(), expectedLength); + assertEquals(response.body(), expectedBody); + } finally { + server.stop(0); + file.toFile().setReadable(true, false); } } @Test public void testNotReadableSegmentGET() throws Exception { - if (!Platform.isWindows()) { // not applicable on Windows - var expectedBody = openHTML + """ -

    File not found

    -

    /dir/aFile.txt

    - """ + closeHTML; - var expectedLength = Integer.toString(expectedBody.getBytes(UTF_8).length); - var root = Files.createDirectory(TEST_DIR.resolve("testNotReadableSegmentGET")); - var dir = Files.createDirectory(root.resolve("dir")); - var file = Files.writeString(dir.resolve("aFile.txt"), "some text", CREATE); + if (Platform.isWindows()) { + throw new SkipException("Not applicable on Windows"); + } + var expectedBody = openHTML + """ +

    File not found

    +

    /dir/aFile.txt

    + """ + closeHTML; + var expectedLength = Integer.toString(expectedBody.getBytes(UTF_8).length); + var root = Files.createDirectory(TEST_DIR.resolve("testNotReadableSegmentGET")); + var dir = Files.createDirectory(root.resolve("dir")); + var file = Files.writeString(dir.resolve("aFile.txt"), "some text", CREATE); - dir.toFile().setReadable(false, false); - assert !Files.isReadable(dir); - assert Files.isReadable(file); + dir.toFile().setReadable(false, false); + assert !Files.isReadable(dir); + assert Files.isReadable(file); - var server = SimpleFileServer.createFileServer(LOOPBACK_ADDR, root, OutputLevel.VERBOSE); - server.start(); - try { - var client = HttpClient.newBuilder().proxy(NO_PROXY).build(); - var request = HttpRequest.newBuilder(uri(server, "dir/aFile.txt")).build(); - var response = client.send(request, BodyHandlers.ofString()); - assertEquals(response.statusCode(), 404); - assertEquals(response.headers().firstValue("content-length").get(), expectedLength); - assertEquals(response.body(), expectedBody); - } finally { - server.stop(0); - dir.toFile().setReadable(true, false); - } + var server = SimpleFileServer.createFileServer(LOOPBACK_ADDR, root, OutputLevel.VERBOSE); + server.start(); + try { + var client = HttpClient.newBuilder().proxy(NO_PROXY).build(); + var request = HttpRequest.newBuilder(uri(server, "dir/aFile.txt")).build(); + var response = client.send(request, BodyHandlers.ofString()); + assertEquals(response.statusCode(), 404); + assertEquals(response.headers().firstValue("content-length").get(), expectedLength); + assertEquals(response.body(), expectedBody); + } finally { + server.stop(0); + dir.toFile().setReadable(true, false); } } @@ -680,18 +682,22 @@ public void testIllegalPath() throws Exception { var iae = expectThrows(IAE, () -> SimpleFileServer.createFileServer(addr, p, OutputLevel.INFO)); assertTrue(iae.getMessage().contains("does not exist")); } - { // not readable - if (!Platform.isWindows()) { // not applicable on Windows - Path p = Files.createDirectory(TEST_DIR.resolve("aDir")); - p.toFile().setReadable(false, false); - assert !Files.isReadable(p); - try { - var iae = expectThrows(IAE, () -> SimpleFileServer.createFileServer(addr, p, OutputLevel.INFO)); - assertTrue(iae.getMessage().contains("not readable")); - } finally { - p.toFile().setReadable(true, false); - } - } + } + + @Test + public void testNonReadablePath() throws Exception { + if (Platform.isWindows()) { + throw new SkipException("Not applicable on Windows"); + } + var addr = LOOPBACK_ADDR; + Path p = Files.createDirectory(TEST_DIR.resolve("aDir")); + p.toFile().setReadable(false, false); + assert !Files.isReadable(p); + try { + var iae = expectThrows(IAE, () -> SimpleFileServer.createFileServer(addr, p, OutputLevel.INFO)); + assertTrue(iae.getMessage().contains("not readable")); + } finally { + p.toFile().setReadable(true, false); } } diff --git a/test/jdk/com/sun/nio/sctp/SctpChannel/Bind.java b/test/jdk/com/sun/nio/sctp/SctpChannel/Bind.java index 027f31695ae..ff5ca00846c 100644 --- a/test/jdk/com/sun/nio/sctp/SctpChannel/Bind.java +++ b/test/jdk/com/sun/nio/sctp/SctpChannel/Bind.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * 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 * @bug 4927640 + * @library /test/lib * @summary Tests the SCTP protocol implementation * @author chegar */ @@ -48,18 +49,14 @@ import com.sun.nio.sctp.ShutdownNotification; import static java.lang.System.out; +import jtreg.SkippedException; + /** * Tests bind, bindAddress, unbindAddress, getLocalAddress, and * getAllLocalAddresses. */ public class Bind { void test(String[] args) { - if (!Util.isSCTPSupported()) { - out.println("SCTP protocol is not supported"); - out.println("Test cannot be run"); - return; - } - /* Simply bind tests */ testBind(); @@ -341,6 +338,10 @@ class UnsupportedSocketAddress extends SocketAddress { } void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);} void debug(String message) {if(debug) { System.out.println(message); } } public static void main(String[] args) throws Throwable { + if (!Util.isSCTPSupported()) { + throw new SkippedException("SCTP protocol is not supported"); + } + Class k = new Object(){}.getClass().getEnclosingClass(); try {k.getMethod("instanceMain",String[].class) .invoke( k.newInstance(), (Object) args);} diff --git a/test/jdk/com/sun/nio/sctp/SctpChannel/CloseDescriptors.java b/test/jdk/com/sun/nio/sctp/SctpChannel/CloseDescriptors.java index 0b3ce6ae039..5d62b88f23e 100644 --- a/test/jdk/com/sun/nio/sctp/SctpChannel/CloseDescriptors.java +++ b/test/jdk/com/sun/nio/sctp/SctpChannel/CloseDescriptors.java @@ -24,6 +24,7 @@ /* * @test * @bug 8238274 + * @key intermittent * @summary Potential leak file descriptor for SCTP * @requires (os.family == "linux") * @library /test/lib @@ -45,6 +46,8 @@ import com.sun.nio.sctp.SctpChannel; import com.sun.nio.sctp.SctpServerChannel; +import jtreg.SkippedException; + public class CloseDescriptors { private static Selector selector; private static final int LOOP = 10; @@ -54,7 +57,7 @@ public class CloseDescriptors { public static void main(String[] args) throws Exception { if (!Util.isSCTPSupported()) { - throw new jtreg.SkippedException("SCTP protocol is not supported"); + throw new SkippedException("SCTP protocol is not supported"); } List lsofDirs = List.of("/usr/bin", "/usr/sbin"); @@ -63,7 +66,7 @@ public static void main(String[] args) throws Exception { .filter(f -> Files.isExecutable(f)) .findFirst(); if (!lsof.isPresent()) { - throw new jtreg.SkippedException("Cannot locate lsof in " + lsofDirs); + throw new SkippedException("Cannot locate lsof in " + lsofDirs); } try (ServerSocket ss = new ServerSocket(0)) { diff --git a/test/jdk/com/sun/nio/sctp/SctpChannel/CommUp.java b/test/jdk/com/sun/nio/sctp/SctpChannel/CommUp.java index 8cbe034b00d..320e556f800 100644 --- a/test/jdk/com/sun/nio/sctp/SctpChannel/CommUp.java +++ b/test/jdk/com/sun/nio/sctp/SctpChannel/CommUp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * 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 * @bug 6863110 + * @library /test/lib * @summary Newly connected/accepted SctpChannel should fire OP_READ if registered with a Selector * @author chegar */ @@ -49,6 +50,8 @@ import static java.nio.channels.SelectionKey.OP_CONNECT; import static java.nio.channels.SelectionKey.OP_READ; +import jtreg.SkippedException; + public class CommUp { static CountDownLatch acceptLatch = new CountDownLatch(1); static final int TIMEOUT = 10000; @@ -61,12 +64,6 @@ public class CommUp { void test(String[] args) { SocketAddress address = null; - if (!Util.isSCTPSupported()) { - out.println("SCTP protocol is not supported"); - out.println("Test cannot be run"); - return; - } - if (args.length == 2) { /* requested to connecct to a specific address */ try { @@ -355,6 +352,10 @@ public HandlerResult handleNotification( void sleep(long millis) { try { Thread.currentThread().sleep(millis); } catch(InterruptedException ie) { unexpected(ie); }} public static void main(String[] args) throws Throwable { + if (!Util.isSCTPSupported()) { + throw new SkippedException("SCTP protocol is not supported"); + } + Class k = new Object(){}.getClass().getEnclosingClass(); try {k.getMethod("instanceMain",String[].class) .invoke( k.newInstance(), (Object) args);} diff --git a/test/jdk/com/sun/nio/sctp/SctpChannel/Connect.java b/test/jdk/com/sun/nio/sctp/SctpChannel/Connect.java index fccc12a9f06..4a8df971bad 100644 --- a/test/jdk/com/sun/nio/sctp/SctpChannel/Connect.java +++ b/test/jdk/com/sun/nio/sctp/SctpChannel/Connect.java @@ -23,6 +23,7 @@ /* @test * @bug 4927640 + * @library /test/lib * @summary Tests the SCTP protocol implementation * @author chegar */ @@ -43,6 +44,8 @@ import static java.lang.System.out; import static java.lang.System.err; +import jtreg.SkippedException; + /** * Tests connect, finishConnect, isConnectionPending, * getRemoteAddresses and association. @@ -50,12 +53,6 @@ public class Connect { void test(String[] args) { - if (!Util.isSCTPSupported()) { - out.println("SCTP protocol is not supported"); - out.println("Test cannot be run"); - return; - } - doTest(); } @@ -235,6 +232,10 @@ void testCCE(Callable callable) { void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);} void debug(String message) {if(debug) { System.out.println(message); } } public static void main(String[] args) throws Throwable { + if (!Util.isSCTPSupported()) { + throw new SkippedException("SCTP protocol is not supported"); + } + Class k = new Object(){}.getClass().getEnclosingClass(); try {k.getMethod("instanceMain",String[].class) .invoke( k.newInstance(), (Object) args);} diff --git a/test/jdk/com/sun/nio/sctp/SctpChannel/Receive.java b/test/jdk/com/sun/nio/sctp/SctpChannel/Receive.java index 23005bbf849..48eb413a9ca 100644 --- a/test/jdk/com/sun/nio/sctp/SctpChannel/Receive.java +++ b/test/jdk/com/sun/nio/sctp/SctpChannel/Receive.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * 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 * @bug 4927640 + * @library /test/lib * @summary Tests the SCTP protocol implementation * @author chegar */ @@ -48,6 +49,8 @@ import static java.lang.System.out; import static java.lang.System.err; +import jtreg.SkippedException; + public class Receive { /* Latches used to synchronize between the client and server so that * connections without any IO may not be closed without being accepted */ @@ -61,13 +64,6 @@ void test(String[] args) { SocketAddress address = null; Server server; - - if (!Util.isSCTPSupported()) { - out.println("SCTP protocol is not supported"); - out.println("Test cannot be run"); - return; - } - if (args.length == 2) { /* requested to connecct to a specific address */ try { @@ -349,6 +345,10 @@ public HandlerResult handleNotification( void debug(String message) {if(debug) { System.out.println(Thread.currentThread() + " " + message); } } public static void main(String[] args) throws Throwable { + if (!Util.isSCTPSupported()) { + throw new SkippedException("SCTP protocol is not supported"); + } + Class k = new Object(){}.getClass().getEnclosingClass(); try {k.getMethod("instanceMain",String[].class) .invoke( k.newInstance(), (Object) args);} diff --git a/test/jdk/com/sun/nio/sctp/SctpChannel/ReceiveIntoDirect.java b/test/jdk/com/sun/nio/sctp/SctpChannel/ReceiveIntoDirect.java index e7b23d0aaed..48d89c34ca4 100644 --- a/test/jdk/com/sun/nio/sctp/SctpChannel/ReceiveIntoDirect.java +++ b/test/jdk/com/sun/nio/sctp/SctpChannel/ReceiveIntoDirect.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* @test * @bug 8034181 + * @library /test/lib * @summary SIGBUS in SctpChannelImpl receive * @author chegar */ @@ -45,6 +46,8 @@ import static java.lang.System.err; import static java.nio.charset.StandardCharsets.US_ASCII; +import jtreg.SkippedException; + public class ReceiveIntoDirect { /* suitably small message to NOT overrun small buffers */ final byte[] msgBytes = "Hello".getBytes(US_ASCII); @@ -56,12 +59,6 @@ void test(String[] args) throws IOException { SocketAddress address = null; Server server; - if (!Util.isSCTPSupported()) { - out.println("SCTP protocol is not supported"); - out.println("Test cannot be run"); - return; - } - if (args.length == 2) { /* requested to connecct to a specific address */ try { @@ -264,6 +261,10 @@ public HandlerResult handleNotification( void debug(String message) {if(debug) { System.out.println(Thread.currentThread() + " " + message); } } public static void main(String[] args) throws Throwable { + if (!Util.isSCTPSupported()) { + throw new SkippedException("SCTP protocol is not supported"); + } + Class k = new Object(){}.getClass().getEnclosingClass(); try {k.getMethod("instanceMain",String[].class) .invoke( k.newInstance(), (Object) args);} diff --git a/test/jdk/com/sun/nio/sctp/SctpChannel/Send.java b/test/jdk/com/sun/nio/sctp/SctpChannel/Send.java index 93e462a1820..35a28f4eb38 100644 --- a/test/jdk/com/sun/nio/sctp/SctpChannel/Send.java +++ b/test/jdk/com/sun/nio/sctp/SctpChannel/Send.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * 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 * @bug 4927640 + * @library /test/lib * @summary Tests the SCTP protocol implementation * @author chegar */ @@ -48,6 +49,8 @@ import static java.lang.System.out; import static java.lang.System.err; +import jtreg.SkippedException; + public class Send { /* Latches used to synchronize between the client and server so that * connections without any IO may not be closed without being accepted */ @@ -60,12 +63,6 @@ void test(String[] args) { SocketAddress address = null; Server server = null; - if (!Util.isSCTPSupported()) { - out.println("SCTP protocol is not supported"); - out.println("Test cannot be run"); - return; - } - if (args.length == 2) { /* requested to connecct to a specific address */ try { @@ -451,6 +448,10 @@ public HandlerResult handleNotification( void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);} void debug(String message) {if(debug) { System.out.println(message); } } public static void main(String[] args) throws Throwable { + if (!Util.isSCTPSupported()) { + throw new SkippedException("SCTP protocol is not supported"); + } + Class k = new Object(){}.getClass().getEnclosingClass(); try {k.getMethod("instanceMain",String[].class) .invoke( k.newInstance(), (Object) args);} diff --git a/test/jdk/com/sun/nio/sctp/SctpChannel/Shutdown.java b/test/jdk/com/sun/nio/sctp/SctpChannel/Shutdown.java index 41ba744315c..0891851fe86 100644 --- a/test/jdk/com/sun/nio/sctp/SctpChannel/Shutdown.java +++ b/test/jdk/com/sun/nio/sctp/SctpChannel/Shutdown.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * 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 * @bug 4927640 + * @library /test/lib * @summary Tests the SCTP protocol implementation * @author chegar */ @@ -43,6 +44,8 @@ import static java.lang.System.out; import static java.lang.System.err; +import jtreg.SkippedException; + public class Shutdown { static CountDownLatch finishedLatch = new CountDownLatch(1); static CountDownLatch sentLatch = new CountDownLatch(1); @@ -51,12 +54,6 @@ void test(String[] args) { SocketAddress address = null; ShutdownServer server = null; - if (!Util.isSCTPSupported()) { - out.println("SCTP protocol is not supported"); - out.println("Test cannot be run"); - return; - } - if (args.length == 2) { /* requested to connecct to a specific address */ try { @@ -272,6 +269,10 @@ public HandlerResult handleNotification( void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);} void debug(String message) {if(debug) { System.out.println(message); } } public static void main(String[] args) throws Throwable { + if (!Util.isSCTPSupported()) { + throw new SkippedException("SCTP protocol is not supported"); + } + Class k = new Object(){}.getClass().getEnclosingClass(); try {k.getMethod("instanceMain",String[].class) .invoke( k.newInstance(), (Object) args);} diff --git a/test/jdk/com/sun/nio/sctp/SctpChannel/SocketOptionTests.java b/test/jdk/com/sun/nio/sctp/SctpChannel/SocketOptionTests.java index 052f9999e57..857efbb63f5 100644 --- a/test/jdk/com/sun/nio/sctp/SctpChannel/SocketOptionTests.java +++ b/test/jdk/com/sun/nio/sctp/SctpChannel/SocketOptionTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * 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 * @bug 4927640 + * @library /test/lib * @summary Tests the SCTP protocol implementation * @author chegar */ @@ -43,6 +44,8 @@ import static com.sun.nio.sctp.SctpStandardSocketOptions.*; import static java.lang.System.out; +import jtreg.SkippedException; + public class SocketOptionTests { final String osName = AccessController.doPrivileged( (PrivilegedAction)() -> System.getProperty("os.name")); @@ -66,12 +69,6 @@ void optionalSupport(SctpChannel sc, SctpSocketOption name, } void test(String[] args) { - if (!Util.isSCTPSupported()) { - out.println("SCTP protocol is not supported"); - out.println("Test cannot be run"); - return; - } - try (SctpChannel sc = SctpChannel.open()) { /* check supported options */ @@ -190,6 +187,10 @@ void sctpPrimaryAddr() throws IOException { void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);} void debug(String message) {if(debug) { System.out.println(message); } } public static void main(String[] args) throws Throwable { + if (!Util.isSCTPSupported()) { + throw new SkippedException("SCTP protocol is not supported"); + } + Class k = new Object(){}.getClass().getEnclosingClass(); try {k.getMethod("instanceMain",String[].class) .invoke( k.newInstance(), (Object) args);} diff --git a/test/jdk/com/sun/nio/sctp/SctpMultiChannel/Branch.java b/test/jdk/com/sun/nio/sctp/SctpMultiChannel/Branch.java index ffd8eb361c3..9beb8c74c3e 100644 --- a/test/jdk/com/sun/nio/sctp/SctpMultiChannel/Branch.java +++ b/test/jdk/com/sun/nio/sctp/SctpMultiChannel/Branch.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * 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 * @bug 4927640 + * @library /test/lib * @summary Tests the SCTP protocol implementation * @author chegar */ @@ -48,6 +49,8 @@ import static java.lang.System.out; import static java.lang.System.err; +import jtreg.SkippedException; + public class Branch { /* Latches used to synchronize between the client and server so that * connections without any IO may not be closed without being accepted */ @@ -58,12 +61,6 @@ void test(String[] args) { SocketAddress address = null; Server server = null; - if (!Util.isSCTPSupported()) { - out.println("SCTP protocol is not supported"); - out.println("Test cannot be run"); - return; - } - if (args.length == 2) { /* requested to connecct to a specific address */ try { @@ -277,6 +274,10 @@ public HandlerResult handleNotification( void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);} void debug(String message) {if(debug) { System.out.println(message); } } public static void main(String[] args) throws Throwable { + if (!Util.isSCTPSupported()) { + throw new SkippedException("SCTP protocol is not supported"); + } + Class k = new Object(){}.getClass().getEnclosingClass(); try {k.getMethod("instanceMain",String[].class) .invoke( k.newInstance(), (Object) args);} diff --git a/test/jdk/com/sun/nio/sctp/SctpMultiChannel/CloseDescriptors.java b/test/jdk/com/sun/nio/sctp/SctpMultiChannel/CloseDescriptors.java index 08340312532..fdafec80745 100644 --- a/test/jdk/com/sun/nio/sctp/SctpMultiChannel/CloseDescriptors.java +++ b/test/jdk/com/sun/nio/sctp/SctpMultiChannel/CloseDescriptors.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* @test * @bug 8269481 + * @library /test/lib * @summary Tests that file descriptors are closed * @requires (os.family == "linux") * @run main/othervm CloseDescriptors @@ -38,6 +39,8 @@ import com.sun.nio.sctp.MessageInfo; import com.sun.nio.sctp.SctpMultiChannel; +import jtreg.SkippedException; + public class CloseDescriptors { private static final int NUM = 5; @@ -46,9 +49,7 @@ public class CloseDescriptors { public static void main(String[] args) throws Exception { if (!Util.isSCTPSupported()) { - System.out.println("SCTP protocol is not supported"); - System.out.println("Test cannot be run"); - return; + throw new SkippedException("SCTP protocol is not supported"); } List lsofDirs = List.of("/usr/bin", "/usr/sbin"); @@ -57,9 +58,7 @@ public static void main(String[] args) throws Exception { .filter(f -> Files.isExecutable(f)) .findFirst(); if (!lsof.isPresent()) { - System.out.println("Cannot locate lsof in " + lsofDirs); - System.out.println("Test cannot be run"); - return; + throw new SkippedException("Cannot locate lsof in " + lsofDirs); } try (ServerSocket ss = new ServerSocket(0)) { diff --git a/test/jdk/com/sun/nio/sctp/SctpMultiChannel/Send.java b/test/jdk/com/sun/nio/sctp/SctpMultiChannel/Send.java index feb914a410e..8fb551dd8f4 100644 --- a/test/jdk/com/sun/nio/sctp/SctpMultiChannel/Send.java +++ b/test/jdk/com/sun/nio/sctp/SctpMultiChannel/Send.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * 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 * @bug 4927640 + * @library /test/lib * @summary Tests the SCTP protocol implementation * @author chegar */ @@ -42,6 +43,8 @@ import static java.lang.System.out; import static java.lang.System.err; +import jtreg.SkippedException; + public class Send { /* Latches used to synchronize between the client and server so that * connections without any IO may not be closed without being accepted */ @@ -52,12 +55,6 @@ void test(String[] args) { SocketAddress address = null; Server server = null; - if (!Util.isSCTPSupported()) { - out.println("SCTP protocol is not supported"); - out.println("Test cannot be run"); - return; - } - if (args.length == 2) { /* requested to connecct to a specific address */ try { @@ -355,6 +352,10 @@ public void run() { void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);} void debug(String message) {if(debug) { System.out.println(message); } } public static void main(String[] args) throws Throwable { + if (!Util.isSCTPSupported()) { + throw new SkippedException("SCTP protocol is not supported"); + } + Class k = new Object(){}.getClass().getEnclosingClass(); try {k.getMethod("instanceMain",String[].class) .invoke( k.newInstance(), (Object) args);} diff --git a/test/jdk/com/sun/nio/sctp/SctpMultiChannel/SendFailed.java b/test/jdk/com/sun/nio/sctp/SctpMultiChannel/SendFailed.java index 7ebbcfb6079..a64d4d58270 100644 --- a/test/jdk/com/sun/nio/sctp/SctpMultiChannel/SendFailed.java +++ b/test/jdk/com/sun/nio/sctp/SctpMultiChannel/SendFailed.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, 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 * @bug 8067846 + * @library /test/lib * @summary Test for send failed notification */ @@ -35,6 +36,8 @@ import static java.lang.System.out; import static java.nio.ByteBuffer.*; +import jtreg.SkippedException; + public class SendFailed { static final SocketAddress remoteAddress = new InetSocketAddress(InetAddress.getLoopbackAddress(), 3000); @@ -45,12 +48,6 @@ public class SendFailed { void test(String[] args) throws IOException { SocketAddress address = null; - if (!Util.isSCTPSupported()) { - out.println("SCTP protocol is not supported"); - out.println("Test cannot be run"); - return; - } - System.out.println("remote address: " + remoteAddress); System.out.println("Note, remote address should not be up"); @@ -186,6 +183,10 @@ static void assertSameContent(ByteBuffer bb1, ByteBuffer bb2) { void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);} void debug(String message, Object... args) {if(debug) { out.printf(message, args); } } public static void main(String[] args) throws Throwable { + if (!Util.isSCTPSupported()) { + throw new SkippedException("SCTP protocol is not supported"); + } + Class k = new Object(){}.getClass().getEnclosingClass(); try {k.getMethod("instanceMain",String[].class) .invoke( k.newInstance(), (Object) args);} diff --git a/test/jdk/com/sun/nio/sctp/SctpMultiChannel/SocketOptionTests.java b/test/jdk/com/sun/nio/sctp/SctpMultiChannel/SocketOptionTests.java index 2da35d6eda5..3a681884b9a 100644 --- a/test/jdk/com/sun/nio/sctp/SctpMultiChannel/SocketOptionTests.java +++ b/test/jdk/com/sun/nio/sctp/SctpMultiChannel/SocketOptionTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * 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 * @bug 4927640 + * @library /test/lib * @summary Tests the SCTP protocol implementation * @author chegar */ @@ -51,6 +52,8 @@ import static com.sun.nio.sctp.SctpStandardSocketOptions.*; import static java.lang.System.out; +import jtreg.SkippedException; + public class SocketOptionTests { final String osName = AccessController.doPrivileged( (PrivilegedAction)() -> System.getProperty("os.name")); @@ -74,12 +77,6 @@ void optionalSupport(SctpMultiChannel smc, SctpSocketOption name, } void test(String[] args) { - if (!Util.isSCTPSupported()) { - out.println("SCTP protocol is not supported"); - out.println("Test cannot be run"); - return; - } - try { SctpMultiChannel smc = SctpMultiChannel.open(); @@ -244,6 +241,10 @@ public HandlerResult handleNotification( void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);} void debug(String message) {if(debug) { System.out.println(message); } } public static void main(String[] args) throws Throwable { + if (!Util.isSCTPSupported()) { + throw new SkippedException("SCTP protocol is not supported"); + } + Class k = new Object(){}.getClass().getEnclosingClass(); try {k.getMethod("instanceMain",String[].class) .invoke( k.newInstance(), (Object) args);} diff --git a/test/jdk/com/sun/nio/sctp/SctpServerChannel/Accept.java b/test/jdk/com/sun/nio/sctp/SctpServerChannel/Accept.java index 99d6e26c939..56522a85f6b 100644 --- a/test/jdk/com/sun/nio/sctp/SctpServerChannel/Accept.java +++ b/test/jdk/com/sun/nio/sctp/SctpServerChannel/Accept.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * 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 * @bug 4927640 + * @library /test/lib * @summary Tests the SCTP protocol implementation * @author chegar */ @@ -41,6 +42,8 @@ import static java.lang.System.out; import static java.lang.System.err; +import jtreg.SkippedException; + public class Accept { static CountDownLatch acceptLatch = new CountDownLatch(1); static CountDownLatch closeByIntLatch = new CountDownLatch(1); @@ -50,12 +53,6 @@ public class Accept { void test(String[] args) { SocketAddress address = null; - if (!Util.isSCTPSupported()) { - out.println("SCTP protocol is not supported"); - out.println("Test cannot be run"); - return; - } - if (args.length == 2) { /* requested to connecct to a specific address */ try { @@ -262,6 +259,10 @@ static class TestSocketAddress extends SocketAddress {} void join(Thread thread, long millis) { try { thread.join(millis); } catch(InterruptedException ie) { unexpected(ie); }} public static void main(String[] args) throws Throwable { + if (!Util.isSCTPSupported()) { + throw new SkippedException("SCTP protocol is not supported"); + } + Class k = new Object(){}.getClass().getEnclosingClass(); try {k.getMethod("instanceMain",String[].class) .invoke( k.newInstance(), (Object) args);} diff --git a/test/jdk/com/sun/nio/sctp/SctpServerChannel/NonBlockingAccept.java b/test/jdk/com/sun/nio/sctp/SctpServerChannel/NonBlockingAccept.java index 49ba4d64b5b..d60f02d50ec 100644 --- a/test/jdk/com/sun/nio/sctp/SctpServerChannel/NonBlockingAccept.java +++ b/test/jdk/com/sun/nio/sctp/SctpServerChannel/NonBlockingAccept.java @@ -23,6 +23,7 @@ /* @test * @bug 4927640 + * @library /test/lib * @summary Tests the SCTP protocol implementation * @author chegar */ @@ -42,6 +43,8 @@ import static java.lang.System.out; import static java.lang.System.err; +import jtreg.SkippedException; + public class NonBlockingAccept { static CountDownLatch acceptLatch = new CountDownLatch(1); static final int SEL_TIMEOUT = 10000; @@ -51,12 +54,6 @@ void test(String[] args) { SocketAddress address = null; NonblockingServer server; - if (!Util.isSCTPSupported()) { - out.println("SCTP protocol is not supported"); - out.println("Test cannot be run"); - return; - } - if (args.length == 2) { /* requested to connecct to a specific address */ try { @@ -218,6 +215,10 @@ static class TestSocketAddress extends SocketAddress {} void sleep(long millis) { try { Thread.currentThread().sleep(millis); } catch(InterruptedException ie) { unexpected(ie); }} public static void main(String[] args) throws Throwable { + if (!Util.isSCTPSupported()) { + throw new SkippedException("SCTP protocol is not supported"); + } + Class k = new Object(){}.getClass().getEnclosingClass(); try {k.getMethod("instanceMain",String[].class) .invoke( k.newInstance(), (Object) args);} diff --git a/test/jdk/java/awt/Cursor/CursorDragTest/ListDragCursor.java b/test/jdk/java/awt/Cursor/CursorDragTest/ListDragCursor.java index 32923f1d78b..da0394a1392 100644 --- a/test/jdk/java/awt/Cursor/CursorDragTest/ListDragCursor.java +++ b/test/jdk/java/awt/Cursor/CursorDragTest/ListDragCursor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,42 +25,60 @@ * @test * @bug 4313052 * @summary Test cursor changes after mouse dragging ends - * @library /java/awt/regtesthelpers - * @build PassFailJFrame * @run main/manual ListDragCursor */ +import java.awt.BorderLayout; +import java.awt.Button; import java.awt.Cursor; +import java.awt.EventQueue; import java.awt.Frame; import java.awt.List; import java.awt.Panel; import java.awt.TextArea; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; public class ListDragCursor { - public static void main(String[] args) throws Exception { - String INSTRUCTIONS = """ + private static final String INSTRUCTIONS = """ 1. Move mouse to the TextArea. 2. Press the left mouse button. 3. Drag mouse to the list. 4. Release the left mouse button. - If the mouse cursor starts as a Text Line Cursor and changes - to a regular Pointer Cursor, then Hand Cursor when hovering - the list, pass the test. This test fails if the cursor does - not update at all when pointing over the different components. + The mouse cursor should appear as an I-beam cursor + and should stay the same while dragging across the + components. Once you reach the list, release the + left mouse button. As soon as you release the left + mouse button, the cursor should change to a Hand + cursor. If true, this test passes. + + The test fails if the cursor updates while dragging + over the components before releasing the left + mouse button. """; - PassFailJFrame.builder() - .title("Test Instructions") - .instructions(INSTRUCTIONS) - .rows((int) INSTRUCTIONS.lines().count() + 2) - .columns(35) - .testUI(ListDragCursor::createUI) - .build() - .awaitAndCheck(); + private static Frame testFrame; + private static Frame instructionsFrame; + + private static final CountDownLatch countDownLatch = new CountDownLatch(1); + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(() -> { + instructionsFrame = createInstructionsFrame(); + testFrame = createTestFrame(); + }); + if (!countDownLatch.await(5, TimeUnit.MINUTES)) { + throw new RuntimeException("Test timeout : No action was" + + " taken on the test."); + } + } finally { + EventQueue.invokeAndWait(ListDragCursor::disposeFrames); + } } - public static Frame createUI() { + static Frame createTestFrame() { Frame frame = new Frame("Cursor change after drag"); Panel panel = new Panel(); @@ -78,7 +96,51 @@ public static Frame createUI() { panel.add(list); frame.add(panel); - frame.setBounds(300, 100, 300, 150); + frame.setSize(300, 150); + frame.setLocation(instructionsFrame.getX() + + instructionsFrame.getWidth(), + instructionsFrame.getY()); + frame.setVisible(true); + return frame; + } + + static Frame createInstructionsFrame() { + Frame frame = new Frame("Test Instructions"); + Panel mainPanel = new Panel(new BorderLayout()); + TextArea textArea = new TextArea(INSTRUCTIONS, + 15, 35, TextArea.SCROLLBARS_NONE); + + Panel btnPanel = new Panel(); + Button passBtn = new Button("Pass"); + Button failBtn = new Button("Fail"); + btnPanel.add(passBtn); + btnPanel.add(failBtn); + + passBtn.addActionListener(e -> { + countDownLatch.countDown(); + System.out.println("Test passed."); + }); + failBtn.addActionListener(e -> { + countDownLatch.countDown(); + throw new RuntimeException("Test Failed."); + }); + + mainPanel.add(textArea, BorderLayout.CENTER); + mainPanel.add(btnPanel, BorderLayout.SOUTH); + + frame.add(mainPanel); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); return frame; } + + static void disposeFrames() { + if (testFrame != null) { + testFrame.dispose(); + } + if (instructionsFrame != null) { + instructionsFrame.dispose(); + } + } } diff --git a/test/jdk/java/awt/Desktop/BrowseTest.java b/test/jdk/java/awt/Desktop/BrowseTest.java index 33de1ecdca7..28e08fe16c7 100644 --- a/test/jdk/java/awt/Desktop/BrowseTest.java +++ b/test/jdk/java/awt/Desktop/BrowseTest.java @@ -40,10 +40,27 @@ public class BrowseTest extends JPanel { static final String INSTRUCTIONS = """ - This test could launch default file manager to open user's home - directory, and default web browser to show the URL of java vendor. - After test execution close the native file manager and web browser + Set your default browser as per the test platform. + macOS - Safari + windows - MS Edge + linux - Firefox + + This test checks 2 cases: + + 1) Directory URI: + On macOS and windows, verify that a browser window opens and + EITHER the browser OR native file manager shows the user's + home directory. + + On Linux verify that the user's home directory is shown by the + default file manager. + + 2) Web URI: + Verify that the Web URI (URL of java vendor) opens in the browser. + + After test execution close the native file manager and any web browser windows if they were launched by test. + Also check output for any unexpected EXCEPTIONS, if you see any failure messages press Fail otherwise press Pass. """; @@ -53,7 +70,7 @@ public BrowseTest() { URI dirURI = new File(System.getProperty("user.home")).toURI(); URI webURI = URI.create(System.getProperty("java.vendor.url", "http://www.java.com")); - boolean failed = false; + PassFailJFrame.log("Testing 1st case: Directory URI ..."); try { PassFailJFrame.log("Try to browse " + dirURI + " ..."); desktop.browse(dirURI); @@ -62,6 +79,7 @@ public BrowseTest() { PassFailJFrame.log("EXCEPTION: " + e.getMessage()); } + PassFailJFrame.log("Testing 2nd case: Web URI ..."); try { PassFailJFrame.log("Try to browse " + webURI + " ..."); desktop.browse(webURI); diff --git a/test/jdk/java/awt/Desktop/EditAndPrintTest/EditAndPrintTest.java b/test/jdk/java/awt/Desktop/EditAndPrintTest/EditAndPrintTest.java index b2d7ef28df1..77d86ceb42a 100644 --- a/test/jdk/java/awt/Desktop/EditAndPrintTest/EditAndPrintTest.java +++ b/test/jdk/java/awt/Desktop/EditAndPrintTest/EditAndPrintTest.java @@ -48,7 +48,7 @@ public class EditAndPrintTest extends JPanel { This test tries to edit and print a directory, which will expectedly raise IOException. Then this test would edit and print a .txt file, which should be successful. After test execution close the editor if it was launched by test. - If you see any EXCEPTION messages in the output press FAIL. + If you see any EXCEPTION messages in case of .txt file in the output press FAIL. """; static Desktop desktop; diff --git a/test/jdk/java/awt/FileDialog/DoubleActionESC.java b/test/jdk/java/awt/FileDialog/DoubleActionESC.java index 748c3aeb5e4..e8bb4963aa0 100644 --- a/test/jdk/java/awt/FileDialog/DoubleActionESC.java +++ b/test/jdk/java/awt/FileDialog/DoubleActionESC.java @@ -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 @@ -34,12 +34,15 @@ import java.awt.event.KeyEvent; import java.util.concurrent.CountDownLatch; +import static java.util.concurrent.TimeUnit.SECONDS; + /* * @test * @bug 5097243 * @summary Tests that FileDialog can be closed by ESC any time * @key headful * @run main DoubleActionESC + * @run main/othervm -Dsun.awt.disableGtkFileDialogs=true DoubleActionESC */ public class DoubleActionESC { @@ -49,47 +52,48 @@ public class DoubleActionESC { private static Robot robot; private static volatile Point p; private static volatile Dimension d; - private static volatile CountDownLatch latch; private static final int REPEAT_COUNT = 2; + private static final long LATCH_TIMEOUT = 10; - public static void main(String[] args) throws Exception { - latch = new CountDownLatch(1); + private static final CountDownLatch latch = new CountDownLatch(REPEAT_COUNT); + public static void main(String[] args) throws Exception { robot = new Robot(); - robot.setAutoDelay(100); + robot.setAutoDelay(50); try { EventQueue.invokeAndWait(() -> { createAndShowUI(); }); + robot.waitForIdle(); robot.delay(1000); + EventQueue.invokeAndWait(() -> { p = showBtn.getLocationOnScreen(); d = showBtn.getSize(); }); for (int i = 0; i < REPEAT_COUNT; ++i) { - Thread thread = new Thread(() -> { - robot.mouseMove(p.x + d.width / 2, p.y + d.height / 2); - robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); - robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); - }); - thread.start(); - robot.delay(3000); + robot.mouseMove(p.x + d.width / 2, p.y + d.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(1000); - Thread thread1 = new Thread(() -> { - robot.keyPress(KeyEvent.VK_ESCAPE); - robot.keyRelease(KeyEvent.VK_ESCAPE); - robot.waitForIdle(); - }); - thread1.start(); - robot.delay(3000); + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.keyRelease(KeyEvent.VK_ESCAPE); + robot.waitForIdle(); + robot.delay(1000); } - latch.await(); - if (fd.isVisible()) { - throw new RuntimeException("File Dialog is not closed"); + if (!latch.await(LATCH_TIMEOUT, SECONDS)) { + throw new RuntimeException("Test failed: Latch timeout reached"); } + EventQueue.invokeAndWait(() -> { + if (fd.isVisible()) { + throw new RuntimeException("File Dialog is not closed"); + } + }); } finally { EventQueue.invokeAndWait(() -> { if (f != null) { diff --git a/test/jdk/java/awt/Focus/ComponentLostFocusTest.java b/test/jdk/java/awt/Focus/ComponentLostFocusTest.java index 6af8322b2cd..8045ace43d5 100644 --- a/test/jdk/java/awt/Focus/ComponentLostFocusTest.java +++ b/test/jdk/java/awt/Focus/ComponentLostFocusTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2024, 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 @@ -35,13 +35,20 @@ import java.awt.Frame; import java.awt.KeyboardFocusManager; import java.awt.Point; +import java.awt.Rectangle; import java.awt.Robot; import java.awt.TextField; +import java.awt.Toolkit; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.awt.event.InputEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; +import java.io.File; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javax.imageio.ImageIO; public class ComponentLostFocusTest { @@ -49,10 +56,10 @@ public class ComponentLostFocusTest { static TextField tf; static Robot r; static Dialog dialog = null; - static volatile boolean passed; static volatile Point loc; static volatile int width; static volatile int top; + static final CountDownLatch focusGainedLatch = new CountDownLatch(1); private static void createTestUI() { @@ -75,11 +82,7 @@ public void windowGainedFocus(WindowEvent e) { public static void doTest() { System.out.println("dialog.setVisible.... "); - new Thread(new Runnable() { - public void run() { - dialog.setVisible(true); - } - }).start(); + new Thread(() -> dialog.setVisible(true)).start(); // The bug is that this construction leads to the redundant xRequestFocus // By the way, the requestFocusInWindow() works fine before the fix @@ -98,7 +101,7 @@ public void run() { tf.addFocusListener(new FocusAdapter() { public void focusGained(FocusEvent e) { System.out.println("TextField gained focus: " + e); - passed = true; + focusGainedLatch.countDown(); } }); @@ -116,6 +119,17 @@ private static void doRequestFocusToTextField() { tf.requestFocus(); } + private static void captureScreen() { + try { + final Rectangle screenBounds = new Rectangle( + Toolkit.getDefaultToolkit().getScreenSize()); + ImageIO.write(r.createScreenCapture(screenBounds), + "png", new File("ComponentLostFocusTest.png")); + } catch (Exception e) { + e.printStackTrace(); + } + } + public static final void main(String args[]) throws Exception { r = new Robot(); r.setAutoDelay(100); @@ -138,9 +152,10 @@ public static final void main(String args[]) throws Exception { System.out.println("Focus owner: " + KeyboardFocusManager.getCurrentKeyboardFocusManager(). getFocusOwner()); - - if (!passed) { - throw new RuntimeException("TextField got no focus! Test failed."); + if (!focusGainedLatch.await(5, TimeUnit.SECONDS)) { + captureScreen(); + throw new RuntimeException("Waited too long, " + + "TextField got no focus! Test failed."); } } finally { EventQueue.invokeAndWait(() -> { @@ -151,4 +166,3 @@ public static final void main(String args[]) throws Exception { } } } - diff --git a/test/jdk/java/awt/Focus/InactiveFocusRace.java b/test/jdk/java/awt/Focus/InactiveFocusRace.java index efca2dbf53a..c1c9ac3f78e 100644 --- a/test/jdk/java/awt/Focus/InactiveFocusRace.java +++ b/test/jdk/java/awt/Focus/InactiveFocusRace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ */ import java.awt.Button; +import java.awt.EventQueue; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.KeyboardFocusManager; @@ -48,19 +49,27 @@ public class InactiveFocusRace { Button activeButton, inactiveButton1, inactiveButton2; Semaphore sema; final static int TIMEOUT = 10000; + private static Robot robot; public static void main(String[] args) throws Exception { try { + robot = new Robot(); InactiveFocusRace test = new InactiveFocusRace(); - test.init(); + EventQueue.invokeAndWait(() -> { + test.init(); + }); + robot.waitForIdle(); + robot.delay(1000); test.start(); } finally { - if (activeFrame != null) { - activeFrame.dispose(); - } - if (inactiveFrame != null) { - inactiveFrame.dispose(); - } + EventQueue.invokeAndWait(() -> { + if (activeFrame != null) { + activeFrame.dispose(); + } + if (inactiveFrame != null) { + inactiveFrame.dispose(); + } + }); } } @@ -91,24 +100,40 @@ public void focusGained(FocusEvent e) { sema.raise(); } }); + inactiveFrame.addWindowListener(new WindowAdapter() { + public void windowActivated(WindowEvent e) { + System.err.println("inactive Window activated"); + sema.raise(); + } + }); activeFrame.addWindowListener(new WindowAdapter() { public void windowActivated(WindowEvent e) { System.err.println("Window activated"); sema.raise(); } }); + inactiveFrame.setVisible(true); } public void start() { - Robot robot = null; + + + // Wait for inactive frame to become active try { - robot = new Robot(); - } catch (Exception e) { - throw new RuntimeException("Unable to create robot"); + sema.doWait(TIMEOUT); + } catch (InterruptedException ie) { + throw new RuntimeException("Wait was interrupted"); + } + if (!sema.getState()) { + throw new RuntimeException("Frame doesn't become active on show"); } + sema.setState(false); - inactiveFrame.setVisible(true); - activeFrame.setVisible(true); + try { + EventQueue.invokeAndWait(() -> activeFrame.setVisible(true)); + } catch (Exception e) { + throw new RuntimeException("Interrupted active frame rendering"); + } // Wait for active frame to become active try { diff --git a/test/jdk/tools/jpackage/resources/query-msi-property.js b/test/jdk/java/awt/Frame/BogusFocusableWindowState/BogusFocusableWindowState.java similarity index 52% rename from test/jdk/tools/jpackage/resources/query-msi-property.js rename to test/jdk/java/awt/Frame/BogusFocusableWindowState/BogusFocusableWindowState.java index d821f5a8a54..efcb9c098f0 100644 --- a/test/jdk/tools/jpackage/resources/query-msi-property.js +++ b/test/jdk/java/awt/Frame/BogusFocusableWindowState/BogusFocusableWindowState.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,45 +21,30 @@ * questions. */ +import java.awt.Window; -function readMsi(msiPath, callback) { - var installer = new ActiveXObject('WindowsInstaller.Installer') - var database = installer.OpenDatabase(msiPath, 0 /* msiOpenDatabaseModeReadOnly */) - - return callback(database) -} - - -function queryAllProperties(db) { - var reply = {} - - var view = db.OpenView("SELECT `Property`, `Value` FROM Property") - view.Execute() - - try { - while(true) { - var record = view.Fetch() - if (!record) { - break +/** + * @test + * @bug 8346952 8361521 + * @summary Verifies no exception occurs when triggering updateCG() + * for an ownerless window. + * @key headful + */ +public final class BogusFocusableWindowState { + + public static void main(String[] args) { + Window frame = new Window(null) { + @Override + public boolean getFocusableWindowState() { + removeNotify(); + return true; } - - var name = record.StringData(1) - var value = record.StringData(2) - - reply[name] = value + }; + try { + frame.pack(); + frame.setVisible(true); + } finally { + frame.dispose(); } - } finally { - view.Close() } - - return reply } - - -(function () { - var msi = WScript.arguments(0) - var propName = WScript.arguments(1) - - var props = readMsi(msi, queryAllProperties) - WScript.Echo(props[propName]) -})() diff --git a/test/jdk/java/awt/Frame/GetGraphicsStressTest/GetGraphicsStressTest.java b/test/jdk/java/awt/Frame/GetGraphicsStressTest/GetGraphicsStressTest.java index 96febfb6744..52961d2827f 100644 --- a/test/jdk/java/awt/Frame/GetGraphicsStressTest/GetGraphicsStressTest.java +++ b/test/jdk/java/awt/Frame/GetGraphicsStressTest/GetGraphicsStressTest.java @@ -27,7 +27,7 @@ /** * @test - * @bug 8235638 8235739 8285094 + * @bug 8235638 8235739 8285094 8346952 * @key headful */ public final class GetGraphicsStressTest { diff --git a/test/jdk/java/awt/List/MouseDraggedOriginatedByScrollBarTest.java b/test/jdk/java/awt/List/MouseDraggedOriginatedByScrollBarTest.java index 600d38fe393..6858359d6b4 100644 --- a/test/jdk/java/awt/List/MouseDraggedOriginatedByScrollBarTest.java +++ b/test/jdk/java/awt/List/MouseDraggedOriginatedByScrollBarTest.java @@ -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 @@ -24,41 +24,46 @@ /* * @test * @bug 6240151 + * @key headful * @summary XToolkit: Dragging the List scrollbar initiates DnD - * @library /java/awt/regtesthelpers - * @build PassFailJFrame - * @run main/manual MouseDraggedOriginatedByScrollBarTest + * @requires os.family == "linux" + * @run main MouseDraggedOriginatedByScrollBarTest */ +import java.awt.EventQueue; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.List; -import java.awt.event.MouseMotionAdapter; +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.awt.event.MouseMotionAdapter; public class MouseDraggedOriginatedByScrollBarTest { - - private static final String INSTRUCTIONS = """ - 1) Click and drag the scrollbar of the list. - 2) Keep dragging till the mouse pointer goes out the scrollbar. - 3) The test failed if you see messages about events. The test passed if you don't."""; + private static Frame frame; + private static volatile Point loc; + private static List list; + private static final int XOFFSET = 10; + private static final int YOFFSET = 20; public static void main(String[] args) throws Exception { - PassFailJFrame.builder() - .title("MouseDraggedOriginatedByScrollBarTest Instructions") - .instructions(INSTRUCTIONS) - .rows((int) INSTRUCTIONS.lines().count() + 2) - .columns(35) - .testUI(MouseDraggedOriginatedByScrollBarTest::createTestUI) - .logArea() - .build() - .awaitAndCheck(); + try { + EventQueue.invokeAndWait(() -> createUI()); + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } } - private static Frame createTestUI() { - Frame frame = new Frame(); - List list = new List(4, false); + private static void createUI() { + frame = new Frame(); + list = new List(4, false); list.add("000"); list.add("111"); @@ -77,27 +82,52 @@ private static Frame createTestUI() { new MouseMotionAdapter(){ @Override public void mouseDragged(MouseEvent me){ - PassFailJFrame.log(me.toString()); + System.out.println(me); + throw new RuntimeException("Mouse dragged event detected."); } }); list.addMouseListener( new MouseAdapter() { public void mousePressed(MouseEvent me) { - PassFailJFrame.log(me.toString()); + System.out.println(me); + throw new RuntimeException("Mouse pressed event detected."); } public void mouseReleased(MouseEvent me) { - PassFailJFrame.log(me.toString()); + System.out.println(me); + throw new RuntimeException("Mouse released event detected."); } public void mouseClicked(MouseEvent me){ - PassFailJFrame.log(me.toString()); + System.out.println(me); + throw new RuntimeException("Mouse clicked event detected."); } }); frame.setLayout(new FlowLayout()); frame.pack(); - return frame; + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private static void test() throws Exception { + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(1000); + robot.setAutoWaitForIdle(true); + + EventQueue.invokeAndWait(() -> { + Point p = list.getLocationOnScreen(); + p.translate(list.getWidth() - XOFFSET, YOFFSET); + loc = p; + }); + robot.mouseMove(loc.x, loc.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + for (int i = 0; i < 30; i++) { + robot.mouseMove(loc.x, loc.y + i); + } + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(100); } } diff --git a/test/jdk/java/awt/TextField/SetEchoCharTest4/SetEchoCharTest4.java b/test/jdk/java/awt/TextField/SetEchoCharTest4/SetEchoCharTest4.java index c1cc07afac0..e96485dcb54 100644 --- a/test/jdk/java/awt/TextField/SetEchoCharTest4/SetEchoCharTest4.java +++ b/test/jdk/java/awt/TextField/SetEchoCharTest4/SetEchoCharTest4.java @@ -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 @@ -27,7 +27,6 @@ import java.awt.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.lang.reflect.InvocationTargetException; /* * @test @@ -54,16 +53,17 @@ public class SetEchoCharTest4 extends Frame implements ActionListener { Make sure the actual text matches what you typed in for each field. Press Pass if everything's ok, otherwise Fail - """; + """; public SetEchoCharTest4() { + super("SetEchoCharTest4"); setLayout(new FlowLayout()); tf1.setEchoChar('*'); tf2.setEchoChar('$'); tf3.setEchoChar('#'); addStuff(); b.addActionListener(this); - setSize (200,200); + setSize (300, 150); } private void addStuff() { @@ -78,7 +78,6 @@ public void actionPerformed(ActionEvent ae) { PassFailJFrame.log("TextField2 = " + tf2.getText()); PassFailJFrame.log("TextField3 = " + tf3.getText()); PassFailJFrame.log("--------------"); - setVisible(false); remove(tf1); remove(tf2); remove(tf3); @@ -86,16 +85,14 @@ public void actionPerformed(ActionEvent ae) { addStuff(); } - public static void main(String[] args) throws InterruptedException, - InvocationTargetException { + public static void main(String[] args) throws Exception { PassFailJFrame.builder() - .title("Set Echo Character Test") - .testUI(SetEchoCharTest4::new) - .instructions(INSTRUCTIONS) - .rows((int) INSTRUCTIONS.lines().count() + 1) - .columns(40) - .logArea() - .build() - .awaitAndCheck(); + .title("Set Echo Character Test") + .testUI(SetEchoCharTest4::new) + .instructions(INSTRUCTIONS) + .columns(40) + .logArea() + .build() + .awaitAndCheck(); } } diff --git a/test/jdk/java/awt/TextField/SetEchoCharWordOpsTest.java b/test/jdk/java/awt/TextField/SetEchoCharWordOpsTest.java index 825c21fdc96..9116a4dff3b 100644 --- a/test/jdk/java/awt/TextField/SetEchoCharWordOpsTest.java +++ b/test/jdk/java/awt/TextField/SetEchoCharWordOpsTest.java @@ -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 @@ -30,7 +30,7 @@ /* * @test - * @bug 6191897 + * @bug 6191897 8354646 * @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 diff --git a/test/jdk/java/awt/Toolkit/Headless/WrappedToolkitTest/TestWrapped.java b/test/jdk/java/awt/Toolkit/Headless/WrappedToolkitTest/TestWrapped.java index e2ded58e7f2..4b4041dbcfd 100644 --- a/test/jdk/java/awt/Toolkit/Headless/WrappedToolkitTest/TestWrapped.java +++ b/test/jdk/java/awt/Toolkit/Headless/WrappedToolkitTest/TestWrapped.java @@ -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 @@ -22,55 +22,52 @@ */ /* - * test + * @test * @bug 6282388 - * @summary Tests that AWT use correct toolkit to be wrapped into HeadlessToolkit - * @author artem.ananiev@sun.com: area=awt.headless - * @run shell WrappedToolkitTest.sh + * @summary Tests that AWT uses correct toolkit wrapped into HeadlessToolkit + * @modules java.desktop/sun.awt:open + * @library /test/lib + * @run main/othervm -Djava.awt.headless=true TestWrapped */ -import java.awt.*; +import java.awt.Toolkit; +import java.lang.Class; +import java.lang.reflect.Field; -import java.lang.reflect.*; +import jdk.test.lib.Platform; -import sun.awt.*; +public final class TestWrapped { -public class TestWrapped -{ - public static void main(String[] args) - { - try - { - if (args.length != 1) { - System.err.println("No correct toolkit class name is specified, test is not run"); - System.exit(0); + private static final String HEADLESS_TOOLKIT = "sun.awt.HeadlessToolkit"; + private static final String MACOSX_TOOLKIT = "sun.lwawt.macosx.LWCToolkit"; + private static final String UNIX_TOOLKIT = "sun.awt.X11.XToolkit"; + private static final String WINDOWS_TOOLKIT = "sun.awt.windows.WToolkit"; + + public static void main(String[] args) throws Exception { + String expectedToolkitClassName; + if (Platform.isWindows()) { + expectedToolkitClassName = WINDOWS_TOOLKIT; + } else if (Platform.isOSX()) { + expectedToolkitClassName = MACOSX_TOOLKIT; + } else { + expectedToolkitClassName = UNIX_TOOLKIT; } - String correctToolkitClassName = args[0]; Toolkit tk = Toolkit.getDefaultToolkit(); - Class tkClass = tk.getClass(); - if (!tkClass.getName().equals("sun.awt.HeadlessToolkit")) - { - System.err.println(tkClass.getName()); - System.err.println("Error: default toolkit is not an instance of HeadlessToolkit"); - System.exit(-1); + Class tkClass = tk.getClass(); + if (!tkClass.getName().equals(HEADLESS_TOOLKIT)) { + System.err.println("Expected: " + HEADLESS_TOOLKIT); + System.err.println("Actual: " + tkClass.getName()); + throw new RuntimeException("Wrong default toolkit"); } Field f = tkClass.getDeclaredField("tk"); f.setAccessible(true); - Class wrappedClass = f.get(tk).getClass(); - if (!wrappedClass.getName().equals(correctToolkitClassName)) { - System.err.println(wrappedClass.getName()); - System.err.println("Error: wrapped toolkit is not an instance of " + correctToolkitClassName); - System.exit(-1); - } + Class wrappedClass = f.get(tk).getClass(); + if (!wrappedClass.getName().equals(expectedToolkitClassName)) { + System.err.println("Expected: " + expectedToolkitClassName); + System.err.println("Actual: " + wrappedClass.getName()); + throw new RuntimeException("Wrong wrapped toolkit"); } - catch (Exception z) - { - z.printStackTrace(System.err); - System.exit(-1); - } - - System.exit(0); } } diff --git a/test/jdk/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh b/test/jdk/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh deleted file mode 100644 index ac0cf58942c..00000000000 --- a/test/jdk/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh +++ /dev/null @@ -1,221 +0,0 @@ -#!/bin/ksh -p - -# -# Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -# -# @test -# @bug 6282388 8030640 -# @summary Tests that AWT use correct toolkit to be wrapped into HeadlessToolkit -# @author artem.ananiev@sun.com: area=awt.headless -# compile TestWrapped.java -# @run shell WrappedToolkitTest.sh - -# Beginning of subroutines: -status=1 - -#Call this from anywhere to fail the test with an error message -# usage: fail "reason why the test failed" -fail() - { echo "The test failed :-(" - echo "$*" 1>&2 - echo "exit status was $status" - exit $status - } #end of fail() - -#Call this from anywhere to pass the test with a message -# usage: pass "reason why the test passed if applicable" -pass() - { echo "The test passed!!!" - echo "$*" 1>&2 - exit 0 - } #end of pass() - -# end of subroutines - - -# The beginning of the script proper - -# Checking for proper OS -OS=`uname -s` -case "$OS" in - AIX | CYGWIN* | Darwin | Linux ) - FILESEP="/" - ;; - - Windows* ) - FILESEP="\\" - ;; - - # catch all other OSs - * ) - echo "Unrecognized system! $OS" - fail "Unrecognized system! $OS" - ;; -esac - -# check that some executable or other file you need is available, abort if not -# note that the name of the executable is in the fail string as well. -# this is how to check for presence of the compiler, etc. -#RESOURCE=`whence SomeProgramOrFileNeeded` -#if [ "${RESOURCE}" = "" ] ; -# then fail "Need SomeProgramOrFileNeeded to perform the test" ; -#fi - -# Want this test to run standalone as well as in the harness, so do the -# following to copy the test's directory into the harness's scratch directory -# and set all appropriate variables: - -if [ -z "${TESTJAVA}" ] ; then - # TESTJAVA is not set, so the test is running stand-alone. - # TESTJAVA holds the path to the root directory of the build of the JDK - # to be tested. That is, any java files run explicitly in this shell - # should use TESTJAVA in the path to the java interpreter. - # So, we'll set this to the JDK spec'd on the command line. If none - # is given on the command line, tell the user that and use a cheesy - # default. - # THIS IS THE JDK BEING TESTED. - if [ -n "$1" ] ; - then TESTJAVA=$1 - else fail "no JDK specified on command line!" - fi - TESTSRC=. - TESTCLASSES=. - STANDALONE=1; -fi -echo "JDK under test is: $TESTJAVA" - -#if in test harness, then copy the entire directory that the test is in over -# to the scratch directory. This catches any support files needed by the test. -if [ -z "${STANDALONE}" ] ; - then cp ${TESTSRC}/* . -fi -case "$OS" in - Windows* | CYGWIN* ) - ${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} \ - --add-exports java.desktop/sun.awt=ALL-UNNAMED \ - --add-exports java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \ - *.java - status=$? - if [ ! $status -eq "0" ]; then - fail "Compilation failed"; - fi - ;; - - AIX | Linux ) - ${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} \ - --add-exports java.desktop/sun.awt=ALL-UNNAMED \ - --add-exports java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \ - *.java - status=$? - if [ ! $status -eq "0" ]; then - fail "Compilation failed"; - fi - ;; - - Darwin) - ${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} \ - --add-exports java.desktop/sun.awt=ALL-UNNAMED \ - --add-exports java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \ - *.java - status=$? - if [ ! $status -eq "0" ]; then - fail "Compilation failed"; - fi - ;; - -esac - -#Just before executing anything, make sure it has executable permission! -chmod 777 ./* - -############### YOUR TEST CODE HERE!!!!!!! ############# - -case "$OS" in - Windows* | CYGWIN* ) - ${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \ - --add-opens java.desktop/sun.awt=ALL-UNNAMED \ - --add-opens java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \ - TestWrapped sun.awt.windows.WToolkit - status=$? - if [ ! $status -eq "0" ]; then - fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.awt.windows.WToolkit"; - fi - ${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \ - --add-opens java.desktop/sun.awt=ALL-UNNAMED \ - --add-opens java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \ - -Dawt.toolkit=sun.awt.windows.WToolkit \ - TestWrapped sun.awt.windows.WToolkit - status=$? - if [ ! $status -eq "0" ]; then - fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.awt.windows.WToolkit"; - fi - ;; - - AIX | Linux ) - ${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \ - --add-opens java.desktop/sun.awt=ALL-UNNAMED \ - --add-opens java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \ - -Dawt.toolkit=sun.awt.X11.XToolkit \ - TestWrapped sun.awt.X11.XToolkit - status=$? - if [ ! $status -eq "0" ]; then - fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.awt.xawt.XToolkit"; - fi - AWT_TOOLKIT=XToolkit ${TESTJAVA}/bin/java ${TESTVMOPTS} \ - --add-opens java.desktop/sun.awt=ALL-UNNAMED \ - --add-opens java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \ - -Djava.awt.headless=true \ - TestWrapped sun.awt.X11.XToolkit - status=$? - if [ ! $status -eq "0" ]; then - fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.awt.xawt.XToolkit"; - fi - ;; - - Darwin) - ${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \ - --add-opens java.desktop/sun.awt=ALL-UNNAMED \ - --add-opens java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \ - TestWrapped sun.lwawt.macosx.LWCToolkit - status=$? - if [ ! $status -eq "0" ]; then - fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.lwawt.macosx.LWCToolkit"; - fi - ${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \ - --add-opens java.desktop/sun.awt=ALL-UNNAMED \ - --add-opens java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \ - -Dawt.toolkit=sun.lwawt.macosx.LWCToolkit \ - TestWrapped sun.lwawt.macosx.LWCToolkit - status=$? - if [ ! $status -eq "0" ]; then - fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.lwawt.macosx.LWCToolkit"; - fi - ;; - -esac - -pass "All the tests are PASSED"; - -#For additional examples of how to write platform independent KSH scripts, -# see the jtreg file itself. It is a KSH script for both Solaris and Win32 diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/SerializationSpecTest.java b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/SerializationSpecTest.java new file mode 100644 index 00000000000..aa50d814264 --- /dev/null +++ b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/SerializationSpecTest.java @@ -0,0 +1,99 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.OptionalDataException; + +/** + * @test + * @bug 8367384 + * @summary Verify ICC_Profile serialization per spec, all name/data cases + */ +public final class SerializationSpecTest { + + public static void main(String[] args) throws Exception { + // Serialization form for ICC_Profile includes version, profile name, + // and profile data. If the name is invalid or does not match a standard + // profile, the data is used. An exception is thrown only if both the + // name and the data are invalid, or if one of them is missing or is of + // the wrong type. + + // Naming conventions used in test file names: + // null : null reference + // valid : valid standard profile name or valid profile data (byte[]) + // invalid : unrecognized name or data with incorrect ICC header + // wrongType: incorrect type, e.g., int[] instead of String or byte[] + + // No name or data + test("empty", OptionalDataException.class); + + // Cases where only the profile name is present (no profile data) + test("null", OptionalDataException.class); + test("valid", OptionalDataException.class); + test("invalid", OptionalDataException.class); + test("wrongType", InvalidObjectException.class); + + // The test files are named as _.ser + test("null_null", InvalidObjectException.class); + test("null_valid", null); // valid data is enough if name is null + test("null_invalid", InvalidObjectException.class); + test("null_wrongType", InvalidObjectException.class); + + test("invalid_null", InvalidObjectException.class); + test("invalid_valid", null); // valid data is enough if name is invalid + test("invalid_invalid", InvalidObjectException.class); + test("invalid_wrongType", InvalidObjectException.class); + + test("wrongType_null", InvalidObjectException.class); + test("wrongType_valid", InvalidObjectException.class); + test("wrongType_invalid", InvalidObjectException.class); + test("wrongType_wrongType", InvalidObjectException.class); + + test("valid_null", null); // the valid name is enough + test("valid_valid", null); // the valid name is enough + test("valid_invalid", null); // the valid name is enough + test("valid_wrongType", InvalidObjectException.class); + } + + private static void test(String test, Class expected) { + String fileName = test + ".ser"; + File file = new File(System.getProperty("test.src", "."), fileName); + Class actual = null; + try (var fis = new FileInputStream(file); + var ois = new ObjectInputStream(fis)) + { + ois.readObject(); + } catch (Exception e) { + actual = e.getClass(); + } + if (actual != expected) { + System.err.println("Test: " + test); + System.err.println("Expected: " + expected); + System.err.println("Actual: " + actual); + throw new RuntimeException("Test failed"); + } + } +} diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/empty.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/empty.ser new file mode 100644 index 00000000000..3fd70024d65 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/empty.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid.ser new file mode 100644 index 00000000000..dfe071e69dc Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_invalid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_invalid.ser new file mode 100644 index 00000000000..60fb02f7783 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_invalid.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_null.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_null.ser new file mode 100644 index 00000000000..60fb02f7783 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_null.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_valid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_valid.ser new file mode 100644 index 00000000000..e01b5766f62 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_valid.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_wrongType.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_wrongType.ser new file mode 100644 index 00000000000..65485f041d7 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_wrongType.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null.ser new file mode 100644 index 00000000000..1fc2022f868 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_invalid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_invalid.ser new file mode 100644 index 00000000000..b2847de4f46 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_invalid.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_null.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_null.ser new file mode 100644 index 00000000000..31c87a6cb65 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_null.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_valid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_valid.ser new file mode 100644 index 00000000000..b32c838c80a Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_valid.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_wrongType.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_wrongType.ser new file mode 100644 index 00000000000..3279eec381d Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_wrongType.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid.ser new file mode 100644 index 00000000000..a6512d244cf Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_invalid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_invalid.ser new file mode 100644 index 00000000000..dbe11f2c6d6 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_invalid.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_null.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_null.ser new file mode 100644 index 00000000000..dbe11f2c6d6 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_null.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_valid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_valid.ser new file mode 100644 index 00000000000..fbe90d0eb6e Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_valid.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_wrongType.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_wrongType.ser new file mode 100644 index 00000000000..3538676276f Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_wrongType.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType.ser new file mode 100644 index 00000000000..3469f871ef6 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_invalid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_invalid.ser new file mode 100644 index 00000000000..7da24ee9b96 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_invalid.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_null.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_null.ser new file mode 100644 index 00000000000..2c1536cc094 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_null.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_valid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_valid.ser new file mode 100644 index 00000000000..2c1536cc094 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_valid.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_wrongType.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_wrongType.ser new file mode 100644 index 00000000000..8520dffcf4c Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_wrongType.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/StandardProfilesRoundTrip.java b/test/jdk/java/awt/color/ICC_Profile/Serialization/StandardProfilesRoundTrip.java new file mode 100644 index 00000000000..6b29fd7f22a --- /dev/null +++ b/test/jdk/java/awt/color/ICC_Profile/Serialization/StandardProfilesRoundTrip.java @@ -0,0 +1,73 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.color.ColorSpace; +import java.awt.color.ICC_Profile; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +/** + * @test + * @bug 8367384 + * @summary Checks ICC_Profile serialization for standard profiles + */ +public final class StandardProfilesRoundTrip { + + private static final ICC_Profile[] PROFILES = { + ICC_Profile.getInstance(ColorSpace.CS_sRGB), + ICC_Profile.getInstance(ColorSpace.CS_LINEAR_RGB), + ICC_Profile.getInstance(ColorSpace.CS_CIEXYZ), + ICC_Profile.getInstance(ColorSpace.CS_PYCC), + ICC_Profile.getInstance(ColorSpace.CS_GRAY) + }; + + public static void main(String[] args) throws Exception { + // Test profiles one by one + for (ICC_Profile profile : PROFILES) { + test(profile); + } + // Test all profiles at once + test(PROFILES); + } + + private static void test(ICC_Profile... profiles) throws Exception { + byte[] data; + try (var bos = new ByteArrayOutputStream(); + var oos = new ObjectOutputStream(bos)) + { + for (ICC_Profile p : profiles) { + oos.writeObject(p); + } + data = bos.toByteArray(); + } + try (var ois = new ObjectInputStream(new ByteArrayInputStream(data))) { + for (ICC_Profile p : profiles) { + if (p != ois.readObject()) { + throw new RuntimeException("Wrong deserialized object"); + } + } + } + } +} diff --git a/test/jdk/java/awt/color/ICC_Profile/SerializedFormSize.java b/test/jdk/java/awt/color/ICC_Profile/SerializedFormSize.java new file mode 100644 index 00000000000..bb8d7a0ab88 --- /dev/null +++ b/test/jdk/java/awt/color/ICC_Profile/SerializedFormSize.java @@ -0,0 +1,72 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.color.ColorSpace; +import java.awt.color.ICC_Profile; +import java.io.ByteArrayOutputStream; +import java.io.ObjectOutputStream; + +/** + * @test + * @bug 8369032 + * @summary Checks the size of the serialized ICC_Profile for standard and + * non-standard profiles. + */ +public final class SerializedFormSize { + + private static final ICC_Profile[] PROFILES = { + ICC_Profile.getInstance(ColorSpace.CS_sRGB), + ICC_Profile.getInstance(ColorSpace.CS_LINEAR_RGB), + ICC_Profile.getInstance(ColorSpace.CS_CIEXYZ), + ICC_Profile.getInstance(ColorSpace.CS_PYCC), + ICC_Profile.getInstance(ColorSpace.CS_GRAY) + }; + + public static void main(String[] args) throws Exception { + for (ICC_Profile profile : PROFILES) { + byte[] data = profile.getData(); + int dataSize = data.length; + int min = 3; // At least version, name and data fields + int max = 200; // Small enough to confirm no data saved + + // Standard profile: should serialize to a small size, no data + test(profile, min, max); + // Non-standard profile: includes full data, but only once + test(ICC_Profile.getInstance(data), dataSize, dataSize + max); + } + } + + private static void test(ICC_Profile p, int min, int max) throws Exception { + try (var bos = new ByteArrayOutputStream(); + var oos = new ObjectOutputStream(bos)) + { + oos.writeObject(p); + int size = bos.size(); + if (size < min || size > max) { + System.err.println("Expected: >= " + min + " and <= " + max); + System.err.println("Actual: " + size); + throw new RuntimeException("Wrong size"); + } + } + } +} diff --git a/test/jdk/java/awt/color/ICC_Profile/ValidateICCHeaderData/ValidateICCHeaderData.java b/test/jdk/java/awt/color/ICC_Profile/ValidateICCHeaderData/ValidateICCHeaderData.java index 9867b727a09..62c5d4962e4 100644 --- a/test/jdk/java/awt/color/ICC_Profile/ValidateICCHeaderData/ValidateICCHeaderData.java +++ b/test/jdk/java/awt/color/ICC_Profile/ValidateICCHeaderData/ValidateICCHeaderData.java @@ -161,8 +161,8 @@ public static void main(String[] args) throws Exception { testProfileCreation(false); System.out.println("CASE 14: Passed \n"); - System.out.println("CASE 15: Testing Deserialization of ICC_Profile ..."); - testDeserialization(); + System.out.println("CASE 15: Testing loading of ICC_Profile from file ..."); + testLoading(); System.out.println("CASE 15: Passed \n"); System.out.println("Successfully completed testing all 15 cases. Test Passed !!"); @@ -261,9 +261,9 @@ private static void testInvalidHeaderSize() { } } - private static void testDeserialization() throws IOException { - //invalidSRGB.icc is serialized on older version of JDK - //Upon deserialization, the invalid profile is expected to throw IAE + private static void testLoading() throws IOException { + // invalidSRGB.icc is a profile file that was produced by an older JDK + // When attempting to load it, the current JDK is expected to throw IAE try { ICC_Profile.getInstance("./invalidSRGB.icc"); throw new RuntimeException("Test Failed ! Expected IAE NOT thrown"); diff --git a/test/jdk/java/awt/event/KeyEvent/KeyCharTest/KeyCharTest.java b/test/jdk/java/awt/event/KeyEvent/KeyCharTest/KeyCharTest.java index 83b6e7735ea..819c041308c 100644 --- a/test/jdk/java/awt/event/KeyEvent/KeyCharTest/KeyCharTest.java +++ b/test/jdk/java/awt/event/KeyEvent/KeyCharTest/KeyCharTest.java @@ -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 keyPressed(KeyEvent e){ } 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 @@ public void start () { 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 --git a/test/jdk/java/awt/event/MouseEvent/AltGraphModifierTest/AltGraphModifierTest.java b/test/jdk/java/awt/event/MouseEvent/AltGraphModifierTest/AltGraphModifierTest.java index 47d808f336d..c8730b28964 100644 --- a/test/jdk/java/awt/event/MouseEvent/AltGraphModifierTest/AltGraphModifierTest.java +++ b/test/jdk/java/awt/event/MouseEvent/AltGraphModifierTest/AltGraphModifierTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, 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 @@ -22,51 +22,57 @@ */ /* - @test - @bug 8041928 8158616 - @requires (os.family != "mac") - @summary Confirm that the Alt-Gr Modifier bit is set correctly. - @run main/manual AltGraphModifierTest + * @test + * @bug 8041928 8158616 + * @requires (os.family != "mac") + * @summary Confirm that the Alt-Gr Modifier bit is set correctly. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual AltGraphModifierTest */ -import java.awt.Button; -import java.awt.Dialog; import java.awt.Frame; -import java.awt.Panel; -import java.awt.TextArea; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.InputEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; public class AltGraphModifierTest { - private static void init() throws Exception { - String[] instructions - = { - "This test is for verifying Alt-Gr modifier of an event.", - "Linux :-", - "1. Please check if Alt-Gr key is present on keyboard.", - "2. If present, press the Alt-Gr key and perform", - " mouse click on the TestWindow.", - "3. Navigate to System Settings-> Keyboard-> Shortcuts->", - " Typing.", - "4. Select an option for the Alternative Characters Key", - " For example. Right Alt", - "5. Close the settings and navigate to test", - "6. Press Right Alt Key & perform mouse click on the", - " TestWindow", - "7. Test will exit by itself with appropriate result.", - " ", - }; - Sysout.createDialog(); - Sysout.printInstructions(instructions); + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + This test is for verifying Alt-Gr modifier of an event. + Please check if Alt-Gr key is present on keyboard. + If not present, press Pass. + On Windows: + Press Alt-Gr or Right Alt key and simultaneously + perform mouse click on the "TestWindow". + On Linux: + Navigate to + System Settings-> Keyboard-> Special Character Entry + Select "Right Alt" option for the "Alternate Characters Key" + Close the settings and navigate to test + Press Right Alt Key & simultaneously + perform mouse click on the "TestWindow". + + If the system does not have such setting, press Pass. + After the test, change the Setting of "Alternate Characters Key" + back to "Layout default". + + If "Alt-Gr Modifier bit is set" message is displayed in logArea, + press Pass else press Fail. + """; + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(AltGraphModifierTest::initTestWindow) + .logArea() + .build() + .awaitAndCheck(); } - static Frame mainFrame; - public static void initTestWindow() { - mainFrame = new Frame(); + public static Frame initTestWindow() { + Frame mainFrame = new Frame(); mainFrame.setTitle("TestWindow"); mainFrame.setBounds(700, 10, 300, 300); mainFrame.addMouseListener(new MouseAdapter() { @@ -74,186 +80,12 @@ public static void initTestWindow() { public void mousePressed(MouseEvent e) { int ex = e.getModifiersEx(); if ((ex & InputEvent.ALT_GRAPH_DOWN_MASK) == 0) { - AltGraphModifierTest.fail("Alt-Gr Modifier bit is not set."); + PassFailJFrame.log("Alt-Gr Modifier bit is not set."); } else { - AltGraphModifierTest.pass(); + PassFailJFrame.log("Alt-Gr Modifier bit is set"); } } }); - mainFrame.setVisible(true); - } - - public static void dispose() { - Sysout.dispose(); - mainFrame.dispose(); - } - - /** - * *************************************************** - * Standard Test Machinery Section DO NOT modify anything in this section -- - * it's a standard chunk of code which has all of the synchronisation - * necessary for the test harness. By keeping it the same in all tests, it - * is easier to read and understand someone else's test, as well as insuring - * that all tests behave correctly with the test harness. There is a section - * following this for test-defined classes - * **************************************************** - */ - private static boolean theTestPassed = false; - private static boolean testGeneratedInterrupt = false; - private static String failureMessage = ""; - private static Thread mainThread = null; - final private static int sleepTime = 300000; - - public static void main(String args[]) throws Exception { - mainThread = Thread.currentThread(); - try { - init(); - initTestWindow(); - } catch (Exception e) { - e.printStackTrace(); - } - try { - mainThread.sleep(sleepTime); - } catch (InterruptedException e) { - dispose(); - if (testGeneratedInterrupt && !theTestPassed) { - throw new Exception(failureMessage); - } - } - if (!testGeneratedInterrupt) { - dispose(); - throw new RuntimeException("Timed out after " + sleepTime / 1000 - + " seconds"); - } - } - - public static synchronized void pass() { - theTestPassed = true; - testGeneratedInterrupt = true; - mainThread.interrupt(); - } - - public static synchronized void fail(String whyFailed) { - theTestPassed = false; - testGeneratedInterrupt = true; - failureMessage = whyFailed; - mainThread.interrupt(); - } -} - -// *********** End Standard Test Machinery Section ********** -/** - * ************************************************** - * 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 Frame frame; - - public static void createDialog() { - frame = new Frame(); - dialog = new TestDialog(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 dispose() { - dialog.dispose(); - frame.dispose(); - } -} - -/** - * 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 implements ActionListener { - TextArea instructionsText; - TextArea messageText; - int maxStringLength = 80; - Panel buttonP; - Button failB; - - // 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); - - buttonP = new Panel(); - failB = new Button("Fail"); - failB.setActionCommand("fail"); - failB.addActionListener(this); - buttonP.add("Center", failB); - - add("South", buttonP); - pack(); - setVisible(true); - } - - // DO NOT call this directly, go through Sysout - public void printInstructions(String[] instructions) { - instructionsText.setText(""); - String printStr, remainingStr; - for (int i = 0; i < instructions.length; i++) { - remainingStr = instructions[i]; - while (remainingStr.length() > 0) { - if (remainingStr.length() >= maxStringLength) { - int posOfSpace = remainingStr. - lastIndexOf(' ', maxStringLength - 1); - - if (posOfSpace <= 0) { - posOfSpace = maxStringLength - 1; - } - - printStr = remainingStr.substring(0, posOfSpace + 1); - remainingStr = remainingStr.substring(posOfSpace + 1); - } - else { - printStr = remainingStr; - remainingStr = ""; - } - instructionsText.append(printStr + "\n"); - } - } - } - - public void displayMessage(String messageIn) { - messageText.append(messageIn + "\n"); - } - - public void actionPerformed(ActionEvent e) { - if (e.getActionCommand() == "fail") { - AltGraphModifierTest.fail("User Clicked Fail"); - } + return mainFrame; } } diff --git a/test/jdk/java/awt/font/FontNames/LocaleFamilyNames.java b/test/jdk/java/awt/font/FontNames/LocaleFamilyNames.java index 5356464334e..0fc27ea3de0 100644 --- a/test/jdk/java/awt/font/FontNames/LocaleFamilyNames.java +++ b/test/jdk/java/awt/font/FontNames/LocaleFamilyNames.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, 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 @@ -26,29 +26,32 @@ * @bug 4935798 6521210 6901159 * @summary Tests that all family names that are reported in all locales * correspond to some font returned from getAllFonts(). - * @run main LocaleFamilyNames + * @run main/othervm/timeout=360 LocaleFamilyNames */ import java.awt.*; import java.util.*; public class LocaleFamilyNames { public static void main(String[] args) throws Exception { + System.out.println("Start time: " + java.time.LocalDateTime.now()); GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - Font[] all_fonts = ge.getAllFonts(); - Locale[] all_locales = Locale.getAvailableLocales(); + System.out.println("Number of fonts: " + all_fonts.length); + System.out.println("Number of locales: " + all_locales.length); + HashSet all_families = new HashSet(); for (int i=0; i indices[i + 1]) { + throw new RuntimeException("Glyph character indices are supposed to be monotonically growing, but character index at position " + + i + " is bigger then the one at position " + (i + 1) + ", i.e. " + indices[i] + " > " + indices[i + 1] + "."); + } + } } } diff --git a/test/jdk/java/awt/font/LineBreakMeasurer/KhmerLineBreakTest.java b/test/jdk/java/awt/font/LineBreakMeasurer/KhmerLineBreakTest.java new file mode 100644 index 00000000000..855ad1b320b --- /dev/null +++ b/test/jdk/java/awt/font/LineBreakMeasurer/KhmerLineBreakTest.java @@ -0,0 +1,115 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8361381 + * @summary GlyphLayout behavior differs on JDK 11+ compared to JDK 8 + */ + +import java.awt.*; +import java.awt.font.FontRenderContext; +import java.awt.font.LineBreakMeasurer; +import java.awt.font.TextAttribute; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; +import java.text.BreakIterator; +import java.util.Locale; + +public class KhmerLineBreakTest { + static String khmer = "បានស្នើសុំនៅតែត្រូវបានបដិសេធ"; + /* + + This is part of the output we get from `ExtendedTextSourceLabel::createCharinfo()` + when running with `-Dsun.java2d.debugfonts=true`. It's a listing of the 28 code points + of the `khmer` string defined above and displays their x-position during rendering as + well as their advance. Code points with zero advance belong to the glyph cluster which + is started by the first preceding code point with a non-zero advance. There should be no + breaks at characters with zero advance, because this would break a glyph cluster. + + 0 ch: 1794 x: 0.0 xa: 68.115234 + 1 ch: 17b6 x: 68.115234 xa: 0.0 + 2 ch: 1793 x: 68.115234 xa: 45.410156 + 3 ch: 179f x: 113.52539 xa: 90.82031 + 4 ch: 17d2 x: 204.3457 xa: 0.0 + 5 ch: 1793 x: 204.3457 xa: 0.0 + 6 ch: 17be x: 204.3457 xa: 0.0 + 7 ch: 179f x: 204.3457 xa: 68.115234 + 8 ch: 17bb x: 272.46094 xa: 0.0 + 9 ch: 17c6 x: 272.46094 xa: 0.0 + 10 ch: 1793 x: 272.46094 xa: 90.82031 + 11 ch: 17c5 x: 363.28125 xa: 0.0 + 12 ch: 178f x: 363.28125 xa: 68.115234 + 13 ch: 17c2 x: 431.39648 xa: 0.0 + 14 ch: 178f x: 431.39648 xa: 68.115234 + 15 ch: 17d2 x: 499.51172 xa: 0.0 + 16 ch: 179a x: 499.51172 xa: 0.0 + 17 ch: 17bc x: 499.51172 xa: 0.0 + 18 ch: 179c x: 499.51172 xa: 22.705078 + 19 ch: 1794 x: 522.2168 xa: 68.115234 + 20 ch: 17b6 x: 590.33203 xa: 0.0 + 21 ch: 1793 x: 590.33203 xa: 45.410156 + 22 ch: 1794 x: 635.7422 xa: 45.410156 + 23 ch: 178a x: 681.15234 xa: 45.410156 + 24 ch: 17b7 x: 726.5625 xa: 0.0 + 25 ch: 179f x: 726.5625 xa: 90.82031 + 26 ch: 17c1 x: 817.3828 xa: 0.0 + 27 ch: 1792 x: 817.3828 xa: 45.410156 + + */ + static boolean[] possibleBreak = new boolean[] + { true, false, true, true, false, false, false, true, false, false, + true, false, true, false, true, false, false, false, true, true, + false, true, true, true, false, true, false, true, true /* */ }; + static Locale locale = new Locale.Builder().setLanguage("km").setRegion("KH").build(); + static BreakIterator breakIterator = BreakIterator.getLineInstance(locale); + static FontRenderContext frc = new FontRenderContext(null, true, true); + + public static void main(String[] args) { + Font[] allFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts(); + for (int i=0; i < allFonts.length; i++) { + if (allFonts[i].canDisplayUpTo(khmer) == -1) { + Font font = allFonts[i].deriveFont(Font.PLAIN, 60f); + System.out.println("Trying font: " + font.getFontName()); + AttributedString attrStr = new AttributedString(khmer); + attrStr.addAttribute(TextAttribute.FONT, font); + AttributedCharacterIterator it = attrStr.getIterator(); + for (int width = 200; width < 400; width += 10) { + LineBreakMeasurer measurer = new LineBreakMeasurer(it, breakIterator, frc); + System.out.print(width + " : "); + while (measurer.getPosition() < it.getEndIndex()) { + int nextOffset = measurer.nextOffset(width); + System.out.print(nextOffset + " "); + if (!possibleBreak[nextOffset]) { + System.out.println(); + throw new RuntimeException("Invalid break at offset " + nextOffset + " (width = " + width + " font = " + font.getFontName() + ")"); + } + measurer.setPosition(nextOffset); + } + System.out.println(); + } + System.out.println("OK"); + } + } + } +} diff --git a/test/jdk/java/awt/font/TextLayout/MyanmarTextTest.java b/test/jdk/java/awt/font/TextLayout/MyanmarTextTest.java index 32c748ce80f..20db89ff0c6 100644 --- a/test/jdk/java/awt/font/TextLayout/MyanmarTextTest.java +++ b/test/jdk/java/awt/font/TextLayout/MyanmarTextTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -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 class MyanmarTextTest { 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 void checkPositions() { } 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 --git a/test/jdk/java/awt/font/TextLayout/TestLayoutVsICU.java b/test/jdk/java/awt/font/TextLayout/TestLayoutVsICU.java deleted file mode 100644 index a12fd802fd5..00000000000 --- a/test/jdk/java/awt/font/TextLayout/TestLayoutVsICU.java +++ /dev/null @@ -1,889 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Copyright (C) 2013-2014 IBM Corporation and Others. All Rights Reserved. - */ - -import java.awt.Color; -import java.awt.Composite; -import java.awt.Font; -import java.awt.FontFormatException; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GraphicsConfiguration; -import java.awt.Image; -import java.awt.Paint; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.RenderingHints.Key; -import java.awt.Shape; -import java.awt.Stroke; -import java.awt.font.FontRenderContext; -import java.awt.font.GlyphVector; -import java.awt.font.TextLayout; -import java.awt.geom.AffineTransform; -import java.awt.image.BufferedImage; -import java.awt.image.BufferedImageOp; -import java.awt.image.ImageObserver; -import java.awt.image.RenderedImage; -import java.awt.image.renderable.RenderableImage; -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.text.AttributedCharacterIterator; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.MissingResourceException; -import java.util.TreeMap; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - -/** - * This test runs against a test XML file. It opens the fonts and attempts - * to shape and layout glyphs. - * Note that the test is highly environment dependent- you must have - * the same versions of the same fonts available or the test will fail. - * - * It is similar to letest which is part of ICU. - * For reference, here are some reference items: - * ICU's test file: - * http://source.icu-project.org/repos/icu/icu/trunk/source/test/testdata/letest.xml - * ICU's readme for the similar test: - * http://source.icu-project.org/repos/icu/icu/trunk/source/test/letest/readme.html - * - * @bug 8054203 - * @test - * @summary manual test of layout engine behavior. Takes an XML control file. - * @compile TestLayoutVsICU.java - * @author srl - * @run main/manual - */ -public class TestLayoutVsICU { - - public static boolean OPT_DRAW = false; - public static boolean OPT_VERBOSE = false; - public static boolean OPT_FAILMISSING = false; - public static boolean OPT_NOTHROW= false; // if true - don't stop on failure - - public static int docs = 0; // # docs processed - public static int skipped = 0; // cases skipped due to bad font - public static int total = 0; // cases processed - public static int bad = 0; // cases with errs - - public static final String XML_LAYOUT_TESTS = "layout-tests"; // top level - public static final String XML_TEST_CASE = "test-case"; - public static final String XML_TEST_FONT = "test-font"; - public static final String XML_TEST_TEXT = "test-text"; - public static final String XML_RESULT_GLYPHS = "result-glyphs"; - public static final String XML_ID = "id"; - public static final String XML_SCRIPT = "script"; - public static final String XML_NAME = "name"; - public static final String XML_VERSION = "version"; - public static final String XML_CHECKSUM = "checksum"; - public static final String XML_RESULT_INDICES = "result-indices"; - public static final String XML_RESULT_POSITIONS = "result-positions"; - - /** - * @param args - * @throws IOException - * @throws SAXException - * @throws ParserConfigurationException - */ - public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException { - System.out.println("Java " + System.getProperty("java.version") + " from " + System.getProperty("java.vendor")); - TestLayoutVsICU tlvi = null; - for(String arg : args) { - if(arg.equals("-d")) { - OPT_DRAW = true; - } else if(arg.equals("-n")) { - OPT_NOTHROW = true; - } else if(arg.equals("-v")) { - OPT_VERBOSE = true; - } else if(arg.equals("-f")) { - OPT_FAILMISSING = true; - } else { - if(tlvi == null) { - tlvi = new TestLayoutVsICU(); - } - try { - tlvi.show(arg); - } finally { - if(OPT_VERBOSE) { - System.out.println("# done with " + arg); - } - } - } - } - - if(tlvi == null) { - throw new IllegalArgumentException("No XML input. Usage: " + TestLayoutVsICU.class.getSimpleName() + " [-d][-v][-f] letest.xml ..."); - } else { - System.out.println("\n\nRESULTS:\n"); - System.out.println(skipped+"\tskipped due to missing font"); - System.out.println(total+"\ttested of which:"); - System.out.println(bad+"\twere bad"); - - if(bad>0) { - throw new InternalError("One or more failure(s)"); - } - } - } - - String id; - - private void show(String arg) throws ParserConfigurationException, SAXException, IOException { - id = ""; - File xmlFile = new File(arg); - if(!xmlFile.exists()) { - throw new FileNotFoundException("Can't open input XML file " + arg); - } - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - DocumentBuilder db = dbf.newDocumentBuilder(); - if(OPT_VERBOSE) { - System.out.println("# Parsing " + xmlFile.getAbsolutePath()); - } - Document doc = db.parse(xmlFile); - Element e = doc.getDocumentElement(); - if(!XML_LAYOUT_TESTS.equals(e.getNodeName())) { - throw new IllegalArgumentException("Document " + xmlFile.getAbsolutePath() + " does not have as its base"); - } - - NodeList testCases = e.getElementsByTagName(XML_TEST_CASE); - for(int caseNo=0;caseNo testCaseAttrs = attrs(testCase); - id = testCaseAttrs.get(XML_ID); - final String script = testCaseAttrs.get(XML_SCRIPT); - String testText = null; - Integer[] expectGlyphs = null; - Integer[] expectIndices = null; - Map fontAttrs = null; - if(OPT_VERBOSE) { - System.out.println("#"+caseNo+" id="+id + ", script="+script); - } - NodeList children = testCase.getChildNodes(); - for(int sub=0;sub glyphs = new ArrayList(); - Graphics2D myg2 = new Graphics2D(){ - - @Override - public void draw(Shape s) { - // TODO Auto-generated method stub - - } - - @Override - public boolean drawImage(Image img, AffineTransform xform, - ImageObserver obs) { - // TODO Auto-generated method stub - return false; - } - - @Override - public void drawImage(BufferedImage img, - BufferedImageOp op, int x, int y) { - // TODO Auto-generated method stub - - } - - @Override - public void drawRenderedImage(RenderedImage img, - AffineTransform xform) { - // TODO Auto-generated method stub - - } - - @Override - public void drawRenderableImage(RenderableImage img, - AffineTransform xform) { - // TODO Auto-generated method stub - - } - - @Override - public void drawString(String str, int x, int y) { - // TODO Auto-generated method stub - - } - - @Override - public void drawString(String str, float x, float y) { - // TODO Auto-generated method stub - - } - - @Override - public void drawString( - AttributedCharacterIterator iterator, int x, int y) { - // TODO Auto-generated method stub - - } - - @Override - public void drawString( - AttributedCharacterIterator iterator, float x, - float y) { - // TODO Auto-generated method stub - - } - - @Override - public void drawGlyphVector(GlyphVector g, float x, float y) { - if(x!=0.0 || y!=0.0) { - throw new InternalError("x,y should be 0 but got " + x+","+y); - } - //System.err.println("dGV : " + g.toString() + " @ "+x+","+y); - glyphs.add(g); - } - - @Override - public void fill(Shape s) { - // TODO Auto-generated method stub - - } - - @Override - public boolean hit(Rectangle rect, Shape s, boolean onStroke) { - // TODO Auto-generated method stub - return false; - } - - @Override - public GraphicsConfiguration getDeviceConfiguration() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void setComposite(Composite comp) { - // TODO Auto-generated method stub - - } - - @Override - public void setPaint(Paint paint) { - // TODO Auto-generated method stub - - } - - @Override - public void setStroke(Stroke s) { - // TODO Auto-generated method stub - - } - - @Override - public void setRenderingHint(Key hintKey, Object hintValue) { - // TODO Auto-generated method stub - - } - - @Override - public Object getRenderingHint(Key hintKey) { - // TODO Auto-generated method stub - return null; - } - - @Override - public void setRenderingHints(Map hints) { - // TODO Auto-generated method stub - - } - - @Override - public void addRenderingHints(Map hints) { - // TODO Auto-generated method stub - - } - - @Override - public RenderingHints getRenderingHints() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void translate(int x, int y) { - // TODO Auto-generated method stub - - } - - @Override - public void translate(double tx, double ty) { - // TODO Auto-generated method stub - - } - - @Override - public void rotate(double theta) { - // TODO Auto-generated method stub - - } - - @Override - public void rotate(double theta, double x, double y) { - // TODO Auto-generated method stub - - } - - @Override - public void scale(double sx, double sy) { - // TODO Auto-generated method stub - - } - - @Override - public void shear(double shx, double shy) { - // TODO Auto-generated method stub - - } - - @Override - public void transform(AffineTransform Tx) { - // TODO Auto-generated method stub - - } - - @Override - public void setTransform(AffineTransform Tx) { - // TODO Auto-generated method stub - - } - - @Override - public AffineTransform getTransform() { - // TODO Auto-generated method stub - return null; - } - - @Override - public Paint getPaint() { - // TODO Auto-generated method stub - return null; - } - - @Override - public Composite getComposite() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void setBackground(Color color) { - // TODO Auto-generated method stub - - } - - @Override - public Color getBackground() { - // TODO Auto-generated method stub - return null; - } - - @Override - public Stroke getStroke() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void clip(Shape s) { - // TODO Auto-generated method stub - - } - - @Override - public FontRenderContext getFontRenderContext() { - // TODO Auto-generated method stub - return null; - } - - @Override - public Graphics create() { - // TODO Auto-generated method stub - return null; - } - - @Override - public Color getColor() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void setColor(Color c) { - // TODO Auto-generated method stub - - } - - @Override - public void setPaintMode() { - // TODO Auto-generated method stub - - } - - @Override - public void setXORMode(Color c1) { - // TODO Auto-generated method stub - - } - - @Override - public Font getFont() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void setFont(Font font) { - // TODO Auto-generated method stub - - } - - @Override - public FontMetrics getFontMetrics(Font f) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Rectangle getClipBounds() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void clipRect(int x, int y, int width, int height) { - // TODO Auto-generated method stub - - } - - @Override - public void setClip(int x, int y, int width, int height) { - // TODO Auto-generated method stub - - } - - @Override - public Shape getClip() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void setClip(Shape clip) { - // TODO Auto-generated method stub - - } - - @Override - public void copyArea(int x, int y, int width, int height, - int dx, int dy) { - // TODO Auto-generated method stub - - } - - @Override - public void drawLine(int x1, int y1, int x2, int y2) { - // TODO Auto-generated method stub - - } - - @Override - public void fillRect(int x, int y, int width, int height) { - // TODO Auto-generated method stub - - } - - @Override - public void clearRect(int x, int y, int width, int height) { - // TODO Auto-generated method stub - - } - - @Override - public void drawRoundRect(int x, int y, int width, - int height, int arcWidth, int arcHeight) { - // TODO Auto-generated method stub - - } - - @Override - public void fillRoundRect(int x, int y, int width, - int height, int arcWidth, int arcHeight) { - // TODO Auto-generated method stub - - } - - @Override - public void drawOval(int x, int y, int width, int height) { - // TODO Auto-generated method stub - - } - - @Override - public void fillOval(int x, int y, int width, int height) { - // TODO Auto-generated method stub - - } - - @Override - public void drawArc(int x, int y, int width, int height, - int startAngle, int arcAngle) { - // TODO Auto-generated method stub - - } - - @Override - public void fillArc(int x, int y, int width, int height, - int startAngle, int arcAngle) { - // TODO Auto-generated method stub - - } - - @Override - public void drawPolyline(int[] xPoints, int[] yPoints, - int nPoints) { - // TODO Auto-generated method stub - - } - - @Override - public void drawPolygon(int[] xPoints, int[] yPoints, - int nPoints) { - // TODO Auto-generated method stub - - } - - @Override - public void fillPolygon(int[] xPoints, int[] yPoints, - int nPoints) { - // TODO Auto-generated method stub - - } - - @Override - public boolean drawImage(Image img, int x, int y, - ImageObserver observer) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean drawImage(Image img, int x, int y, - int width, int height, ImageObserver observer) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean drawImage(Image img, int x, int y, - Color bgcolor, ImageObserver observer) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean drawImage(Image img, int x, int y, - int width, int height, Color bgcolor, - ImageObserver observer) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean drawImage(Image img, int dx1, int dy1, - int dx2, int dy2, int sx1, int sy1, int sx2, - int sy2, ImageObserver observer) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean drawImage(Image img, int dx1, int dy1, - int dx2, int dy2, int sx1, int sy1, int sx2, - int sy2, Color bgcolor, ImageObserver observer) { - // TODO Auto-generated method stub - return false; - } - - @Override - public void dispose() { - // TODO Auto-generated method stub - - } - - }; - tl.draw(myg2, 0, 0); - if(glyphs.size() != 1) { - err("drew " + glyphs.size() + " times - expected 1"); - total++; - bad++; - continue; - } - boolean isBad = false; - GlyphVector gv = glyphs.get(0); - - // GLYPHS - int gotGlyphs[] = gv.getGlyphCodes(0, gv.getNumGlyphs(), new int[gv.getNumGlyphs()]); - - int count = Math.min(gotGlyphs.length, expectGlyphs.length); // go up to this count - - for(int i=0;i> OK: " + gotGlyphs.length + " glyphs"); - } - } - - - if(isBad) { - bad++; - System.out.println("* FAIL: " + id + " /\t" + fontName); - } else { - System.out.println("* OK : " + id + " /\t" + fontName); - } - total++; - } - } - - - private boolean verifyFont(File f, Map fontAttrs) { - InputStream fis = null; - String fontName = fontAttrs.get(XML_NAME); - int count=0; - try { - fis = new BufferedInputStream(new FileInputStream(f)); - - int i = 0; - int r; - try { - while((r=fis.read())!=-1) { - i+=(int)r; - count++; - } - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return false; - } - if(OPT_VERBOSE) { - System.out.println("for " + f.getAbsolutePath() + " chks = 0x" + Integer.toHexString(i) + " size=" + count); - } - String theirStr = fontAttrs.get("rchecksum"); - - String ourStr = Integer.toHexString(i).toLowerCase(); - - if(theirStr!=null) { - if(theirStr.startsWith("0x")) { - theirStr = theirStr.substring(2).toLowerCase(); - } else { - theirStr = theirStr.toLowerCase(); - } - long theirs = Integer.parseInt(theirStr, 16); - if(theirs != i) { - err("WARNING: rchecksum for " + fontName + " was " + i + " (0x"+ourStr+") "+ " but file said " + theirs +" (0x"+theirStr+") - perhaps a different font?"); - return false; - } else { - if(OPT_VERBOSE) { - System.out.println(" rchecksum for " + fontName + " OK"); - } - return true; - } - } else { - //if(OPT_VERBOSE) { - System.err.println("WARNING: rchecksum for " + fontName + " was " + i + " (0x"+ourStr+") "+ " but rchecksum was MISSING. Old ICU data?"); - //} - } - } catch (FileNotFoundException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return false; - } finally { - try { - fis.close(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - return true; - } - - - private Integer[] parseHexArray(String hex) { - List ret = new ArrayList(); - String items[] = hex.split("[\\s,]"); - for(String i : items) { - if(i.isEmpty()) continue; - if(i.startsWith("0x")) { - i = i.substring(2); - } - ret.add(Integer.parseInt(i, 16)); - } - return ret.toArray(new Integer[0]); - } - - - private void err(String string) { - if(OPT_NOTHROW) { - System.out.println(id+" ERROR: " + string +" (continuing due to -n)"); - } else { - throw new InternalError(id+ ": " + string); - } - } - - - private Font getFont(String fontName, Map fontAttrs) { - Font f; - if(false) - try { - f = Font.getFont(fontName); - if(f!=null) { - if(OPT_VERBOSE) { - System.out.println("Loaded default path to " + fontName); - } - return f; - } - } catch(Throwable t) { - if(OPT_VERBOSE) { - t.printStackTrace(); - System.out.println("problem loading font " + fontName + " - " + t.toString()); - } - } - - File homeDir = new File(System.getProperty("user.home")); - File fontDir = new File(homeDir, "fonts"); - File fontFile = new File(fontDir, fontName); - //System.out.println("## trying " + fontFile.getAbsolutePath()); - if(fontFile.canRead()) { - try { - if(!verifyFont(fontFile,fontAttrs)) { - System.out.println("Warning: failed to verify " + fontName); - } - f = Font.createFont(Font.TRUETYPE_FONT, fontFile); - if(f!=null & OPT_VERBOSE) { - System.out.println("> loaded from " + fontFile.getAbsolutePath() + " - " + f.toString()); - } - return f; - } catch (FontFormatException e) { - if(OPT_VERBOSE) { - e.printStackTrace(); - System.out.println("problem loading font " + fontName + " - " + e.toString()); - } - } catch (IOException e) { - if(OPT_VERBOSE) { - e.printStackTrace(); - System.out.println("problem loading font " + fontName + " - " + e.toString()); - } - } - } - return null; - } - - - private static Map attrs(Node testCase) { - Map rv = new TreeMap(); - NamedNodeMap nnm = testCase.getAttributes(); - for(int i=0;i - - - - - - - - - - श्रीमद् भगवद्गीता अध्याय अर्जुन विषाद योग धृतराष्ट्र उवाचृ धर्मक्षेत्रे कुरुक्षेत्रे समवेता युयुत्सवः मामकाः पाण्डवाश्चैव किमकुर्वत संजव - - - 0x0000009E, 0x0000009A, 0x00000051, 0x00000222, 0x00000098, 0x00000091, 0x00000051, 0x00000003, - 0x00000097, 0x00000082, 0x0000009D, 0x000001A5, 0x0000FFFF, 0x0000FFFF, 0x00000222, 0x0000008F, - 0x00000221, 0x00000003, 0x0000005C, 0x000000DA, 0x0000FFFF, 0x00000099, 0x00000221, 0x00000099, - 0x00000003, 0x0000005C, 0x00000087, 0x000001D5, 0x0000005B, 0x0000FFFF, 0x00000093, 0x00000003, - 0x000001D2, 0x0000009D, 0x0000009F, 0x00000221, 0x00000091, 0x00000003, 0x00000099, 0x0000022A, - 0x00000082, 0x00000003, 0x00000092, 0x000001D9, 0x0000008F, 0x0000009A, 0x00000221, 0x000001B4, - 0x0000FFFF, 0x0000FFFF, 0x0000009A, 0x00000051, 0x00000003, 0x00000060, 0x0000009D, 0x00000221, - 0x00000085, 0x000001D9, 0x00000003, 0x00000092, 0x00000098, 0x0000005B, 0x0000FFFF, 0x000000A2, - 0x0000FFFF, 0x0000FFFF, 0x0000022F, 0x0000008F, 0x0000009A, 0x00000051, 0x0000022F, 0x00000003, - 0x00000080, 0x000001D5, 0x0000009A, 0x000001FD, 0x000000A2, 0x0000FFFF, 0x0000FFFF, 0x0000022F, - 0x0000008F, 0x0000009A, 0x00000051, 0x0000022F, 0x00000003, 0x000000A0, 0x00000098, 0x0000009D, - 0x0000022F, 0x0000008F, 0x00000221, 0x00000003, 0x00000099, 0x000001D5, 0x00000099, 0x000001D5, - 0x000000D7, 0x0000FFFF, 0x000000A0, 0x0000009D, 0x0000022C, 0x00000003, 0x00000098, 0x00000221, - 0x00000098, 0x00000080, 0x00000221, 0x0000022C, 0x00000003, 0x00000094, 0x00000221, 0x000000D6, - 0x0000FFFF, 0x0000008C, 0x0000009D, 0x00000221, 0x000001B1, 0x0000FFFF, 0x0000FFFF, 0x00000230, - 0x0000009D, 0x00000003, 0x000001D1, 0x00000080, 0x00000098, 0x00000080, 0x000001D5, 0x0000009D, - 0x0000005B, 0x0000FFFF, 0x0000008F, 0x00000003, 0x000000A0, 0x00000232, 0x00000087, 0x0000009D - - - - 0x00000000, 0x00000002, 0x00000001, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007, - 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F, - 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000016, 0x00000017, - 0x00000018, 0x00000019, 0x0000001C, 0x0000001D, 0x0000001A, 0x0000001B, 0x0000001E, 0x0000001F, - 0x00000021, 0x00000020, 0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000026, 0x00000027, - 0x00000028, 0x00000029, 0x0000002A, 0x0000002B, 0x0000002C, 0x0000002D, 0x0000002E, 0x0000002F, - 0x00000030, 0x00000031, 0x00000033, 0x00000032, 0x00000034, 0x00000035, 0x00000036, 0x00000037, - 0x00000038, 0x00000039, 0x0000003A, 0x0000003B, 0x0000003E, 0x0000003C, 0x0000003D, 0x0000003F, - 0x00000040, 0x00000041, 0x00000042, 0x00000043, 0x00000045, 0x00000044, 0x00000046, 0x00000047, - 0x00000048, 0x00000049, 0x0000004A, 0x0000004B, 0x0000004C, 0x0000004D, 0x0000004E, 0x0000004F, - 0x00000050, 0x00000052, 0x00000051, 0x00000053, 0x00000054, 0x00000055, 0x00000056, 0x00000057, - 0x00000058, 0x00000059, 0x0000005A, 0x0000005B, 0x0000005C, 0x0000005D, 0x0000005E, 0x0000005F, - 0x00000060, 0x00000061, 0x00000062, 0x00000063, 0x00000064, 0x00000065, 0x00000066, 0x00000067, - 0x00000068, 0x00000069, 0x0000006A, 0x0000006B, 0x0000006C, 0x0000006D, 0x0000006E, 0x0000006F, - 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, 0x00000075, 0x00000076, 0x00000077, - 0x00000078, 0x00000079, 0x0000007B, 0x0000007A, 0x0000007C, 0x0000007D, 0x0000007E, 0x00000081, - 0x0000007F, 0x00000080, 0x00000082, 0x00000083, 0x00000084, 0x00000085, 0x00000086, 0x00000087 - - - - 0.000000, 0.000000, 9.468750, 0.000000, 19.130859, -0.451172, 15.984375, 0.000000, - 19.640625, 0.000000, 29.109375, 0.000000, 40.177734, -0.451172, 37.078125, 0.000000, - 43.078125, 0.000000, 52.546875, 0.000000, 62.015625, 0.000000, 69.984375, 0.000000, - 77.953125, 0.000000, 77.953125, 0.000000, 77.953125, 0.000000, 81.609375, 0.000000, - 89.578125, 0.000000, 93.234375, 0.000000, 99.234375, 0.000000, 109.171875, 0.000000, - 116.437500, 0.000000, 116.437500, 0.000000, 125.906250, 0.000000, 129.562500, 0.000000, - 139.031250, 0.000000, 145.031250, 0.000000, 154.968750, 0.000000, 164.718750, -0.011719, - 164.718750, 0.263672, 164.437500, 0.000000, 164.437500, 0.000000, 173.906250, 0.000000, - 179.906250, 0.000000, 184.265625, 0.000000, 192.234375, 0.000000, 200.203125, 0.000000, - 203.859375, 0.000000, 211.828125, 0.000000, 217.828125, 0.000000, 227.296875, 0.000000, - 231.375000, 0.000000, 240.843750, 0.000000, 246.843750, 0.000000, 256.740234, -0.011719, - 256.312500, 0.000000, 264.281250, 0.000000, 270.796875, 0.000000, 274.453125, 0.000000, - 282.796875, 0.000000, 282.796875, 0.000000, 282.796875, 0.000000, 292.458984, -0.451172, - 289.312500, 0.000000, 295.312500, 0.000000, 303.281250, 0.000000, 311.250000, 0.000000, - 314.906250, 0.000000, 324.890625, -0.011719, 324.375000, 0.000000, 330.375000, 0.000000, - 339.843750, 0.000000, 349.675781, 0.263672, 349.312500, 0.000000, 349.312500, 0.000000, - 360.187500, 0.000000, 360.187500, 0.000000, 359.384766, 0.275391, 360.187500, 0.000000, - 368.156250, 0.000000, 377.818359, -0.451172, 372.996094, 0.263672, 374.671875, 0.000000, - 380.671875, 0.000000, 388.371094, -0.011719, 391.546875, 0.000000, 398.062500, 0.000000, - 399.421875, 0.000000, 410.296875, 0.000000, 410.296875, 0.000000, 409.494141, 0.275391, - 410.296875, 0.000000, 418.265625, 0.000000, 427.927734, -0.451172, 423.105469, 0.263672, - 424.781250, 0.000000, 430.781250, 0.000000, 440.250000, 0.000000, 449.718750, 0.000000, - 456.832031, 0.263672, 457.687500, 0.000000, 465.656250, 0.000000, 469.312500, 0.000000, - 475.312500, 0.000000, 484.921875, -0.011719, 484.781250, 0.000000, 494.390625, -0.011719, - 494.250000, 0.000000, 500.179688, 0.000000, 500.179688, 0.000000, 509.648438, 0.000000, - 517.617188, 0.000000, 521.976562, 0.000000, 527.976562, 0.000000, 537.445312, 0.000000, - 541.101562, 0.000000, 550.570312, 0.000000, 561.445312, 0.000000, 565.101562, 0.000000, - 569.460938, 0.000000, 575.460938, 0.000000, 583.429688, 0.000000, 587.085938, 0.000000, - 594.351562, 0.000000, 594.351562, 0.000000, 602.320312, 0.000000, 610.289062, 0.000000, - 613.945312, 0.000000, 624.820312, 0.000000, 624.820312, 0.000000, 624.691406, 0.263672, - 624.820312, 0.000000, 632.789062, 0.000000, 638.789062, 0.000000, 643.148438, 0.000000, - 654.023438, 0.000000, 663.492188, 0.000000, 671.191406, -0.011719, 674.367188, 0.000000, - 682.628906, 0.263672, 682.335938, 0.000000, 682.335938, 0.000000, 690.304688, 0.000000, - 696.304688, 0.000000, 705.140625, 0.439453, 705.773438, 0.000000, 715.242188, 0.000000, - 723.210938, 0.000000 - - - - - - - أساسًا، تتعامل الحواسيب فقط مع الأرقام، وتقوم بتخزين الأحرف والمحارف الأخرى بعد أن تُعطي رقما معينا لكل واحد منها. وقبل اختراع "يونِكود"، كان هناك مئات الأنظمة للتشفير وتخصيص هذه الأرقام للمحارف، ولم يوجد نظام تشفير واحد يحتوي على جميع المحارف الضرورية - - - 0x0000CE28, 0x0000CE87, 0x0000CE41, 0x0000CE81, 0x0000CE42, 0x0000CE54, 0x0000CE73, 0x0000CE21, - 0x00000003, 0x0000CE65, 0x0000CE41, 0x0000CE22, 0x0000CE38, 0x0000CE78, 0x0000CE73, 0x0000CE21, - 0x00000003, 0x0000CE5E, 0x0000CE88, 0x0000CE78, 0x0000CE33, 0x00000003, 0x0000CE84, 0x0000CE74, - 0x0000CE5F, 0x00000003, 0x0000CE85, 0x0000CE82, 0x0000CE2C, 0x0000CE38, 0x0000CE87, 0x00000003, - 0x0000CE3E, 0x0000CE37, 0x0000CE21, 0x0000CE81, 0x00000003, 0x0000CE42, 0x0000CE88, 0x0000CE68, - 0x0000CE4C, 0x0000CE2B, 0x00000003, 0x0000CE75, 0x0000CE22, 0x0000CE5C, 0x0000CE7B, 0x00000003, - 0x0000CE3E, 0x0000CE33, 0x0000CE82, 0x0000CE87, 0x00000003, 0x0000CE76, 0x0000CE73, 0x0000CE81, - 0x00000003, 0x00000588, 0x0000CE65, 0x0000CE41, 0x0000CE22, 0x0000CE38, 0x0000CE78, 0x0000CE74, - 0x0000CE73, 0x00000003, 0x0000CE75, 0x0000CE22, 0x0000CE6B, 0x0000CE41, 0x0000FFFE, 0x0000CE8B, - 0x0000CE21, 0x00000003, 0x0000CE7D, 0x0000CE40, 0x0000CE7F, 0x00000003, 0x0000CE4E, 0x0000CE88, - 0x0000CE50, 0x0000CE3C, 0x0000CE2B, 0x0000CE81, 0x00000003, 0x0000CE42, 0x0000CE88, 0x0000CE68, - 0x0000CE4C, 0x0000CE2C, 0x0000CE74, 0x0000CE73, 0x00000003, 0x0000CE28, 0x0000CE78, 0x0000CE5C, - 0x0000CE7B, 0x0000FFFE, 0x0000CE8B, 0x0000CE21, 0x00000003, 0x0000CE29, 0x0000CE22, 0x0000CE20, - 0x0000CE77, 0x00000003, 0x0000CE6D, 0x0000CE22, 0x0000CE7C, 0x0000CE7F, 0x00000003, 0x0000CE79, - 0x0000CE22, 0x0000CE6F, 0x00000003, 0x00000588, 0x00000005, 0x0000CE3D, 0x0000CE82, 0x0000CE70, - 0x000005B5, 0x0000CE7B, 0x0000CE82, 0x0000CE87, 0x00000005, 0x00000003, 0x0000CE5D, 0x0000CE21, - 0x0000CE42, 0x0000CE2C, 0x0000CE3B, 0x0000CE21, 0x00000003, 0x0000CE72, 0x0000CE26, 0x0000CE6B, - 0x0000CE81, 0x00000003, 0x00000011, 0x0000CE22, 0x0000CE80, 0x0000CE7C, 0x0000CE77, 0x00000003, - 0x0000CE3E, 0x0000CE37, 0x0000CE21, 0x0000CE81, 0x00000003, 0x0000CE72, 0x0000CE70, 0x0000CE73, - 0x00000003, 0x0000CE22, 0x0000CE7C, 0x0000CE88, 0x0000CE60, 0x0000CE77, 0x00000003, 0x0000CE22, - 0x0000CE78, 0x0000CE6B, 0x0000CE41, 0x00000003, 0x0000CE86, 0x0000CE58, 0x0000CE60, 0x000005B4, - 0x0000CE2B, 0x00000003, 0x0000CE79, 0x0000CE17, 0x00000003, 0x0000CE3E, 0x0000CE60, 0x0000CE25, - 0x00000003, 0x0000CE83, 0x0000CE42, 0x0000CE3B, 0x0000FFFE, 0x0000CE8B, 0x0000CE21, 0x00000003, - 0x0000CE65, 0x0000CE41, 0x0000CE22, 0x0000CE38, 0x0000CE78, 0x0000CE73, 0x0000CE21, 0x0000CE81, - 0x00000003, 0x0000CE65, 0x0000CE42, 0x0000CE37, 0x0000FFFE, 0x0000CE8B, 0x0000CE21, 0x00000003, - 0x0000CE7A, 0x0000CE87, 0x0000CE44, 0x0000CE3C, 0x0000CE2C, 0x0000CE25, 0x00000003, 0x0000CE75, - 0x0000CE82, 0x0000CE6C, 0x0000CE2B, 0x0000CE81, 0x00000003, 0x00000588, 0x0000CE75, 0x0000CE22, - 0x0000CE6B, 0x0000CE41, 0x0000FFFE, 0x0000CE8B, 0x0000CE21, 0x00000003, 0x0000CE5E, 0x0000CE77, - 0x00000003, 0x0000CE56, 0x0000CE6C, 0x0000CE67, 0x00000003, 0x0000CE24, 0x0000CE88, 0x0000CE47, - 0x0000CE21, 0x0000CE82, 0x0000CE38, 0x0000CE73, 0x0000CE21, 0x00000003, 0x0000CE72, 0x0000CE77, - 0x0000CE22, 0x0000CE60, 0x0000CE2C, 0x0000CE2B, 0x00000003, 0x00000588, 0x0000CE22, 0x000005B0, - 0x0000CE47, 0x0000CE22, 0x0000CE47, 0x0000CE17 - - - - 0x000000FB, 0x000000FA, 0x000000F9, 0x000000F8, 0x000000F7, 0x000000F6, 0x000000F5, 0x000000F4, - 0x000000F3, 0x000000F2, 0x000000F1, 0x000000F0, 0x000000EF, 0x000000EE, 0x000000ED, 0x000000EC, - 0x000000EB, 0x000000EA, 0x000000E9, 0x000000E8, 0x000000E7, 0x000000E6, 0x000000E5, 0x000000E4, - 0x000000E3, 0x000000E2, 0x000000E1, 0x000000E0, 0x000000DF, 0x000000DE, 0x000000DD, 0x000000DC, - 0x000000DB, 0x000000DA, 0x000000D9, 0x000000D8, 0x000000D7, 0x000000D6, 0x000000D5, 0x000000D4, - 0x000000D3, 0x000000D2, 0x000000D1, 0x000000D0, 0x000000CF, 0x000000CE, 0x000000CD, 0x000000CC, - 0x000000CB, 0x000000CA, 0x000000C9, 0x000000C8, 0x000000C7, 0x000000C6, 0x000000C5, 0x000000C4, - 0x000000C3, 0x000000C2, 0x000000C1, 0x000000C0, 0x000000BF, 0x000000BE, 0x000000BD, 0x000000BC, - 0x000000BB, 0x000000BA, 0x000000B9, 0x000000B8, 0x000000B7, 0x000000B6, 0x000000B5, 0x000000B4, - 0x000000B3, 0x000000B2, 0x000000B1, 0x000000B0, 0x000000AF, 0x000000AE, 0x000000AD, 0x000000AC, - 0x000000AB, 0x000000AA, 0x000000A9, 0x000000A8, 0x000000A7, 0x000000A6, 0x000000A5, 0x000000A4, - 0x000000A3, 0x000000A2, 0x000000A1, 0x000000A0, 0x0000009F, 0x0000009E, 0x0000009D, 0x0000009C, - 0x0000009B, 0x0000009A, 0x00000099, 0x00000098, 0x00000097, 0x00000096, 0x00000095, 0x00000094, - 0x00000093, 0x00000092, 0x00000091, 0x00000090, 0x0000008F, 0x0000008E, 0x0000008D, 0x0000008C, - 0x0000008B, 0x0000008A, 0x00000089, 0x00000088, 0x00000087, 0x00000086, 0x00000085, 0x00000084, - 0x00000083, 0x00000082, 0x00000081, 0x00000080, 0x0000007F, 0x0000007E, 0x0000007D, 0x0000007C, - 0x0000007B, 0x0000007A, 0x00000079, 0x00000078, 0x00000077, 0x00000076, 0x00000075, 0x00000074, - 0x00000073, 0x00000072, 0x00000071, 0x00000070, 0x0000006F, 0x0000006E, 0x0000006D, 0x0000006C, - 0x0000006B, 0x0000006A, 0x00000069, 0x00000068, 0x00000067, 0x00000066, 0x00000065, 0x00000064, - 0x00000063, 0x00000062, 0x00000061, 0x00000060, 0x0000005F, 0x0000005E, 0x0000005D, 0x0000005C, - 0x0000005B, 0x0000005A, 0x00000059, 0x00000058, 0x00000057, 0x00000056, 0x00000055, 0x00000054, - 0x00000053, 0x00000052, 0x00000051, 0x00000050, 0x0000004F, 0x0000004E, 0x0000004D, 0x0000004C, - 0x0000004B, 0x0000004A, 0x00000049, 0x00000048, 0x00000047, 0x00000046, 0x00000045, 0x00000044, - 0x00000043, 0x00000042, 0x00000041, 0x00000040, 0x0000003F, 0x0000003E, 0x0000003D, 0x0000003C, - 0x0000003B, 0x0000003A, 0x00000039, 0x00000038, 0x00000037, 0x00000036, 0x00000035, 0x00000034, - 0x00000033, 0x00000032, 0x00000031, 0x00000030, 0x0000002F, 0x0000002E, 0x0000002D, 0x0000002C, - 0x0000002B, 0x0000002A, 0x00000029, 0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024, - 0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001F, 0x0000001E, 0x0000001D, 0x0000001C, - 0x0000001B, 0x0000001A, 0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015, 0x00000014, - 0x00000013, 0x00000012, 0x00000011, 0x00000010, 0x0000000F, 0x0000000E, 0x0000000D, 0x0000000C, - 0x0000000B, 0x0000000A, 0x00000009, 0x00000008, 0x00000007, 0x00000006, 0x00000005, 0x00000004, - 0x00000003, 0x00000002, 0x00000001, 0x00000000 - - - - 0.000000, 0.000000, 4.007812, 0.000000, 8.226562, 0.000000, 12.679688, 0.000000, - 18.679688, 0.000000, 23.132812, 0.000000, 31.289062, 0.000000, 34.312500, 0.000000, - 36.375000, 0.000000, 41.062500, 0.000000, 50.296875, 0.000000, 54.750000, 0.000000, - 56.859375, 0.000000, 62.367188, 0.000000, 66.632812, 0.000000, 69.656250, 0.000000, - 71.718750, 0.000000, 76.406250, 0.000000, 81.421875, 0.000000, 85.664062, 0.000000, - 89.929688, 0.000000, 95.742188, 0.000000, 100.429688, 0.000000, 108.796875, 0.000000, - 112.171875, 0.000000, 115.734375, 0.000000, 120.421875, 0.000000, 128.765625, 0.000000, - 134.765625, 0.000000, 139.007812, 0.000000, 144.515625, 0.000000, 148.734375, 0.000000, - 153.421875, 0.000000, 157.359375, 0.000000, 163.171875, 0.000000, 165.234375, 0.000000, - 171.234375, 0.000000, 175.921875, 0.000000, 180.375000, 0.000000, 184.617188, 0.000000, - 188.085938, 0.000000, 195.117188, 0.000000, 199.312500, 0.000000, 204.000000, 0.000000, - 208.007812, 0.000000, 210.117188, 0.000000, 217.054688, 0.000000, 220.429688, 0.000000, - 225.117188, 0.000000, 229.054688, 0.000000, 234.867188, 0.000000, 240.867188, 0.000000, - 245.085938, 0.000000, 249.773438, 0.000000, 253.781250, 0.000000, 256.804688, 0.000000, - 262.804688, 0.000000, 267.492188, 0.000000, 271.007812, 0.000000, 280.242188, 0.000000, - 284.695312, 0.000000, 286.804688, 0.000000, 292.312500, 0.000000, 296.578125, 0.000000, - 299.953125, 0.000000, 302.976562, 0.000000, 307.664062, 0.000000, 311.671875, 0.000000, - 313.781250, 0.000000, 317.882812, 0.000000, 322.335938, 0.000000, 322.335938, 0.000000, - 328.500000, 0.000000, 330.562500, 0.000000, 335.250000, 0.000000, 339.140625, 0.000000, - 343.078125, 0.000000, 348.984375, 0.000000, 353.671875, 0.000000, 366.445312, 0.000000, - 370.687500, 0.000000, 378.843750, 0.000000, 384.351562, 0.000000, 388.546875, 0.000000, - 394.546875, 0.000000, 399.234375, 0.000000, 403.687500, 0.000000, 407.929688, 0.000000, - 411.398438, 0.000000, 418.429688, 0.000000, 422.671875, 0.000000, 426.046875, 0.000000, - 429.070312, 0.000000, 433.757812, 0.000000, 437.765625, 0.000000, 442.031250, 0.000000, - 448.968750, 0.000000, 452.343750, 0.000000, 452.343750, 0.000000, 458.507812, 0.000000, - 460.570312, 0.000000, 465.257812, 0.000000, 474.492188, 0.000000, 476.601562, 0.000000, - 480.843750, 0.000000, 485.109375, 0.000000, 489.796875, 0.000000, 497.437500, 0.000000, - 499.546875, 0.000000, 503.765625, 0.000000, 509.671875, 0.000000, 514.359375, 0.000000, - 521.671875, 0.000000, 523.781250, 0.000000, 529.453125, 0.000000, 534.140625, 0.000000, - 537.656250, 0.000000, 543.046875, 0.000000, 546.585938, 0.000000, 552.585938, 0.000000, - 560.367188, 0.000000, 560.367188, 0.000000, 563.742188, 0.000000, 569.742188, 0.000000, - 573.960938, 0.000000, 579.351562, 0.000000, 584.039062, 0.000000, 589.851562, 0.000000, - 591.914062, 0.000000, 596.367188, 0.000000, 600.609375, 0.000000, 606.421875, 0.000000, - 608.484375, 0.000000, 613.171875, 0.000000, 619.570312, 0.000000, 623.812500, 0.000000, - 627.914062, 0.000000, 633.914062, 0.000000, 638.601562, 0.000000, 641.929688, 0.000000, - 644.039062, 0.000000, 647.789062, 0.000000, 652.007812, 0.000000, 656.273438, 0.000000, - 660.960938, 0.000000, 664.898438, 0.000000, 670.710938, 0.000000, 672.773438, 0.000000, - 678.773438, 0.000000, 683.460938, 0.000000, 689.859375, 0.000000, 697.640625, 0.000000, - 700.664062, 0.000000, 705.351562, 0.000000, 707.460938, 0.000000, 711.679688, 0.000000, - 715.921875, 0.000000, 719.390625, 0.000000, 723.656250, 0.000000, 728.343750, 0.000000, - 730.453125, 0.000000, 734.718750, 0.000000, 738.820312, 0.000000, 743.273438, 0.000000, - 747.960938, 0.000000, 756.328125, 0.000000, 763.265625, 0.000000, 766.734375, 0.000000, - 766.734375, 0.000000, 770.929688, 0.000000, 775.617188, 0.000000, 782.929688, 0.000000, - 785.273438, 0.000000, 789.960938, 0.000000, 793.898438, 0.000000, 797.367188, 0.000000, - 800.812500, 0.000000, 805.500000, 0.000000, 813.843750, 0.000000, 818.296875, 0.000000, - 824.109375, 0.000000, 824.109375, 0.000000, 830.273438, 0.000000, 832.335938, 0.000000, - 837.023438, 0.000000, 846.257812, 0.000000, 850.710938, 0.000000, 852.820312, 0.000000, - 858.328125, 0.000000, 862.593750, 0.000000, 865.617188, 0.000000, 867.679688, 0.000000, - 873.679688, 0.000000, 878.367188, 0.000000, 887.601562, 0.000000, 892.054688, 0.000000, - 897.867188, 0.000000, 897.867188, 0.000000, 904.031250, 0.000000, 906.093750, 0.000000, - 910.781250, 0.000000, 918.257812, 0.000000, 922.476562, 0.000000, 926.929688, 0.000000, - 932.437500, 0.000000, 936.679688, 0.000000, 940.125000, 0.000000, 944.812500, 0.000000, - 948.820312, 0.000000, 954.820312, 0.000000, 958.289062, 0.000000, 962.484375, 0.000000, - 968.484375, 0.000000, 973.171875, 0.000000, 976.687500, 0.000000, 980.695312, 0.000000, - 982.804688, 0.000000, 986.906250, 0.000000, 991.359375, 0.000000, 991.359375, 0.000000, - 997.523438, 0.000000, 999.585938, 0.000000, 1004.273438, 0.000000, 1009.289062, 0.000000, - 1013.554688, 0.000000, 1018.242188, 0.000000, 1026.187500, 0.000000, 1029.656250, 0.000000, - 1033.757812, 0.000000, 1038.445312, 0.000000, 1047.796875, 0.000000, 1052.039062, 0.000000, - 1058.859375, 0.000000, 1060.921875, 0.000000, 1066.921875, 0.000000, 1072.429688, 0.000000, - 1075.453125, 0.000000, 1077.515625, 0.000000, 1082.203125, 0.000000, 1088.601562, 0.000000, - 1092.867188, 0.000000, 1094.976562, 0.000000, 1098.445312, 0.000000, 1102.687500, 0.000000, - 1106.882812, 0.000000, 1111.570312, 0.000000, 1115.085938, 0.000000, 1117.195312, 0.000000, - 1117.195312, 0.000000, 1124.015625, 0.000000, 1126.125000, 0.000000, 1132.945312, 0.000000, - 1135.289062, 0.000000 - - - - - - - أساسًا، تتعامل الحواسيب فقط مع الأرقام، وتقوم بتخزين الأحرف والمحارف الأخرى بعد أن تُعطي رقما معينا لكل واحد منها. وقبل اختراع "يونِكود"، كان هناك مئات الأنظمة للتشفير وتخصيص هذه الأرقام للمحارف، ولم يوجد نظام تشفير واحد يحتوي على جميع المحارف الضرورية - - - 0x00000872, 0x000008D1, 0x000003F9, 0x0000040B, 0x0000088C, 0x0000089E, 0x000008BD, 0x000003EF, - 0x00000003, 0x00000404, 0x000003F9, 0x0000086C, 0x00000882, 0x000008C2, 0x000008BD, 0x000003EF, - 0x00000003, 0x000008A8, 0x000008D2, 0x000008C2, 0x0000087D, 0x00000003, 0x000008CE, 0x000008BE, - 0x000008A9, 0x00000003, 0x0000040D, 0x000008CC, 0x00000876, 0x00000882, 0x000008D1, 0x00000003, - 0x00000888, 0x00000881, 0x000003EF, 0x0000040B, 0x00000003, 0x0000088C, 0x000008D2, 0x000008B2, - 0x00000896, 0x00000875, 0x00000003, 0x00000408, 0x0000086C, 0x000008A6, 0x000008C5, 0x00000003, - 0x00000888, 0x0000087D, 0x000008CC, 0x000008D1, 0x00000003, 0x000008C0, 0x000008BD, 0x0000040B, - 0x00000003, 0x000003E6, 0x00000404, 0x000003F9, 0x0000086C, 0x00000882, 0x000008C2, 0x000008BE, - 0x000008BD, 0x00000003, 0x00000408, 0x0000086C, 0x000008B5, 0x000003F9, 0x0000FFFF, 0x000008D5, - 0x000003EF, 0x00000003, 0x0000040A, 0x0000088A, 0x000008C9, 0x00000003, 0x00000898, 0x000008D2, - 0x0000089A, 0x00000886, 0x00000875, 0x0000040B, 0x00000003, 0x0000088C, 0x000008D2, 0x000008B2, - 0x00000896, 0x00000876, 0x000008BE, 0x000008BD, 0x00000003, 0x00000872, 0x000008C2, 0x000008A6, - 0x000008C5, 0x0000FFFF, 0x000008D5, 0x000003EF, 0x00000003, 0x000003F2, 0x0000086C, 0x0000086A, - 0x000008C1, 0x00000003, 0x00000406, 0x0000086C, 0x000008C6, 0x000008C9, 0x00000003, 0x00000409, - 0x0000086C, 0x000008B9, 0x00000003, 0x000003E6, 0x00000005, 0x000003F7, 0x000008CC, 0x000008BA, - 0x00000413, 0x000008C5, 0x000008CC, 0x000008D1, 0x00000005, 0x00000003, 0x00000401, 0x000003EF, - 0x0000088C, 0x00000876, 0x00000885, 0x000003EF, 0x00000003, 0x000008BC, 0x00000870, 0x000008B5, - 0x0000040B, 0x00000003, 0x00000011, 0x0000086C, 0x000008CA, 0x000008C6, 0x000008C1, 0x00000003, - 0x00000888, 0x00000881, 0x000003EF, 0x0000040B, 0x00000003, 0x000008BC, 0x000008BA, 0x000008BD, - 0x00000003, 0x0000086C, 0x000008C6, 0x000008D2, 0x000008AA, 0x000008C1, 0x00000003, 0x0000086C, - 0x000008C2, 0x000008B5, 0x000003F9, 0x00000003, 0x000008D0, 0x000008A2, 0x000008AA, 0x00000412, - 0x00000875, 0x00000003, 0x00000409, 0x000003EB, 0x00000003, 0x00000888, 0x000008AA, 0x0000086F, - 0x00000003, 0x0000040C, 0x0000088C, 0x00000885, 0x0000FFFF, 0x000008D5, 0x000003EF, 0x00000003, - 0x00000404, 0x000003F9, 0x0000086C, 0x00000882, 0x000008C2, 0x000008BD, 0x000003EF, 0x0000040B, - 0x00000003, 0x00000404, 0x0000088C, 0x00000881, 0x0000FFFF, 0x000008D5, 0x000003EF, 0x00000003, - 0x000008C4, 0x000008D1, 0x0000088E, 0x00000886, 0x00000876, 0x0000086F, 0x00000003, 0x00000408, - 0x000008CC, 0x000008B6, 0x00000875, 0x0000040B, 0x00000003, 0x000003E6, 0x00000408, 0x0000086C, - 0x000008B5, 0x000003F9, 0x0000FFFF, 0x000008D5, 0x000003EF, 0x00000003, 0x000008A8, 0x000008C1, - 0x00000003, 0x000008A0, 0x000008B6, 0x000008B1, 0x00000003, 0x0000086E, 0x000008D2, 0x00000891, - 0x000003EF, 0x000008CC, 0x00000882, 0x000008BD, 0x000003EF, 0x00000003, 0x000008BC, 0x000008C1, - 0x0000086C, 0x000008AA, 0x00000876, 0x00000875, 0x00000003, 0x000003E6, 0x0000086C, 0x0000040E, - 0x00000891, 0x0000086C, 0x00000891, 0x000003EB - - - - 0x000000FB, 0x000000FA, 0x000000F9, 0x000000F8, 0x000000F7, 0x000000F6, 0x000000F5, 0x000000F4, - 0x000000F3, 0x000000F2, 0x000000F1, 0x000000F0, 0x000000EF, 0x000000EE, 0x000000ED, 0x000000EC, - 0x000000EB, 0x000000EA, 0x000000E9, 0x000000E8, 0x000000E7, 0x000000E6, 0x000000E5, 0x000000E4, - 0x000000E3, 0x000000E2, 0x000000E1, 0x000000E0, 0x000000DF, 0x000000DE, 0x000000DD, 0x000000DC, - 0x000000DB, 0x000000DA, 0x000000D9, 0x000000D8, 0x000000D7, 0x000000D6, 0x000000D5, 0x000000D4, - 0x000000D3, 0x000000D2, 0x000000D1, 0x000000D0, 0x000000CF, 0x000000CE, 0x000000CD, 0x000000CC, - 0x000000CB, 0x000000CA, 0x000000C9, 0x000000C8, 0x000000C7, 0x000000C6, 0x000000C5, 0x000000C4, - 0x000000C3, 0x000000C2, 0x000000C1, 0x000000C0, 0x000000BF, 0x000000BE, 0x000000BD, 0x000000BC, - 0x000000BB, 0x000000BA, 0x000000B9, 0x000000B8, 0x000000B7, 0x000000B6, 0x000000B5, 0x000000B4, - 0x000000B3, 0x000000B2, 0x000000B1, 0x000000B0, 0x000000AF, 0x000000AE, 0x000000AD, 0x000000AC, - 0x000000AB, 0x000000AA, 0x000000A9, 0x000000A8, 0x000000A7, 0x000000A6, 0x000000A5, 0x000000A4, - 0x000000A3, 0x000000A2, 0x000000A1, 0x000000A0, 0x0000009F, 0x0000009E, 0x0000009D, 0x0000009C, - 0x0000009B, 0x0000009A, 0x00000099, 0x00000098, 0x00000097, 0x00000096, 0x00000095, 0x00000094, - 0x00000093, 0x00000092, 0x00000091, 0x00000090, 0x0000008F, 0x0000008E, 0x0000008D, 0x0000008C, - 0x0000008B, 0x0000008A, 0x00000089, 0x00000088, 0x00000087, 0x00000086, 0x00000085, 0x00000084, - 0x00000083, 0x00000082, 0x00000081, 0x00000080, 0x0000007F, 0x0000007E, 0x0000007D, 0x0000007C, - 0x0000007B, 0x0000007A, 0x00000079, 0x00000078, 0x00000077, 0x00000076, 0x00000075, 0x00000074, - 0x00000073, 0x00000072, 0x00000071, 0x00000070, 0x0000006F, 0x0000006E, 0x0000006D, 0x0000006C, - 0x0000006B, 0x0000006A, 0x00000069, 0x00000068, 0x00000067, 0x00000066, 0x00000065, 0x00000064, - 0x00000063, 0x00000062, 0x00000061, 0x00000060, 0x0000005F, 0x0000005E, 0x0000005D, 0x0000005C, - 0x0000005B, 0x0000005A, 0x00000059, 0x00000058, 0x00000057, 0x00000056, 0x00000055, 0x00000054, - 0x00000053, 0x00000052, 0x00000051, 0x00000050, 0x0000004F, 0x0000004E, 0x0000004D, 0x0000004C, - 0x0000004B, 0x0000004A, 0x00000049, 0x00000048, 0x00000047, 0x00000046, 0x00000045, 0x00000044, - 0x00000043, 0x00000042, 0x00000041, 0x00000040, 0x0000003F, 0x0000003E, 0x0000003D, 0x0000003C, - 0x0000003B, 0x0000003A, 0x00000039, 0x00000038, 0x00000037, 0x00000036, 0x00000035, 0x00000034, - 0x00000033, 0x00000032, 0x00000031, 0x00000030, 0x0000002F, 0x0000002E, 0x0000002D, 0x0000002C, - 0x0000002B, 0x0000002A, 0x00000029, 0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024, - 0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001F, 0x0000001E, 0x0000001D, 0x0000001C, - 0x0000001B, 0x0000001A, 0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015, 0x00000014, - 0x00000013, 0x00000012, 0x00000011, 0x00000010, 0x0000000F, 0x0000000E, 0x0000000D, 0x0000000C, - 0x0000000B, 0x0000000A, 0x00000009, 0x00000008, 0x00000007, 0x00000006, 0x00000005, 0x00000004, - 0x00000003, 0x00000002, 0x00000001, 0x00000000 - - - - 0.000000, 0.000000, 6.316406, 0.000000, 10.382812, 0.000000, 15.492188, 0.000000, - 21.035156, 0.000000, 27.058594, 0.000000, 39.527344, 0.000000, 43.792969, 0.000000, - 47.408203, 0.000000, 51.205078, 0.000000, 66.216797, 0.000000, 71.326172, 0.000000, - 74.695312, 0.000000, 83.367188, 0.000000, 90.826172, 0.000000, 95.091797, 0.000000, - 98.707031, 0.000000, 102.503906, 0.000000, 109.962891, 0.000000, 114.949219, 0.000000, - 122.408203, 0.000000, 130.687500, 0.000000, 134.484375, 0.000000, 145.787109, 0.000000, - 150.773438, 0.000000, 156.884766, 0.000000, 160.681641, 0.000000, 172.277344, 0.000000, - 177.919922, 0.000000, 182.906250, 0.000000, 191.578125, 0.000000, 195.644531, 0.000000, - 199.441406, 0.000000, 206.507812, 0.000000, 214.787109, 0.000000, 218.402344, 0.000000, - 223.945312, 0.000000, 227.742188, 0.000000, 233.765625, 0.000000, 238.751953, 0.000000, - 245.185547, 0.000000, 257.982422, 0.000000, 262.048828, 0.000000, 265.845703, 0.000000, - 272.654297, 0.000000, 276.023438, 0.000000, 285.240234, 0.000000, 289.306641, 0.000000, - 293.103516, 0.000000, 300.169922, 0.000000, 308.449219, 0.000000, 314.091797, 0.000000, - 318.158203, 0.000000, 321.955078, 0.000000, 329.572266, 0.000000, 333.837891, 0.000000, - 339.380859, 0.000000, 343.177734, 0.000000, 346.974609, 0.000000, 361.986328, 0.000000, - 367.095703, 0.000000, 370.464844, 0.000000, 379.136719, 0.000000, 386.595703, 0.000000, - 391.582031, 0.000000, 395.847656, 0.000000, 399.644531, 0.000000, 406.453125, 0.000000, - 409.822266, 0.000000, 415.523438, 0.000000, 420.632812, 0.000000, 420.632812, 0.000000, - 427.441406, 0.000000, 431.056641, 0.000000, 434.853516, 0.000000, 441.357422, 0.000000, - 448.423828, 0.000000, 455.912109, 0.000000, 459.708984, 0.000000, 479.255859, 0.000000, - 484.242188, 0.000000, 496.710938, 0.000000, 505.382812, 0.000000, 509.449219, 0.000000, - 514.992188, 0.000000, 518.789062, 0.000000, 524.812500, 0.000000, 529.798828, 0.000000, - 536.232422, 0.000000, 549.029297, 0.000000, 554.015625, 0.000000, 559.001953, 0.000000, - 563.267578, 0.000000, 567.064453, 0.000000, 573.380859, 0.000000, 580.839844, 0.000000, - 590.056641, 0.000000, 594.123047, 0.000000, 594.123047, 0.000000, 600.931641, 0.000000, - 604.546875, 0.000000, 608.343750, 0.000000, 620.636719, 0.000000, 624.005859, 0.000000, - 628.992188, 0.000000, 635.830078, 0.000000, 639.626953, 0.000000, 653.361328, 0.000000, - 656.730469, 0.000000, 661.716797, 0.000000, 669.205078, 0.000000, 673.001953, 0.000000, - 683.777344, 0.000000, 687.146484, 0.000000, 692.660156, 0.000000, 696.457031, 0.000000, - 700.253906, 0.000000, 704.736328, 0.000000, 711.105469, 0.000000, 716.748047, 0.000000, - 722.994141, 0.000000, 722.994141, 0.000000, 727.060547, 0.000000, 732.703125, 0.000000, - 736.769531, 0.000000, 741.251953, 0.000000, 745.048828, 0.000000, 752.507812, 0.000000, - 756.123047, 0.000000, 762.146484, 0.000000, 767.132812, 0.000000, 775.412109, 0.000000, - 779.027344, 0.000000, 782.824219, 0.000000, 794.203125, 0.000000, 799.189453, 0.000000, - 804.890625, 0.000000, 810.433594, 0.000000, 814.230469, 0.000000, 818.027344, 0.000000, - 821.396484, 0.000000, 828.128906, 0.000000, 833.115234, 0.000000, 839.953125, 0.000000, - 843.750000, 0.000000, 850.816406, 0.000000, 859.095703, 0.000000, 862.710938, 0.000000, - 868.253906, 0.000000, 872.050781, 0.000000, 883.429688, 0.000000, 889.675781, 0.000000, - 893.941406, 0.000000, 897.738281, 0.000000, 901.107422, 0.000000, 906.093750, 0.000000, - 911.080078, 0.000000, 917.800781, 0.000000, 924.638672, 0.000000, 928.435547, 0.000000, - 931.804688, 0.000000, 939.263672, 0.000000, 944.964844, 0.000000, 950.074219, 0.000000, - 953.871094, 0.000000, 965.173828, 0.000000, 974.390625, 0.000000, 981.111328, 0.000000, - 981.111328, 0.000000, 985.177734, 0.000000, 988.974609, 0.000000, 999.750000, 0.000000, - 1003.365234, 0.000000, 1007.162109, 0.000000, 1014.228516, 0.000000, 1020.949219, 0.000000, - 1025.015625, 0.000000, 1028.812500, 0.000000, 1040.408203, 0.000000, 1046.431641, 0.000000, - 1054.710938, 0.000000, 1054.710938, 0.000000, 1061.519531, 0.000000, 1065.134766, 0.000000, - 1068.931641, 0.000000, 1083.943359, 0.000000, 1089.052734, 0.000000, 1092.421875, 0.000000, - 1101.093750, 0.000000, 1108.552734, 0.000000, 1112.818359, 0.000000, 1116.433594, 0.000000, - 1121.976562, 0.000000, 1125.773438, 0.000000, 1140.785156, 0.000000, 1146.808594, 0.000000, - 1155.087891, 0.000000, 1155.087891, 0.000000, 1161.896484, 0.000000, 1165.511719, 0.000000, - 1169.308594, 0.000000, 1180.541016, 0.000000, 1184.607422, 0.000000, 1190.630859, 0.000000, - 1199.302734, 0.000000, 1204.289062, 0.000000, 1208.355469, 0.000000, 1212.152344, 0.000000, - 1218.960938, 0.000000, 1224.603516, 0.000000, 1231.037109, 0.000000, 1235.103516, 0.000000, - 1240.646484, 0.000000, 1244.443359, 0.000000, 1248.240234, 0.000000, 1255.048828, 0.000000, - 1258.417969, 0.000000, 1264.119141, 0.000000, 1269.228516, 0.000000, 1269.228516, 0.000000, - 1276.037109, 0.000000, 1279.652344, 0.000000, 1283.449219, 0.000000, 1290.908203, 0.000000, - 1297.746094, 0.000000, 1301.542969, 0.000000, 1311.427734, 0.000000, 1317.861328, 0.000000, - 1323.562500, 0.000000, 1327.359375, 0.000000, 1341.492188, 0.000000, 1346.478516, 0.000000, - 1357.904297, 0.000000, 1361.519531, 0.000000, 1367.162109, 0.000000, 1375.833984, 0.000000, - 1380.099609, 0.000000, 1383.714844, 0.000000, 1387.511719, 0.000000, 1398.890625, 0.000000, - 1405.728516, 0.000000, 1409.097656, 0.000000, 1415.818359, 0.000000, 1420.804688, 0.000000, - 1424.871094, 0.000000, 1428.667969, 0.000000, 1432.464844, 0.000000, 1435.833984, 0.000000, - 1435.833984, 0.000000, 1447.259766, 0.000000, 1450.628906, 0.000000, 1462.054688, 0.000000, - 1465.669922, 0.000000 - - - - - - - บทที่๑พายุไซโคลนโดโรธีอาศัยอยู่ท่ามกลางทุ่งใหญ่ในแคนซัสกับลุงเฮนรีชาวไร่และป้าเอ็มภรรยาชาวไร่บ้านของพวกเขาหลังเล็กเพราะไม้สร้างบ้านต้องขนมาด้วยเกวียนเป็นระยะทางหลายไมล์ - - - 0x000000F3, 0x000000F0, 0x000000F0, 0x0000010E, 0x0000011D, 0x00000126, 0x000000F7, 0x0000010B, - 0x000000FB, 0x00000111, 0x00000119, 0x000000E4, 0x00000117, 0x000000DD, 0x000000FE, 0x000000F2, - 0x00000117, 0x000000ED, 0x00000117, 0x000000FC, 0x000000F1, 0x0000010E, 0x00000106, 0x0000010B, - 0x00000101, 0x0000010A, 0x000000FB, 0x00000106, 0x000000FB, 0x00000112, 0x0000013B, 0x000000F0, - 0x0000013B, 0x0000010B, 0x000000FA, 0x000000DA, 0x000000FE, 0x0000010B, 0x000000E0, 0x000000F0, - 0x00000111, 0x0000013B, 0x000000E0, 0x00000118, 0x00000104, 0x000000E6, 0x0000013B, 0x00000118, - 0x000000F2, 0x00000116, 0x000000DD, 0x000000F2, 0x000000E4, 0x0000010A, 0x00000103, 0x000000DA, - 0x0000010A, 0x000000F3, 0x000000FE, 0x00000111, 0x000000E0, 0x00000115, 0x00000107, 0x000000F2, - 0x000000FC, 0x0000010E, 0x000000E3, 0x0000010B, 0x00000100, 0x00000119, 0x000000FC, 0x0000013B, - 0x00000116, 0x000000FE, 0x00000109, 0x000000F4, 0x00000137, 0x0000010B, 0x00000115, 0x00000106, - 0x0000011C, 0x000000FA, 0x000000F9, 0x000000FC, 0x000000FC, 0x000000FB, 0x0000010B, 0x000000E3, - 0x0000010B, 0x00000100, 0x00000119, 0x000000FC, 0x0000013B, 0x000000F3, 0x0000013C, 0x0000010B, - 0x000000F2, 0x000000DB, 0x00000106, 0x000000E0, 0x000000F7, 0x00000100, 0x000000DA, 0x00000115, - 0x000000DB, 0x0000010B, 0x00000104, 0x000000FE, 0x0000010A, 0x000000E0, 0x00000115, 0x000000FE, - 0x0000011C, 0x000000DA, 0x00000115, 0x000000F7, 0x000000FC, 0x0000010B, 0x00000109, 0x00000119, - 0x000000FA, 0x0000013C, 0x00000103, 0x000000FC, 0x0000013C, 0x0000010B, 0x000000E0, 0x000000F3, - 0x0000013C, 0x0000010B, 0x000000F2, 0x000000EE, 0x0000013C, 0x00000106, 0x000000E0, 0x000000DB, - 0x000000F2, 0x000000FA, 0x0000010B, 0x000000ED, 0x0000013C, 0x00000100, 0x000000FB, 0x00000115, - 0x000000DA, 0x00000100, 0x0000010E, 0x000000FB, 0x000000F2, 0x00000115, 0x000000F4, 0x00000143, - 0x000000F2, 0x000000FC, 0x00000109, 0x000000FB, 0x00000109, 0x000000F0, 0x0000010B, 0x000000E0, - 0x00000104, 0x000000FE, 0x0000010B, 0x000000FB, 0x00000119, 0x000000FA, 0x000000FE, 0x0000013F - - - - 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007, - 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F, - 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000016, 0x00000017, - 0x00000018, 0x00000019, 0x0000001A, 0x0000001B, 0x0000001C, 0x0000001D, 0x0000001E, 0x0000001F, - 0x00000020, 0x00000021, 0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000026, 0x00000027, - 0x00000028, 0x00000029, 0x0000002A, 0x0000002B, 0x0000002C, 0x0000002D, 0x0000002E, 0x0000002F, - 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034, 0x00000035, 0x00000036, 0x00000037, - 0x00000038, 0x00000039, 0x0000003A, 0x0000003B, 0x0000003C, 0x0000003D, 0x0000003E, 0x0000003F, - 0x00000040, 0x00000041, 0x00000042, 0x00000043, 0x00000044, 0x00000045, 0x00000046, 0x00000047, - 0x00000048, 0x00000049, 0x0000004A, 0x0000004B, 0x0000004C, 0x0000004D, 0x0000004E, 0x0000004F, - 0x00000050, 0x00000051, 0x00000052, 0x00000053, 0x00000054, 0x00000055, 0x00000056, 0x00000057, - 0x00000058, 0x00000059, 0x0000005A, 0x0000005B, 0x0000005C, 0x0000005D, 0x0000005E, 0x0000005F, - 0x00000060, 0x00000061, 0x00000062, 0x00000063, 0x00000064, 0x00000065, 0x00000066, 0x00000067, - 0x00000068, 0x00000069, 0x0000006A, 0x0000006B, 0x0000006C, 0x0000006D, 0x0000006E, 0x0000006F, - 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, 0x00000075, 0x00000076, 0x00000077, - 0x00000078, 0x00000079, 0x0000007A, 0x0000007B, 0x0000007C, 0x0000007D, 0x0000007E, 0x0000007F, - 0x00000080, 0x00000081, 0x00000082, 0x00000083, 0x00000084, 0x00000085, 0x00000086, 0x00000087, - 0x00000088, 0x00000089, 0x0000008A, 0x0000008B, 0x0000008C, 0x0000008D, 0x0000008E, 0x0000008F, - 0x00000090, 0x00000091, 0x00000092, 0x00000093, 0x00000094, 0x00000095, 0x00000096, 0x00000097, - 0x00000098, 0x00000099, 0x0000009A, 0x0000009B, 0x0000009C, 0x0000009D, 0x0000009E, 0x0000009F, - 0x000000A0, 0x000000A1, 0x000000A2, 0x000000A3, 0x000000A4, 0x000000A5, 0x000000A6, 0x000000A7 - - - - 0.000000, 0.000000, 5.399414, 0.000000, 10.798828, 0.000000, 16.198242, 0.000000, - 16.198242, 0.000000, 16.198242, 0.000000, 21.046875, 0.000000, 26.616211, 0.000000, - 30.035156, 0.000000, 34.151367, 0.000000, 34.151367, 0.000000, 38.279297, 0.000000, - 43.558594, 0.000000, 47.663086, 0.000000, 52.438477, 0.000000, 57.178711, 0.000000, - 62.698242, 0.000000, 66.802734, 0.000000, 71.601562, 0.000000, 75.706055, 0.000000, - 79.810547, 0.000000, 84.369141, 0.000000, 84.369141, 0.000000, 89.097656, 0.000000, - 92.516602, 0.000000, 97.195312, 0.000000, 97.195312, 0.000000, 101.311523, 0.000000, - 106.040039, 0.000000, 110.156250, 0.000000, 110.156250, 0.000000, 110.156250, 0.000000, - 115.555664, 0.000000, 115.555664, 0.000000, 118.974609, 0.000000, 124.013672, 0.000000, - 128.765625, 0.000000, 133.505859, 0.000000, 136.924805, 0.000000, 140.704102, 0.000000, - 146.103516, 0.000000, 146.103516, 0.000000, 146.103516, 0.000000, 149.882812, 0.000000, - 153.553711, 0.000000, 159.158203, 0.000000, 165.421875, 0.000000, 165.421875, 0.000000, - 169.092773, 0.000000, 174.612305, 0.000000, 179.135742, 0.000000, 183.911133, 0.000000, - 189.430664, 0.000000, 194.709961, 0.000000, 194.709961, 0.000000, 199.989258, 0.000000, - 204.741211, 0.000000, 204.741211, 0.000000, 210.140625, 0.000000, 214.880859, 0.000000, - 214.880859, 0.000000, 218.660156, 0.000000, 220.675781, 0.000000, 225.128906, 0.000000, - 230.648438, 0.000000, 234.752930, 0.000000, 234.752930, 0.000000, 239.613281, 0.000000, - 243.032227, 0.000000, 247.280273, 0.000000, 251.408203, 0.000000, 255.512695, 0.000000, - 255.512695, 0.000000, 260.036133, 0.000000, 264.776367, 0.000000, 269.071289, 0.000000, - 274.470703, 0.000000, 274.470703, 0.000000, 277.889648, 0.000000, 279.905273, 0.000000, - 284.633789, 0.000000, 284.633789, 0.000000, 289.672852, 0.000000, 294.641602, 0.000000, - 298.746094, 0.000000, 302.850586, 0.000000, 306.966797, 0.000000, 310.385742, 0.000000, - 315.246094, 0.000000, 318.665039, 0.000000, 322.913086, 0.000000, 327.041016, 0.000000, - 331.145508, 0.000000, 331.145508, 0.000000, 336.544922, 0.000000, 336.544922, 0.000000, - 339.963867, 0.000000, 345.483398, 0.000000, 350.258789, 0.000000, 354.987305, 0.000000, - 358.766602, 0.000000, 364.335938, 0.000000, 368.583984, 0.000000, 373.335938, 0.000000, - 375.351562, 0.000000, 380.126953, 0.000000, 383.545898, 0.000000, 389.150391, 0.000000, - 393.890625, 0.000000, 393.890625, 0.000000, 397.669922, 0.000000, 399.685547, 0.000000, - 404.425781, 0.000000, 404.425781, 0.000000, 409.177734, 0.000000, 411.193359, 0.000000, - 416.762695, 0.000000, 420.867188, 0.000000, 424.286133, 0.000000, 428.581055, 0.000000, - 432.708984, 0.000000, 437.748047, 0.000000, 437.748047, 0.000000, 443.027344, 0.000000, - 447.131836, 0.000000, 447.131836, 0.000000, 450.550781, 0.000000, 454.330078, 0.000000, - 459.729492, 0.000000, 459.729492, 0.000000, 463.148438, 0.000000, 468.667969, 0.000000, - 473.478516, 0.000000, 473.478516, 0.000000, 478.207031, 0.000000, 481.986328, 0.000000, - 486.761719, 0.000000, 492.281250, 0.000000, 497.320312, 0.000000, 500.739258, 0.000000, - 505.538086, 0.000000, 505.538086, 0.000000, 509.786133, 0.000000, 513.902344, 0.000000, - 515.917969, 0.000000, 520.669922, 0.000000, 524.917969, 0.000000, 524.917969, 0.000000, - 529.034180, 0.000000, 534.553711, 0.000000, 536.569336, 0.000000, 541.968750, 0.000000, - 541.968750, 0.000000, 547.488281, 0.000000, 551.592773, 0.000000, 555.887695, 0.000000, - 560.003906, 0.000000, 564.298828, 0.000000, 569.698242, 0.000000, 573.117188, 0.000000, - 576.896484, 0.000000, 582.500977, 0.000000, 587.241211, 0.000000, 590.660156, 0.000000, - 594.776367, 0.000000, 598.904297, 0.000000, 603.943359, 0.000000, 608.683594, 0.000000, - 608.683594, 0.000000 - - - - - - - أساسًا، تتعامل الحواسيب فقط مع الأرقام، وتقوم بتخزين الأحرف والمحارف الأخرى بعد أن تُعطي رقما معينا لكل واحد منها. وقبل اختراع "يونِكود"، كان هناك مئات الأنظمة للتشفير وتخصيص هذه الأرقام للمحارف، ولم يوجد نظام تشفير واحد يحتوي على جميع المحارف الضرورية - - - 0x00000872, 0x000008D1, 0x000003F9, 0x0000040B, 0x0000088C, 0x0000089E, 0x000008BD, 0x000003EF, - 0x00000003, 0x00000404, 0x000003F9, 0x0000086C, 0x00000882, 0x000008C2, 0x000008BD, 0x000003EF, - 0x00000003, 0x000008A8, 0x000008D2, 0x000008C2, 0x0000087D, 0x00000003, 0x000008CE, 0x000008BE, - 0x000008A9, 0x00000003, 0x0000040D, 0x000008CC, 0x00000876, 0x00000882, 0x000008D1, 0x00000003, - 0x00000888, 0x00000881, 0x000003EF, 0x0000040B, 0x00000003, 0x0000088C, 0x000008D2, 0x000008B2, - 0x00000896, 0x00000875, 0x00000003, 0x00000408, 0x0000086C, 0x000008A6, 0x000008C5, 0x00000003, - 0x00000888, 0x0000087D, 0x000008CC, 0x000008D1, 0x00000003, 0x000008C0, 0x000008BD, 0x0000040B, - 0x00000003, 0x000003E6, 0x00000404, 0x000003F9, 0x0000086C, 0x00000882, 0x000008C2, 0x000008BE, - 0x000008BD, 0x00000003, 0x00000408, 0x0000086C, 0x000008B5, 0x000003F9, 0x0000FFFF, 0x000008D5, - 0x000003EF, 0x00000003, 0x0000040A, 0x0000088A, 0x000008C9, 0x00000003, 0x00000898, 0x000008D2, - 0x0000089A, 0x00000886, 0x00000875, 0x0000040B, 0x00000003, 0x0000088C, 0x000008D2, 0x000008B2, - 0x00000896, 0x00000876, 0x000008BE, 0x000008BD, 0x00000003, 0x00000872, 0x000008C2, 0x000008A6, - 0x000008C5, 0x0000FFFF, 0x000008D5, 0x000003EF, 0x00000003, 0x000003F2, 0x0000086C, 0x0000086A, - 0x000008C1, 0x00000003, 0x00000406, 0x0000086C, 0x000008C6, 0x000008C9, 0x00000003, 0x00000409, - 0x0000086C, 0x000008B9, 0x00000003, 0x000003E6, 0x00000005, 0x000003F7, 0x000008CC, 0x000008BA, - 0x00000413, 0x000008C5, 0x000008CC, 0x000008D1, 0x00000005, 0x00000003, 0x00000401, 0x000003EF, - 0x0000088C, 0x00000876, 0x00000885, 0x000003EF, 0x00000003, 0x000008BC, 0x00000870, 0x000008B5, - 0x0000040B, 0x00000003, 0x00000011, 0x0000086C, 0x000008CA, 0x000008C6, 0x000008C1, 0x00000003, - 0x00000888, 0x00000881, 0x000003EF, 0x0000040B, 0x00000003, 0x000008BC, 0x000008BA, 0x000008BD, - 0x00000003, 0x0000086C, 0x000008C6, 0x000008D2, 0x000008AA, 0x000008C1, 0x00000003, 0x0000086C, - 0x000008C2, 0x000008B5, 0x000003F9, 0x00000003, 0x000008D0, 0x000008A2, 0x000008AA, 0x00000412, - 0x00000875, 0x00000003, 0x00000409, 0x000003EB, 0x00000003, 0x00000888, 0x000008AA, 0x0000086F, - 0x00000003, 0x0000040C, 0x0000088C, 0x00000885, 0x0000FFFF, 0x000008D5, 0x000003EF, 0x00000003, - 0x00000404, 0x000003F9, 0x0000086C, 0x00000882, 0x000008C2, 0x000008BD, 0x000003EF, 0x0000040B, - 0x00000003, 0x00000404, 0x0000088C, 0x00000881, 0x0000FFFF, 0x000008D5, 0x000003EF, 0x00000003, - 0x000008C4, 0x000008D1, 0x0000088E, 0x00000886, 0x00000876, 0x0000086F, 0x00000003, 0x00000408, - 0x000008CC, 0x000008B6, 0x00000875, 0x0000040B, 0x00000003, 0x000003E6, 0x00000408, 0x0000086C, - 0x000008B5, 0x000003F9, 0x0000FFFF, 0x000008D5, 0x000003EF, 0x00000003, 0x000008A8, 0x000008C1, - 0x00000003, 0x000008A0, 0x000008B6, 0x000008B1, 0x00000003, 0x0000086E, 0x000008D2, 0x00000891, - 0x000003EF, 0x000008CC, 0x00000882, 0x000008BD, 0x000003EF, 0x00000003, 0x000008BC, 0x000008C1, - 0x0000086C, 0x000008AA, 0x00000876, 0x00000875, 0x00000003, 0x000003E6, 0x0000086C, 0x0000040E, - 0x00000891, 0x0000086C, 0x00000891, 0x000003EB - - - - 0x000000FB, 0x000000FA, 0x000000F9, 0x000000F8, 0x000000F7, 0x000000F6, 0x000000F5, 0x000000F4, - 0x000000F3, 0x000000F2, 0x000000F1, 0x000000F0, 0x000000EF, 0x000000EE, 0x000000ED, 0x000000EC, - 0x000000EB, 0x000000EA, 0x000000E9, 0x000000E8, 0x000000E7, 0x000000E6, 0x000000E5, 0x000000E4, - 0x000000E3, 0x000000E2, 0x000000E1, 0x000000E0, 0x000000DF, 0x000000DE, 0x000000DD, 0x000000DC, - 0x000000DB, 0x000000DA, 0x000000D9, 0x000000D8, 0x000000D7, 0x000000D6, 0x000000D5, 0x000000D4, - 0x000000D3, 0x000000D2, 0x000000D1, 0x000000D0, 0x000000CF, 0x000000CE, 0x000000CD, 0x000000CC, - 0x000000CB, 0x000000CA, 0x000000C9, 0x000000C8, 0x000000C7, 0x000000C6, 0x000000C5, 0x000000C4, - 0x000000C3, 0x000000C2, 0x000000C1, 0x000000C0, 0x000000BF, 0x000000BE, 0x000000BD, 0x000000BC, - 0x000000BB, 0x000000BA, 0x000000B9, 0x000000B8, 0x000000B7, 0x000000B6, 0x000000B5, 0x000000B4, - 0x000000B3, 0x000000B2, 0x000000B1, 0x000000B0, 0x000000AF, 0x000000AE, 0x000000AD, 0x000000AC, - 0x000000AB, 0x000000AA, 0x000000A9, 0x000000A8, 0x000000A7, 0x000000A6, 0x000000A5, 0x000000A4, - 0x000000A3, 0x000000A2, 0x000000A1, 0x000000A0, 0x0000009F, 0x0000009E, 0x0000009D, 0x0000009C, - 0x0000009B, 0x0000009A, 0x00000099, 0x00000098, 0x00000097, 0x00000096, 0x00000095, 0x00000094, - 0x00000093, 0x00000092, 0x00000091, 0x00000090, 0x0000008F, 0x0000008E, 0x0000008D, 0x0000008C, - 0x0000008B, 0x0000008A, 0x00000089, 0x00000088, 0x00000087, 0x00000086, 0x00000085, 0x00000084, - 0x00000083, 0x00000082, 0x00000081, 0x00000080, 0x0000007F, 0x0000007E, 0x0000007D, 0x0000007C, - 0x0000007B, 0x0000007A, 0x00000079, 0x00000078, 0x00000077, 0x00000076, 0x00000075, 0x00000074, - 0x00000073, 0x00000072, 0x00000071, 0x00000070, 0x0000006F, 0x0000006E, 0x0000006D, 0x0000006C, - 0x0000006B, 0x0000006A, 0x00000069, 0x00000068, 0x00000067, 0x00000066, 0x00000065, 0x00000064, - 0x00000063, 0x00000062, 0x00000061, 0x00000060, 0x0000005F, 0x0000005E, 0x0000005D, 0x0000005C, - 0x0000005B, 0x0000005A, 0x00000059, 0x00000058, 0x00000057, 0x00000056, 0x00000055, 0x00000054, - 0x00000053, 0x00000052, 0x00000051, 0x00000050, 0x0000004F, 0x0000004E, 0x0000004D, 0x0000004C, - 0x0000004B, 0x0000004A, 0x00000049, 0x00000048, 0x00000047, 0x00000046, 0x00000045, 0x00000044, - 0x00000043, 0x00000042, 0x00000041, 0x00000040, 0x0000003F, 0x0000003E, 0x0000003D, 0x0000003C, - 0x0000003B, 0x0000003A, 0x00000039, 0x00000038, 0x00000037, 0x00000036, 0x00000035, 0x00000034, - 0x00000033, 0x00000032, 0x00000031, 0x00000030, 0x0000002F, 0x0000002E, 0x0000002D, 0x0000002C, - 0x0000002B, 0x0000002A, 0x00000029, 0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024, - 0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001F, 0x0000001E, 0x0000001D, 0x0000001C, - 0x0000001B, 0x0000001A, 0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015, 0x00000014, - 0x00000013, 0x00000012, 0x00000011, 0x00000010, 0x0000000F, 0x0000000E, 0x0000000D, 0x0000000C, - 0x0000000B, 0x0000000A, 0x00000009, 0x00000008, 0x00000007, 0x00000006, 0x00000005, 0x00000004, - 0x00000003, 0x00000002, 0x00000001, 0x00000000 - - - - 0.000000, 0.000000, 6.316406, 0.000000, 10.382812, 0.000000, 15.492188, 0.000000, - 21.035156, 0.000000, 27.058594, 0.000000, 39.527344, 0.000000, 43.792969, 0.000000, - 47.408203, 0.000000, 51.205078, 0.000000, 66.216797, 0.000000, 71.326172, 0.000000, - 74.695312, 0.000000, 83.367188, 0.000000, 90.826172, 0.000000, 95.091797, 0.000000, - 98.707031, 0.000000, 102.503906, 0.000000, 109.962891, 0.000000, 114.949219, 0.000000, - 122.408203, 0.000000, 130.687500, 0.000000, 134.484375, 0.000000, 145.787109, 0.000000, - 150.773438, 0.000000, 156.884766, 0.000000, 160.681641, 0.000000, 172.277344, 0.000000, - 177.919922, 0.000000, 182.906250, 0.000000, 191.578125, 0.000000, 195.644531, 0.000000, - 199.441406, 0.000000, 206.507812, 0.000000, 214.787109, 0.000000, 218.402344, 0.000000, - 223.945312, 0.000000, 227.742188, 0.000000, 233.765625, 0.000000, 238.751953, 0.000000, - 245.185547, 0.000000, 257.982422, 0.000000, 262.048828, 0.000000, 265.845703, 0.000000, - 272.654297, 0.000000, 276.023438, 0.000000, 285.240234, 0.000000, 289.306641, 0.000000, - 293.103516, 0.000000, 300.169922, 0.000000, 308.449219, 0.000000, 314.091797, 0.000000, - 318.158203, 0.000000, 321.955078, 0.000000, 329.572266, 0.000000, 333.837891, 0.000000, - 339.380859, 0.000000, 343.177734, 0.000000, 346.974609, 0.000000, 361.986328, 0.000000, - 367.095703, 0.000000, 370.464844, 0.000000, 379.136719, 0.000000, 386.595703, 0.000000, - 391.582031, 0.000000, 395.847656, 0.000000, 399.644531, 0.000000, 406.453125, 0.000000, - 409.822266, 0.000000, 415.523438, 0.000000, 420.632812, 0.000000, 420.632812, 0.000000, - 427.441406, 0.000000, 431.056641, 0.000000, 434.853516, 0.000000, 441.357422, 0.000000, - 448.423828, 0.000000, 455.912109, 0.000000, 459.708984, 0.000000, 479.255859, 0.000000, - 484.242188, 0.000000, 496.710938, 0.000000, 505.382812, 0.000000, 509.449219, 0.000000, - 514.992188, 0.000000, 518.789062, 0.000000, 524.812500, 0.000000, 529.798828, 0.000000, - 536.232422, 0.000000, 549.029297, 0.000000, 554.015625, 0.000000, 559.001953, 0.000000, - 563.267578, 0.000000, 567.064453, 0.000000, 573.380859, 0.000000, 580.839844, 0.000000, - 590.056641, 0.000000, 594.123047, 0.000000, 594.123047, 0.000000, 600.931641, 0.000000, - 604.546875, 0.000000, 608.343750, 0.000000, 620.636719, 0.000000, 624.005859, 0.000000, - 628.992188, 0.000000, 635.830078, 0.000000, 639.626953, 0.000000, 653.361328, 0.000000, - 656.730469, 0.000000, 661.716797, 0.000000, 669.205078, 0.000000, 673.001953, 0.000000, - 683.777344, 0.000000, 687.146484, 0.000000, 692.660156, 0.000000, 696.457031, 0.000000, - 700.253906, 0.000000, 704.736328, 0.000000, 711.105469, 0.000000, 716.748047, 0.000000, - 722.994141, 0.000000, 722.994141, 0.000000, 727.060547, 0.000000, 732.703125, 0.000000, - 736.769531, 0.000000, 741.251953, 0.000000, 745.048828, 0.000000, 752.507812, 0.000000, - 756.123047, 0.000000, 762.146484, 0.000000, 767.132812, 0.000000, 775.412109, 0.000000, - 779.027344, 0.000000, 782.824219, 0.000000, 794.203125, 0.000000, 799.189453, 0.000000, - 804.890625, 0.000000, 810.433594, 0.000000, 814.230469, 0.000000, 818.027344, 0.000000, - 821.396484, 0.000000, 828.128906, 0.000000, 833.115234, 0.000000, 839.953125, 0.000000, - 843.750000, 0.000000, 850.816406, 0.000000, 859.095703, 0.000000, 862.710938, 0.000000, - 868.253906, 0.000000, 872.050781, 0.000000, 883.429688, 0.000000, 889.675781, 0.000000, - 893.941406, 0.000000, 897.738281, 0.000000, 901.107422, 0.000000, 906.093750, 0.000000, - 911.080078, 0.000000, 917.800781, 0.000000, 924.638672, 0.000000, 928.435547, 0.000000, - 931.804688, 0.000000, 939.263672, 0.000000, 944.964844, 0.000000, 950.074219, 0.000000, - 953.871094, 0.000000, 965.173828, 0.000000, 974.390625, 0.000000, 981.111328, 0.000000, - 981.111328, 0.000000, 985.177734, 0.000000, 988.974609, 0.000000, 999.750000, 0.000000, - 1003.365234, 0.000000, 1007.162109, 0.000000, 1014.228516, 0.000000, 1020.949219, 0.000000, - 1025.015625, 0.000000, 1028.812500, 0.000000, 1040.408203, 0.000000, 1046.431641, 0.000000, - 1054.710938, 0.000000, 1054.710938, 0.000000, 1061.519531, 0.000000, 1065.134766, 0.000000, - 1068.931641, 0.000000, 1083.943359, 0.000000, 1089.052734, 0.000000, 1092.421875, 0.000000, - 1101.093750, 0.000000, 1108.552734, 0.000000, 1112.818359, 0.000000, 1116.433594, 0.000000, - 1121.976562, 0.000000, 1125.773438, 0.000000, 1140.785156, 0.000000, 1146.808594, 0.000000, - 1155.087891, 0.000000, 1155.087891, 0.000000, 1161.896484, 0.000000, 1165.511719, 0.000000, - 1169.308594, 0.000000, 1180.541016, 0.000000, 1184.607422, 0.000000, 1190.630859, 0.000000, - 1199.302734, 0.000000, 1204.289062, 0.000000, 1208.355469, 0.000000, 1212.152344, 0.000000, - 1218.960938, 0.000000, 1224.603516, 0.000000, 1231.037109, 0.000000, 1235.103516, 0.000000, - 1240.646484, 0.000000, 1244.443359, 0.000000, 1248.240234, 0.000000, 1255.048828, 0.000000, - 1258.417969, 0.000000, 1264.119141, 0.000000, 1269.228516, 0.000000, 1269.228516, 0.000000, - 1276.037109, 0.000000, 1279.652344, 0.000000, 1283.449219, 0.000000, 1290.908203, 0.000000, - 1297.746094, 0.000000, 1301.542969, 0.000000, 1311.427734, 0.000000, 1317.861328, 0.000000, - 1323.562500, 0.000000, 1327.359375, 0.000000, 1341.492188, 0.000000, 1346.478516, 0.000000, - 1357.904297, 0.000000, 1361.519531, 0.000000, 1367.162109, 0.000000, 1375.833984, 0.000000, - 1380.099609, 0.000000, 1383.714844, 0.000000, 1387.511719, 0.000000, 1398.890625, 0.000000, - 1405.728516, 0.000000, 1409.097656, 0.000000, 1415.818359, 0.000000, 1420.804688, 0.000000, - 1424.871094, 0.000000, 1428.667969, 0.000000, 1432.464844, 0.000000, 1435.833984, 0.000000, - 1435.833984, 0.000000, 1447.259766, 0.000000, 1450.628906, 0.000000, 1462.054688, 0.000000, - 1465.669922, 0.000000 - - - - - - - ुं ं॑ - - - 0x0000029C, 0x000001D5, 0x00000232, 0x00000003, 0x0000029C, 0x00000232, 0x00000233 - - - - 0x00000000, 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000003, 0x00000004 - - - - 0.000000, 0.000000, 7.541016, 0.000000, 7.541016, 0.000000, 7.541016, 0.000000, - 13.541016, 0.000000, 21.082031, 0.000000, 19.953125, -6.052734, 21.082031, 0.000000 - - - - - - - कँ कं कः क॑ क॒ कँ॑ कं॒ कँंः क॒॑ - - - 0x00000080, 0x00000231, 0x00000003, 0x00000080, 0x00000232, 0x00000003, 0x00000080, 0x0000022C, - 0x00000003, 0x00000080, 0x00000233, 0x00000003, 0x00000080, 0x000001DF, 0x00000003, 0x00000080, - 0x00000231, 0x00000233, 0x00000003, 0x00000080, 0x000001DF, 0x00000232, 0x00000003, 0x00000080, - 0x00000231, 0x0000029C, 0x00000232, 0x0000029C, 0x0000022C, 0x00000003, 0x00000080, 0x00000233, - 0x0000029C, 0x000001DF - - - - 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007, - 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F, - 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000015, 0x00000014, 0x00000016, 0x00000017, - 0x00000018, 0x00000019, 0x00000019, 0x0000001A, 0x0000001A, 0x0000001B, 0x0000001C, 0x0000001D, - 0x0000001E, 0x0000001E - - - - 0.000000, 0.000000, 10.001953, -0.087891, 10.875000, 0.000000, 16.875000, 0.000000, - 23.783203, 0.439453, 27.750000, 0.000000, 33.750000, 0.000000, 44.625000, 0.000000, - 48.984375, 0.000000, 54.984375, 0.000000, 63.546875, -1.669922, 65.859375, 0.000000, - 71.859375, 0.000000, 80.332031, 0.492188, 82.734375, 0.000000, 88.734375, 0.000000, - 98.736328, -0.087891, 97.431641, -6.228516, 99.609375, 0.000000, 105.609375, 0.000000, - 114.082031, 0.492188, 112.517578, 0.439453, 116.484375, 0.000000, 122.484375, 0.000000, - 132.486328, -0.087891, 133.359375, 0.000000, 140.900391, 0.000000, 140.900391, 0.000000, - 148.441406, 0.000000, 152.800781, 0.000000, 158.800781, 0.000000, 167.363281, -1.669922, - 169.675781, 0.000000, 177.216797, 0.000000, 177.216797, 0.000000 - - - - - - - रू क़् क्ष क्कि क्रि ट्रि हिन्दी र्क्रिं क्षत्रज्ञत्रक्ष श्र थ्र श्र कके र्कें केूकूेकेृ र्कू क़ क क् क्ष क्ष् क्ष्क ज़ ज ज् ज्ञ ज्ञ् ज्ञ्क र्क र्क्क ड्र क्क क़्क क़्क क़् क्ष्क क्ष् त्र्क द्द कि हि रू रु र्के र्कं क् कु के द्द्द क़्ष क्ष र्क्षे द्दत्र्क ज्ञ क्त्व ज्ञ्क र्कँ र्किँ र्केँ र्क्रिँ हिंदी ह्मिह्यिखि ङ्क ङ्म ङ्क्त ङ्ख ङ्ग ङ्घ ङ्क्ष ङ्क्ष्व ङ्क्ष्य र्क्त्वि र्र्र्र कै के कु कू कृ कॅ कॆ हु हू हॆ है हे - - - 0x0000009A, 0x000001FE, 0x00000003, 0x000000A4, 0x00000051, 0x00000003, 0x000000A2, 0x0000FFFF, - 0x0000FFFF, 0x00000003, 0x000001D4, 0x000000C8, 0x0000FFFF, 0x00000080, 0x00000003, 0x000001D1, - 0x00000080, 0x0000009A, 0x00000051, 0x00000003, 0x000001D1, 0x0000008A, 0x0000009A, 0x00000051, - 0x00000003, 0x000001D1, 0x000000A1, 0x000000DB, 0x0000FFFF, 0x00000091, 0x00000223, 0x00000003, - 0x000001D1, 0x00000080, 0x000000E2, 0x0000FFFF, 0x0000009A, 0x00000051, 0x00000232, 0x00000003, - 0x000000A2, 0x0000FFFF, 0x0000FFFF, 0x0000008F, 0x000000E2, 0x0000FFFF, 0x000000A3, 0x0000FFFF, - 0x0000FFFF, 0x0000008F, 0x000000E2, 0x0000FFFF, 0x000000A2, 0x0000FFFF, 0x0000FFFF, 0x00000003, - 0x0000009E, 0x0000009A, 0x00000051, 0x00000003, 0x00000090, 0x0000009A, 0x00000051, 0x00000003, - 0x0000009E, 0x0000009A, 0x00000051, 0x00000003, 0x00000080, 0x00000080, 0x0000022F, 0x00000003, - 0x00000080, 0x0000022F, 0x0000024D, 0x0000FFFF, 0x0000FFFF, 0x00000003, 0x00000080, 0x0000022F, - 0x0000029C, 0x000001D7, 0x00000080, 0x000001D7, 0x0000029C, 0x0000022F, 0x00000080, 0x0000022F, - 0x0000029C, 0x000001D9, 0x00000003, 0x00000080, 0x000001D7, 0x0000005B, 0x0000FFFF, 0x00000003, - 0x000000A4, 0x00000003, 0x00000080, 0x00000003, 0x00000080, 0x00000051, 0x00000003, 0x000000A2, - 0x0000FFFF, 0x0000FFFF, 0x00000003, 0x000000A2, 0x0000FFFF, 0x0000FFFF, 0x00000051, 0x00000003, - 0x000000EA, 0x0000FFFF, 0x0000FFFF, 0x0000FFFF, 0x00000080, 0x00000003, 0x00000003, 0x000000AB, - 0x0000FFFF, 0x00000003, 0x00000087, 0x00000003, 0x00000087, 0x00000051, 0x00000003, 0x000000A3, - 0x0000FFFF, 0x0000FFFF, 0x00000003, 0x000000A3, 0x0000FFFF, 0x0000FFFF, 0x00000051, 0x00000003, - 0x000000EB, 0x0000FFFF, 0x0000FFFF, 0x0000FFFF, 0x00000080, 0x00000003, 0x00000080, 0x0000005B, - 0x0000FFFF, 0x00000003, 0x000000C8, 0x0000FFFF, 0x00000080, 0x0000005B, 0x0000FFFF, 0x00000003, - 0x0000008C, 0x0000009A, 0x00000051, 0x00000003, 0x000000C8, 0x0000FFFF, 0x00000080, 0x00000003, - 0x000000EC, 0x0000FFFF, 0x00000080, 0x00000003, 0x000000EC, 0x0000FFFF, 0x00000080, 0x00000003, - 0x000000A4, 0x00000051, 0x00000003, 0x000000EA, 0x0000FFFF, 0x0000FFFF, 0x0000FFFF, 0x00000080, - 0x00000003, 0x000000A2, 0x0000FFFF, 0x0000FFFF, 0x00000051, 0x00000003, 0x000000D7, 0x0000FFFF, - 0x000000E2, 0x0000FFFF, 0x00000080, 0x00000003, 0x000001A7, 0x0000FFFF, 0x0000FFFF, 0x00000003, - 0x000001D1, 0x00000080, 0x00000003, 0x000001D1, 0x000000A1, 0x00000003, 0x0000009A, 0x000001FE, - 0x00000003, 0x0000009A, 0x000001FD, 0x00000003, 0x00000080, 0x0000022F, 0x0000005A, 0x0000FFFF, - 0x00000003, 0x00000080, 0x0000024D, 0x0000FFFF, 0x0000FFFF, 0x00000003, 0x00000080, 0x00000051, - 0x00000003, 0x00000080, 0x000001D5, 0x00000003, 0x00000080, 0x0000022F, 0x00000003, 0x000000D9, - 0x0000FFFF, 0x000001A7, 0x0000FFFF, 0x0000FFFF, 0x00000003, 0x000000EC, 0x0000FFFF, 0x0000009F, - 0x00000003, 0x000000A2, 0x0000FFFF, 0x0000FFFF, 0x00000003, 0x000000A2, 0x0000FFFF, 0x0000FFFF, - 0x0000022F, 0x0000005A, 0x0000FFFF, 0x00000003, 0x000001A7, 0x0000FFFF, 0x0000FFFF, 0x000000D7, - 0x0000FFFF, 0x000000E2, 0x0000FFFF, 0x00000080, 0x00000003, 0x000000A3, 0x0000FFFF, 0x0000FFFF, - 0x00000003, 0x000000C8, 0x0000FFFF, 0x000000D7, 0x0000FFFF, 0x0000009D, 0x00000003, 0x000000EB, - 0x0000FFFF, 0x0000FFFF, 0x0000FFFF, 0x00000080, 0x00000003, 0x00000080, 0x0000024C, 0x0000FFFF, - 0x0000FFFF, 0x00000003, 0x000001D1, 0x00000080, 0x0000024C, 0x0000FFFF, 0x0000FFFF, 0x00000003, - 0x00000080, 0x0000022F, 0x0000024C, 0x0000FFFF, 0x0000FFFF, 0x00000003, 0x000001D1, 0x00000080, - 0x000000E2, 0x0000FFFF, 0x0000009A, 0x00000051, 0x00000231, 0x00000003, 0x000001D1, 0x000000A1, - 0x00000232, 0x00000091, 0x00000223, 0x00000003, 0x000001D3, 0x000001BA, 0x0000FFFF, 0x0000FFFF, - 0x000001D3, 0x000001BB, 0x0000FFFF, 0x0000FFFF, 0x000001D4, 0x00000081, 0x00000003, 0x000000CC, - 0x0000FFFF, 0x00000080, 0x00000003, 0x000001A2, 0x0000FFFF, 0x0000FFFF, 0x00000003, 0x000000CC, - 0x0000FFFF, 0x000001A0, 0x0000FFFF, 0x0000FFFF, 0x00000003, 0x000000CC, 0x0000FFFF, 0x00000081, - 0x00000003, 0x000000CC, 0x0000FFFF, 0x00000082, 0x00000003, 0x000000CC, 0x0000FFFF, 0x00000083, - 0x00000003, 0x000000CC, 0x0000FFFF, 0x000000A2, 0x0000FFFF, 0x0000FFFF, 0x00000003, 0x000000CC, - 0x0000FFFF, 0x000000EA, 0x0000FFFF, 0x0000FFFF, 0x0000FFFF, 0x0000009D, 0x00000003, 0x000000CC, - 0x0000FFFF, 0x000000EA, 0x0000FFFF, 0x0000FFFF, 0x0000FFFF, 0x00000099, 0x00000003, 0x000001D4, - 0x000000C8, 0x0000FFFF, 0x000000D7, 0x0000FFFF, 0x0000009D, 0x0000005B, 0x0000FFFF, 0x00000003, - 0x0000009A, 0x00000051, 0x0000009A, 0x000000E2, 0x0000FFFF, 0x0000009A, 0x00000051, 0x00000003, - 0x00000080, 0x00000230, 0x00000003, 0x00000080, 0x0000022F, 0x00000003, 0x00000080, 0x000001D5, - 0x00000003, 0x00000080, 0x000001D7, 0x00000003, 0x00000080, 0x000001D9, 0x00000003, 0x00000080, - 0x0000022D, 0x00000003, 0x00000080, 0x0000022E, 0x00000003, 0x000000A1, 0x000001D5, 0x00000003, - 0x000000A1, 0x000001D7, 0x00000003, 0x000000A1, 0x0000022E, 0x00000003, 0x000000A1, 0x00000230, - 0x00000003, 0x000000A1, 0x0000022F - - - - 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007, - 0x00000008, 0x00000009, 0x0000000D, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000E, 0x00000012, - 0x0000000F, 0x00000011, 0x00000010, 0x00000013, 0x00000017, 0x00000014, 0x00000016, 0x00000015, - 0x00000018, 0x0000001A, 0x00000019, 0x0000001B, 0x0000001C, 0x0000001D, 0x0000001E, 0x0000001F, - 0x00000025, 0x00000022, 0x00000024, 0x00000023, 0x00000020, 0x00000021, 0x00000026, 0x00000027, - 0x00000028, 0x00000029, 0x0000002A, 0x0000002B, 0x0000002D, 0x0000002C, 0x0000002E, 0x0000002F, - 0x00000030, 0x00000031, 0x00000033, 0x00000032, 0x00000034, 0x00000035, 0x00000036, 0x00000037, - 0x00000038, 0x0000003A, 0x00000039, 0x0000003B, 0x0000003C, 0x0000003E, 0x0000003D, 0x0000003F, - 0x00000040, 0x00000042, 0x00000041, 0x00000043, 0x00000044, 0x00000045, 0x00000046, 0x00000047, - 0x0000004A, 0x0000004B, 0x00000048, 0x00000049, 0x0000004C, 0x0000004D, 0x0000004E, 0x0000004F, - 0x00000050, 0x00000050, 0x00000051, 0x00000052, 0x00000053, 0x00000053, 0x00000054, 0x00000055, - 0x00000056, 0x00000056, 0x00000057, 0x0000005A, 0x0000005B, 0x00000058, 0x00000059, 0x0000005C, - 0x0000005D, 0x0000005E, 0x0000005F, 0x00000060, 0x00000061, 0x00000062, 0x00000063, 0x00000064, - 0x00000065, 0x00000066, 0x00000067, 0x00000068, 0x00000069, 0x0000006A, 0x0000006B, 0x0000006C, - 0x0000006D, 0x0000006E, 0x0000006F, 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, - 0x00000075, 0x00000076, 0x00000077, 0x00000078, 0x00000079, 0x0000007A, 0x0000007B, 0x0000007C, - 0x0000007D, 0x0000007E, 0x0000007F, 0x00000080, 0x00000081, 0x00000082, 0x00000083, 0x00000084, - 0x00000085, 0x00000086, 0x00000087, 0x00000088, 0x00000089, 0x0000008A, 0x0000008D, 0x0000008B, - 0x0000008C, 0x0000008E, 0x00000091, 0x00000092, 0x00000093, 0x0000008F, 0x00000090, 0x00000094, - 0x00000095, 0x00000097, 0x00000096, 0x00000098, 0x00000099, 0x0000009A, 0x0000009B, 0x0000009C, - 0x0000009D, 0x0000009E, 0x0000009F, 0x000000A0, 0x000000A1, 0x000000A2, 0x000000A3, 0x000000A4, - 0x000000A5, 0x000000A6, 0x000000A7, 0x000000A8, 0x000000A9, 0x000000AA, 0x000000AB, 0x000000AC, - 0x000000AD, 0x000000AE, 0x000000AF, 0x000000B0, 0x000000B1, 0x000000B2, 0x000000B3, 0x000000B4, - 0x000000B5, 0x000000B6, 0x000000B7, 0x000000B8, 0x000000B9, 0x000000BA, 0x000000BB, 0x000000BC, - 0x000000BE, 0x000000BD, 0x000000BF, 0x000000C1, 0x000000C0, 0x000000C2, 0x000000C3, 0x000000C4, - 0x000000C5, 0x000000C6, 0x000000C7, 0x000000C8, 0x000000CB, 0x000000CC, 0x000000C9, 0x000000CA, - 0x000000CD, 0x000000D0, 0x000000CE, 0x000000CF, 0x000000D1, 0x000000D2, 0x000000D3, 0x000000D4, - 0x000000D5, 0x000000D6, 0x000000D7, 0x000000D8, 0x000000D9, 0x000000DA, 0x000000DB, 0x000000DC, - 0x000000DD, 0x000000DE, 0x000000DF, 0x000000E0, 0x000000E1, 0x000000E2, 0x000000E3, 0x000000E4, - 0x000000E5, 0x000000E6, 0x000000E7, 0x000000E8, 0x000000E9, 0x000000EC, 0x000000ED, 0x000000EE, - 0x000000EF, 0x000000EA, 0x000000EB, 0x000000F0, 0x000000F1, 0x000000F2, 0x000000F3, 0x000000F4, - 0x000000F5, 0x000000F6, 0x000000F7, 0x000000F8, 0x000000F9, 0x000000FA, 0x000000FB, 0x000000FC, - 0x000000FD, 0x000000FE, 0x000000FF, 0x00000100, 0x00000101, 0x00000102, 0x00000103, 0x00000104, - 0x00000105, 0x00000106, 0x00000107, 0x00000108, 0x00000109, 0x0000010C, 0x0000010A, 0x0000010B, - 0x0000010D, 0x0000010E, 0x00000112, 0x00000111, 0x0000010F, 0x00000110, 0x00000113, 0x00000114, - 0x00000117, 0x00000118, 0x00000115, 0x00000116, 0x00000119, 0x0000011A, 0x00000120, 0x0000011D, - 0x0000011F, 0x0000011E, 0x0000011B, 0x0000011C, 0x00000121, 0x00000122, 0x00000124, 0x00000123, - 0x00000125, 0x00000126, 0x00000127, 0x00000128, 0x0000012C, 0x00000129, 0x0000012A, 0x0000012B, - 0x00000130, 0x0000012D, 0x0000012E, 0x0000012F, 0x00000132, 0x00000131, 0x00000133, 0x00000134, - 0x00000135, 0x00000136, 0x00000137, 0x00000138, 0x00000139, 0x0000013A, 0x0000013B, 0x0000013C, - 0x0000013D, 0x0000013E, 0x0000013F, 0x00000140, 0x00000141, 0x00000142, 0x00000143, 0x00000144, - 0x00000145, 0x00000146, 0x00000147, 0x00000148, 0x00000149, 0x0000014A, 0x0000014B, 0x0000014C, - 0x0000014D, 0x0000014E, 0x0000014F, 0x00000150, 0x00000151, 0x00000152, 0x00000153, 0x00000154, - 0x00000155, 0x00000156, 0x00000157, 0x00000158, 0x00000159, 0x0000015A, 0x0000015B, 0x0000015C, - 0x0000015D, 0x0000015E, 0x0000015F, 0x00000160, 0x00000161, 0x00000162, 0x00000163, 0x0000016B, - 0x00000166, 0x00000167, 0x00000168, 0x00000169, 0x0000016A, 0x00000164, 0x00000165, 0x0000016C, - 0x0000016F, 0x00000170, 0x00000171, 0x00000173, 0x00000172, 0x0000016D, 0x0000016E, 0x00000174, - 0x00000175, 0x00000176, 0x00000177, 0x00000178, 0x00000179, 0x0000017A, 0x0000017B, 0x0000017C, - 0x0000017D, 0x0000017E, 0x0000017F, 0x00000180, 0x00000181, 0x00000182, 0x00000183, 0x00000184, - 0x00000185, 0x00000186, 0x00000187, 0x00000188, 0x00000189, 0x0000018A, 0x0000018B, 0x0000018C, - 0x0000018D, 0x0000018E, 0x0000018F, 0x00000190, 0x00000191, 0x00000192, 0x00000193, 0x00000194, - 0x00000195, 0x00000196, 0x00000197 - - - - 0.000000, 0.000000, 6.515625, 0.000000, 8.121094, 0.000000, 14.121094, 0.000000, - 24.861328, -0.451172, 24.996094, 0.000000, 30.996094, 0.000000, 41.871094, 0.000000, - 41.871094, 0.000000, 41.871094, 0.000000, 47.871094, 0.000000, 52.230469, 0.000000, - 60.949219, 0.000000, 60.949219, 0.000000, 71.824219, 0.000000, 77.824219, 0.000000, - 82.183594, 0.000000, 93.058594, 0.000000, 102.720703, -0.451172, 99.574219, 0.000000, - 105.574219, 0.000000, 109.933594, 0.000000, 117.902344, 0.000000, 127.564453, -0.451172, - 124.417969, 0.000000, 130.417969, 0.000000, 134.777344, 0.000000, 142.746094, 0.000000, - 150.011719, 0.000000, 150.011719, 0.000000, 157.980469, 0.000000, 161.636719, 0.000000, - 167.636719, 0.000000, 171.996094, 0.000000, 182.871094, 0.000000, 186.621094, 0.000000, - 186.621094, 0.000000, 196.283203, -0.451172, 191.613281, 0.439453, 193.136719, 0.000000, - 199.136719, 0.000000, 210.011719, 0.000000, 210.011719, 0.000000, 210.011719, 0.000000, - 217.980469, 0.000000, 221.730469, 0.000000, 221.730469, 0.000000, 232.605469, 0.000000, - 232.605469, 0.000000, 232.605469, 0.000000, 240.574219, 0.000000, 244.324219, 0.000000, - 244.324219, 0.000000, 255.199219, 0.000000, 255.199219, 0.000000, 255.199219, 0.000000, - 261.199219, 0.000000, 270.667969, 0.000000, 280.330078, -0.451172, 277.183594, 0.000000, - 283.183594, 0.000000, 292.652344, 0.000000, 302.314453, -0.451172, 299.167969, 0.000000, - 305.167969, 0.000000, 314.636719, 0.000000, 324.298828, -0.451172, 321.152344, 0.000000, - 327.152344, 0.000000, 338.027344, 0.000000, 344.783203, 0.263672, 348.902344, 0.000000, - 354.902344, 0.000000, 361.658203, 0.263672, 362.279297, 0.263672, 365.777344, 0.000000, - 365.777344, 0.000000, 365.777344, 0.000000, 371.777344, 0.000000, 378.533203, 0.263672, - 382.652344, 0.000000, 390.193359, 0.000000, 390.193359, 0.000000, 397.916016, -0.011719, - 401.068359, 0.000000, 408.609375, 0.000000, 408.609375, 0.000000, 415.365234, 0.263672, - 419.484375, 0.000000, 427.025391, 0.000000, 427.025391, 0.000000, 433.025391, 0.000000, - 440.748047, -0.011719, 440.929688, 0.263672, 443.900391, 0.000000, 443.900391, 0.000000, - 449.900391, 0.000000, 460.775391, 0.000000, 466.775391, 0.000000, 477.650391, 0.000000, - 483.650391, 0.000000, 494.390625, -0.451172, 494.525391, 0.000000, 500.525391, 0.000000, - 511.400391, 0.000000, 511.400391, 0.000000, 511.400391, 0.000000, 517.400391, 0.000000, - 528.275391, 0.000000, 528.275391, 0.000000, 531.457031, -0.451172, 528.275391, 0.000000, - 534.275391, 0.000000, 542.994141, 0.000000, 542.994141, 0.000000, 542.994141, 0.000000, - 542.994141, 0.000000, 553.869141, 0.000000, 559.869141, 0.000000, 565.869141, 0.000000, - 575.337891, 0.000000, 575.337891, 0.000000, 581.337891, 0.000000, 590.806641, 0.000000, - 596.806641, 0.000000, 609.597656, -0.451172, 606.275391, 0.000000, 612.275391, 0.000000, - 623.150391, 0.000000, 623.150391, 0.000000, 623.150391, 0.000000, 629.150391, 0.000000, - 640.025391, 0.000000, 640.025391, 0.000000, 643.207031, -0.451172, 640.025391, 0.000000, - 646.025391, 0.000000, 653.994141, 0.000000, 653.994141, 0.000000, 653.994141, 0.000000, - 653.994141, 0.000000, 664.869141, 0.000000, 670.869141, 0.000000, 678.773438, 0.263672, - 681.744141, 0.000000, 681.744141, 0.000000, 687.744141, 0.000000, 696.462891, 0.000000, - 696.462891, 0.000000, 704.367188, 0.263672, 707.337891, 0.000000, 707.337891, 0.000000, - 713.337891, 0.000000, 721.306641, 0.000000, 730.968750, -0.451172, 727.822266, 0.000000, - 733.822266, 0.000000, 742.541016, 0.000000, 742.541016, 0.000000, 753.416016, 0.000000, - 759.416016, 0.000000, 768.134766, 0.000000, 768.134766, 0.000000, 779.009766, 0.000000, - 785.009766, 0.000000, 793.728516, 0.000000, 793.728516, 0.000000, 804.603516, 0.000000, - 810.603516, 0.000000, 821.343750, -0.451172, 821.478516, 0.000000, 827.478516, 0.000000, - 836.197266, 0.000000, 836.197266, 0.000000, 836.197266, 0.000000, 836.197266, 0.000000, - 847.072266, 0.000000, 853.072266, 0.000000, 863.947266, 0.000000, 863.947266, 0.000000, - 867.128906, -0.451172, 863.947266, 0.000000, 869.947266, 0.000000, 875.876953, 0.000000, - 875.876953, 0.000000, 879.626953, 0.000000, 879.626953, 0.000000, 890.501953, 0.000000, - 896.501953, 0.000000, 903.064453, 0.000000, 903.064453, 0.000000, 903.064453, 0.000000, - 909.064453, 0.000000, 913.423828, 0.000000, 924.298828, 0.000000, 930.298828, 0.000000, - 934.658203, 0.000000, 942.626953, 0.000000, 948.626953, 0.000000, 955.142578, 0.000000, - 956.748047, 0.000000, 962.748047, 0.000000, 969.263672, 0.000000, 970.623047, 0.000000, - 976.623047, 0.000000, 983.378906, 0.263672, 983.853516, 0.164062, 987.498047, 0.000000, - 987.498047, 0.000000, 993.498047, 0.000000, 1000.875000, 0.263672, 1004.373047, 0.000000, - 1004.373047, 0.000000, 1004.373047, 0.000000, 1010.373047, 0.000000, 1021.113281, -0.451172, - 1021.248047, 0.000000, 1027.248047, 0.000000, 1034.947266, -0.011719, 1038.123047, 0.000000, - 1044.123047, 0.000000, 1050.878906, 0.263672, 1054.998047, 0.000000, 1060.998047, 0.000000, - 1068.966797, 0.000000, 1068.966797, 0.000000, 1075.529297, 0.000000, 1075.529297, 0.000000, - 1075.529297, 0.000000, 1081.529297, 0.000000, 1090.248047, 0.000000, 1090.248047, 0.000000, - 1098.216797, 0.000000, 1104.216797, 0.000000, 1115.091797, 0.000000, 1115.091797, 0.000000, - 1115.091797, 0.000000, 1121.091797, 0.000000, 1131.966797, 0.000000, 1131.966797, 0.000000, - 1131.164062, 0.275391, 1131.638672, 0.175781, 1131.966797, 0.000000, 1131.966797, 0.000000, - 1137.966797, 0.000000, 1144.529297, 0.000000, 1144.529297, 0.000000, 1144.529297, 0.000000, - 1150.458984, 0.000000, 1150.458984, 0.000000, 1154.208984, 0.000000, 1154.208984, 0.000000, - 1165.083984, 0.000000, 1171.083984, 0.000000, 1181.958984, 0.000000, 1181.958984, 0.000000, - 1181.958984, 0.000000, 1187.958984, 0.000000, 1196.677734, 0.000000, 1196.677734, 0.000000, - 1202.607422, 0.000000, 1202.607422, 0.000000, 1210.576172, 0.000000, 1216.576172, 0.000000, - 1224.544922, 0.000000, 1224.544922, 0.000000, 1224.544922, 0.000000, 1224.544922, 0.000000, - 1235.419922, 0.000000, 1241.419922, 0.000000, 1249.236328, 0.263672, 1252.294922, 0.000000, - 1252.294922, 0.000000, 1252.294922, 0.000000, 1258.294922, 0.000000, 1262.654297, 0.000000, - 1270.470703, 0.263672, 1273.529297, 0.000000, 1273.529297, 0.000000, 1273.529297, 0.000000, - 1279.529297, 0.000000, 1286.285156, 0.263672, 1287.345703, 0.263672, 1290.404297, 0.000000, - 1290.404297, 0.000000, 1290.404297, 0.000000, 1296.404297, 0.000000, 1300.763672, 0.000000, - 1311.638672, 0.000000, 1315.388672, 0.000000, 1315.388672, 0.000000, 1325.050781, -0.451172, - 1323.474609, -0.087891, 1321.904297, 0.000000, 1327.904297, 0.000000, 1332.263672, 0.000000, - 1338.767578, 0.439453, 1340.232422, 0.000000, 1348.201172, 0.000000, 1351.857422, 0.000000, - 1357.857422, 0.000000, 1362.216797, 0.000000, 1372.388672, 0.000000, 1372.388672, 0.000000, - 1372.388672, 0.000000, 1376.748047, 0.000000, 1386.919922, 0.000000, 1386.919922, 0.000000, - 1386.919922, 0.000000, 1391.279297, 0.000000, 1402.154297, 0.000000, 1408.154297, 0.000000, - 1416.123047, 0.000000, 1416.123047, 0.000000, 1426.998047, 0.000000, 1432.998047, 0.000000, - 1446.076172, 0.000000, 1446.076172, 0.000000, 1446.076172, 0.000000, 1452.076172, 0.000000, - 1460.044922, 0.000000, 1460.044922, 0.000000, 1471.294922, 0.000000, 1471.294922, 0.000000, - 1471.294922, 0.000000, 1477.294922, 0.000000, 1485.263672, 0.000000, 1485.263672, 0.000000, - 1496.138672, 0.000000, 1502.138672, 0.000000, 1510.107422, 0.000000, 1510.107422, 0.000000, - 1519.576172, 0.000000, 1525.576172, 0.000000, 1533.544922, 0.000000, 1533.544922, 0.000000, - 1543.013672, 0.000000, 1549.013672, 0.000000, 1556.982422, 0.000000, 1556.982422, 0.000000, - 1567.857422, 0.000000, 1567.857422, 0.000000, 1567.857422, 0.000000, 1573.857422, 0.000000, - 1581.826172, 0.000000, 1581.826172, 0.000000, 1590.544922, 0.000000, 1590.544922, 0.000000, - 1590.544922, 0.000000, 1590.544922, 0.000000, 1598.513672, 0.000000, 1604.513672, 0.000000, - 1612.482422, 0.000000, 1612.482422, 0.000000, 1621.201172, 0.000000, 1621.201172, 0.000000, - 1621.201172, 0.000000, 1621.201172, 0.000000, 1630.669922, 0.000000, 1636.669922, 0.000000, - 1641.029297, 0.000000, 1649.748047, 0.000000, 1649.748047, 0.000000, 1655.677734, 0.000000, - 1655.677734, 0.000000, 1663.939453, 0.263672, 1663.646484, 0.000000, 1663.646484, 0.000000, - 1669.646484, 0.000000, 1679.308594, -0.451172, 1676.162109, 0.000000, 1682.677734, 0.000000, - 1686.427734, 0.000000, 1686.427734, 0.000000, 1696.089844, -0.451172, 1692.943359, 0.000000, - 1698.943359, 0.000000, 1706.314453, 0.263672, 1709.818359, 0.000000, 1715.818359, 0.000000, - 1722.574219, 0.263672, 1726.693359, 0.000000, 1732.693359, 0.000000, 1740.392578, -0.011719, - 1743.568359, 0.000000, 1749.568359, 0.000000, 1757.291016, -0.011719, 1760.443359, 0.000000, - 1766.443359, 0.000000, 1774.376953, -0.011719, 1777.318359, 0.000000, 1783.318359, 0.000000, - 1791.738281, -0.439453, 1794.193359, 0.000000, 1800.193359, 0.000000, 1808.121094, 0.263672, - 1811.068359, 0.000000, 1817.068359, 0.000000, 1823.085938, -0.011719, 1825.037109, 0.000000, - 1831.037109, 0.000000, 1837.078125, -0.011719, 1839.005859, 0.000000, 1845.005859, 0.000000, - 1852.529297, 0.263672, 1852.974609, 0.000000, 1858.974609, 0.000000, 1865.941406, 0.263672, - 1866.943359, 0.000000, 1872.943359, 0.000000, 1879.294922, 0.263672, 1880.912109, 0.000000 - - - - - - - 中华人民共和国 台湾 中華人民共和國 臺灣 - - - 0x000020BC, 0x000025DD, 0x00002149, 0x00003EA0, 0x00002400, 0x0000271B, 0x0000298C, 0x00000003, - 0x0000267F, 0x0000410D, 0x00000003, 0x000020BC, 0x0000567E, 0x00002149, 0x00003EA0, 0x00002400, - 0x0000271B, 0x0000299A, 0x00000003, 0x00005489, 0x000042F2 - - - - 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007, - 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F, - 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014 - - - - 0.000000, 0.000000, 12.000000, 0.000000, 24.000000, 0.000000, 36.000000, 0.000000, - 48.000000, 0.000000, 60.000000, 0.000000, 72.000000, 0.000000, 84.000000, 0.000000, - 87.333984, 0.000000, 99.333984, 0.000000, 111.333984, 0.000000, 114.667969, 0.000000, - 126.667969, 0.000000, 138.667969, 0.000000, 150.667969, 0.000000, 162.667969, 0.000000, - 174.667969, 0.000000, 186.667969, 0.000000, 198.667969, 0.000000, 202.001953, 0.000000, - 214.001953, 0.000000, 226.001953, 0.000000 - - - - - - - - - - - - शङ़ु - - - 0x00000002, 0x00000001, 0x00000006, 0x0000FFFF - - - - 0x00000000, 0x00000001, 0x00000002, 0x00000003 - - - - 0.000000, 0.000000, 7.572000, 0.000000, 15.108000, 0.000000, 15.108000, 0.000000, - 15.108000, 0.000000 - - - - - - - - - क्ष र्क क्‍ष र्‍क - - - 0x000000A2, 0x0000FFFF, 0x0000FFFF, 0x00000003, 0x00000080, 0x0000005B, 0x0000FFFF, 0x00000003, - 0x00000080, 0x00000051, 0x00000001, 0x0000009F, 0x00000003, 0x0000009A, 0x00000051, 0x00000001, - 0x00000080 - - - - 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000006, 0x00000004, 0x00000005, 0x00000007, - 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F, - 0x00000010 - - - - 0.000000, 0.000000, 10.875000, 0.000000, 10.875000, 0.000000, 10.875000, 0.000000, - 16.875000, 0.000000, 24.779297, 0.263672, 27.750000, 0.000000, 27.750000, 0.000000, - 33.750000, 0.000000, 44.490234, -0.451172, 44.625000, 0.000000, 44.625000, 0.000000, - 52.593750, 0.000000, 58.593750, 0.000000, 68.255859, -0.451172, 65.109375, 0.000000, - 65.109375, 0.000000, 75.984375, 0.000000 - - - - - - - 마만만 - - - 0x00000000, 0x0000FFFF, 0x00000000, 0x0000FFFF, 0x0000FFFF, 0x00000000, 0x0000FFFF - - - - 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006 - - - - 0.000000, 0.000000, 9.000000, 0.000000, 9.000000, 0.000000, 18.000000, 0.000000, - 18.000000, 0.000000, 18.000000, 0.000000, 27.000000, 0.000000, 27.000000, 0.000000 - - - - - - - מָשְׁכֵנִיאַחֲרֶיךָנָּרוּצָההֱבִיאַנִיהַמֶּלֶךְחֲדָרָיונָגִילָהוְנִשְׂמְחָהבָּךְנַזְכִּירָהדֹדֶיךָמִיַּיִןמֵישָׁרִיםאֲהֵבוּךָ - - - 0x0000FFFF, 0x00000055, 0x0000FFFF, 0x0000004B, 0x0000001D, 0x00000097, 0x00000021, 0x00000094, - 0x0000001B, 0x0000002D, 0x00000027, 0x00000096, 0x0000003A, 0x0000009A, 0x0000FFFF, 0x00000066, - 0x00000027, 0x00000097, 0x0000002F, 0x00000030, 0x00000096, 0x00000027, 0x00000099, 0x0000FFFF, - 0x00000051, 0x00000096, 0x0000002F, 0x0000FFFF, 0x00000055, 0x00000027, 0x00000098, 0x0000001F, - 0x0000009C, 0x0000001F, 0x00000021, 0x0000009A, 0x0000003A, 0x00000027, 0x00000096, 0x0000FFFF, - 0x00000056, 0x00000092, 0x00000024, 0x00000099, 0x00000031, 0x0000FFFF, 0x00000054, 0x0000009A, - 0x0000FFFF, 0x00000043, 0x00000021, 0x0000009A, 0x00000025, 0x00000092, 0x0000002F, 0x00000092, - 0x0000FFFF, 0x00000067, 0x00000096, 0x00000031, 0x00000092, 0x00000023, 0x00000021, 0x0000009A, - 0x0000002B, 0x00000027, 0x00000096, 0x0000001E, 0x0000009A, 0x00000031, 0x00000023, 0x00000027, - 0x0000009A, 0x0000003A, 0x0000009A, 0x0000001F, 0x00000094, 0x00000025, 0x0000FFFF, 0x00000054, - 0x00000098, 0x0000002B, 0x00000098, 0x0000FFFF, 0x0000005D, 0x00000099, 0x00000021, 0x00000027, - 0x00000096, 0x00000031, 0x00000099, 0x0000001B, 0x00000027, 0x00000096, 0x0000001D, 0x00000093, - 0x00000021, 0x00000021, 0x0000009A, 0x00000038, 0x0000FFFF, 0x0000004B, 0x0000003A, 0x0000009A, - 0x0000FFFF, 0x0000005E, 0x0000FFFF, 0x00000055, 0x00000027, 0x00000098, 0x0000003A, 0x00000094, - 0x00000025, 0x00000099, 0x0000001B, 0x00000027, 0x00000096, 0x00000031, 0x00000097, 0x00000029, - 0x00000092, 0x0000FFFF, 0x00000066, 0x0000009A, 0x0000002F - - - - 0x0000007C, 0x0000007B, 0x0000007A, 0x00000079, 0x00000078, 0x00000077, 0x00000076, 0x00000075, - 0x00000074, 0x00000073, 0x00000072, 0x00000071, 0x00000070, 0x0000006F, 0x0000006E, 0x0000006D, - 0x0000006C, 0x0000006B, 0x0000006A, 0x00000069, 0x00000068, 0x00000067, 0x00000066, 0x00000065, - 0x00000064, 0x00000063, 0x00000062, 0x00000061, 0x00000060, 0x0000005F, 0x0000005E, 0x0000005D, - 0x0000005C, 0x0000005B, 0x0000005A, 0x00000059, 0x00000058, 0x00000057, 0x00000056, 0x00000055, - 0x00000054, 0x00000053, 0x00000052, 0x00000051, 0x00000050, 0x0000004F, 0x0000004E, 0x0000004D, - 0x0000004C, 0x0000004B, 0x0000004A, 0x00000049, 0x00000048, 0x00000047, 0x00000046, 0x00000045, - 0x00000044, 0x00000043, 0x00000042, 0x00000041, 0x00000040, 0x0000003F, 0x0000003E, 0x0000003D, - 0x0000003C, 0x0000003B, 0x0000003A, 0x00000039, 0x00000038, 0x00000037, 0x00000036, 0x00000035, - 0x00000034, 0x00000033, 0x00000032, 0x00000031, 0x00000030, 0x0000002F, 0x0000002E, 0x0000002D, - 0x0000002C, 0x0000002B, 0x0000002A, 0x00000029, 0x00000028, 0x00000027, 0x00000026, 0x00000025, - 0x00000024, 0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001F, 0x0000001E, 0x0000001D, - 0x0000001C, 0x0000001B, 0x0000001A, 0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015, - 0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000010, 0x0000000F, 0x0000000E, 0x0000000D, - 0x0000000C, 0x0000000B, 0x0000000A, 0x00000009, 0x00000008, 0x00000007, 0x00000006, 0x00000005, - 0x00000004, 0x00000003, 0x00000002, 0x00000001, 0x00000000 - - - - 0.000000, 0.000000, 0.000000, 0.000000, 5.806641, 0.000000, 5.806641, 0.000000, - 9.087891, 0.000000, 18.679688, 0.000000, 15.251953, 0.000000, 25.365234, 0.000000, - 21.878906, 0.000000, 28.787109, 0.000000, 35.191406, 0.000000, 42.966797, 0.000000, - 38.279297, 0.000000, 47.982422, 0.000000, 44.085938, 0.000000, 44.085938, 0.000000, - 52.347656, 0.000000, 58.453125, 0.000000, 55.113281, 0.000000, 62.021484, 0.000000, - 66.292969, 0.000000, 64.886719, 0.000000, 69.292969, 0.000000, 67.886719, 0.000000, - 67.886719, 0.000000, 74.050781, 0.000000, 70.710938, 0.000000, 77.619141, 0.000000, - 77.619141, 0.000000, 83.425781, 0.000000, 90.527344, 0.000000, 86.513672, 0.000000, - 91.804688, 0.000000, 92.390625, 0.000000, 98.267578, 0.000000, 109.347656, 0.000000, - 104.894531, 0.000000, 110.701172, 0.000000, 116.250000, 0.000000, 113.701172, 0.000000, - 113.554688, 0.000000, 121.242188, 0.000000, 119.484375, 0.000000, 124.552734, 0.000000, - 122.677734, 0.000000, 126.679688, 0.000000, 126.679688, 0.000000, 135.210938, 0.000000, - 132.486328, 0.000000, 132.251953, 0.000000, 138.416016, 0.000000, 148.734375, 0.000000, - 145.042969, 0.000000, 155.308594, 0.000000, 151.968750, 0.000000, 162.773438, 0.000000, - 158.876953, 0.000000, 158.876953, 0.000000, 168.398438, 0.000000, 166.523438, 0.000000, - 172.546875, 0.000000, 170.525391, 0.000000, 173.689453, 0.000000, 182.718750, 0.000000, - 180.199219, 0.000000, 185.583984, 0.000000, 190.107422, 0.000000, 187.998047, 0.000000, - 194.132812, 0.000000, 192.257812, 0.000000, 196.259766, 0.000000, 199.423828, 0.000000, - 206.964844, 0.000000, 202.511719, 0.000000, 212.332031, 0.000000, 208.318359, 0.000000, - 217.886719, 0.000000, 214.195312, 0.000000, 221.121094, 0.000000, 221.121094, 0.000000, - 229.447266, 0.000000, 226.927734, 0.000000, 235.652344, 0.000000, 232.312500, 0.000000, - 232.312500, 0.000000, 242.648438, 0.000000, 239.220703, 0.000000, 245.847656, 0.000000, - 250.195312, 0.000000, 248.320312, 0.000000, 255.808594, 0.000000, 252.322266, 0.000000, - 259.230469, 0.000000, 265.042969, 0.000000, 262.083984, 0.000000, 271.675781, 0.000000, - 268.248047, 0.000000, 274.875000, 0.000000, 284.197266, 0.000000, 281.501953, 0.000000, - 287.250000, 0.000000, 287.250000, 0.000000, 290.531250, 0.000000, 298.212891, 0.000000, - 296.337891, 0.000000, 296.337891, 0.000000, 300.339844, 0.000000, 300.339844, 0.000000, - 306.146484, 0.000000, 313.687500, 0.000000, 309.234375, 0.000000, 318.732422, 0.000000, - 315.041016, 0.000000, 325.453125, 0.000000, 321.966797, 0.000000, 328.875000, 0.000000, - 333.222656, 0.000000, 331.347656, 0.000000, 338.044922, 0.000000, 335.349609, 0.000000, - 345.175781, 0.000000, 341.279297, 0.000000, 341.279297, 0.000000, 352.558594, 0.000000, - 349.218750, 0.000000, 356.126953, 0.000000 - - - - - - - Ţhiş iş a ţeşţ. - - - 0x00000107, 0x00000049, 0x0000004A, 0x00000104, 0x00000001, 0x0000004A, 0x00000104, 0x00000001, - 0x00000042, 0x00000001, 0x00000108, 0x00000046, 0x00000104, 0x00000108, 0x0000000F - - - - 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007, - 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E - - - - 0.000000, 0.000000, 7.356000, 0.000000, 14.340000, 0.000000, 17.832001, 0.000000, - 22.920000, 0.000000, 25.920000, 0.000000, 29.412001, 0.000000, 34.500000, 0.000000, - 37.500000, 0.000000, 43.500000, 0.000000, 46.500000, 0.000000, 50.411999, 0.000000, - 56.160000, 0.000000, 61.248001, 0.000000, 65.160004, 0.000000, 68.160004, 0.000000 - - - - - - - - - فتح بینچ خلیج شیخ پہنچ - - - 0x0000003B, 0x00000344, 0x000001D5, 0x00000318, 0x00000349, 0x0000007C, 0x00000003, 0x0000003D, - 0x00000348, 0x000001D5, 0x00000346, 0x000000B5, 0x00000003, 0x0000003A, 0x00000348, 0x000001D5, - 0x000002E3, 0x00000344, 0x00000087, 0x00000003, 0x0000003B, 0x00000344, 0x000001D5, 0x00000348, - 0x000001E5, 0x00000347, 0x0000006E, 0x00000003, 0x0000003C, 0x00000345, 0x000001D5, 0x00000344, - 0x0000011D - - - - 0x00000015, 0x00000014, 0x00000014, 0x00000013, 0x00000012, 0x00000012, 0x00000011, 0x00000010, - 0x0000000F, 0x0000000F, 0x0000000E, 0x0000000E, 0x0000000D, 0x0000000C, 0x0000000B, 0x0000000B, - 0x0000000A, 0x00000009, 0x00000009, 0x00000008, 0x00000007, 0x00000006, 0x00000006, 0x00000005, - 0x00000005, 0x00000004, 0x00000004, 0x00000003, 0x00000002, 0x00000001, 0x00000001, 0x00000000, - 0x00000000 - - - - 0.000000, 0.000000, 3.205078, -11.097656, 1.406250, 0.000000, 4.558594, -1.376953, - 9.421875, -5.273438, 7.505859, -6.843750, 11.537109, 0.000000, 12.726562, 0.000000, - 20.455078, -4.798828, 15.357422, 0.000000, 19.289062, -13.072266, 18.509766, -1.376953, - 22.552734, 0.000000, 23.742188, 0.000000, 30.246094, -4.798828, 25.148438, 0.000000, - 28.300781, -1.376953, 32.917969, -13.792969, 30.158203, -7.792969, 35.208984, 0.000000, - 36.398438, 0.000000, 39.603516, -11.097656, 37.804688, 0.000000, 45.632812, 3.181641, - 40.957031, -1.376953, 44.853516, -6.046875, 42.457031, -5.572266, 46.066406, 0.000000, - 47.255859, 0.000000, 49.376953, -11.396484, 48.662109, 0.000000, 52.769531, -14.332031, - 51.814453, -1.376953, 56.789062, 0.000000 - - - - - - - ണു് - - - 0x00000023, 0x0000003C, 0x00000045 - - - - 0x00000000, 0x00000001, 0x00000002 - - - - 0.000000, 0.000000, 15.117188, 0.000000, 18.503906, 0.000000, 18.503906, 0.000000 - - - - - - - 中華人民共和國 臺灣 - - - 0x00000292, 0x000024E8, 0x000002D1, 0x00001582, 0x000004A1, 0x00000650, 0x000007E2, 0x00000021, - 0x00002395, 0x00001896 - - - - 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007, - 0x00000008, 0x00000009 - - - - 0.000000, 0.000000, 12.000000, 0.000000, 24.000000, 0.000000, 36.000000, 0.000000, - 48.000000, 0.000000, 60.000000, 0.000000, 72.000000, 0.000000, 84.000000, 0.000000, - 90.000000, 0.000000, 102.000000, 0.000000, 114.000000, 0.000000 - - - - - - - ప్రకాష్ - - - 0x00000057, 0x0000023B, 0x0000FFFF, 0x00000125, 0x00000066, 0x00000241, 0x0000FFFF - - - - 0x00000000, 0x00000002, 0x00000001, 0x00000003, 0x00000004, 0x00000005, 0x00000006 - - - - 0.000000, 0.000000, 8.285156, 0.000000, 14.894531, 0.000000, 14.894531, 0.000000, - 21.503906, 0.000000, 25.136719, 0.000000, 33.421875, 0.000000, 33.421875, 0.000000 - - - - - - - บทที่๑พายุไซโคลนโดโรธีอาศัยอยู่ท่ามกลางทุ่งใหญ่ในแคนซัสกับลุงเฮนรีชาวไร่และป้าเอ็มภรรยาชาวไร่บ้านของพวกเขาหลังเล็กเพราะไม้สร้างบ้านต้องขนมาด้วยเกวียนเป็นระยะทางหลายไมล์ - - - 0x0000009D, 0x0000009A, 0x0000009A, 0x000000B8, 0x000000C9, 0x000000D2, 0x000000A1, 0x000000B5, - 0x000000A5, 0x000000BB, 0x000000C5, 0x0000008E, 0x000000C3, 0x00000087, 0x000000A8, 0x0000009C, - 0x000000C3, 0x00000097, 0x000000C3, 0x000000A6, 0x0000009B, 0x000000B8, 0x000000B0, 0x000000B5, - 0x000000AB, 0x000000B4, 0x000000A5, 0x000000B0, 0x000000A5, 0x000000BC, 0x0000006E, 0x0000009A, - 0x0000006E, 0x000000B5, 0x000000A4, 0x00000084, 0x000000A8, 0x000000B5, 0x0000008A, 0x0000009A, - 0x000000BB, 0x0000006E, 0x0000008A, 0x000000C4, 0x000000AE, 0x00000090, 0x0000006E, 0x000000C4, - 0x0000009C, 0x000000C2, 0x00000087, 0x0000009C, 0x0000008E, 0x000000B4, 0x000000AD, 0x00000084, - 0x000000B4, 0x0000009D, 0x000000A8, 0x000000BB, 0x0000008A, 0x000000C1, 0x000000B1, 0x0000009C, - 0x000000A6, 0x000000B8, 0x0000008D, 0x000000B5, 0x000000AA, 0x000000C5, 0x000000A6, 0x0000006E, - 0x000000C2, 0x000000A8, 0x000000B3, 0x0000009E, 0x0000006F, 0x000000B5, 0x000000C1, 0x000000B0, - 0x000000C8, 0x000000A4, 0x000000A3, 0x000000A6, 0x000000A6, 0x000000A5, 0x000000B5, 0x0000008D, - 0x000000B5, 0x000000AA, 0x000000C5, 0x000000A6, 0x0000006E, 0x0000009D, 0x0000006F, 0x000000B5, - 0x0000009C, 0x00000085, 0x000000B0, 0x0000008A, 0x000000A1, 0x000000AA, 0x00000084, 0x000000C1, - 0x00000085, 0x000000B5, 0x000000AE, 0x000000A8, 0x000000B4, 0x0000008A, 0x000000C1, 0x000000A8, - 0x000000C8, 0x00000084, 0x000000C1, 0x000000A1, 0x000000A6, 0x000000B5, 0x000000B3, 0x000000C5, - 0x000000A4, 0x0000006F, 0x000000AD, 0x000000A6, 0x0000006F, 0x000000B5, 0x0000008A, 0x0000009D, - 0x0000006F, 0x000000B5, 0x0000009C, 0x00000098, 0x0000006F, 0x000000B0, 0x0000008A, 0x00000085, - 0x0000009C, 0x000000A4, 0x000000B5, 0x00000097, 0x0000006F, 0x000000AA, 0x000000A5, 0x000000C1, - 0x00000084, 0x000000AA, 0x000000B8, 0x000000A5, 0x0000009C, 0x000000C1, 0x0000009E, 0x000000C8, - 0x0000009C, 0x000000A6, 0x000000B3, 0x000000A5, 0x000000B3, 0x0000009A, 0x000000B5, 0x0000008A, - 0x000000AE, 0x000000A8, 0x000000B5, 0x000000A5, 0x000000C5, 0x000000A4, 0x000000A8, 0x00000072 - - - - 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007, - 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F, - 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000016, 0x00000017, - 0x00000018, 0x00000019, 0x0000001A, 0x0000001B, 0x0000001C, 0x0000001D, 0x0000001E, 0x0000001F, - 0x00000020, 0x00000021, 0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000026, 0x00000027, - 0x00000028, 0x00000029, 0x0000002A, 0x0000002B, 0x0000002C, 0x0000002D, 0x0000002E, 0x0000002F, - 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034, 0x00000035, 0x00000036, 0x00000037, - 0x00000038, 0x00000039, 0x0000003A, 0x0000003B, 0x0000003C, 0x0000003D, 0x0000003E, 0x0000003F, - 0x00000040, 0x00000041, 0x00000042, 0x00000043, 0x00000044, 0x00000045, 0x00000046, 0x00000047, - 0x00000048, 0x00000049, 0x0000004A, 0x0000004B, 0x0000004C, 0x0000004D, 0x0000004E, 0x0000004F, - 0x00000050, 0x00000051, 0x00000052, 0x00000053, 0x00000054, 0x00000055, 0x00000056, 0x00000057, - 0x00000058, 0x00000059, 0x0000005A, 0x0000005B, 0x0000005C, 0x0000005D, 0x0000005E, 0x0000005F, - 0x00000060, 0x00000061, 0x00000062, 0x00000063, 0x00000064, 0x00000065, 0x00000066, 0x00000067, - 0x00000068, 0x00000069, 0x0000006A, 0x0000006B, 0x0000006C, 0x0000006D, 0x0000006E, 0x0000006F, - 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, 0x00000075, 0x00000076, 0x00000077, - 0x00000078, 0x00000079, 0x0000007A, 0x0000007B, 0x0000007C, 0x0000007D, 0x0000007E, 0x0000007F, - 0x00000080, 0x00000081, 0x00000082, 0x00000083, 0x00000084, 0x00000085, 0x00000086, 0x00000087, - 0x00000088, 0x00000089, 0x0000008A, 0x0000008B, 0x0000008C, 0x0000008D, 0x0000008E, 0x0000008F, - 0x00000090, 0x00000091, 0x00000092, 0x00000093, 0x00000094, 0x00000095, 0x00000096, 0x00000097, - 0x00000098, 0x00000099, 0x0000009A, 0x0000009B, 0x0000009C, 0x0000009D, 0x0000009E, 0x0000009F, - 0x000000A0, 0x000000A1, 0x000000A2, 0x000000A3, 0x000000A4, 0x000000A5, 0x000000A6, 0x000000A7 - - - - 0.000000, 0.000000, 5.399414, 0.000000, 10.798828, 0.000000, 15.072266, 0.000000, - 15.072266, 0.000000, 16.198242, 0.000000, 21.046875, 0.000000, 26.616211, 0.000000, - 30.035156, 0.000000, 31.312500, 0.000000, 34.151367, 0.000000, 38.279297, 0.000000, - 43.558594, 0.000000, 47.663086, 0.000000, 52.438477, 0.000000, 57.178711, 0.000000, - 62.698242, 0.000000, 66.802734, 0.000000, 71.601562, 0.000000, 75.706055, 0.000000, - 79.810547, 0.000000, 84.029297, 0.000000, 84.369141, 0.000000, 89.097656, 0.000000, - 92.516602, 0.000000, 97.614258, 0.000000, 97.195312, 0.000000, 101.311523, 0.000000, - 106.040039, 0.000000, 107.375977, 0.000000, 108.326172, -0.084961, 110.156250, 0.000000, - 113.497070, -0.084961, 115.555664, 0.000000, 118.974609, 0.000000, 124.013672, 0.000000, - 128.765625, 0.000000, 133.505859, 0.000000, 136.924805, 0.000000, 140.704102, 0.000000, - 143.036133, 0.000000, 144.044922, -0.084961, 146.103516, 0.000000, 149.882812, 0.000000, - 153.553711, 0.000000, 159.158203, 0.000000, 163.377930, -0.084961, 165.421875, 0.000000, - 169.092773, 0.000000, 174.612305, 0.000000, 179.135742, 0.000000, 183.911133, 0.000000, - 189.430664, 0.000000, 194.879883, 0.000000, 194.709961, 0.000000, 199.989258, 0.000000, - 204.092773, -0.084961, 204.741211, 0.000000, 210.140625, 0.000000, 212.828125, 0.000000, - 214.880859, 0.000000, 218.660156, 0.000000, 220.675781, 0.000000, 225.128906, 0.000000, - 230.648438, 0.000000, 234.105469, 0.000000, 234.752930, 0.000000, 239.613281, 0.000000, - 243.032227, 0.000000, 247.280273, 0.000000, 251.408203, 0.000000, 253.932617, -0.084961, - 255.512695, 0.000000, 260.036133, 0.000000, 264.776367, 0.000000, 269.071289, 0.000000, - 272.704102, 0.000000, 274.470703, 0.000000, 277.889648, 0.000000, 279.905273, 0.000000, - 284.768555, 0.000000, 284.633789, 0.000000, 289.672852, 0.000000, 294.641602, 0.000000, - 298.746094, 0.000000, 302.850586, 0.000000, 306.966797, 0.000000, 310.385742, 0.000000, - 315.246094, 0.000000, 318.665039, 0.000000, 322.913086, 0.000000, 327.041016, 0.000000, - 329.565430, -0.084961, 331.145508, 0.000000, 335.911133, 0.000000, 336.544922, 0.000000, - 339.963867, 0.000000, 345.483398, 0.000000, 350.258789, 0.000000, 354.987305, 0.000000, - 358.766602, 0.000000, 364.335938, 0.000000, 368.583984, 0.000000, 373.335938, 0.000000, - 375.351562, 0.000000, 380.126953, 0.000000, 383.545898, 0.000000, 389.150391, 0.000000, - 394.306641, 0.000000, 393.890625, 0.000000, 397.669922, 0.000000, 399.685547, 0.000000, - 404.548828, 0.000000, 404.425781, 0.000000, 409.177734, 0.000000, 411.193359, 0.000000, - 416.762695, 0.000000, 420.867188, 0.000000, 424.286133, 0.000000, 428.581055, 0.000000, - 432.708984, 0.000000, 438.123047, 0.000000, 437.748047, 0.000000, 443.027344, 0.000000, - 446.976562, 0.000000, 447.131836, 0.000000, 450.550781, 0.000000, 454.330078, 0.000000, - 459.095703, 0.000000, 459.729492, 0.000000, 463.148438, 0.000000, 468.667969, 0.000000, - 473.847656, 0.000000, 473.478516, 0.000000, 478.207031, 0.000000, 481.986328, 0.000000, - 486.761719, 0.000000, 492.281250, 0.000000, 497.320312, 0.000000, 500.739258, 0.000000, - 505.860352, 0.000000, 505.538086, 0.000000, 509.786133, 0.000000, 513.902344, 0.000000, - 515.917969, 0.000000, 520.669922, 0.000000, 523.947266, 0.000000, 524.917969, 0.000000, - 529.034180, 0.000000, 534.553711, 0.000000, 536.569336, 0.000000, 540.846680, 0.000000, - 541.968750, 0.000000, 547.488281, 0.000000, 551.592773, 0.000000, 555.887695, 0.000000, - 560.003906, 0.000000, 564.298828, 0.000000, 569.698242, 0.000000, 573.117188, 0.000000, - 576.896484, 0.000000, 582.500977, 0.000000, 587.241211, 0.000000, 590.660156, 0.000000, - 594.776367, 0.000000, 598.904297, 0.000000, 603.943359, 0.000000, 608.894531, 0.000000, - 608.683594, 0.000000 - - - - - - - - - ‭ﻲﺑﺮﻌﻟﺎﺑ - - - 0x0000FFFF, 0x00000206, 0x000001A5, 0x000001C2, 0x000001E0, 0x000001F3, 0x000001A2, 0x000001A5 - - - - 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007 - - - - 0.000000, 0.000000, 0.000000, 0.000000, 5.759766, 0.000000, 7.980469, 0.000000, - 11.748047, 0.000000, 15.298828, 0.000000, 17.302734, 0.000000, 19.763672, 0.000000, - 21.984375, 0.000000 - - - - - - - ﻲﺑﺮﻌﻟﺎﺑ - - - 0x000001A5, 0x000001A2, 0x000001F3, 0x000001E0, 0x000001C2, 0x000001A5, 0x00000206 - - - - 0x00000006, 0x00000005, 0x00000004, 0x00000003, 0x00000002, 0x00000001, 0x00000000 - - - - 0.000000, 0.000000, 2.220703, 0.000000, 4.681641, 0.000000, 6.685547, 0.000000, - 10.236328, 0.000000, 14.003906, 0.000000, 16.224609, 0.000000, 21.984375, 0.000000 - - - - - - - ḤḤ - - - 0x000009A3, 0x000009A3 - - - - 0x00000000, 0x00000001 - - - - 0.000000, 0.000000, 8.666016, 0.000000, 17.332031, 0.000000 - - - - - - - र्य र्‌य - - - 0x00000099, 0x0000005B, 0x0000FFFF, 0x00000003, 0x0000009A, 0x00000051, 0x00000001, 0x00000099 - - - - 0x00000002, 0x00000000, 0x00000001, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007 - - - - 0.000000, 0.000000, 9.726562, 0.263672, 9.468750, 0.000000, 9.468750, 0.000000, - 15.468750, 0.000000, 25.130859, -0.451172, 21.984375, 0.000000, 21.984375, 0.000000, - 31.453125, 0.000000 - - - - - - - - - - - Li kien kien, li kieku kieku. - - - 0x0000000D, 0x00000024, 0x00000001, 0x00000026, 0x00000024, 0x00000020, 0x00000029, 0x00000001, - 0x00000026, 0x00000024, 0x00000020, 0x00000029, 0x000001D0, 0x00000001, 0x00000027, 0x00000024, - 0x00000001, 0x00000026, 0x00000024, 0x00000020, 0x00000026, 0x00000030, 0x00000001, 0x00000026, - 0x00000024, 0x00000020, 0x00000026, 0x00000030, 0x000001CF - - - - 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007, - 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F, - 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000016, 0x00000017, - 0x00000018, 0x00000019, 0x0000001A, 0x0000001B, 0x0000001C - - - - 0.000000, 0.000000, 7.200000, 0.000000, 14.400000, 0.000000, 21.599998, 0.000000, - 28.799999, 0.000000, 36.000000, 0.000000, 43.200001, 0.000000, 50.400002, 0.000000, - 57.600002, 0.000000, 64.800003, 0.000000, 72.000000, 0.000000, 79.199997, 0.000000, - 86.399994, 0.000000, 93.599991, 0.000000, 100.799988, 0.000000, 107.999985, 0.000000, - 115.199982, 0.000000, 122.399979, 0.000000, 129.599976, 0.000000, 136.799973, 0.000000, - 143.999969, 0.000000, 151.199966, 0.000000, 158.399963, 0.000000, 165.599960, 0.000000, - 172.799957, 0.000000, 179.999954, 0.000000, 187.199951, 0.000000, 194.399948, 0.000000, - 201.599945, 0.000000, 208.799942, 0.000000 - - - - - - - Il-Mistoqsija oħt l-għerf. - - - 0x0000000A, 0x00000027, 0x00000210, 0x0000000E, 0x00000024, 0x0000002E, 0x0000002F, 0x0000002A, - 0x0000002C, 0x0000002E, 0x00000024, 0x00000025, 0x0000001C, 0x00000001, 0x0000002A, 0x0000011F, - 0x0000002F, 0x00000001, 0x00000027, 0x00000210, 0x00000022, 0x0000011F, 0x00000020, 0x0000002D, - 0x00000021, 0x000001FB - - - - 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007, - 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F, - 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000016, 0x00000017, - 0x00000018, 0x00000019 - - - - 0.000000, 0.000000, 3.096000, 0.000000, 6.156000, 0.000000, 9.888000, 0.000000, - 18.552000, 0.000000, 21.504000, 0.000000, 26.532000, 0.000000, 30.467999, 0.000000, - 36.972000, 0.000000, 43.571999, 0.000000, 48.599998, 0.000000, 51.551998, 0.000000, - 54.515999, 0.000000, 60.660000, 0.000000, 63.084000, 0.000000, 69.587997, 0.000000, - 76.115997, 0.000000, 80.171997, 0.000000, 82.596001, 0.000000, 85.655998, 0.000000, - 89.388000, 0.000000, 95.435997, 0.000000, 101.963997, 0.000000, 107.916000, 0.000000, - 112.080002, 0.000000, 114.984001, 0.000000, 117.972000, 0.000000 - - - - - - - ༄༅།། ཏིན་ཏིན་གྱི་དཔའ་རྩལ - - - 0x00000145, 0x0000FFFF, 0x00000151, 0x00000151, 0x00000003, 0x0000046C, 0x00000BFD, 0x0000059A, - 0x0000014E, 0x0000046C, 0x00000BFD, 0x0000059A, 0x0000014E, 0x000002CA, 0x0000FFFF, 0x00000BFD, - 0x0000014E, 0x0000050E, 0x00000611, 0x00000848, 0x0000014E, 0x0000093C, 0x0000FFFF, 0x0000098B - - - - 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007, - 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F, - 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000016, 0x00000017 - - - - 0.000000, 0.000000, 14.906250, 0.000000, 14.906250, 0.000000, 17.648438, 0.000000, - 20.390625, 0.000000, 23.906250, 0.000000, 29.109375, 0.000000, 29.109375, 0.000000, - 34.171875, 0.000000, 35.929688, 0.000000, 41.132812, 0.000000, 41.132812, 0.000000, - 46.195312, 0.000000, 47.953125, 0.000000, 54.773438, 0.000000, 54.773438, 0.000000, - 54.773438, 0.000000, 56.531250, 0.000000, 61.875000, 0.000000, 67.570312, 0.000000, - 73.195312, 0.000000, 74.953125, 0.000000, 80.437500, 0.000000, 80.437500, 0.000000, - 87.328125, 0.000000 - - - - - - - ᄊᆞᆷ ᄒᆞᆫ글 ᄀᆞᇹ ᄫᆞᆼ - - - 0x000044FF, 0x00004707, 0x00004859, 0x00000005, 0x0000462B, 0x00004707, 0x00004785, 0x000019B2, - 0x00000005, 0x00004361, 0x00004707, 0x0000498D, 0x00000005, 0x000044C3, 0x00004707, 0x00004911 - - - - 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007, - 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F - - - - 0.000000, 0.000000, 12.000000, 0.000000, 12.000000, 0.000000, 12.000000, 0.000000, - 14.700000, 0.000000, 26.700001, 0.000000, 26.700001, 0.000000, 26.700001, 0.000000, - 38.700001, 0.000000, 41.400002, 0.000000, 53.400002, 0.000000, 53.400002, 0.000000, - 53.400002, 0.000000, 56.100002, 0.000000, 68.100006, 0.000000, 68.100006, 0.000000, - 68.100006, 0.000000 - - - - - - - के े - - - 0x00000901, 0x00000931, 0x00000003, 0x00000956, 0x00000931 - - - - 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000003 - - - - 0.000000, 0.000000, 5.935547, 0.000000, 8.548828, 0.000000, 12.345703, 0.000000, - 17.085938, 0.000000, 18.345703, 0.000000 - - - - - - - - अँग्रेज़ी - - - 0x000008F1, 0x000008EE, 0x000009CB, 0x0000FFFF, 0x0000FFFF, 0x00000931, 0x00000940, 0x0000FFFF, - 0x0000092A - - - - 0x00000000, 0x00000001, 0x00000002, 0x00000004, 0x00000003, 0x00000005, 0x00000006, 0x00000007, - 0x00000008 - - - - 0.000000, 0.000000, 9.076172, 0.000000, 9.076172, 0.000000, 16.025391, 0.000000, - 16.025391, 0.000000, 16.025391, 0.000000, 16.025391, 0.000000, 23.976562, 0.000000, - 23.976562, 0.000000, 27.304688, 0.000000 - - - - diff --git a/test/jdk/java/awt/image/XBMDecoder/XBMDecoderTest.java b/test/jdk/java/awt/image/XBMDecoder/XBMDecoderTest.java new file mode 100644 index 00000000000..9694043d1bb --- /dev/null +++ b/test/jdk/java/awt/image/XBMDecoder/XBMDecoderTest.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8361748 + * @summary Tests XBM image size limits and if XBMImageDecoder.produceImage() + * throws appropriate error when parsing invalid XBM image data. + * @run main XBMDecoderTest + */ + +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.PrintStream; +import java.util.Arrays; +import javax.swing.ImageIcon; + +public class XBMDecoderTest { + + public static void main(String[] args) throws Exception { + String dir = System.getProperty("test.src"); + PrintStream originalErr = System.err; + boolean validCase; + + File currentDir = new File(dir); + File[] files = currentDir.listFiles((File d, String s) + -> s.endsWith(".xbm")); + + for (File file : files) { + String fileName = file.getName(); + validCase = fileName.startsWith("valid"); + + System.out.println("--- Testing " + fileName + " ---"); + try (FileInputStream fis = new FileInputStream(file); + ByteArrayOutputStream errContent = new ByteArrayOutputStream()) { + System.setErr(new PrintStream(errContent)); + + ImageIcon icon = new ImageIcon(fis.readAllBytes()); + boolean isErrEmpty = errContent.toString().isEmpty(); + + if (!isErrEmpty) { + System.out.println("Expected ImageFormatException occurred."); + System.out.print(errContent); + } + if (validCase && !isErrEmpty) { + throw new RuntimeException("Test failed: Error stream not empty"); + } else if (!validCase && isErrEmpty && hasPixelData(icon.getImage())) { + throw new RuntimeException("Test failed: ImageFormatException" + + " expected but not thrown"); + } + if (validCase && !hasPixelData(icon.getImage())) { + throw new RuntimeException("Test failed: the parsed image " + + "does not contain any pixel data"); + } + System.out.println("PASSED\n"); + } finally { + System.setErr(originalErr); + } + } + } + + private static boolean hasPixelData(Image img) { + int w = img.getWidth(null); + int h = img.getHeight(null); + BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = bi.createGraphics(); + g.drawImage(img, 0, 0, null); + g.dispose(); + int[] pixels = bi.getRGB(0, 0, w, h, null, 0, w); + if (Arrays.stream(pixels).allMatch(i -> i == 0)) { + return false; + } + return true; + } +} diff --git a/test/jdk/java/awt/image/XBMDecoder/invalid.xbm b/test/jdk/java/awt/image/XBMDecoder/invalid.xbm new file mode 100644 index 00000000000..8a8cfc27632 --- /dev/null +++ b/test/jdk/java/awt/image/XBMDecoder/invalid.xbm @@ -0,0 +1,2 @@ +#define k_ht 3 +h` k[] = { 01x0, 42222222222236319330:: diff --git a/test/jdk/java/awt/image/XBMDecoder/invalid_empty.xbm b/test/jdk/java/awt/image/XBMDecoder/invalid_empty.xbm new file mode 100644 index 00000000000..5cfb8e21cf8 --- /dev/null +++ b/test/jdk/java/awt/image/XBMDecoder/invalid_empty.xbm @@ -0,0 +1,6 @@ +#define test_width 16 +#define test_height 3 +#define ht_x 1 +#define ht_y 2 +static unsigned char test_bits[] = { +}; diff --git a/test/jdk/java/awt/image/XBMDecoder/invalid_hex.xbm b/test/jdk/java/awt/image/XBMDecoder/invalid_hex.xbm new file mode 100644 index 00000000000..1286eee1d9b --- /dev/null +++ b/test/jdk/java/awt/image/XBMDecoder/invalid_hex.xbm @@ -0,0 +1,3 @@ +#define k_width 16 +#define k_height 1 +k[] = { 0x10, 1234567890}; diff --git a/test/jdk/java/awt/image/XBMDecoder/invalid_ht.xbm b/test/jdk/java/awt/image/XBMDecoder/invalid_ht.xbm new file mode 100644 index 00000000000..5244651a4cb --- /dev/null +++ b/test/jdk/java/awt/image/XBMDecoder/invalid_ht.xbm @@ -0,0 +1,3 @@ +#define k_wt 16 +#define k_ht 0 +k[] = { 0x10, 0x12}; diff --git a/test/jdk/java/awt/image/XBMDecoder/invalid_plus.xbm b/test/jdk/java/awt/image/XBMDecoder/invalid_plus.xbm new file mode 100644 index 00000000000..714907084f2 --- /dev/null +++ b/test/jdk/java/awt/image/XBMDecoder/invalid_plus.xbm @@ -0,0 +1,3 @@ +#define test_width 16 +#define test_height 2 +static unsigned char test_bits[] = { 0x13, 0x11, 0xAB+, 0xff }; \ No newline at end of file diff --git a/test/jdk/java/awt/image/XBMDecoder/valid.xbm b/test/jdk/java/awt/image/XBMDecoder/valid.xbm new file mode 100644 index 00000000000..23b57b2c811 --- /dev/null +++ b/test/jdk/java/awt/image/XBMDecoder/valid.xbm @@ -0,0 +1,6 @@ +#define test_width 16 +#define test_height 3 +#define ht_x 1 +#define ht_y 2 +static unsigned char test_bits[] = { +0x13, 0x11, 0x15, 0x00, 0xAB, 0xcd }; diff --git a/test/jdk/java/awt/image/XBMDecoder/valid_hex.xbm b/test/jdk/java/awt/image/XBMDecoder/valid_hex.xbm new file mode 100644 index 00000000000..e365d802447 --- /dev/null +++ b/test/jdk/java/awt/image/XBMDecoder/valid_hex.xbm @@ -0,0 +1,4 @@ +#define test_width 16 +#define test_height 2 +static unsigned char test_bits[] = { 0x13, 0x11, + 0xAB, 0xff }; diff --git a/test/jdk/java/awt/image/XBMDecoder/valid_multiline.xbm b/test/jdk/java/awt/image/XBMDecoder/valid_multiline.xbm new file mode 100644 index 00000000000..e24bc10e9b0 --- /dev/null +++ b/test/jdk/java/awt/image/XBMDecoder/valid_multiline.xbm @@ -0,0 +1,8 @@ +#define test_width 16 +#define test_height 3 +#define ht_x 1 +#define ht_y 2 +static unsigned char test_bits[] = { +0x20, 0x10, +0x25, 0x01, +0xAC, 0xab }; diff --git a/test/jdk/java/awt/print/Dialog/DialogType.java b/test/jdk/java/awt/print/Dialog/DialogType.java index 472b89e44f2..b8801583dd0 100644 --- a/test/jdk/java/awt/print/Dialog/DialogType.java +++ b/test/jdk/java/awt/print/Dialog/DialogType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 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 @@ -26,49 +26,63 @@ * @bug 6568874 * @key printer * @summary Verify the native dialog works with attribute sets. - * @run main/manual=yesno DialogType + * @library /java/awt/regtesthelpers /test/lib + * @build PassFailJFrame + * @run main/manual DialogType */ -import java.awt.print.*; -import javax.print.attribute.*; -import javax.print.attribute.standard.*; +import java.awt.print.PrinterJob; + +import javax.print.attribute.Attribute; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.PrintRequestAttributeSet; +import javax.print.attribute.standard.DialogTypeSelection; + +import jtreg.SkippedException; public class DialogType { + private static PrinterJob job; + + private static final String INSTRUCTIONS = """ + Two print dialogs are shown in succession. + Click Cancel in the dialogs to close them. + + On macOS & on Windows, the first dialog is a native + dialog provided by the OS, the second dialog is + implemented in Swing, the dialogs differ in appearance. - static String[] instructions = { - "This test assumes and requires that you have a printer installed", - "It verifies that the dialogs behave properly when using new API", - "to optionally select a native dialog where one is present.", - "Two dialogs are shown in succession.", - "The test passes as long as no exceptions are thrown, *AND*", - "if running on Windows only, the first dialog is a native windows", - "control which differs in appearance from the second dialog", - "" - }; + The test passes as long as no exceptions are thrown. + (If there's an exception, the test will fail automatically.) - public static void main(String[] args) { + The test verifies that the dialogs behave properly when using new API + to optionally select a native dialog where one is present. + """; - for (int i=0;i"}, the * instructions are displayed as HTML, as supported by Swing, which - * provides richer formatting options. + * provides richer formatting options. To handle navigating links in the + * instructions, call {@link Builder#hyperlinkListener} to install a listener. *

    * The instructions are displayed in a text component with word-wrapping * so that there's no horizontal scroll bar. If the text doesn't fit, a @@ -592,6 +594,7 @@ private static void createUI(String title, String instructions, frame.add(createInstructionUIPanel(instructions, testTimeOut, rows, columns, + null, false, false, 0), BorderLayout.CENTER); @@ -610,6 +613,7 @@ private static void createUI(Builder builder) { createInstructionUIPanel(builder.instructions, builder.testTimeOut, builder.rows, builder.columns, + builder.hyperlinkListener, builder.screenCapture, builder.addLogArea, builder.logAreaRows); @@ -631,6 +635,7 @@ private static void createUI(Builder builder) { private static JComponent createInstructionUIPanel(String instructions, long testTimeOut, int rows, int columns, + HyperlinkListener hyperlinkListener, boolean enableScreenCapture, boolean addLogArea, int logAreaRows) { @@ -643,6 +648,9 @@ private static JComponent createInstructionUIPanel(String instructions, JTextComponent text = instructions.startsWith("") ? configureHTML(instructions, rows, columns) : configurePlainText(instructions, rows, columns); + if (hyperlinkListener != null && text instanceof JEditorPane ep) { + ep.addHyperlinkListener(hyperlinkListener); + } text.setEditable(false); text.setBorder(createTextBorder()); text.setCaretPosition(0); @@ -716,7 +724,7 @@ private static JTextComponent configureHTML(String instructions, // Reduce the list default margins styles.addRule("ol, ul { margin-left-ltr: 30; margin-left-rtl: 30 }"); // Make the size of code (and other elements) the same as other text - styles.addRule("code, kbd, samp, pre { font-size: inherit }"); + styles.addRule("code, kbd, samp, pre { font-size: inherit; background: #DDD; }"); return text; } @@ -1398,6 +1406,7 @@ public static final class Builder { private int rows; private int columns; private boolean screenCapture; + private HyperlinkListener hyperlinkListener; private boolean addLogArea; private int logAreaRows = 10; @@ -1478,6 +1487,18 @@ public Builder columns(int columns) { return this; } + /** + * Sets a {@link HyperlinkListener} for navigating links inside + * the instructions pane. + * + * @param hyperlinkListener the listener + * @return this builder + */ + public Builder hyperlinkListener(HyperlinkListener hyperlinkListener) { + this.hyperlinkListener = hyperlinkListener; + return this; + } + public Builder screenCapture() { this.screenCapture = true; return this; diff --git a/test/jdk/java/foreign/TestUpcallStructScope.java b/test/jdk/java/foreign/TestUpcallStructScope.java index 14809139dff..d9729cb8f3b 100644 --- a/test/jdk/java/foreign/TestUpcallStructScope.java +++ b/test/jdk/java/foreign/TestUpcallStructScope.java @@ -43,13 +43,18 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.BiConsumer; import java.util.function.Consumer; import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.assertEquals; public class TestUpcallStructScope extends NativeTestHelper { static final MethodHandle MH_do_upcall; + static final MethodHandle MH_do_upcall_ptr; static final MethodHandle MH_Consumer_accept; + static final MethodHandle MH_BiConsumer_accept; static { System.loadLibrary("TestUpcallStructScope"); @@ -57,17 +62,29 @@ public class TestUpcallStructScope extends NativeTestHelper { findNativeOrThrow("do_upcall"), FunctionDescriptor.ofVoid(C_POINTER, S_PDI_LAYOUT) ); + MH_do_upcall_ptr = LINKER.downcallHandle( + findNativeOrThrow("do_upcall_ptr"), + FunctionDescriptor.ofVoid(C_POINTER, S_PDI_LAYOUT, C_POINTER) + ); try { MH_Consumer_accept = MethodHandles.publicLookup().findVirtual(Consumer.class, "accept", MethodType.methodType(void.class, Object.class)); + MH_BiConsumer_accept = MethodHandles.publicLookup().findVirtual(BiConsumer.class, "accept", + MethodType.methodType(void.class, Object.class, Object.class)); } catch (NoSuchMethodException | IllegalAccessException e) { throw new RuntimeException(e); } } - private static MethodHandle methodHandle (Consumer callback) { - return MH_Consumer_accept.bindTo(callback).asType(MethodType.methodType(void.class, MemorySegment.class)); + private static MethodHandle methodHandle(Consumer callback) { + return MH_Consumer_accept.bindTo(callback) + .asType(MethodType.methodType(void.class, MemorySegment.class)); + } + + private static MethodHandle methodHandle(BiConsumer callback) { + return MH_BiConsumer_accept.bindTo(callback) + .asType(MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class)); } @Test @@ -85,4 +102,22 @@ public void testUpcall() throws Throwable { assertFalse(captured.scope().isAlive()); } + @Test + public void testOtherPointer() throws Throwable { + AtomicReference capturedSegment = new AtomicReference<>(); + MethodHandle target = methodHandle((_, addr) -> capturedSegment.set(addr)); + FunctionDescriptor upcallDesc = FunctionDescriptor.ofVoid(S_PDI_LAYOUT, C_POINTER); + MemorySegment argAddr = MemorySegment.ofAddress(42); + try (Arena arena = Arena.ofConfined()) { + MemorySegment upcallStub = LINKER.upcallStub(target, upcallDesc, arena); + MemorySegment argSegment = arena.allocate(S_PDI_LAYOUT); + MH_do_upcall_ptr.invoke(upcallStub, argSegment, argAddr); + } + + // We've captured the address '42' from the upcall. This should have + // the global scope, so it should still be alive here. + MemorySegment captured = capturedSegment.get(); + assertEquals(argAddr, captured); + assertTrue(captured.scope().isAlive()); + } } diff --git a/test/jdk/java/foreign/libTestUpcallStructScope.c b/test/jdk/java/foreign/libTestUpcallStructScope.c index e778133b496..e18543d5b1a 100644 --- a/test/jdk/java/foreign/libTestUpcallStructScope.c +++ b/test/jdk/java/foreign/libTestUpcallStructScope.c @@ -28,3 +28,7 @@ struct S_PDI { void* p0; double p1; int p2; }; EXPORT void do_upcall(void (*cb)(struct S_PDI), struct S_PDI a0) { cb(a0); } + +EXPORT void do_upcall_ptr(void (*cb)(struct S_PDI, void*), struct S_PDI a0, void* ptr) { + cb(a0, ptr); +} diff --git a/test/jdk/java/io/Console/DefaultCharsetTest.java b/test/jdk/java/io/Console/DefaultCharsetTest.java index 0fca8a3cc3f..981d92ce282 100644 --- a/test/jdk/java/io/Console/DefaultCharsetTest.java +++ b/test/jdk/java/io/Console/DefaultCharsetTest.java @@ -21,33 +21,66 @@ * questions. */ -import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import java.nio.file.Files; +import java.nio.file.Paths; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static jdk.test.lib.Utils.*; /** * @test - * @bug 8341975 8351435 + * @bug 8341975 8351435 8361613 * @summary Tests the default charset. It should honor `stdout.encoding` * which should be the same as System.out.charset() - * @modules jdk.internal.le - * @run junit/othervm -Djdk.console=jdk.internal.le -Dstdout.encoding=UTF-8 DefaultCharsetTest - * @run junit/othervm -Djdk.console=jdk.internal.le -Dstdout.encoding=ISO-8859-1 DefaultCharsetTest - * @run junit/othervm -Djdk.console=jdk.internal.le -Dstdout.encoding=US-ASCII DefaultCharsetTest - * @run junit/othervm -Djdk.console=jdk.internal.le -Dstdout.encoding=foo DefaultCharsetTest - * @run junit/othervm -Djdk.console=jdk.internal.le DefaultCharsetTest + * @requires (os.family == "linux") | (os.family == "mac") + * @library /test/lib + * @build jdk.test.lib.Utils + * jdk.test.lib.JDKToolFinder + * jdk.test.lib.process.ProcessTools + * @run junit DefaultCharsetTest */ public class DefaultCharsetTest { - @Test - public void testDefaultCharset() { + @BeforeAll + static void checkExpectAvailability() { + // check "expect" command availability + var expect = Paths.get("/usr/bin/expect"); + Assumptions.assumeTrue(Files.exists(expect) && Files.isExecutable(expect), + "'" + expect + "' not found. Test ignored."); + } + @ParameterizedTest + @ValueSource(strings = {"UTF-8", "ISO-8859-1", "US-ASCII", "foo", ""}) + void testDefaultCharset(String stdoutEncoding) throws Exception { + // invoking "expect" command + OutputAnalyzer oa = ProcessTools.executeProcess( + "expect", + "-n", + TEST_SRC + "/defaultCharset.exp", + TEST_CLASSES, + TEST_JDK + "/bin/java", + "-Dstdout.encoding=" + stdoutEncoding, + getClass().getName()); + oa.reportDiagnosticSummary(); + oa.shouldHaveExitValue(0); + } + + public static void main(String... args) { var stdoutEncoding = System.getProperty("stdout.encoding"); var sysoutCharset = System.out.charset(); var consoleCharset = System.console().charset(); - System.out.println(""" - stdout.encoding = %s - System.out.charset() = %s - System.console().charset() = %s - """.formatted(stdoutEncoding, sysoutCharset.name(), consoleCharset.name())); - assertEquals(consoleCharset, sysoutCharset, - "Charsets for System.out and Console differ for stdout.encoding: %s".formatted(stdoutEncoding)); + System.out.printf(""" + stdout.encoding = %s + System.out.charset() = %s + System.console().charset() = %s + """, stdoutEncoding, sysoutCharset.name(), consoleCharset.name()); + if (!consoleCharset.equals(sysoutCharset)) { + System.err.printf("Charsets for System.out and Console differ for stdout.encoding: %s%n", stdoutEncoding); + System.exit(-1); + } } } diff --git a/test/jdk/java/io/Console/LocaleTest.java b/test/jdk/java/io/Console/LocaleTest.java index 1cab84a9af7..e9a281749b1 100644 --- a/test/jdk/java/io/Console/LocaleTest.java +++ b/test/jdk/java/io/Console/LocaleTest.java @@ -21,28 +21,40 @@ * questions. */ -import java.io.File; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.List; import java.util.Locale; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.function.Predicate; +import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.Test; + +import static jdk.test.lib.Utils.*; /** * @test - * @bug 8330276 8351435 + * @bug 8330276 8351435 8361613 * @summary Tests Console methods that have Locale as an argument + * @requires (os.family == "linux") | (os.family == "mac") * @library /test/lib - * @modules jdk.internal.le jdk.localedata + * @build jdk.test.lib.Utils + * jdk.test.lib.JDKToolFinder + * jdk.test.lib.process.ProcessTools + * @modules jdk.localedata + * @run junit LocaleTest */ public class LocaleTest { - private static Calendar TODAY = new GregorianCalendar(2024, Calendar.APRIL, 22); - private static String FORMAT = "%1$tY-%1$tB-%1$te %1$tA"; + private static final Calendar TODAY = new GregorianCalendar(2024, Calendar.APRIL, 22); + private static final String FORMAT = "%1$tY-%1$tB-%1$te %1$tA"; // We want to limit the expected strings within US-ASCII charset, as // the native encoding is determined as such, which is used by // the `Process` class under jtreg environment. - private static List EXPECTED = List.of( + private static final List EXPECTED = List.of( String.format(Locale.UK, FORMAT, TODAY), String.format(Locale.FRANCE, FORMAT, TODAY), String.format(Locale.GERMANY, FORMAT, TODAY), @@ -53,56 +65,61 @@ public class LocaleTest { String.format((Locale)null, FORMAT, TODAY) ); - public static void main(String... args) throws Throwable { - if (args.length == 0) { - // no arg will launch the child process that actually perform tests - var pb = ProcessTools.createTestJavaProcessBuilder( - "-Djdk.console=jdk.internal.le", - "LocaleTest", "dummy"); - var input = new File(System.getProperty("test.src", "."), "input.txt"); - pb.redirectInput(input); - var oa = ProcessTools.executeProcess(pb); - if (oa.getExitValue() == -1) { - System.out.println("System.console() returns null. Ignoring the test."); - } else { - var output = oa.asLines(); - var resultText = - """ - Actual output: %s - Expected output: %s - """.formatted(output, EXPECTED); - if (!output.equals(EXPECTED)) { - throw new RuntimeException("Standard out had unexpected strings:\n" + resultText); - } else { - oa.shouldHaveExitValue(0); - System.out.println("Formatting with explicit Locale succeeded.\n" + resultText); - } - } + @Test + void testLocale() throws Exception { + // check "expect" command availability + var expect = Paths.get("/usr/bin/expect"); + Assumptions.assumeTrue(Files.exists(expect) && Files.isExecutable(expect), + "'" + expect + "' not found. Test ignored."); + + // invoking "expect" command + OutputAnalyzer oa = ProcessTools.executeProcess( + "expect", + "-n", + TEST_SRC + "/locale.exp", + TEST_CLASSES, + TEST_JDK + "/bin/java", + getClass().getName()); + + var stdout = + oa.stdoutAsLines().stream().filter(Predicate.not(String::isEmpty)).toList(); + var resultText = + """ + Actual output: %s + Expected output: %s + """.formatted(stdout, EXPECTED); + if (!stdout.equals(EXPECTED)) { + throw new RuntimeException("Standard out had unexpected strings:\n" + resultText); } else { - var con = System.console(); - if (con != null) { - // tests these additional methods that take a Locale - con.format(Locale.UK, FORMAT, TODAY); - con.printf("\n"); - con.printf(Locale.FRANCE, FORMAT, TODAY); - con.printf("\n"); - con.readLine(Locale.GERMANY, FORMAT, TODAY); - con.printf("\n"); - con.readPassword(Locale.of("es"), FORMAT, TODAY); - con.printf("\n"); + oa.shouldHaveExitValue(0); + System.out.println("Formatting with explicit Locale succeeded.\n" + resultText); + } + } + + public static void main(String... args) throws Throwable { + var con = System.console(); + if (con != null) { + // tests these additional methods that take a Locale + con.format(Locale.UK, FORMAT, TODAY); + con.printf("\n"); + con.printf(Locale.FRANCE, FORMAT, TODAY); + con.printf("\n"); + con.readLine(Locale.GERMANY, FORMAT, TODAY); + con.printf("\n"); + con.readPassword(Locale.of("es"), FORMAT, TODAY); + con.printf("\n"); - // tests null locale - con.format((Locale)null, FORMAT, TODAY); - con.printf("\n"); - con.printf((Locale)null, FORMAT, TODAY); - con.printf("\n"); - con.readLine((Locale)null, FORMAT, TODAY); - con.printf("\n"); - con.readPassword((Locale)null, FORMAT, TODAY); - } else { - // Exit with -1 - System.exit(-1); - } + // tests null locale + con.format((Locale)null, FORMAT, TODAY); + con.printf("\n"); + con.printf((Locale)null, FORMAT, TODAY); + con.printf("\n"); + con.readLine((Locale)null, FORMAT, TODAY); + con.printf("\n"); + con.readPassword((Locale)null, FORMAT, TODAY); + } else { + // Exit with -1 + System.exit(-1); } } } diff --git a/test/jdk/java/io/Console/ModuleSelectionTest.java b/test/jdk/java/io/Console/ModuleSelectionTest.java index d9885699ebf..f5f02ae13f4 100644 --- a/test/jdk/java/io/Console/ModuleSelectionTest.java +++ b/test/jdk/java/io/Console/ModuleSelectionTest.java @@ -21,38 +21,88 @@ * questions. */ -/** +/* * @test - * @bug 8295803 8299689 8351435 + * @bug 8295803 8299689 8351435 8361613 8366261 * @summary Tests System.console() returns correct Console (or null) from the expected * module. - * @modules java.base/java.io:+open - * @run main/othervm ModuleSelectionTest java.base - * @run main/othervm -Djdk.console=jdk.internal.le ModuleSelectionTest jdk.internal.le - * @run main/othervm -Djdk.console=java.base ModuleSelectionTest java.base - * @run main/othervm --limit-modules java.base ModuleSelectionTest java.base + * @library /test/lib + * @build jdk.test.lib.Utils + * jdk.test.lib.process.ProcessTools + * @run junit ModuleSelectionTest */ import java.io.Console; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.stream.Stream; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import static jdk.test.lib.Utils.*; public class ModuleSelectionTest { + private static Stream options() { + return Stream.of( + Arguments.of("-Djdk.console=foo", "java.base"), + Arguments.of("-Djdk.console=java.base", "java.base"), + Arguments.of("-Djdk.console=jdk.internal.le", "jdk.internal.le"), + Arguments.of("--limit-modules java.base", "java.base") + ); + } + + @ParameterizedTest + @MethodSource("options") + void testNonTTY(String opts) throws Exception { + opts = opts + + " --add-opens java.base/java.io=ALL-UNNAMED ModuleSelectionTest null"; + OutputAnalyzer output = ProcessTools.executeTestJava(opts.split(" ")); + output.reportDiagnosticSummary(); + output.shouldHaveExitValue(0); + } + + @ParameterizedTest + @MethodSource("options") + void testTTY(String opts, String expected) throws Exception { + // check "expect" command availability + var expect = Paths.get("/usr/bin/expect"); + Assumptions.assumeTrue(Files.exists(expect) && Files.isExecutable(expect), + "'" + expect + "' not found. Test ignored."); + + opts = "expect -n " + TEST_SRC + "/moduleSelection.exp " + + TEST_CLASSES + " " + + expected + " " + + TEST_JDK + "/bin/java" + + " --add-opens java.base/java.io=ALL-UNNAMED " + + opts; + // invoking "expect" command + OutputAnalyzer output = ProcessTools.executeProcess(opts.split(" ")); + output.reportDiagnosticSummary(); + output.shouldHaveExitValue(0); + } + public static void main(String... args) throws Throwable { var con = System.console(); var pc = Class.forName("java.io.ProxyingConsole"); var jdkc = Class.forName("jdk.internal.io.JdkConsole"); - var istty = (boolean)MethodHandles.privateLookupIn(Console.class, MethodHandles.lookup()) - .findStatic(Console.class, "istty", MethodType.methodType(boolean.class)) - .invoke(); + var lookup = MethodHandles.privateLookupIn(Console.class, MethodHandles.lookup()); + var istty = (boolean)lookup.findStatic(Console.class, "isStdinTty", MethodType.methodType(boolean.class)) + .invoke() && + (boolean)lookup.findStatic(Console.class, "isStdoutTty", MethodType.methodType(boolean.class)) + .invoke(); + var impl = con != null ? MethodHandles.privateLookupIn(pc, MethodHandles.lookup()) .findGetter(pc, "delegate", jdkc) .invoke(con) : null; - var expected = switch (args[0]) { - case "java.base" -> istty ? "java.base" : "null"; - default -> args[0]; - }; + var expected = args[0]; var actual = con == null ? "null" : impl.getClass().getModule().getName(); if (!actual.equals(expected)) { @@ -62,7 +112,7 @@ public static void main(String... args) throws Throwable { Actual: %s """.formatted(expected, actual)); } else { - System.out.printf("%s is the expected implementation. (tty: %s)\n", impl, istty); + System.out.printf("%s is the expected implementation. (tty: %s)\n", actual, istty); } } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/TEST.properties b/test/jdk/java/io/Console/defaultCharset.exp similarity index 73% rename from test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/TEST.properties rename to test/jdk/java/io/Console/defaultCharset.exp index 8b51b2a9115..5b1418db28c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/TEST.properties +++ b/test/jdk/java/io/Console/defaultCharset.exp @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -21,4 +21,12 @@ # questions. # -exclusiveAccess.dirs=. +# simply invoking java under expect command +set classpath [lrange $argv 0 0] +set java [lrange $argv 1 1] +set stdoutProp [lrange $argv 2 2] +set clsname [lrange $argv 3 3] +eval spawn $java -classpath $classpath $stdoutProp $clsname +expect eof +set result [wait] +exit [lindex $result 3] diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/TEST.properties b/test/jdk/java/io/Console/locale.exp similarity index 70% rename from test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/TEST.properties rename to test/jdk/java/io/Console/locale.exp index 8b51b2a9115..a88ea43feac 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/TEST.properties +++ b/test/jdk/java/io/Console/locale.exp @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -21,4 +21,17 @@ # questions. # -exclusiveAccess.dirs=. +# simply invoking java under expect command +set classpath [lrange $argv 0 0] +set java [lrange $argv 1 1] +set clsname [lrange $argv 2 2] +eval spawn -noecho $java -classpath $classpath $clsname + +# sends CR 4 times (readLine x 2, readPassword x 2) +send "\r" +send "\r" +send "\r" +send "\r" +expect eof +set result [wait] +exit [lindex $result 3] diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach020/TEST.properties b/test/jdk/java/io/Console/moduleSelection.exp similarity index 75% rename from test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach020/TEST.properties rename to test/jdk/java/io/Console/moduleSelection.exp index 8b51b2a9115..2b44afe72e4 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach020/TEST.properties +++ b/test/jdk/java/io/Console/moduleSelection.exp @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -21,4 +21,10 @@ # questions. # -exclusiveAccess.dirs=. +# simply invoking java under expect command +set classpath [lrange $argv 0 0] +set expected [lrange $argv 1 1] +set java [lrange $argv 2 2] +set opts [lrange $argv 3 end] +eval spawn $java $opts -classpath $classpath ModuleSelectionTest $expected +expect eof diff --git a/test/jdk/java/io/File/MaxPath.java b/test/jdk/java/io/File/MaxPath.java index 269b291709c..30951ac0d85 100644 --- a/test/jdk/java/io/File/MaxPath.java +++ b/test/jdk/java/io/File/MaxPath.java @@ -24,21 +24,14 @@ /* @test @bug 6481955 @summary Path length less than MAX_PATH (260) works on Windows - @library /test/lib + @requires (os.family == "windows") */ import java.io.File; import java.io.IOException; -import jtreg.SkippedException; - public class MaxPath { public static void main(String[] args) throws Exception { - String osName = System.getProperty("os.name"); - if (!osName.startsWith("Windows")) { - throw new SkippedException("This test is run only on Windows"); - } - int MAX_PATH = 260; String dir = new File(".").getAbsolutePath() + "\\"; String padding = "1234567890123456789012345678901234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890"; diff --git a/test/jdk/java/io/File/MaxPathLength.java b/test/jdk/java/io/File/MaxPathLength.java index 0e0b099afd9..02b60f124d1 100644 --- a/test/jdk/java/io/File/MaxPathLength.java +++ b/test/jdk/java/io/File/MaxPathLength.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, 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 @@ -24,30 +24,31 @@ /* @test @bug 4759207 4403166 4165006 4403166 6182812 6274272 7160013 @summary Test to see if win32 path length can be greater than 260 + @library .. /test/lib */ import java.io.*; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.DirectoryNotEmptyException; +import jdk.test.lib.Platform; public class MaxPathLength { private static String sep = File.separator; private static String pathComponent = sep + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; private static String fileName = - "areallylongfilenamethatsforsur"; - private static boolean isWindows = false; + "areallylongfilenamethatsforsur"; private static final int MAX_LENGTH = 256; + private static final int FILE_EXISTS_SLEEP = 100; + + private static final int MAX_PATH_COMPONENTS_WINDOWS = 20; + private static int counter = 0; public static void main(String[] args) throws Exception { - String osName = System.getProperty("os.name"); - if (osName.startsWith("Windows")) { - isWindows = true; - } for (int i = 4; i < 7; i++) { String name = fileName; @@ -59,14 +60,9 @@ public static void main(String[] args) throws Exception { } // test long paths on windows - // And these long pathes cannot be handled on Solaris and Mac platforms - if (isWindows) { - String name = fileName; - while (name.length() < MAX_LENGTH) { - testLongPath (20, name, false); - testLongPath (20, name, true); - name = getNextName(name); - } + // And these long paths cannot be handled on Linux and Mac platforms + if (Platform.isWindows()) { + testLongPath(); } } @@ -146,7 +142,7 @@ static void testLongPath(int max, String fn, if (flist == null || !fn.equals(flist[0].getName())) throw new RuntimeException ("File.listFiles() failed"); - if (isWindows && + if (Platform.isWindows() && !fu.getCanonicalPath().equals(f.getCanonicalPath())) throw new RuntimeException ("getCanonicalPath() failed"); @@ -162,7 +158,7 @@ static void testLongPath(int max, String fn, String abPath = f.getAbsolutePath(); if (!abPath.startsWith("\\\\") || abPath.length() < 1093) { - throw new RuntimeException ("File.renameTo() failed for lenth=" + throw new RuntimeException ("File.renameTo() failed for length=" + abPath.length()); } } else { @@ -189,7 +185,7 @@ static void testLongPath(int max, String fn, Files.deleteIfExists(p); // Test if the file is really deleted and wait for 1 second at most for (int j = 0; j < 10 && Files.exists(p); j++) { - Thread.sleep(100); + Thread.sleep(FILE_EXISTS_SLEEP); } } catch (DirectoryNotEmptyException ex) { // Give up the clean-up, let jtreg handle it. @@ -199,4 +195,13 @@ static void testLongPath(int max, String fn, } } } -} + + private static void testLongPath () throws Exception { + String name = fileName; + while (name.length() < MAX_LENGTH) { + testLongPath(MAX_PATH_COMPONENTS_WINDOWS, name, false); + testLongPath(MAX_PATH_COMPONENTS_WINDOWS, name, true); + name = getNextName(name); + } + } +} \ No newline at end of file diff --git a/test/jdk/java/io/File/SymLinks.java b/test/jdk/java/io/File/SymLinks.java index 967250c8430..40205a41557 100644 --- a/test/jdk/java/io/File/SymLinks.java +++ b/test/jdk/java/io/File/SymLinks.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -281,22 +281,7 @@ static void go() throws IOException { assertTrue(link2dir.isDirectory()); assertTrue(link2link2dir.isDirectory()); - // on Windows we test with the DOS hidden attribute set - if (System.getProperty("os.name").startsWith("Windows")) { - DosFileAttributeView view = Files - .getFileAttributeView(file.toPath(), DosFileAttributeView.class); - view.setHidden(true); - try { - assertTrue(file.isHidden()); - assertTrue(link2file.isHidden()); - assertTrue(link2link2file.isHidden()); - } finally { - view.setHidden(false); - } - assertFalse(file.isHidden()); - assertFalse(link2file.isHidden()); - assertFalse(link2link2file.isHidden()); - } + testDOSHiddenAttributes(); header("length"); @@ -362,6 +347,26 @@ static void go() throws IOException { } } + static void testDOSHiddenAttributes() throws IOException { + // on Windows we test with the DOS hidden attribute set + if (System.getProperty("os.name").startsWith("Windows")) { + header("testDOSHiddenAttributes"); + DosFileAttributeView view = Files + .getFileAttributeView(file.toPath(), DosFileAttributeView.class); + view.setHidden(true); + try { + assertTrue(file.isHidden()); + assertTrue(link2file.isHidden()); + assertTrue(link2link2file.isHidden()); + } finally { + view.setHidden(false); + } + assertFalse(file.isHidden()); + assertFalse(link2file.isHidden()); + assertFalse(link2link2file.isHidden()); + } + } + public static void main(String[] args) throws IOException { if (supportsSymLinks(top)) { try { diff --git a/test/jdk/java/io/FileDescriptor/Sync.java b/test/jdk/java/io/FileDescriptor/Sync.java index 587d0bbe758..5864d5798df 100644 --- a/test/jdk/java/io/FileDescriptor/Sync.java +++ b/test/jdk/java/io/FileDescriptor/Sync.java @@ -39,7 +39,7 @@ public class Sync { static final String TEST_DIR = System.getProperty("test.dir", "."); - static final int TRIES = 10_000; + static final int TRIES = 1_000; public static void testWith(File file) throws Exception { try (FileOutputStream fos = new FileOutputStream(file)) { diff --git a/test/jdk/java/lang/IO/IO.java b/test/jdk/java/lang/IO/IO.java index dbb83db5f80..2b13657b58e 100644 --- a/test/jdk/java/lang/IO/IO.java +++ b/test/jdk/java/lang/IO/IO.java @@ -50,10 +50,9 @@ /* * @test - * @bug 8305457 8342936 8351435 8344706 + * @bug 8305457 8342936 8351435 8344706 8361613 * @summary java.lang.IO tests * @library /test/lib - * @modules jdk.internal.le * @run junit IO */ @ExtendWith(IO.TimingExtension.class) @@ -78,22 +77,6 @@ public static void prepareTTY() { } catch (Exception _) { } } - /* - * Unlike printTest, which tests a _default_ console that is normally - * jdk.internal.org.jline.JdkConsoleProviderImpl, this test tests - * jdk.internal.io.JdkConsoleImpl. Those console implementations operate - * in different conditions and, thus, are tested separately. - * - * To test jdk.internal.io.JdkConsoleImpl one needs to ensure that both - * conditions are met: - * - * - a non-existent console provider is requested - * - isatty is true - * - * To achieve isatty, the test currently uses the EXPECT(1) Unix command, - * which does not work for Windows. Later, a library like pty4j or JPty - * might be used instead of EXPECT, to cover both Unix and Windows. - */ @ParameterizedTest @ValueSource(strings = {"println", "print"}) public void outputTestInteractive(String mode) throws Exception { @@ -102,8 +85,6 @@ public void outputTestInteractive(String mode) throws Exception { expect.toString(), Path.of(testSrc, "output.exp").toAbsolutePath().toString(), System.getProperty("test.jdk") + "/bin/java", - "--enable-preview", - "-Djdk.console=gibberish", Path.of(testSrc, "Output.java").toAbsolutePath().toString(), mode); assertEquals(0, output.getExitValue()); @@ -130,7 +111,7 @@ public void outputTestInteractive(String mode) throws Exception { */ @ParameterizedTest @MethodSource("args") - public void inputTestInteractive(String console, String prompt) throws Exception { + public void inputTestInteractive(String prompt) throws Exception { var testSrc = System.getProperty("test.src", "."); var command = new ArrayList(); command.add(expect.toString()); @@ -138,9 +119,6 @@ public void inputTestInteractive(String console, String prompt) throws Exception : "input"; command.add(Path.of(testSrc, expectInputName + ".exp").toAbsolutePath().toString()); command.add(System.getProperty("test.jdk") + "/bin/java"); - command.add("--enable-preview"); - if (console != null) - command.add("-Djdk.console=" + console); command.add(Path.of(testSrc, "Input.java").toAbsolutePath().toString()); command.add(prompt == null ? "0" : PROMPT_NONE.equals(prompt) ? "2" : "1"); command.add(String.valueOf(prompt)); @@ -152,33 +130,11 @@ public void inputTestInteractive(String console, String prompt) throws Exception private static final String PROMPT_NONE = "prompt-none"; public static Stream args() { - // cross product: consoles x prompts - return Stream.of("jdk.internal.le", "gibberish").flatMap(console -> Stream.of(null, "?", "%s", PROMPT_NONE) - .map(prompt -> new String[]{console, prompt}).map(Arguments::of)); + // prompts + return Stream.of(null, "?", "%s", PROMPT_NONE).map(Arguments::of); } } - @ParameterizedTest - @ValueSource(strings = {"println", "print"}) - public void printTest(String mode) throws Exception { - var file = Path.of(System.getProperty("test.src", "."), "Output.java") - .toAbsolutePath().toString(); - var pb = ProcessTools.createTestJavaProcessBuilder("-Djdk.console=jdk.internal.le", "--enable-preview", file, mode); - OutputAnalyzer output = ProcessTools.executeProcess(pb); - assertEquals(0, output.getExitValue()); - assertTrue(output.getStderr().isEmpty()); - output.reportDiagnosticSummary(); - String out = output.getStdout(); - // The first half of the output is produced by Console, the second - // half is produced by IO: those halves must match. - // Executing Console and IO in the same VM (as opposed to - // consecutive VM runs, which are cleaner) to be able to compare string - // representation of objects. - assertFalse(out.isBlank()); - assertEquals(out.substring(0, out.length() / 2), - out.substring(out.length() / 2)); - } - @Test //JDK-8342936 public void printlnNoParamsTest() throws Exception { var file = Path.of("PrintlnNoParams.java"); @@ -193,7 +149,7 @@ void main() { } """); } - var pb = ProcessTools.createTestJavaProcessBuilder("-Djdk.console=jdk.internal.le", "--enable-preview", file.toString()); + var pb = ProcessTools.createTestJavaProcessBuilder(file.toString()); OutputAnalyzer output = ProcessTools.executeProcess(pb); assertEquals(0, output.getExitValue()); assertTrue(output.getStderr().isEmpty()); diff --git a/test/jdk/java/lang/Math/FusedMultiplyAddTests.java b/test/jdk/java/lang/Math/FusedMultiplyAddTests.java index 61a3bfb0de1..014a4dedc0f 100644 --- a/test/jdk/java/lang/Math/FusedMultiplyAddTests.java +++ b/test/jdk/java/lang/Math/FusedMultiplyAddTests.java @@ -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 @@ -23,7 +23,7 @@ /* * @test - * @bug 4851642 8253409 + * @bug 4851642 8253409 8362207 * @summary Tests for Math.fusedMac and StrictMath.fusedMac. * @build Tests * @build FusedMultiplyAddTests @@ -352,8 +352,9 @@ private static int testSimpleF() { {1.0f+Math.ulp(1.0f), 1.0f+Math.ulp(1.0f), -1.0f-2.0f*Math.ulp(1.0f), Math.ulp(1.0f)*Math.ulp(1.0f)}, - // Double-rounding if done in double precision - {0x1.fffffep23f, 0x1.000004p28f, 0x1.fep5f, 0x1.000002p52f} + // Double-rounding if done in double precision and/or double fma + {0x1.fffffep23f, 0x1.000004p28f, 0x1.fep5f, 0x1.000002p52f}, + {0x1.001p0f, 0x1.001p0f, 0x1p-100f, 0x1.002002p0f}, }; for (float[] testCase: testCases) diff --git a/test/jdk/java/lang/ProcessBuilder/Basic.java b/test/jdk/java/lang/ProcessBuilder/Basic.java index ed9a0f9fb70..d73d4f13516 100644 --- a/test/jdk/java/lang/ProcessBuilder/Basic.java +++ b/test/jdk/java/lang/ProcessBuilder/Basic.java @@ -28,7 +28,7 @@ * 6464154 6523983 6206031 4960438 6631352 6631966 6850957 6850958 * 4947220 7018606 7034570 4244896 5049299 8003488 8054494 8058464 * 8067796 8224905 8263729 8265173 8272600 8231297 8282219 8285517 - * 8352533 + * 8352533 8368192 * @key intermittent * @summary Basic tests for Process and Environment Variable code * @modules java.base/java.lang:open @@ -696,7 +696,7 @@ private static class TrueExe { public static String path() { return path; } private static final String path = path0(); private static String path0(){ - if (!Platform.isBusybox("/bin/true")) { + if (!Files.isSymbolicLink(Paths.get("/bin/true"))) { return "/bin/true"; } else { File trueExe = new File("true"); @@ -711,7 +711,7 @@ private static class FalseExe { public static String path() { return path; } private static final String path = path0(); private static String path0(){ - if (!Platform.isBusybox("/bin/false")) { + if (!Files.isSymbolicLink(Paths.get("/bin/false"))) { return "/bin/false"; } else { File falseExe = new File("false"); @@ -777,30 +777,29 @@ private static boolean matches(String str, String regex) { return Pattern.compile(regex).matcher(str).find(); } - private static String matchAndExtract(String str, String regex) { - Matcher matcher = Pattern.compile(regex).matcher(str); - if (matcher.find()) { - return matcher.group(); - } else { - return ""; - } + // Return the string with the matching regex removed + private static String matchAndRemove(String str, String regex) { + return Pattern.compile(regex) + .matcher(str) + .replaceAll(""); } /* Only used for Mac OS X -- - * Mac OS X (may) add the variable __CF_USER_TEXT_ENCODING to an empty - * environment. The environment variable JAVA_MAIN_CLASS_ may also - * be set in Mac OS X. - * Remove them both from the list of env variables + * Mac OS X (may) add the variables: __CF_USER_TEXT_ENCODING, JAVA_MAIN_CLASS_, + * and TMPDIR. + * Remove them from the list of env variables */ private static String removeMacExpectedVars(String vars) { // Check for __CF_USER_TEXT_ENCODING - String cleanedVars = vars.replace("__CF_USER_TEXT_ENCODING=" - +cfUserTextEncoding+",",""); + String cleanedVars = matchAndRemove(vars, + "__CF_USER_TEXT_ENCODING=" + cfUserTextEncoding + ","); // Check for JAVA_MAIN_CLASS_ - String javaMainClassStr - = matchAndExtract(cleanedVars, - "JAVA_MAIN_CLASS_\\d+=Basic.JavaChild,"); - return cleanedVars.replace(javaMainClassStr,""); + cleanedVars = matchAndRemove(cleanedVars, + "JAVA_MAIN_CLASS_\\d+=Basic.JavaChild,"); + // Check and remove TMPDIR + cleanedVars = matchAndRemove(cleanedVars, + "TMPDIR=[^,]*,"); + return cleanedVars; } /* Only used for AIX -- diff --git a/test/jdk/java/lang/ProcessBuilder/childSignalDisposition/TestChildSignalDisposition.java b/test/jdk/java/lang/ProcessBuilder/childSignalDisposition/TestChildSignalDisposition.java new file mode 100644 index 00000000000..50fe054ee34 --- /dev/null +++ b/test/jdk/java/lang/ProcessBuilder/childSignalDisposition/TestChildSignalDisposition.java @@ -0,0 +1,70 @@ +/* + * 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 id=posix_spawn + * @bug 8364611 + * @summary Check that childs start with SIG_DFL as SIGPIPE disposition + * @requires os.family != "windows" + * @library /test/lib + * @run main/othervm/native -Djdk.lang.Process.launchMechanism=posix_spawn -agentlib:ChangeSignalDisposition TestChildSignalDisposition + */ + +/** + * @test id=fork + * @bug 8364611 + * @summary Check that childs start with SIG_DFL as SIGPIPE disposition + * @requires os.family != "windows" + * @library /test/lib + * @run main/othervm/native -Djdk.lang.Process.launchMechanism=fork -agentlib:ChangeSignalDisposition TestChildSignalDisposition + */ + +/** + * @test id=vfork + * @bug 8364611 + * @summary Check that childs start with SIG_DFL as SIGPIPE disposition + * @requires os.family == "linux" + * @library /test/lib + * @run main/othervm/native -Djdk.lang.Process.launchMechanism=vfork -agentlib:ChangeSignalDisposition TestChildSignalDisposition + */ + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +public class TestChildSignalDisposition { + // This test has two native parts: + // - a library injected into the JVM with -agentlib changes signal disposition of the VM process for SIGPIPE to + // SIG_IGN + // - a small native executable that prints out, in its main function, all signal handler dispositions, to be executed + // as a child process. + // + // What should happen: In child process, SIGPIPE should be set to default. + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createNativeTestProcessBuilder("PrintSignalDisposition"); + OutputAnalyzer output = ProcessTools.executeProcess(pb); + output.shouldHaveExitValue(0); + output.shouldNotMatch("SIGPIPE: +ignore"); + output.shouldNotMatch("SIGPIPE: +block"); + output.shouldMatch("SIGPIPE: +default"); + output.reportDiagnosticSummary(); + } +} diff --git a/test/jdk/java/lang/ProcessBuilder/childSignalDisposition/exePrintSignalDisposition.c b/test/jdk/java/lang/ProcessBuilder/childSignalDisposition/exePrintSignalDisposition.c new file mode 100644 index 00000000000..8235cdc7410 --- /dev/null +++ b/test/jdk/java/lang/ProcessBuilder/childSignalDisposition/exePrintSignalDisposition.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include "jvmti.h" +#include +#include +#include + +static const struct { int sig; const char* name; } signals[] = { + { SIGABRT, "SIGABRT" }, { SIGALRM, "SIGALRM" }, { SIGBUS, "SIGBUS" }, { SIGCHLD, "SIGCHLD" }, { SIGCONT, "SIGCONT" }, + { SIGFPE, "SIGFPE" }, { SIGHUP, "SIGHUP" }, { SIGILL, "SIGILL" }, { SIGINT, "SIGINT" }, { SIGKILL, "SIGKILL" }, + { SIGPIPE, "SIGPIPE" }, { SIGQUIT, "SIGQUIT" }, { SIGSEGV, "SIGSEGV" }, { SIGSTOP, "SIGSTOP" }, { SIGTERM, "SIGTERM" }, + { SIGTSTP, "SIGTSTP" }, { SIGTTIN, "SIGTTIN" }, { SIGTTOU, "SIGTTOU" }, { SIGUSR1, "SIGUSR1" }, { SIGUSR2, "SIGUSR2" }, +#ifdef SIGPOLL + { SIGPOLL, "SIGPOLL" }, +#endif + { SIGPROF, "SIGPROF" }, { SIGSYS, "SIGSYS" }, { SIGTRAP, "SIGTRAP" }, { SIGURG, "SIGURG" }, { SIGVTALRM, "SIGVTALRM" }, + { SIGXCPU, "SIGXCPU" }, { SIGXFSZ, "SIGXFSZ" }, { -1, NULL } +}; + +int main(int argc, char** argv) { + + printf("PID: %d\n", getpid()); + + sigset_t current_mask; + sigemptyset(¤t_mask); + if (sigprocmask(SIG_BLOCK /* ignored */, NULL, ¤t_mask) != 0) { + printf("sigprocmask %d\n", errno); + return -1; + } + + for (int n = 0; signals[n].sig != -1; n++) { + printf("%s: ", signals[n].name); + if (sigismember(¤t_mask, signals[n].sig)) { + printf("blocked "); + } + struct sigaction act; + if (sigaction(signals[n].sig, NULL, &act) != 0) { + printf("sigaction %d\n", errno); + printf("\n"); + continue; + } + const void* const handler = (act.sa_flags & SA_SIGINFO ? + (void*)act.sa_sigaction : (void*)act.sa_handler); + if (handler == (void*)SIG_DFL) { + printf("default "); + } else if (handler == (void*)SIG_IGN) { + printf("ignore "); + } else if (handler == (void*)SIG_HOLD) { + printf("hold "); + } else { + printf("%p ", handler); + } +#ifdef _AIX + printf("%X\n", act.sa_flags); +#else + printf("%X %X\n", act.sa_flags, act.sa_mask); +#endif + } + + return 0; +} diff --git a/test/jdk/java/lang/ProcessBuilder/childSignalDisposition/libChangeSignalDisposition.c b/test/jdk/java/lang/ProcessBuilder/childSignalDisposition/libChangeSignalDisposition.c new file mode 100644 index 00000000000..83365bb79c6 --- /dev/null +++ b/test/jdk/java/lang/ProcessBuilder/childSignalDisposition/libChangeSignalDisposition.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include "jvmti.h" +#include +#include + +JNIEXPORT jint JNICALL +Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) { + + if (signal(SIGPIPE, SIG_IGN) != SIG_ERR) { + printf("changed signal disposition for SIGPIPE to SIG_IGN\n"); + } else { + printf("FAILED to change signal disposition for SIGPIPE to SIG_IGN (%d)\n", errno); + return JNI_ERR; + } + + return JNI_OK; +} diff --git a/test/jdk/java/lang/ProcessHandle/InfoTest.java b/test/jdk/java/lang/ProcessHandle/InfoTest.java index 66ac2df830b..38c86db3b91 100644 --- a/test/jdk/java/lang/ProcessHandle/InfoTest.java +++ b/test/jdk/java/lang/ProcessHandle/InfoTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, 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 @@ -295,10 +295,12 @@ public static void test3() { String expected = "sleep"; if (Platform.isWindows()) { expected = "sleep.exe"; - } else if (Platform.isBusybox("/bin/sleep")) { - // With busybox sleep is just a sym link to busybox. - // The busbox executable is seen as ProcessHandle.Info command. - expected = "busybox"; + } else if (Files.isSymbolicLink(Paths.get("/bin/sleep"))) { + // Busybox sleep is a symbolic link to /bin/busybox. + // Rust coreutils sleep is a symbolic link to coreutils + // The busbox/coreutils executables are seen as ProcessHandle.Info command. + Path executable = Files.readSymbolicLink(Paths.get("/bin/sleep")); + expected = executable.getFileName().toString(); } Assert.assertTrue(command.endsWith(expected), "Command: expected: \'" + expected + "\', actual: " + command); diff --git a/test/jdk/java/lang/ProcessHandle/TEST.properties b/test/jdk/java/lang/ProcessHandle/TEST.properties new file mode 100644 index 00000000000..c7e8a6850ca --- /dev/null +++ b/test/jdk/java/lang/ProcessHandle/TEST.properties @@ -0,0 +1 @@ +maxOutputSize=6000000 diff --git a/test/jdk/java/lang/RuntimeTests/ExitLogging-ALL.properties b/test/jdk/java/lang/RuntimeTests/ExitLogging-ALL.properties new file mode 100644 index 00000000000..8e24f2cb34d --- /dev/null +++ b/test/jdk/java/lang/RuntimeTests/ExitLogging-ALL.properties @@ -0,0 +1,8 @@ +############################################################ +# java.lang.Runtime logging level to console to ALL +############################################################ + +handlers= java.util.logging.ConsoleHandler + +java.util.logging.ConsoleHandler.level = ALL +java.lang.Runtime.level = ALL diff --git a/test/jdk/java/lang/RuntimeTests/ExitLogging-FINE.properties b/test/jdk/java/lang/RuntimeTests/ExitLogging-FINE.properties index 6afd902c2d0..b9076403cea 100644 --- a/test/jdk/java/lang/RuntimeTests/ExitLogging-FINE.properties +++ b/test/jdk/java/lang/RuntimeTests/ExitLogging-FINE.properties @@ -1,5 +1,5 @@ ############################################################ -# Enable logging java.lang.Runtime to the console +# java.lang.Runtime logging level to console to FINE ############################################################ handlers= java.util.logging.ConsoleHandler diff --git a/test/jdk/java/lang/RuntimeTests/ExitLogging-FINER.properties b/test/jdk/java/lang/RuntimeTests/ExitLogging-FINER.properties new file mode 100644 index 00000000000..a31f4a35e93 --- /dev/null +++ b/test/jdk/java/lang/RuntimeTests/ExitLogging-FINER.properties @@ -0,0 +1,8 @@ +############################################################ +# java.lang.Runtime logging level to console to FINER +############################################################ + +handlers= java.util.logging.ConsoleHandler + +java.util.logging.ConsoleHandler.level = ALL +java.lang.Runtime.level = FINER diff --git a/test/jdk/java/lang/RuntimeTests/ExitLogging-INFO.properties b/test/jdk/java/lang/RuntimeTests/ExitLogging-INFO.properties index d44a836c760..c09c0adf1ed 100644 --- a/test/jdk/java/lang/RuntimeTests/ExitLogging-INFO.properties +++ b/test/jdk/java/lang/RuntimeTests/ExitLogging-INFO.properties @@ -1,5 +1,5 @@ ############################################################ -# Enable logging java.lang.Runtime to the console +# java.lang.Runtime logging level to console to INFO ############################################################ handlers= java.util.logging.ConsoleHandler diff --git a/test/jdk/java/lang/RuntimeTests/ExitLogging-OFF.properties b/test/jdk/java/lang/RuntimeTests/ExitLogging-OFF.properties new file mode 100644 index 00000000000..6e284846e92 --- /dev/null +++ b/test/jdk/java/lang/RuntimeTests/ExitLogging-OFF.properties @@ -0,0 +1,8 @@ +############################################################ +# java.lang.Runtime logging level to console to OFF +############################################################ + +handlers= java.util.logging.ConsoleHandler + +java.util.logging.ConsoleHandler.level = ALL +java.lang.Runtime.level = OFF diff --git a/test/jdk/java/lang/RuntimeTests/ExitLogging-SEVERE.properties b/test/jdk/java/lang/RuntimeTests/ExitLogging-SEVERE.properties new file mode 100644 index 00000000000..cb6d32581fc --- /dev/null +++ b/test/jdk/java/lang/RuntimeTests/ExitLogging-SEVERE.properties @@ -0,0 +1,8 @@ +############################################################ +# java.lang.Runtime logging level to console to SEVERE +############################################################ + +handlers= java.util.logging.ConsoleHandler + +java.util.logging.ConsoleHandler.level = ALL +java.lang.Runtime.level = SEVERE diff --git a/test/jdk/java/lang/RuntimeTests/ExitLogging-WARNING.properties b/test/jdk/java/lang/RuntimeTests/ExitLogging-WARNING.properties new file mode 100644 index 00000000000..5cd99c8d6c5 --- /dev/null +++ b/test/jdk/java/lang/RuntimeTests/ExitLogging-WARNING.properties @@ -0,0 +1,8 @@ +############################################################ +# java.lang.Runtime logging level to console to WARNING +############################################################ + +handlers= java.util.logging.ConsoleHandler + +java.util.logging.ConsoleHandler.level = ALL +java.lang.Runtime.level = WARNING diff --git a/test/jdk/java/lang/RuntimeTests/RuntimeExitLogTest.java b/test/jdk/java/lang/RuntimeTests/RuntimeExitLogTest.java index da40cdbd742..291c9895e19 100644 --- a/test/jdk/java/lang/RuntimeTests/RuntimeExitLogTest.java +++ b/test/jdk/java/lang/RuntimeTests/RuntimeExitLogTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,7 +49,7 @@ public class RuntimeExitLogTest { private static final String TEST_JDK = System.getProperty("test.jdk"); private static final String TEST_SRC = System.getProperty("test.src"); - + private static final String NEW_LINE = System.lineSeparator(); private static Object HOLD_LOGGER; /** @@ -64,31 +64,80 @@ public static void main(String[] args) throws InterruptedException { System.exit(status); } + /** + * Generate a regular expression pattern that match the expected log output for a Runtime.exit() call. + * The pattern includes the method call stack trace and the exit status. + * @param status the exit status passed to the Runtime.exit() call + * @return the regex pattern as a string + */ + private static String generateStackTraceLogPattern(int status) { + return "(?s)^.+ java\\.lang\\.Shutdown logRuntimeExit\\n" + + ".*: Runtime\\.exit\\(\\) called with status: " + status + "\\n" + + "java\\.lang\\.Throwable: Runtime\\.exit\\(" + status + "\\)\\n" + + "\\s+at java\\.base/java\\.lang\\.Shutdown\\.logRuntimeExit\\(Shutdown\\.java:\\d+\\)\\n" + + "\\s+at(?: .+)"; + } + /** * Test various log level settings, and none. * @return a stream of arguments for parameterized test */ private static Stream logParamProvider() { return Stream.of( - // Logging enabled with level DEBUG + // Logging configuration using the java.util.logging.config.file property + Arguments.of(List.of("-Djava.util.logging.config.file=" + + Path.of(TEST_SRC, "ExitLogging-ALL.properties").toString()), 1, + generateStackTraceLogPattern(1)), + Arguments.of(List.of("-Djava.util.logging.config.file=" + + Path.of(TEST_SRC, "ExitLogging-FINER.properties").toString()), 2, + generateStackTraceLogPattern(2)), Arguments.of(List.of("-Djava.util.logging.config.file=" + - Path.of(TEST_SRC, "ExitLogging-FINE.properties").toString()), 1, - "Runtime.exit() called with status: 1"), - // Logging disabled due to level + Path.of(TEST_SRC, "ExitLogging-FINE.properties").toString()), 3, + generateStackTraceLogPattern(3)), + Arguments.of(List.of("-Djava.util.logging.config.file=" + + Path.of(TEST_SRC, "ExitLogging-INFO.properties").toString()), 4, + ""), + Arguments.of(List.of("-Djava.util.logging.config.file=" + + Path.of(TEST_SRC, "ExitLogging-WARNING.properties").toString()), 5, + ""), + Arguments.of(List.of("-Djava.util.logging.config.file=" + + Path.of(TEST_SRC, "ExitLogging-SEVERE.properties").toString()), 6, + ""), Arguments.of(List.of("-Djava.util.logging.config.file=" + - Path.of(TEST_SRC, "ExitLogging-INFO.properties").toString()), 2, + Path.of(TEST_SRC, "ExitLogging-OFF.properties").toString()), 7, ""), - // Console logger + + // Logging configuration using the jdk.system.logger.level property + Arguments.of(List.of("--limit-modules", "java.base", + "-Djdk.system.logger.level=ALL"), 8, + generateStackTraceLogPattern(8)), + Arguments.of(List.of("--limit-modules", "java.base", + "-Djdk.system.logger.level=TRACE"), 9, + generateStackTraceLogPattern(9)), + Arguments.of(List.of("--limit-modules", "java.base", + "-Djdk.system.logger.level=DEBUG"), 10, + generateStackTraceLogPattern(10)), Arguments.of(List.of("--limit-modules", "java.base", - "-Djdk.system.logger.level=DEBUG"), 3, - "Runtime.exit() called with status: 3"), - // Console logger - Arguments.of(List.of(), 4, ""), + "-Djdk.system.logger.level=INFO"), 11, + ""), + Arguments.of(List.of("--limit-modules", "java.base", + "-Djdk.system.logger.level=WARNING"), 12, + ""), + Arguments.of(List.of("--limit-modules", "java.base", + "-Djdk.system.logger.level=ERROR"), 13, + ""), + Arguments.of(List.of("--limit-modules", "java.base", + "-Djdk.system.logger.level=OFF"), 14, + ""), + // Throwing Handler Arguments.of(List.of("-DThrowingHandler", "-Djava.util.logging.config.file=" + - Path.of(TEST_SRC, "ExitLogging-FINE.properties").toString()), 5, - "Runtime.exit(5) logging failed: Exception in publish") + Path.of(TEST_SRC, "ExitLogging-FINE.properties").toString()), 15, + "Runtime\\.exit\\(15\\) logging failed: Exception in publish"), + + // Default console logging configuration with no additional parameters + Arguments.of(List.of(), 16, "") ); } @@ -115,13 +164,14 @@ public void checkLogger(List logProps, int status, String expectMessage) try (BufferedReader reader = process.inputReader()) { List lines = reader.lines().toList(); boolean match = (expectMessage.isEmpty()) - ? lines.size() == 0 - : lines.stream().filter(s -> s.contains(expectMessage)).findFirst().isPresent(); + ? lines.isEmpty() + : String.join("\n", lines).matches(expectMessage); if (!match) { // Output lines for debug - System.err.println("Expected: \"" + expectMessage + "\""); + System.err.println("Expected pattern (line-break):"); + System.err.println(expectMessage.replaceAll("\\n", NEW_LINE)); System.err.println("---- Actual output begin"); - lines.forEach(l -> System.err.println(l)); + lines.forEach(System.err::println); System.err.println("---- Actual output end"); fail("Unexpected log contents"); } diff --git a/test/jdk/java/lang/String/IndexOf.java b/test/jdk/java/lang/String/IndexOf.java index b4fd17105a8..48f23de79b0 100644 --- a/test/jdk/java/lang/String/IndexOf.java +++ b/test/jdk/java/lang/String/IndexOf.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Intel Corporation. All rights reserved. + * Copyright (c) 2024, 2026, Intel Corporation. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,15 @@ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xcomp -XX:-TieredCompilation -XX:UseAVX=2 -XX:+UnlockDiagnosticVMOptions -XX:+EnableX86ECoreOpts IndexOf */ +/* + * @test + * @bug 8360271 + * @summary test String indexOf() intrinsic + * @requires vm.cpu.features ~= ".*avx2.*" + * @requires vm.compiler2.enabled + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xcomp -XX:-TieredCompilation -XX:UseAVX=2 -XX:+UnlockDiagnosticVMOptions -XX:+EnableX86ECoreOpts -XX:-CompactStrings IndexOf + */ + public class IndexOf { final int scope = 32*2+16+8; final char a, aa, b, c, d; @@ -56,11 +65,11 @@ enum Encoding {LL, UU, UL; } d = 'd'; break; case UU: - a = '\u0061'; + a = '\u1061'; aa = a; - b = '\u0062'; + b = '\u1062'; c = '\u1063'; - d = '\u0064'; + d = '\u1064'; break; default: //case UL: a = 'a'; @@ -73,7 +82,7 @@ enum Encoding {LL, UU, UL; } } // needle =~ /ab*d/ - // badNeedle =~ /ab*db*d/ + // badNeedle =~ /ab*cb*d/ interface Append {void append(int pos, char cc);} String newNeedle(int size, int badPosition) { if (size<2) {throw new RuntimeException("Fix testcase "+size);} diff --git a/test/jdk/java/lang/String/nativeEncoding/libstringPlatformChars.c b/test/jdk/java/lang/String/nativeEncoding/libstringPlatformChars.c index 99dbd92d92e..91c6f8edbc0 100644 --- a/test/jdk/java/lang/String/nativeEncoding/libstringPlatformChars.c +++ b/test/jdk/java/lang/String/nativeEncoding/libstringPlatformChars.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 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 @@ -58,19 +58,23 @@ Java_StringPlatformChars_newString(JNIEnv *env, jclass unused, jbyteArray bytes) char* str; int len = (*env)->GetArrayLength(env, bytes); int i; - jbyte* jbytes; - - str = (char*)malloc(len + 1); - jbytes = (*env)->GetPrimitiveArrayCritical(env, bytes, NULL); + jbyte* jbytes = (*env)->GetPrimitiveArrayCritical(env, bytes, NULL); if (jbytes == NULL) { return NULL; } + str = (char*)malloc(len + 1); + if (str == NULL) { + (*env)->ReleasePrimitiveArrayCritical(env, bytes, (void*)jbytes, 0); + return NULL; + } for (i = 0; i < len; i++) { str[i] = (char)jbytes[i]; } str[len] = '\0'; (*env)->ReleasePrimitiveArrayCritical(env, bytes, (void*)jbytes, 0); - return JNU_NewStringPlatform(env, str); + jstring res = JNU_NewStringPlatform(env, str); + free(str); + return res; } diff --git a/test/jdk/java/lang/StringBuilder/RacingSBThreads.java b/test/jdk/java/lang/StringBuilder/RacingSBThreads.java index 9177f5de1aa..26f5cf9385a 100644 --- a/test/jdk/java/lang/StringBuilder/RacingSBThreads.java +++ b/test/jdk/java/lang/StringBuilder/RacingSBThreads.java @@ -46,7 +46,7 @@ public class RacingSBThreads { private static final int TIMEOUT_SEC = 1; // Duration to run each test case - private static final int N = 10_000_000; // static number of iterations for writes and modifies + private static final int N = 1_000_000; // static number of iterations for writes and modifies private static final int LEN = 100_000; // Length of initial SB // Strings available to be used as the initial contents of a StringBuilder diff --git a/test/jdk/java/lang/Thread/virtual/ParkWithFixedThreadPool.java b/test/jdk/java/lang/Thread/virtual/ParkWithFixedThreadPool.java index 70b73884d92..2b23d866af4 100644 --- a/test/jdk/java/lang/Thread/virtual/ParkWithFixedThreadPool.java +++ b/test/jdk/java/lang/Thread/virtual/ParkWithFixedThreadPool.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/java/lang/Thread/virtual/Starvation.java b/test/jdk/java/lang/Thread/virtual/Starvation.java index 2b8da5fbca8..987c54c1a0c 100644 --- a/test/jdk/java/lang/Thread/virtual/Starvation.java +++ b/test/jdk/java/lang/Thread/virtual/Starvation.java @@ -25,7 +25,7 @@ * @requires vm.continuations * @library /test/lib * @bug 8345294 - * @run main/othervm/timeout=200/native --enable-native-access=ALL-UNNAMED Starvation 100000 + * @run main/othervm/native --enable-native-access=ALL-UNNAMED Starvation */ import java.time.Duration; @@ -37,9 +37,16 @@ public class Starvation { public static void main(String[] args) throws Exception { - int iterations = Integer.parseInt(args[0]); + int iterations; + if (args.length > 0) { + iterations = Integer.parseInt(args[0]); + } else { + int nprocs = Runtime.getRuntime().availableProcessors(); + iterations = 40_000 / nprocs; + } - for (int i = 0; i < iterations; i++) { + for (int i = 1; i <= iterations; i++) { + System.out.format("%s iteration %d of %d ...%n", Instant.now(), i, iterations); var exRef = new AtomicReference(); Thread thread = Thread.startVirtualThread(() -> { try { diff --git a/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenBlocking.java b/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenBlocking.java index 17b63573d85..2645a977a57 100644 --- a/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenBlocking.java +++ b/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenBlocking.java @@ -53,8 +53,8 @@ public static void main(String[] args) throws Exception { int iterations; int value = Integer.parseInt(args[0]); - if (Platform.isOSX() && Platform.isX64()) { - // reduced iterations on macosx-x64 + if (Platform.isOSX()) { + // reduced iterations on macosx iterations = Math.max(value / 4, 1); } else { iterations = value; diff --git a/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenPinned.java b/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenPinned.java index f68b595eed4..ef385e47e21 100644 --- a/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenPinned.java +++ b/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenPinned.java @@ -56,8 +56,8 @@ public static void main(String[] args) throws Exception { int iterations; int value = Integer.parseInt(args[0]); - if (Platform.isOSX() && Platform.isX64()) { - // reduced iterations on macosx-x64 + if (Platform.isOSX()) { + // reduced iterations on macosx iterations = Math.max(value / 4, 1); } else { iterations = value; diff --git a/test/jdk/java/lang/Thread/virtual/stress/ParkALot.java b/test/jdk/java/lang/Thread/virtual/stress/ParkALot.java index c30193bc121..881f316cb8e 100644 --- a/test/jdk/java/lang/Thread/virtual/stress/ParkALot.java +++ b/test/jdk/java/lang/Thread/virtual/stress/ParkALot.java @@ -49,8 +49,8 @@ public class ParkALot { public static void main(String[] args) throws Exception { int iterations; int value = Integer.parseInt(args[0]); - if (Platform.isOSX() && Platform.isX64()) { - // reduced iterations on macosx-x64 + if (Platform.isOSX()) { + // reduced iterations on macosx iterations = Math.max(value / 4, 1); } else { iterations = value; diff --git a/test/jdk/java/lang/Thread/virtual/stress/ParkAfterTimedPark.java b/test/jdk/java/lang/Thread/virtual/stress/ParkAfterTimedPark.java new file mode 100644 index 00000000000..1b173271a79 --- /dev/null +++ b/test/jdk/java/lang/Thread/virtual/stress/ParkAfterTimedPark.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test id=parked + * @bug 8369227 + * @summary Stress test untimed park after a timed park when a thread is unparked around the + * same time that the timeout expires. + * @library /test/lib + * @run main/othervm --enable-native-access=ALL-UNNAMED ParkAfterTimedPark 200 false + */ + +/* + * @test id=pinned + * @summary Stress test untimed park, while pinned, and after a timed park when a thread is + * unparked around the same time that the timeout expires. + * @library /test/lib + * @run main/othervm --enable-native-access=ALL-UNNAMED ParkAfterTimedPark 200 true + */ + +import java.time.Instant; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.LockSupport; +import jdk.test.lib.thread.VThreadPinner; + +public class ParkAfterTimedPark { + public static void main(String[] args) throws Exception { + int iterations = (args.length > 0) ? Integer.parseInt(args[0]) : 100; + boolean pinned = (args.length > 1) ? Boolean.parseBoolean(args[1]) : false; + + for (int i = 1; i <= iterations; i++) { + System.out.println(Instant.now() + " => " + i + " of " + iterations); + for (int timeout = 1; timeout <= 10; timeout++) { + test(timeout, true); + } + } + } + + /** + * Creates two virtual threads. The first does a timed-park for the given time, + * then parks in CountDownLatch.await. A second virtual thread unparks the first + * around the same time that the timeout for the first expires. + */ + private static void test(int millis, boolean pinned) throws Exception { + long nanos = TimeUnit.MILLISECONDS.toNanos(millis); + + var finish = new CountDownLatch(1); + + Thread thread1 = Thread.startVirtualThread(() -> { + LockSupport.parkNanos(nanos); + boolean done = false; + while (!done) { + try { + if (pinned) { + VThreadPinner.runPinned(() -> { + finish.await(); + }); + } else { + finish.await(); + } + done = true; + } catch (InterruptedException e) { } + } + }); + + Thread thread2 = Thread.startVirtualThread(() -> { + int delta = ThreadLocalRandom.current().nextInt(millis); + boolean done = false; + while (!done) { + try { + Thread.sleep(millis - delta); + done = true; + } catch (InterruptedException e) { } + } + LockSupport.unpark(thread1); + }); + + // wait for first thread to park before count down + await(thread1, Thread.State.WAITING); + finish.countDown(); + + thread1.join(); + thread2.join(); + } + + /** + * Waits for the given thread to reach a given state. + */ + private static void await(Thread thread, Thread.State expectedState) throws Exception { + Thread.State state = thread.getState(); + while (state != expectedState) { + if (state == Thread.State.TERMINATED) + throw new RuntimeException("Thread has terminated"); + Thread.sleep(10); + state = thread.getState(); + } + } +} diff --git a/test/jdk/java/lang/Thread/virtual/stress/TimedWaitALot.java b/test/jdk/java/lang/Thread/virtual/stress/TimedWaitALot.java index 6a81a7c5fee..704e299ad8b 100644 --- a/test/jdk/java/lang/Thread/virtual/stress/TimedWaitALot.java +++ b/test/jdk/java/lang/Thread/virtual/stress/TimedWaitALot.java @@ -94,17 +94,20 @@ static void test(boolean notify, boolean interrupt, int... timeouts) throws Exce // start thread to Object.notifyAll at around time that the timeout expires if (notify) { - if (ThreadLocalRandom.current().nextBoolean()) { - synchronized (lock) { + executor.submit(() -> { + if (ThreadLocalRandom.current().nextBoolean()) { + synchronized (lock) { + sleepLessThan(timeout); + lock.notifyAll(); + } + } else { sleepLessThan(timeout); - lock.notifyAll(); - } - } else { - sleepLessThan(timeout); - synchronized (lock) { - lock.notifyAll(); + synchronized (lock) { + lock.notifyAll(); + } } - } + return null; + }); } // start thread to interrupt first thread at around time that the timeout expires diff --git a/test/jdk/java/lang/instrument/RetransformBigClassTest.java b/test/jdk/java/lang/instrument/RetransformBigClassTest.java new file mode 100644 index 00000000000..c4788217be1 --- /dev/null +++ b/test/jdk/java/lang/instrument/RetransformBigClassTest.java @@ -0,0 +1,161 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 8277444 + * + * @library /test/lib + * @compile SimpleIdentityTransformer.java + * @run shell MakeJAR.sh retransformAgent + * @run main/othervm -javaagent:retransformAgent.jar RetransformBigClassTest + */ + +import jdk.test.lib.compiler.InMemoryJavaCompiler; + +/* + * JvmtiClassFileReconstituter::copy_bytecodes restores bytecodes rewritten + * by the linking process. It is used by RetransformClasses. + * JDK-8277444 is a data race between copy_bytecodes and the linking process. + * This test puts the linking process in one thread and the retransforming process + * in another thread. The test uses Class.forName("BigClass", false, classLoader) + * which does not link the class. When the class is used, the linking process starts. + * In another thread retransforming of the class is happening. + * We generate a class with big methods. A number of methods and their size are + * chosen to make the linking and retransforming processes run concurrently. + * We delay the retransforming process to follow the linking process. + * If there is no synchronization between the processes, a data race will happen. + */ +public class RetransformBigClassTest extends AInstrumentationTestCase { + + private static final Object LOCK = new Object(); + private static final int COUNTER_INC_COUNT = 2000; // A number of 'c+=1;' statements in methods of a class. + private static final int MIN_LINK_TIME_MS = 60; // Large enough so the linking and retransforming processes run in parallel. + private static final int RETRANSFORM_CLASSES_DELAY_MS = 37; // We manage to create a data race when a delay is in the range 0.52x - 0.62x of MIN_LINK_TIME_MS. + + private static Class bigClass; + private static byte[] bigClassBytecode; + + private Thread retransformThread; + + RetransformBigClassTest() { + super("RetransformBigClassTest"); + } + + public static void main(String[] args) throws Throwable { + new RetransformBigClassTest().runTest(); + } + + protected final void doRunTest() throws Throwable { + ClassLoader classLoader = new ClassLoader() { + @Override + protected Class findClass(String name) throws ClassNotFoundException { + if (name.equals("BigClass")) { + return defineClass(name, bigClassBytecode, 0, bigClassBytecode.length); + } + + return super.findClass(name); + } + }; + synchronized (LOCK) { + bigClass = Class.forName("BigClass", false, classLoader); + LOCK.notify(); + } + // Make a use of the BigClass + assertTrue(bigClass.getConstructor().newInstance().hashCode() != 0); + retransformThread.join(); + } + + private byte[] createClassBytecode(String className, int methodCount) throws Exception { + String methodBody = ""; + for (int j = 0; j < COUNTER_INC_COUNT; j++) { + methodBody += "c+=1;"; + } + + String classSrc = "public class " + className + " { int c;"; + + for (int i = 0; i < methodCount; i++) { + classSrc += "\npublic void m" + i + "(){"; + classSrc += methodBody; + classSrc += "\n}"; + } + classSrc += "\n}"; + + return InMemoryJavaCompiler.compile(className, classSrc); + } + + // We need a number of methods such that the linking time is greater than + // or equal to MIN_LINK_TIME_MS. + // We create a class having 5 methods and trigger the linking process. + // We measure the time taken and use it to calculate the needed number. + private int findMethodCount() throws Exception { + int methodCount = 5; + final String className = "BigClass" + methodCount; + final byte[] bytecode = createClassBytecode(className, methodCount); + ClassLoader classLoader = new ClassLoader() { + @Override + protected Class findClass(String name) throws ClassNotFoundException { + if (name.equals(className)) { + return defineClass(name, bytecode, 0, bytecode.length); + } + + return super.findClass(name); + } + }; + var bigClass = Class.forName(className, false, classLoader); + long startTime = System.nanoTime(); + assertTrue(bigClass.getConstructor().newInstance().hashCode() != 0); + double linkTimeMs = (System.nanoTime() - startTime) / 1000000.0; + System.out.println("Link time for a class with " + methodCount + " methods each having " + COUNTER_INC_COUNT + " counter increments: " + Math.round(linkTimeMs)); + if (linkTimeMs < MIN_LINK_TIME_MS) { + methodCount = (int)Math.round((MIN_LINK_TIME_MS * methodCount) / linkTimeMs); + } + System.out.println("The number of methods to exceed " + MIN_LINK_TIME_MS + " ms linking time: " + methodCount); + return methodCount; + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + + bigClassBytecode = createClassBytecode("BigClass", findMethodCount()); + fInst.addTransformer(new SimpleIdentityTransformer()); + retransformThread = new Thread(() -> { + try { + synchronized (LOCK) { + while (bigClass == null) { + System.out.println("[retransformThread]: Waiting for bigClass"); + LOCK.wait(); + } + } + Thread.sleep(RETRANSFORM_CLASSES_DELAY_MS); + fInst.retransformClasses(bigClass); + } catch (Exception e) { + e.printStackTrace(); + } + }); + retransformThread.start(); + Thread.sleep(100); + } +} diff --git a/test/jdk/java/lang/invoke/ClassValueTest.java b/test/jdk/java/lang/invoke/ClassValueTest.java index 856653b3f92..34f7af1a8a0 100644 --- a/test/jdk/java/lang/invoke/ClassValueTest.java +++ b/test/jdk/java/lang/invoke/ClassValueTest.java @@ -23,23 +23,23 @@ /* * @test - * @bug 8351045 8351996 - * @enablePreview - * @comment Remove preview if ScopedValue is finalized + * @bug 8351045 8351996 8358535 * @summary tests for class-specific values + * @modules java.base/java.lang:+open * @library /test/lib * @run junit ClassValueTest */ import java.lang.classfile.ClassFile; import java.lang.constant.ClassDesc; +import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.lang.ref.WeakReference; import java.time.Duration; import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Arrays; -import java.util.Iterator; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ThreadLocalRandom; @@ -49,9 +49,7 @@ import jdk.test.lib.util.ForceGC; import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Timeout; import static org.junit.jupiter.api.Assertions.*; @@ -479,4 +477,67 @@ protected Integer computeValue(Class type) { awaitThreads(t); assertEquals(42, clv.get(int.class), "slow computation reinstalled value"); } + + // ClassValue cache invalidated and not reinstated when another + // unrelated entry is removed + @Test + public void testCacheRefresh() throws Throwable { + // Setup + var lookup = MethodHandles.privateLookupIn(ClassValue.class, MethodHandles.lookup()); + var classValueEntryClass = Class.forName("java.lang.ClassValue$Entry"); + MethodHandle getCacheCarefully = lookup.findStatic(ClassValue.class, "getCacheCarefully", + MethodType.methodType(classValueEntryClass.arrayType(), Class.class)); + var classValueMapClass = Class.forName("java.lang.ClassValue$ClassValueMap"); + MethodHandle probeHomeLocation = lookup.findStatic(classValueMapClass, "probeHomeLocation", + MethodType.methodType(classValueEntryClass, classValueEntryClass.arrayType(), ClassValue.class)); + MethodHandle match = lookup.findVirtual(ClassValue.class, "match", + MethodType.methodType(boolean.class, classValueEntryClass)); + + // Work + ClassValue clv = new ClassValue<>() { + @Override + protected String computeValue(Class type) { + return ""; + } + }; + // A class that shouldn't have arbitrary values stuffing the cache + var cleanClass = clv.getClass(); + clv.get(cleanClass); // create cache on clean class + assertTrue(checkDirectCacheMatch( + getCacheCarefully, + probeHomeLocation, + match, + clv, + cleanClass + )); + clv.get(int.class); + clv.remove(int.class); // invalidate cache on clean class + assertFalse(checkDirectCacheMatch( + getCacheCarefully, + probeHomeLocation, + match, + clv, + cleanClass + )); + clv.get(cleanClass); + assertTrue(checkDirectCacheMatch( + getCacheCarefully, + probeHomeLocation, + match, + clv, + cleanClass + )); + } + + private static boolean checkDirectCacheMatch( + MethodHandle getCacheCarefully, + MethodHandle probeHomeLocation, + MethodHandle match, + ClassValue clv, + Class cl + ) throws Throwable { + Object cache = getCacheCarefully.invoke(cl); + Object entry = probeHomeLocation.invoke(cache, clv); + return (boolean) match.invoke(clv, entry); + } } diff --git a/test/jdk/java/lang/invoke/MethodTypeTest.java b/test/jdk/java/lang/invoke/MethodTypeTest.java index c2ae4e0e84f..70949236066 100644 --- a/test/jdk/java/lang/invoke/MethodTypeTest.java +++ b/test/jdk/java/lang/invoke/MethodTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,6 +22,7 @@ */ /* @test + * @bug 8366028 * @summary unit tests for java.lang.invoke.MethodType * @compile MethodTypeTest.java * @run testng/othervm test.java.lang.invoke.MethodTypeTest @@ -35,6 +36,8 @@ import java.util.*; import org.testng.*; + +import static org.testng.Assert.assertThrows; import static org.testng.AssertJUnit.*; import org.testng.annotations.*; @@ -218,6 +221,24 @@ private static String concat(Object... parts) { return sb.toString().replace('.', '/'); } + @DataProvider(name = "badMethodDescriptorStrings") + public String[] badMethodDescriptorStrings() { + return new String[] { + "(I)", + "(V)V", + "([V)V", + "(" + "[".repeat(256) + "J)I", + "(java/lang/Object)V", + "()java/lang/Object", + }; + } + + // JDK-8366028 + @Test(dataProvider = "badMethodDescriptorStrings", expectedExceptions = IllegalArgumentException.class) + public void testFromMethodDescriptorStringNegatives(String desc) { + MethodType.fromMethodDescriptorString(desc, null); + } + @Test public void testHasPrimitives() { System.out.println("hasPrimitives"); diff --git a/test/jdk/java/lang/invoke/TestVHInvokerCaching.java b/test/jdk/java/lang/invoke/TestVHInvokerCaching.java index ccd97f82e9b..0a1ae5914ca 100644 --- a/test/jdk/java/lang/invoke/TestVHInvokerCaching.java +++ b/test/jdk/java/lang/invoke/TestVHInvokerCaching.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ import java.util.List; import static java.lang.invoke.MethodHandles.lookup; -import static org.testng.Assert.assertSame; +import static org.testng.Assert.*; public class TestVHInvokerCaching { @@ -74,7 +74,7 @@ class Holder { MethodHandles.Lookup lookup = lookup(); - for (Field field : Holder.class.getFields()) { + for (Field field : Holder.class.getDeclaredFields()) { String fieldName = field.getName(); Class fieldType = field.getType(); @@ -82,6 +82,8 @@ class Holder { testHandles.add(lookup.findVarHandle(Holder.class, fieldName, fieldType)); } + assertFalse(testHandles.isEmpty()); + return testHandles.stream().map(vh -> new Object[]{ vh }).toArray(Object[][]::new); } } diff --git a/test/jdk/java/lang/module/customfs/ModulesInCustomFileSystem.java b/test/jdk/java/lang/module/customfs/ModulesInCustomFileSystem.java index 801f2e5fca6..e023a3a5839 100644 --- a/test/jdk/java/lang/module/customfs/ModulesInCustomFileSystem.java +++ b/test/jdk/java/lang/module/customfs/ModulesInCustomFileSystem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ * @library /test/lib * @build ModulesInCustomFileSystem m1/* m2/* * jdk.test.lib.util.JarUtils - * @run testng/othervm ModulesInCustomFileSystem + * @run testng/othervm -Djava.io.tmpdir=. ModulesInCustomFileSystem * @summary Test ModuleFinder to find modules in a custom file system */ diff --git a/test/jdk/java/net/CookieHandler/B6644726.java b/test/jdk/java/net/CookieHandler/B6644726.java index b1caa182d73..cc31f64c1b0 100644 --- a/test/jdk/java/net/CookieHandler/B6644726.java +++ b/test/jdk/java/net/CookieHandler/B6644726.java @@ -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 @@ private static void testCookieStore() throws Exception { // 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 @@ private static void testCookieStore() throws Exception { 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 --git a/test/jdk/java/net/CookieStoreTest.java b/test/jdk/java/net/CookieStoreTest.java new file mode 100644 index 00000000000..50a5ab3fac1 --- /dev/null +++ b/test/jdk/java/net/CookieStoreTest.java @@ -0,0 +1,113 @@ +/* + * 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.net.CookieManager; +import java.net.CookieStore; +import java.net.HttpCookie; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +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.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +/* + * @test + * @bug 8365086 + * @summary verify that the implementation of java.net.CookieStore works + * as expected + * @run junit CookieStoreTest + */ +class CookieStoreTest { + + // neither the scheme, host nor the port matters in this test + private static final URI COOKIE_TEST_URI = URI.create("https://127.0.0.1:12345"); + + static List cookieStores() { + final List params = new ArrayList<>(); + // empty CookieStore + params.add(Arguments.of(new CookieManager().getCookieStore(), true)); + + final CookieStore cookieStore = new CookieManager().getCookieStore(); + cookieStore.add(COOKIE_TEST_URI, new HttpCookie("foo", "bar")); + // non-empty CookieStore + params.add(Arguments.of(cookieStore, false)); + + return params; + } + + /* + * Verify that the List returned by CookieStore.getURIs() is immutable. + */ + @ParameterizedTest + @MethodSource("cookieStores") + void testImmutableGetURIs(final CookieStore cookieStore, final boolean expectEmpty) { + final List uris = cookieStore.getURIs(); + assertNotNull(uris, "CookieStore.getURIs() returned null"); + assertEquals(expectEmpty, uris.isEmpty(), "CookieStore.getURIs() returned: " + uris); + assertImmutableList(uris, COOKIE_TEST_URI); + } + + /* + * Verify that the List returned by CookieStore.getCookies() is immutable. + */ + @ParameterizedTest + @MethodSource("cookieStores") + void testImmutableGetCookies(final CookieStore cookieStore, final boolean expectEmpty) { + final List cookies = cookieStore.getCookies(); + assertNotNull(cookies, "CookieStore.getCookies() returned null"); + assertEquals(expectEmpty, cookies.isEmpty(), "CookieStore.getCookies() returned: " + cookies); + assertImmutableList(cookies, new HttpCookie("hello", "world")); + } + + /* + * Verify that the List returned by CookieStore.get(URI) is immutable. + */ + @ParameterizedTest + @MethodSource("cookieStores") + void testImmutableGetCookiesForURI(final CookieStore cookieStore, final boolean expectEmpty) { + final List cookies = cookieStore.get(COOKIE_TEST_URI); + assertNotNull(cookies, "CookieStore.get(URI) returned null"); + assertEquals(expectEmpty, cookies.isEmpty(), "CookieStore.get(URI) returned: " + cookies); + assertImmutableList(cookies, new HttpCookie("hello", "world")); + } + + /* + * Verifies that the attempt to modify the contents of the list will fail + * due to the list being immutable. + */ + private static void assertImmutableList(final List list, T elementToAddOrRemove) { + // the list is expected to be immutable, so each of these operations must fail + assertThrows(UnsupportedOperationException.class, () -> list.add(elementToAddOrRemove)); + assertThrows(UnsupportedOperationException.class, () -> list.remove(elementToAddOrRemove)); + assertThrows(UnsupportedOperationException.class, list::clear); + // even try the replace operation when the list isn't empty + if (!list.isEmpty()) { + assertThrows(UnsupportedOperationException.class, () -> list.set(0, elementToAddOrRemove)); + } + } +} diff --git a/test/jdk/java/net/InetAddress/ptr/Lookup.java b/test/jdk/java/net/InetAddress/ptr/Lookup.java index 1248916023e..39e5f720cef 100644 --- a/test/jdk/java/net/InetAddress/ptr/Lookup.java +++ b/test/jdk/java/net/InetAddress/ptr/Lookup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,6 +46,7 @@ import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; +import jtreg.SkippedException; public class Lookup { private static final String HOST = "icann.org"; @@ -91,8 +92,7 @@ public static void main(String args[]) throws IOException { String tmp = lookupWithIPv4Prefer(); System.out.println("IPv4 lookup results: [" + tmp + "]"); if (SKIP.equals(tmp)) { - System.out.println(HOST + " can't be resolved - test skipped."); - return; + throw new SkippedException(HOST + " can't be resolved - test skipped."); } String[] strs = tmp.split(":"); @@ -104,8 +104,7 @@ public static void main(String args[]) throws IOException { tmp = reverseWithIPv4Prefer(addr); System.out.println("IPv4 reverse lookup results: [" + tmp + "]"); if (SKIP.equals(tmp)) { - System.out.println(addr + " can't be resolved with preferIPv4 - test skipped."); - return; + throw new SkippedException(addr + " can't be resolved with preferIPv4 - test skipped."); } strs = tmp.split(":"); diff --git a/test/jdk/java/net/NetworkInterface/IPv4Only.java b/test/jdk/java/net/NetworkInterface/IPv4Only.java index efa59aa7691..3d12b3282bd 100644 --- a/test/jdk/java/net/NetworkInterface/IPv4Only.java +++ b/test/jdk/java/net/NetworkInterface/IPv4Only.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,12 +29,18 @@ */ -import java.net.*; -import java.util.*; + import jdk.test.lib.net.IPSupport; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.Enumeration; + public class IPv4Only { public static void main(String[] args) throws Exception { + IPSupport.printPlatformSupport(System.out); if (IPSupport.hasIPv4()) { System.out.println("Testing IPv4"); Enumeration nifs = NetworkInterface.getNetworkInterfaces(); @@ -43,7 +49,7 @@ public static void main(String[] args) throws Exception { Enumeration addrs = nif.getInetAddresses(); while (addrs.hasMoreElements()) { InetAddress hostAddr = addrs.nextElement(); - if ( hostAddr instanceof Inet6Address ){ + if (hostAddr instanceof Inet6Address){ throw new RuntimeException( "NetworkInterfaceV6List failed - found v6 address " + hostAddr.getHostAddress() ); } } diff --git a/test/jdk/java/net/Socket/DeadlockTest.java b/test/jdk/java/net/Socket/DeadlockTest.java index 40b001171f1..3e2d38dc142 100644 --- a/test/jdk/java/net/Socket/DeadlockTest.java +++ b/test/jdk/java/net/Socket/DeadlockTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,12 +31,19 @@ * @run main/othervm -Djava.net.preferIPv4Stack=true DeadlockTest */ -import java.net.*; -import java.io.*; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; + import jdk.test.lib.net.IPSupport; public class DeadlockTest { - public static void main(String [] argv) throws Exception { + public static void main(String[] argv) throws Exception { IPSupport.throwSkippedExceptionIfNonOperational(); ServerSocket ss = new ServerSocket(0, 0, InetAddress.getLoopbackAddress()); @@ -52,16 +59,9 @@ public static void main(String [] argv) throws Exception { Thread c1 = new Thread(ct); c1.start(); - // Wait for the client thread to finish - c1.join(20000); - - // If timeout, we assume there is a deadlock - if (c1.isAlive() == true) { - // Close the socket to force the server thread - // terminate too - s1.stop(); - throw new Exception("Takes too long. Dead lock"); - } + // Wait for the client thread to finish. + // If it doesn't finish then it's a sign of a deadlock + c1.join(); } finally { ss.close(); clientSocket.close(); @@ -73,7 +73,7 @@ class ServerThread implements Runnable { private static boolean dbg = false; - ObjectInputStream in; + ObjectInputStream in; ObjectOutputStream out; ServerSocket server; diff --git a/test/jdk/java/net/httpclient/CancelRequestTest.java b/test/jdk/java/net/httpclient/CancelRequestTest.java index 7851b112498..e2ffe905d38 100644 --- a/test/jdk/java/net/httpclient/CancelRequestTest.java +++ b/test/jdk/java/net/httpclient/CancelRequestTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, 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 @@ -273,8 +273,12 @@ HttpClient newHttpClient(boolean share) { // rewrap in "Request Cancelled" when the multi exchange was aborted... private static boolean isCancelled(Throwable t) { while (t instanceof ExecutionException) t = t.getCause(); - if (t instanceof CancellationException) return true; - if (t instanceof IOException) return String.valueOf(t).contains("Request cancelled"); + Throwable cause = t; + while (cause != null) { + if (cause instanceof CancellationException) return true; + if (cause instanceof IOException && String.valueOf(cause).contains("Request cancelled")) return true; + cause = cause.getCause(); + } out.println("Not a cancellation exception: " + t); t.printStackTrace(out); return false; diff --git a/test/jdk/java/net/httpclient/HttpsTunnelAuthTest.java b/test/jdk/java/net/httpclient/HttpsTunnelAuthTest.java index 83961453f05..c6b2c323693 100644 --- a/test/jdk/java/net/httpclient/HttpsTunnelAuthTest.java +++ b/test/jdk/java/net/httpclient/HttpsTunnelAuthTest.java @@ -37,12 +37,11 @@ import java.util.stream.Stream; import javax.net.ssl.SSLContext; import jdk.httpclient.test.lib.common.HttpServerAdapters; -import jdk.httpclient.test.lib.http2.Http2TestServer; import jdk.test.lib.net.SimpleSSLContext; import static java.lang.System.out; -/** +/* * @test * @bug 8262027 * @summary Verify that it's possible to handle proxy authentication manually @@ -62,7 +61,7 @@ //-Djdk.internal.httpclient.debug=true -Dtest.debug=true public class HttpsTunnelAuthTest implements HttpServerAdapters, AutoCloseable { - static final String data[] = { + static final String[] data = { "Lorem ipsum", "dolor sit amet", "consectetur adipiscing elit, sed do eiusmod tempor", @@ -150,7 +149,7 @@ void setUp() throws IOException { @Override public void close() throws Exception { - if (proxy != null) close(proxy::stop); + if (proxy != null) close(proxy); if (http1Server != null) close(http1Server::stop); if (https1Server != null) close(https1Server::stop); if (https2Server != null) close(https2Server::stop); @@ -160,7 +159,8 @@ private void close(AutoCloseable closeable) { try { closeable.close(); } catch (Exception x) { - // OK. + // OK to ignore and just log + System.err.println("ignoring failure during close() of " + closeable + " due to: " + x); } } diff --git a/test/jdk/java/net/httpclient/ManyRequests.java b/test/jdk/java/net/httpclient/ManyRequests.java index 5d698d60ee5..493c2c3a504 100644 --- a/test/jdk/java/net/httpclient/ManyRequests.java +++ b/test/jdk/java/net/httpclient/ManyRequests.java @@ -24,6 +24,7 @@ /* * @test * @bug 8087112 8180044 8256459 + * @key intermittent * @modules java.net.http * java.logging * jdk.httpserver diff --git a/test/jdk/java/net/httpclient/ProxyServer.java b/test/jdk/java/net/httpclient/ProxyServer.java index 747a20772d1..9ec84fe428f 100644 --- a/test/jdk/java/net/httpclient/ProxyServer.java +++ b/test/jdk/java/net/httpclient/ProxyServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ * Two threads are created per client connection. So, it's not * intended for large numbers of parallel connections. */ -public class ProxyServer extends Thread implements Closeable { +public final class ProxyServer implements Closeable { // could use the test library here - Platform.isWindows(), // but it would force all tests that use ProxyServer to @@ -97,9 +97,7 @@ public ProxyServer(Integer port, this(port, debug, null); } - public ProxyServer(Integer port, - Boolean debug, - Credentials credentials) + private ProxyServer(Integer port, Boolean debug, Credentials credentials) throws IOException { this.debug = debug; @@ -108,15 +106,8 @@ public ProxyServer(Integer port, listener.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), port)); this.port = ((InetSocketAddress)listener.getLocalAddress()).getPort(); this.credentials = credentials; - setName("ProxyListener"); - setDaemon(true); - connections = new CopyOnWriteArrayList(); - start(); - } - - public ProxyServer(String s) { - credentials = null; connections = new CopyOnWriteArrayList(); + Thread.ofPlatform().name("ProxyListener").daemon().start(this::run); } /** @@ -148,7 +139,7 @@ public void close() throws IOException { volatile boolean done; - public void run() { + private void run() { int id = 0; try { while (!done) { @@ -656,10 +647,11 @@ public static void main(String[] args) throws Exception { int port = Integer.parseInt(args[0]); boolean debug = args.length > 1 && args[1].equals("-debug"); System.out.println("Debugging : " + debug); - ProxyServer ps = new ProxyServer(port, debug); - System.out.println("Proxy server listening on port " + ps.getPort()); - while (true) { - Thread.sleep(5000); + try (ProxyServer ps = new ProxyServer(port, debug)) { + System.out.println("Proxy server listening on port " + ps.getPort()); + while (true) { + Thread.sleep(5000); + } } } } diff --git a/test/jdk/java/net/httpclient/websocket/DummyWebSocketServer.java b/test/jdk/java/net/httpclient/websocket/DummyWebSocketServer.java index 9034cf9f28a..abc1748e3f2 100644 --- a/test/jdk/java/net/httpclient/websocket/DummyWebSocketServer.java +++ b/test/jdk/java/net/httpclient/websocket/DummyWebSocketServer.java @@ -351,7 +351,14 @@ URI getURI() { if (!started.get()) { throw new IllegalStateException("Not yet started"); } - return URI.create("ws://localhost:" + address.getPort()); + String ip = address.getAddress().isAnyLocalAddress() + ? InetAddress.getLoopbackAddress().getHostAddress() + : address.getAddress().getHostAddress(); + if (ip.indexOf(':') >= 0) { + ip = String.format("[%s]", ip); + } + + return URI.create("ws://" + ip + ":" + address.getPort()); } private boolean readRequest(SocketChannel channel, StringBuilder request) diff --git a/test/jdk/java/net/httpclient/whitebox/RawChannelTestDriver.java b/test/jdk/java/net/httpclient/whitebox/RawChannelTestDriver.java index ac577069b70..ab44fba5ecd 100644 --- a/test/jdk/java/net/httpclient/whitebox/RawChannelTestDriver.java +++ b/test/jdk/java/net/httpclient/whitebox/RawChannelTestDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,11 @@ * @test * @bug 8151299 8164704 * @modules java.net.http/jdk.internal.net.http - * @run testng java.net.http/jdk.internal.net.http.RawChannelTest + * @run testng/othervm java.net.http/jdk.internal.net.http.RawChannelTest */ +// use +// @run testng/othervm -Dseed=6434511950803022575 +// java.net.http/jdk.internal.net.http.RawChannelTest +// to reproduce a failure with a particular seed (e.g. 6434511950803022575) +// if this test is observed failing with that seed //-Djdk.internal.httpclient.websocket.debug=true diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/RawChannelTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/RawChannelTest.java index 9b5764735b2..f6bcdcb4d33 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/RawChannelTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/RawChannelTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ package jdk.internal.net.http; +import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -43,8 +44,9 @@ import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; +import java.util.concurrent.atomic.AtomicReference; + import jdk.internal.net.http.websocket.RawChannel; -import jdk.internal.net.http.websocket.WebSocketRequest; import org.testng.annotations.Test; import static java.net.http.HttpResponse.BodyHandlers.discarding; import static java.util.concurrent.TimeUnit.SECONDS; @@ -57,6 +59,20 @@ */ public class RawChannelTest { + // can't use jdk.test.lib when injected in java.net.httpclient + // Seed can be specified on the @run line with -Dseed= + private static class RandomFactory { + private static long getSeed() { + long seed = Long.getLong("seed", new Random().nextLong()); + System.out.println("Seed from RandomFactory = "+seed+"L"); + return seed; + } + public static Random getRandom() { + return new Random(getSeed()); + } + } + + private static final Random RANDOM = RandomFactory.getRandom(); private final AtomicLong clientWritten = new AtomicLong(); private final AtomicLong serverWritten = new AtomicLong(); private final AtomicLong clientRead = new AtomicLong(); @@ -90,7 +106,8 @@ public void test() throws Exception { server.setReuseAddress(false); server.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); int port = server.getLocalPort(); - new TestServer(server).start(); + TestServer testServer = new TestServer(server); + testServer.start(); final RawChannel chan = channelOf(port); print("RawChannel is %s", String.valueOf(chan)); @@ -129,6 +146,7 @@ public void handle() { } catch (IOException e) { outputCompleted.completeExceptionally(e); e.printStackTrace(); + closeChannel(chan); } return; } @@ -145,6 +163,9 @@ public void handle() { chan.registerEvent(this); writeStall.countDown(); // signal send buffer is full } catch (IOException e) { + print("OP_WRITE failed: " + e); + outputCompleted.completeExceptionally(e); + closeChannel(chan); throw new UncheckedIOException(e); } } @@ -168,6 +189,7 @@ public void handle() { read = chan.read(); } catch (IOException e) { inputCompleted.completeExceptionally(e); + closeChannel(chan); e.printStackTrace(); } if (read == null) { @@ -179,7 +201,10 @@ public void handle() { try { chan.registerEvent(this); } catch (IOException e) { - e.printStackTrace(); + print("OP_READ failed to register event: " + e); + inputCompleted.completeExceptionally(e); + closeChannel(chan); + throw new UncheckedIOException(e); } readStall.countDown(); break; @@ -191,21 +216,33 @@ public void handle() { print("OP_READ read %s bytes (%s total)", total, clientRead.get()); } }); + CompletableFuture.allOf(outputCompleted,inputCompleted) .whenComplete((r,t) -> { - try { - print("closing channel"); - chan.close(); - } catch (IOException x) { - x.printStackTrace(); - } + closeChannel(chan); }); exit.await(); // All done, we need to compare results: assertEquals(clientRead.get(), serverWritten.get()); assertEquals(serverRead.get(), clientWritten.get()); + Throwable serverError = testServer.failed.get(); + if (serverError != null) { + throw new AssertionError("TestServer failed: " + + serverError, serverError); + } } } + private static void closeChannel(RawChannel chan) { + print("closing channel"); + try { + chan.close(); + } catch (IOException x) { + print("Failed to close channel: " + x); + x.printStackTrace(); + } + } + + private static RawChannel channelOf(int port) throws Exception { URI uri = URI.create("http://localhost:" + port + "/"); print("raw channel to %s", uri.toString()); @@ -237,11 +274,24 @@ private static RawChannel channelOf(int port) throws Exception { private class TestServer extends Thread { // Powered by Slowpokes private final ServerSocket server; + private final AtomicReference failed = new AtomicReference<>(); TestServer(ServerSocket server) throws IOException { this.server = server; } + private void fail(Closeable s, String actor, Throwable t) { + failed.compareAndSet(null, t); + print("Server %s got exception: %s", actor, t); + t.printStackTrace(); + try { + s.close(); + } catch (Exception x) { + print("Server %s failed to close socket: %s", actor, t); + } + + } + @Override public void run() { try (Socket s = server.accept()) { @@ -252,21 +302,23 @@ public void run() { Thread reader = new Thread(() -> { try { + print("Server reader started"); long n = readSlowly(is); print("Server read %s bytes", n); s.shutdownInput(); } catch (Exception e) { - e.printStackTrace(); + fail(s, "reader", e); } }); Thread writer = new Thread(() -> { try { + print("Server writer started"); long n = writeSlowly(os); print("Server written %s bytes", n); s.shutdownOutput(); } catch (Exception e) { - e.printStackTrace(); + fail(s, "writer", e); } }); @@ -276,7 +328,7 @@ public void run() { reader.join(); writer.join(); } catch (Exception e) { - e.printStackTrace(); + fail(server,"acceptor", e); } finally { exit.countDown(); } @@ -365,6 +417,8 @@ private static void print(String format, Object... args) { } private static byte[] byteArrayOfSize(int bound) { - return new byte[new Random().nextInt(1 + bound)]; + // bound must be > 1; No need to check it, + // nextInt will throw IllegalArgumentException if needed + return new byte[RANDOM.nextInt(1, bound + 1)]; } } diff --git a/test/jdk/java/net/ipv6tests/TcpTest.java b/test/jdk/java/net/ipv6tests/TcpTest.java index 0ca35737a76..e75397b5181 100644 --- a/test/jdk/java/net/ipv6tests/TcpTest.java +++ b/test/jdk/java/net/ipv6tests/TcpTest.java @@ -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 class TcpTest extends Tests { 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 --git a/test/jdk/java/net/vthread/HttpALot.java b/test/jdk/java/net/vthread/HttpALot.java index c016824a92a..6418e103a35 100644 --- a/test/jdk/java/net/vthread/HttpALot.java +++ b/test/jdk/java/net/vthread/HttpALot.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, 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 @@ -21,7 +21,7 @@ * questions. */ -/** +/* * @test * @bug 8284161 * @summary Stress test the HTTP protocol handler and HTTP server @@ -44,6 +44,7 @@ import java.net.InetSocketAddress; import java.net.Proxy; import java.net.URL; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; @@ -52,6 +53,8 @@ public class HttpALot { + private static final String HELLO = "Hello"; + public static void main(String[] args) throws Exception { int requests = 25_000; if (args.length > 0) { @@ -65,12 +68,20 @@ public static void main(String[] args) throws Exception { InetAddress lb = InetAddress.getLoopbackAddress(); HttpServer server = HttpServer.create(new InetSocketAddress(lb, 0), 1024); ThreadFactory factory = Thread.ofVirtual().factory(); - server.setExecutor(Executors.newThreadPerTaskExecutor(factory)); + final ExecutorService serverExecutor = Executors.newThreadPerTaskExecutor(factory); + server.setExecutor(serverExecutor); server.createContext("/hello", e -> { - byte[] response = "Hello".getBytes("UTF-8"); - e.sendResponseHeaders(200, response.length); - try (OutputStream out = e.getResponseBody()) { - out.write(response); + try { + byte[] response = HELLO.getBytes("UTF-8"); + e.sendResponseHeaders(200, response.length); + try (OutputStream out = e.getResponseBody()) { + out.write(response); + } + } catch (Throwable t) { + System.err.println("failed to handle request " + e.getRequestURI() + + " due to: " + t); + t.printStackTrace(); + throw t; // let it propagate } requestsHandled.incrementAndGet(); }); @@ -85,15 +96,21 @@ public static void main(String[] args) throws Exception { // go server.start(); - try { - factory = Thread.ofVirtual().name("fetcher-", 0).factory(); - try (var executor = Executors.newThreadPerTaskExecutor(factory)) { - for (int i = 1; i <= requests; i++) { - executor.submit(() -> fetch(url)).get(); + try (serverExecutor) { + try { + factory = Thread.ofVirtual().name("fetcher-", 0).factory(); + try (var executor = Executors.newThreadPerTaskExecutor(factory)) { + for (int i = 1; i <= requests; i++) { + final String actual = executor.submit(() -> fetch(url)).get(); + if (!HELLO.equals(actual)) { + throw new RuntimeException("unexpected response: \"" + actual + + "\" for request " + i); + } + } } + } finally { + server.stop(1); } - } finally { - server.stop(1); } if (requestsHandled.get() < requests) { diff --git a/test/jdk/java/nio/Buffer/AllocateDirectInit.java b/test/jdk/java/nio/Buffer/AllocateDirectInit.java index c54536df8ba..472187fdcda 100644 --- a/test/jdk/java/nio/Buffer/AllocateDirectInit.java +++ b/test/jdk/java/nio/Buffer/AllocateDirectInit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2007, 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 @@ -23,29 +23,60 @@ /** * @test - * @bug 4490253 6535542 + * @bug 4490253 6535542 8357959 + * @key randomness + * @library /test/lib + * @build jdk.test.lib.RandomFactory * @summary Verify that newly allocated direct buffers are initialized. + * @run main/othervm AllocateDirectInit */ import java.nio.ByteBuffer; +import java.util.Random; + +import jdk.test.lib.RandomFactory; public class AllocateDirectInit { + private static final int MAX_BIN_LIMIT = 16 * 1024 * 1024; + private static final int MAX_DEC_LIMIT = 10 * 1000 * 1000; + private static final int TRIES_PER_LIMIT = 1024; + + private static final Random RND = RandomFactory.getRandom(); + public static void main(String [] args){ - for (int i = 0; i < 1024; i++) { - ByteBuffer bb = ByteBuffer.allocateDirect(1024); -// printByteBuffer(bb); - for (bb.position(0); bb.position() < bb.limit(); ) { - if ((bb.get() & 0xff) != 0) - throw new RuntimeException("uninitialized buffer, position = " - + bb.position()); + // Try power of two limits + for (int limit = 1; limit < MAX_BIN_LIMIT; limit *= 2) { + check(ByteBuffer.allocateDirect(limit - 1)); + check(ByteBuffer.allocateDirect(limit)); + check(ByteBuffer.allocateDirect(limit + 1)); + } + + // Try power of ten limits + for (int limit = 1; limit < MAX_DEC_LIMIT; limit *= 10) { + check(ByteBuffer.allocateDirect(limit - 1)); + check(ByteBuffer.allocateDirect(limit)); + check(ByteBuffer.allocateDirect(limit + 1)); + } + + // Try random sizes within power of two limits + for (int limit = 1; limit < MAX_BIN_LIMIT; limit *= 2) { + for (int t = 0; t < TRIES_PER_LIMIT; t++) { + check(ByteBuffer.allocateDirect(RND.nextInt(limit))); } } } - private static void printByteBuffer(ByteBuffer bb) { - System.out.print("byte ["); - for (bb.position(0); bb.position() < bb.limit(); ) - System.out.print(" " + Integer.toHexString(bb.get() & 0xff)); - System.out.println(" ]"); + private static void check(ByteBuffer bb) { + while (bb.hasRemaining()) { + if (bb.get() != 0) { + int mismatchPos = bb.position(); + System.out.print("byte ["); + for (bb.position(0); bb.position() < bb.limit(); ) { + System.out.print(" " + Integer.toHexString(bb.get() & 0xff)); + } + System.out.println(" ]"); + throw new RuntimeException("uninitialized buffer, position = " + mismatchPos); + } + } } } diff --git a/test/jdk/java/nio/channels/DatagramChannel/PromiscuousIPv6.java b/test/jdk/java/nio/channels/DatagramChannel/PromiscuousIPv6.java index b7bbba8e16b..6915ee247d1 100644 --- a/test/jdk/java/nio/channels/DatagramChannel/PromiscuousIPv6.java +++ b/test/jdk/java/nio/channels/DatagramChannel/PromiscuousIPv6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ * PromiscuousIPv6 * @run main PromiscuousIPv6 * @key randomness + * @requires (os.family == "linux") | (os.family == "mac") */ import java.nio.ByteBuffer; @@ -201,26 +202,15 @@ static void test(ProtocolFamily family, } } - /* - * returns true if platform allows an IPv6 socket join an IPv4 multicast group - */ - private static boolean supportedByPlatform() { - return Platform.isOSX() || Platform.isLinux(); - } - public static void main(String[] args) throws IOException { boolean hasIPV6MulticastAll; - if (!supportedByPlatform()) { - throw new SkippedException("This test should not be run on this platform"); - } else { - int major = Platform.getOsVersionMajor(); - int minor = Platform.getOsVersionMinor(); - hasIPV6MulticastAll = - Platform.isOSX() || - (Platform.isLinux() && ((major > 4) || ((major == 4 && minor >= 20)))); - } + int major = Platform.getOsVersionMajor(); + int minor = Platform.getOsVersionMinor(); + hasIPV6MulticastAll = + Platform.isOSX() || + (Platform.isLinux() && ((major > 4) || ((major == 4 && minor >= 20)))); NetworkConfiguration.printSystemConfiguration(System.out); List nifs = NetworkConfiguration.probe() diff --git a/test/jdk/java/nio/channels/DatagramChannel/StressNativeSignal.java b/test/jdk/java/nio/channels/DatagramChannel/StressNativeSignal.java index d6d2f083eca..cc726d19c0d 100644 --- a/test/jdk/java/nio/channels/DatagramChannel/StressNativeSignal.java +++ b/test/jdk/java/nio/channels/DatagramChannel/StressNativeSignal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,42 +36,23 @@ import java.util.concurrent.CountDownLatch; public class StressNativeSignal { - private UDPThread udpThread; - private ServerSocketThread serverSocketThread; + private final UDPThread udpThread; + private final ServerSocketThread serverSocketThread; - StressNativeSignal() { + StressNativeSignal() throws IOException { serverSocketThread = initServerSocketThread(); - if (serverSocketThread != null) { - serverSocketThread.start(); - } + serverSocketThread.start(); udpThread = initUDPThread(); - if (udpThread != null) { - udpThread.start(); - } + udpThread.start(); } - private UDPThread initUDPThread() { - UDPThread aUDPThread = null; - try { - aUDPThread = new UDPThread(); - } catch (Exception z) { - System.err.println("failed to create and start a UDPThread"); - z.printStackTrace(); - } - return aUDPThread; + private UDPThread initUDPThread() throws IOException { + return new UDPThread(); } - private ServerSocketThread initServerSocketThread() { - ServerSocketThread aServerSocketThread = null; - try { - aServerSocketThread = new ServerSocketThread(); - - } catch (Exception z) { - System.err.println("failed to create and start a ServerSocketThread"); - z.printStackTrace(); - } - return aServerSocketThread; + private ServerSocketThread initServerSocketThread() throws IOException { + return new ServerSocketThread(); } public static void main(String[] args) throws Throwable { @@ -80,46 +61,39 @@ public static void main(String[] args) throws Throwable { test.shutdown(); } - public void shutdown() { - if ((udpThread != null) && udpThread.isAlive()) { + public void shutdown() throws InterruptedException, IOException { + if (udpThread != null && udpThread.isAlive()) { udpThread.terminate(); - try { - udpThread.join(); - } catch (Exception z) { - z.printStackTrace(System.err); - } + udpThread.join(); + } else { System.out.println("UDPThread test scenario was not run"); } - if ((serverSocketThread != null) && (serverSocketThread.isAlive())) { + if (serverSocketThread != null && serverSocketThread.isAlive()) { serverSocketThread.terminate(); - try { - serverSocketThread.join(); - } catch (Exception z) { - z.printStackTrace(System.err); - } + serverSocketThread.join(); } else { System.out.println("ServerSocketThread test scenario was not run"); } } - public void waitForTestThreadsToStart() { - if ((udpThread != null) && udpThread.isAlive()) { + public void waitForTestThreadsToStart() throws InterruptedException { + if (udpThread != null && udpThread.isAlive()) { udpThread.waitTestThreadStart(); } - if ((serverSocketThread != null) && (serverSocketThread.isAlive())) { + if (serverSocketThread != null && serverSocketThread.isAlive()) { serverSocketThread.waitTestThreadStart(); } } public class ServerSocketThread extends Thread { private volatile boolean shouldTerminate; - private ServerSocket socket; + private final ServerSocket socket; private final CountDownLatch threadStarted = new CountDownLatch(1); - public ServerSocketThread () throws Exception { - socket = new ServerSocket(1122); + public ServerSocketThread() throws IOException { + socket = new ServerSocket(0); } public void run() { @@ -129,7 +103,7 @@ public void run() { Socket client = socket.accept(); client.close(); throw new RuntimeException("Unexpected return from accept call"); - } catch (Exception z) { + } catch (IOException z) { System.err.println("ServerSocketThread: caught exception " + z.getClass().getName()); if (!shouldTerminate) { z.printStackTrace(System.err); @@ -141,7 +115,7 @@ public void terminate() { shouldTerminate = true; try { socket.close(); - } catch (Exception z) { + } catch (IOException z) { z.printStackTrace(System.err); // ignore } @@ -150,7 +124,7 @@ public void terminate() { public void waitTestThreadStart() { try { threadStarted.await(); - } catch (Exception z) { + } catch (InterruptedException z) { z.printStackTrace(System.err); // ignore } @@ -158,15 +132,14 @@ public void waitTestThreadStart() { } public class UDPThread extends Thread { - private DatagramChannel channel; + private final DatagramChannel channel; private volatile boolean shouldTerminate; private final CountDownLatch threadStarted = new CountDownLatch(1); - public UDPThread () throws Exception { - + public UDPThread() throws IOException { channel = DatagramChannel.open(); channel.setOption(StandardSocketOptions.SO_RCVBUF, 6553600); - channel.bind(new InetSocketAddress(19870)); + channel.bind(new InetSocketAddress(0)); } @Override @@ -191,7 +164,7 @@ public void terminate() { shouldTerminate = true; try { channel.close(); - } catch (Exception z) { + } catch (IOException z) { System.err.println("UDPThread: caught exception " + z.getClass().getName()); z.printStackTrace(System.err); // ignore @@ -201,7 +174,7 @@ public void terminate() { public void waitTestThreadStart() { try { threadStarted.await(); - } catch (Exception z) { + } catch (InterruptedException z) { z.printStackTrace(System.err); // ignore } diff --git a/test/jdk/java/nio/channels/FileChannel/directio/DirectIOTest.java b/test/jdk/java/nio/channels/FileChannel/directio/DirectIOTest.java index 34f2bacc7dd..b9dd309d0f7 100644 --- a/test/jdk/java/nio/channels/FileChannel/directio/DirectIOTest.java +++ b/test/jdk/java/nio/channels/FileChannel/directio/DirectIOTest.java @@ -27,11 +27,13 @@ * @summary Test for ExtendedOpenOption.DIRECT flag * @requires (os.family == "linux" | os.family == "aix") * @library /test/lib + * @modules java.base/sun.nio.ch:+open java.base/java.io:+open * @build jdk.test.lib.Platform * @run main/native DirectIOTest */ import java.io.*; +import java.lang.reflect.Field; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.channels.*; @@ -47,10 +49,25 @@ public class DirectIOTest { private static final int BASE_SIZE = 4096; + private static final int TRIES = 3; + + public static int getFD(FileChannel channel) throws Exception { + Field fFdFd = channel.getClass().getDeclaredField("fd"); + fFdFd.setAccessible(true); + FileDescriptor fd = (FileDescriptor) fFdFd.get(channel); + + Field fFd = FileDescriptor.class.getDeclaredField("fd"); + fFd.setAccessible(true); + return fFd.getInt(fd); + } + + private static void testWrite(Path p, long blockSize) throws Exception { + try (FileChannel fc = FileChannel.open(p, + StandardOpenOption.READ, + StandardOpenOption.WRITE, + ExtendedOpenOption.DIRECT)) { + int fd = getFD(fc); - private static int testWrite(Path p, long blockSize) throws Exception { - try (FileChannel fc = FileChannel.open(p, StandardOpenOption.WRITE, - ExtendedOpenOption.DIRECT)) { int bs = (int)blockSize; int size = Math.max(BASE_SIZE, bs); int alignment = bs; @@ -60,22 +77,55 @@ private static int testWrite(Path p, long blockSize) throws Exception { for (int j = 0; j < size; j++) { src.put((byte)0); } - src.flip(); - fc.write(src); - return size; + + // If there is AV or other FS tracing software, it may cache the file + // contents on first access, even though we have asked for DIRECT here. + // Do several attempts to make test more resilient. + + for (int t = 0; t < TRIES; t++) { + flushFileCache(size, fd); + src.flip(); + fc.position(0); + fc.write(src); + if (!isFileInCache(size, fd)) { + return; + } + } + + throw new RuntimeException("DirectIO is not working properly with " + + "write. File still exists in cache!"); } } - private static int testRead(Path p, long blockSize) throws Exception { - try (FileChannel fc = FileChannel.open(p, ExtendedOpenOption.DIRECT)) { + private static void testRead(Path p, long blockSize) throws Exception { + try (FileChannel fc = FileChannel.open(p, + StandardOpenOption.READ, + ExtendedOpenOption.DIRECT)) { + int fd = getFD(fc); + int bs = (int)blockSize; int size = Math.max(BASE_SIZE, bs); int alignment = bs; ByteBuffer dest = ByteBuffer.allocateDirect(size + alignment - 1) .alignedSlice(alignment); assert dest.capacity() != 0; - fc.read(dest); - return size; + + // If there is AV or other FS tracing software, it may cache the file + // contents on first access, even though we have asked for DIRECT here. + // Do several attempts to make test more resilient. + + for (int t = 0; t < TRIES; t++) { + flushFileCache(size, fd); + dest.clear(); + fc.position(0); + fc.read(dest); + if (!isFileInCache(size, fd)) { + return; + } + } + + throw new RuntimeException("DirectIO is not working properly with " + + "read. File still exists in cache!"); } } @@ -84,12 +134,8 @@ public static Path createTempFile() throws IOException { Paths.get(System.getProperty("test.dir", ".")), "test", null); } - private static boolean isFileInCache(int size, Path p) { - String path = p.toString(); - return isFileInCache0(size, path); - } - - private static native boolean isFileInCache0(int size, String path); + private static native boolean flushFileCache(int size, int fd); + private static native boolean isFileInCache(int size, int fd); public static void main(String[] args) throws Exception { Path p = createTempFile(); @@ -98,16 +144,8 @@ public static void main(String[] args) throws Exception { System.loadLibrary("DirectIO"); try { - int size = testWrite(p, blockSize); - if (isFileInCache(size, p)) { - throw new RuntimeException("DirectIO is not working properly with " - + "write. File still exists in cache!"); - } - size = testRead(p, blockSize); - if (isFileInCache(size, p)) { - throw new RuntimeException("DirectIO is not working properly with " - + "read. File still exists in cache!"); - } + testWrite(p, blockSize); + testRead(p, blockSize); } finally { Files.delete(p); } diff --git a/test/jdk/java/nio/channels/FileChannel/directio/libDirectIO.c b/test/jdk/java/nio/channels/FileChannel/directio/libDirectIO.c index 4897500bf2d..5eea51da4c7 100644 --- a/test/jdk/java/nio/channels/FileChannel/directio/libDirectIO.c +++ b/test/jdk/java/nio/channels/FileChannel/directio/libDirectIO.c @@ -45,13 +45,27 @@ static void ThrowException(JNIEnv *env, const char *name, const char *msg) { /* * Class: DirectIO - * Method: isFileInCache0 - * Signature: (ILjava/lang/String;)Z + * Method: flushFileCache + * Signature: (II;)V */ -JNIEXPORT jboolean Java_DirectIOTest_isFileInCache0(JNIEnv *env, +JNIEXPORT void Java_DirectIOTest_flushFileCache(JNIEnv *env, jclass cls, jint file_size, - jstring file_path) { + jint fd) { +#ifdef __linux__ + posix_fadvise(fd, 0, file_size, POSIX_FADV_DONTNEED); +#endif +} + +/* + * Class: DirectIO + * Method: isFileInCache + * Signature: (II;)Z + */ +JNIEXPORT jboolean Java_DirectIOTest_isFileInCache(JNIEnv *env, + jclass cls, + jint file_size, + jint fd) { void *f_mmap; #ifdef __linux__ unsigned char *f_seg; @@ -69,17 +83,10 @@ JNIEXPORT jboolean Java_DirectIOTest_isFileInCache0(JNIEnv *env, size_t index = (file_size + page_size - 1) /page_size; jboolean result = JNI_FALSE; - const char* path = (*env)->GetStringUTFChars(env, file_path, JNI_FALSE); - - int fd = open(path, O_RDWR); - - (*env)->ReleaseStringUTFChars(env, file_path, path); - f_mmap = mmap(0, file_size, PROT_NONE, MAP_SHARED, fd, 0); if (f_mmap == MAP_FAILED) { - close(fd); ThrowException(env, "java/io/IOException", - "test of whether file exists in cache failed"); + "test of whether file exists in cache failed: mmap failed"); } f_seg = malloc(index); if (f_seg != NULL) { @@ -95,9 +102,8 @@ JNIEXPORT jboolean Java_DirectIOTest_isFileInCache0(JNIEnv *env, free(f_seg); } else { ThrowException(env, "java/io/IOException", - "test of whether file exists in cache failed"); + "test of whether file exists in cache failed: malloc failed"); } - close(fd); munmap(f_mmap, file_size); return result; } diff --git a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java index 99a127ca5ad..934bf509d88 100644 --- a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java +++ b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java @@ -40,7 +40,6 @@ * @key intermittent */ -import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; @@ -77,7 +76,7 @@ public Object[][] testCases() { }; } - @Test(dataProvider = "testCases", timeOut=30000) + @Test(dataProvider = "testCases") public void test(String desc, List opts) throws Throwable { String pathVar = Platform.sharedLibraryPathVariableName(); System.out.println(pathVar + "=" + libraryPath); diff --git a/test/jdk/java/nio/channels/vthread/BlockingChannelOps.java b/test/jdk/java/nio/channels/vthread/BlockingChannelOps.java index 7ff02cdfea4..1cdd090d1be 100644 --- a/test/jdk/java/nio/channels/vthread/BlockingChannelOps.java +++ b/test/jdk/java/nio/channels/vthread/BlockingChannelOps.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,7 +21,7 @@ * questions. */ -/** +/* * @test id=default * @bug 8284161 * @summary Test virtual threads doing blocking I/O on NIO channels @@ -29,7 +29,7 @@ * @run junit BlockingChannelOps */ -/** +/* * @test id=poller-modes * @requires (os.family == "linux") | (os.family == "mac") * @library /test/lib @@ -37,7 +37,7 @@ * @run junit/othervm -Djdk.pollerMode=2 BlockingChannelOps */ -/** +/* * @test id=no-vmcontinuations * @requires vm.continuations * @library /test/lib @@ -62,6 +62,7 @@ import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.channels.WritableByteChannel; +import java.util.concurrent.locks.LockSupport; import jdk.test.lib.thread.VThreadRunner; import org.junit.jupiter.api.Test; @@ -161,6 +162,22 @@ void testSocketChannelReadAsyncClose() throws Exception { }); } + /** + * SocketChannel shutdownInput while virtual thread blocked in read. + */ + @Test + void testSocketChannelReadAsyncShutdownInput() throws Exception { + VThreadRunner.run(() -> { + try (var connection = new Connection()) { + SocketChannel sc = connection.channel1(); + runAfterParkedAsync(sc::shutdownInput); + int n = sc.read(ByteBuffer.allocate(100)); + assertEquals(-1, n); + assertTrue(sc.isOpen()); + } + }); + } + /** * Virtual thread interrupted while blocked in SocketChannel read. */ @@ -190,13 +207,15 @@ void testSocketChannelReadInterrupt() throws Exception { @Test void testSocketChannelWriteAsyncClose() throws Exception { VThreadRunner.run(() -> { - boolean retry = true; - while (retry) { + boolean done = false; + while (!done) { try (var connection = new Connection()) { SocketChannel sc = connection.channel1(); // close sc when current thread blocks in write - runAfterParkedAsync(sc::close); + runAfterParkedAsync(sc::close, true); + + // write until channel is closed try { ByteBuffer bb = ByteBuffer.allocate(100*1024); for (;;) { @@ -206,11 +225,39 @@ void testSocketChannelWriteAsyncClose() throws Exception { } } catch (AsynchronousCloseException expected) { // closed when blocked in write - retry = false; + done = true; } catch (ClosedChannelException e) { - // closed when not blocked in write, need to retry test + // closed but not blocked in write, need to retry test + System.err.format("%s, need to retry!%n", e); + } + } + } + }); + } + + + /** + * SocketChannel shutdownOutput while virtual thread blocked in write. + */ + @Test + void testSocketChannelWriteAsyncShutdownOutput() throws Exception { + VThreadRunner.run(() -> { + try (var connection = new Connection()) { + SocketChannel sc = connection.channel1(); + + // shutdown output when current thread blocks in write + runAfterParkedAsync(sc::shutdownOutput); + try { + ByteBuffer bb = ByteBuffer.allocate(100*1024); + for (;;) { + int n = sc.write(bb); + assertTrue(n > 0); + bb.clear(); } + } catch (ClosedChannelException e) { + // expected } + assertTrue(sc.isOpen()); } }); } @@ -221,15 +268,16 @@ void testSocketChannelWriteAsyncClose() throws Exception { @Test void testSocketChannelWriteInterrupt() throws Exception { VThreadRunner.run(() -> { - boolean retry = true; - while (retry) { + boolean done = false; + while (!done) { try (var connection = new Connection()) { SocketChannel sc = connection.channel1(); // interrupt current thread when it blocks in write Thread thisThread = Thread.currentThread(); - runAfterParkedAsync(thisThread::interrupt); + runAfterParkedAsync(thisThread::interrupt, true); + // write until channel is closed try { ByteBuffer bb = ByteBuffer.allocate(100*1024); for (;;) { @@ -240,9 +288,10 @@ void testSocketChannelWriteInterrupt() throws Exception { } catch (ClosedByInterruptException e) { // closed when blocked in write assertTrue(Thread.interrupted()); - retry = false; + done = true; } catch (ClosedChannelException e) { - // closed when not blocked in write, need to retry test + // closed but not blocked in write, need to retry test + System.err.format("%s, need to retry!%n", e); } } } @@ -734,14 +783,16 @@ void testPipeReadInterrupt() throws Exception { @Test void testPipeWriteAsyncClose() throws Exception { VThreadRunner.run(() -> { - boolean retry = true; - while (retry) { + boolean done = false; + while (!done) { Pipe p = Pipe.open(); try (Pipe.SinkChannel sink = p.sink(); Pipe.SourceChannel source = p.source()) { // close sink when current thread blocks in write - runAfterParkedAsync(sink::close); + runAfterParkedAsync(sink::close, true); + + // write until channel is closed try { ByteBuffer bb = ByteBuffer.allocate(100*1024); for (;;) { @@ -751,9 +802,10 @@ void testPipeWriteAsyncClose() throws Exception { } } catch (AsynchronousCloseException e) { // closed when blocked in write - retry = false; + done = true; } catch (ClosedChannelException e) { - // closed when not blocked in write, need to retry test + // closed but not blocked in write, need to retry test + System.err.format("%s, need to retry!%n", e); } } } @@ -766,16 +818,17 @@ void testPipeWriteAsyncClose() throws Exception { @Test void testPipeWriteInterrupt() throws Exception { VThreadRunner.run(() -> { - boolean retry = true; - while (retry) { + boolean done = false; + while (!done) { Pipe p = Pipe.open(); try (Pipe.SinkChannel sink = p.sink(); Pipe.SourceChannel source = p.source()) { // interrupt current thread when it blocks in write Thread thisThread = Thread.currentThread(); - runAfterParkedAsync(thisThread::interrupt); + runAfterParkedAsync(thisThread::interrupt, true); + // write until channel is closed try { ByteBuffer bb = ByteBuffer.allocate(100*1024); for (;;) { @@ -786,9 +839,10 @@ void testPipeWriteInterrupt() throws Exception { } catch (ClosedByInterruptException expected) { // closed when blocked in write assertTrue(Thread.interrupted()); - retry = false; + done = true; } catch (ClosedChannelException e) { - // closed when not blocked in write, need to retry test + // closed but not blocked in write, need to retry test + System.err.format("%s, need to retry!%n", e); } } } @@ -848,26 +902,50 @@ interface ThrowingRunnable { } /** - * Runs the given task asynchronously after the current virtual thread has parked. + * Runs the given task asynchronously after the current virtual thread parks. + * @param writing if the thread will block in write * @return the thread started to run the task */ - static Thread runAfterParkedAsync(ThrowingRunnable task) { + private static Thread runAfterParkedAsync(ThrowingRunnable task, boolean writing) { Thread target = Thread.currentThread(); if (!target.isVirtual()) throw new WrongThreadException(); return Thread.ofPlatform().daemon().start(() -> { try { - Thread.State state = target.getState(); - while (state != Thread.State.WAITING - && state != Thread.State.TIMED_WAITING) { + // wait for target thread to park + while (!isWaiting(target)) { Thread.sleep(20); - state = target.getState(); } - Thread.sleep(20); // give a bit more time to release carrier + + // if the target thread is parked in write then we nudge it a few times + // to avoid wakeup with some bytes written + if (writing) { + for (int i = 0; i < 3; i++) { + LockSupport.unpark(target); + while (!isWaiting(target)) { + Thread.sleep(20); + } + } + } + task.run(); + } catch (Exception e) { e.printStackTrace(); } }); } + + private static Thread runAfterParkedAsync(ThrowingRunnable task) { + return runAfterParkedAsync(task, false); + } + + /** + * Return true if the given Thread is parked. + */ + private static boolean isWaiting(Thread target) { + Thread.State state = target.getState(); + assertNotEquals(Thread.State.TERMINATED, state); + return (state == Thread.State.WAITING || state == Thread.State.TIMED_WAITING); + } } diff --git a/test/jdk/java/nio/charset/Charset/IllegalCharsetName.java b/test/jdk/java/nio/charset/Charset/IllegalCharsetName.java index 266801cf52b..9f2879a3ff0 100644 --- a/test/jdk/java/nio/charset/Charset/IllegalCharsetName.java +++ b/test/jdk/java/nio/charset/Charset/IllegalCharsetName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023, 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 @@ -50,7 +50,7 @@ public void illegalCharsetsTest(String name) { assertThrows(IllegalCharsetNameException.class, () -> Charset.forName(name)); assertThrows(IllegalCharsetNameException.class, - () -> Charset.forName(name)); + () -> Charset.isSupported(name)); } // Charset.forName, Charset.isSupported, and the Charset constructor should @@ -60,7 +60,7 @@ public void emptyCharsetsTest() { assertThrows(IllegalCharsetNameException.class, () -> Charset.forName("")); assertThrows(IllegalCharsetNameException.class, - () -> Charset.forName("")); + () -> Charset.isSupported("")); assertThrows(IllegalCharsetNameException.class, () -> new Charset("", new String[]{}) { @Override diff --git a/test/jdk/java/nio/file/DirectoryStream/SecureDS.java b/test/jdk/java/nio/file/DirectoryStream/SecureDS.java index 6199596b30c..d5d4b1904ea 100644 --- a/test/jdk/java/nio/file/DirectoryStream/SecureDS.java +++ b/test/jdk/java/nio/file/DirectoryStream/SecureDS.java @@ -24,7 +24,7 @@ /* @test * @bug 4313887 6838333 8343020 8357425 * @summary Unit test for java.nio.file.SecureDirectoryStream - * @requires (os.family == "linux" | os.family == "mac") + * @requires (os.family == "linux" | os.family == "mac" | os.family == "aix") * @library .. /test/lib * @build jdk.test.lib.Platform * @run main SecureDS diff --git a/test/jdk/java/nio/file/FileStore/Basic.java b/test/jdk/java/nio/file/FileStore/Basic.java index 0a7b3d5e2f6..052348c1f02 100644 --- a/test/jdk/java/nio/file/FileStore/Basic.java +++ b/test/jdk/java/nio/file/FileStore/Basic.java @@ -38,6 +38,7 @@ import jdk.test.lib.Platform; import jdk.test.lib.util.FileUtils; +import static jdk.test.lib.Asserts.*; public class Basic { @@ -52,11 +53,6 @@ public static void main(String[] args) throws IOException { } } - static void assertTrue(boolean okay) { - if (!okay) - throw new RuntimeException("Assertion failed"); - } - static void checkWithin1GB(String space, long expected, long actual) { long diff = Math.abs(actual - expected); if (diff > G) { @@ -73,8 +69,11 @@ static void testFileAttributes(Path file, FileStore store = Files.getFileStore(file); boolean supported = store.supportsFileAttributeView(viewClass); assertTrue(store.supportsFileAttributeView(viewName) == supported); - boolean haveView = Files.getFileAttributeView(file, viewClass) != null; - assertTrue(haveView == supported); + // If the file attribute view is supported by the FileStore then + // Files.getFileAttributeView should return that view + if (supported) { + assertNotNull(Files.getFileAttributeView(file, viewClass)); + } } static void doTests(Path dir) throws IOException { diff --git a/test/jdk/java/rmi/server/RemoteServer/AddrInUse.java b/test/jdk/java/rmi/server/RemoteServer/AddrInUse.java index 34e343b6193..86ac5b0313b 100644 --- a/test/jdk/java/rmi/server/RemoteServer/AddrInUse.java +++ b/test/jdk/java/rmi/server/RemoteServer/AddrInUse.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,6 @@ /* @test * @bug 4111507 * @summary retryServerSocket should not retry on BindException - * @author Ann Wollrath * * @run main/othervm AddrInUse */ @@ -33,75 +32,54 @@ import java.rmi.registry.LocateRegistry; import java.rmi.server.ExportException; -public class AddrInUse implements Runnable { +public class AddrInUse { - private static int port = -1; - private static final long TIMEOUT = 10000; - - private boolean exportSucceeded = false; - private Throwable exportException = null; - - public void run() { - - /* - * Attempt to create (i.e. export) a registry on the port that - * has already been bound, and record the result. - */ - try { - LocateRegistry.createRegistry(port); - synchronized (this) { - exportSucceeded = true; - notifyAll(); - } - } catch (Throwable t) { - synchronized (this) { - exportException = t; - notifyAll(); - } - } - } + private static volatile Throwable registryExportFailure = null; public static void main(String[] args) throws Exception { - System.err.println("\nRegression test for bug 4111507\n"); - /* * Bind a server socket to a port. */ - ServerSocket server = new ServerSocket(0); - port = server.getLocalPort(); - System.err.println("Created a ServerSocket on port " + port + "..."); - - /* - * Start a thread that creates a registry on the same port, - * and analyze the result. - */ - System.err.println("create a registry on the same port..."); - System.err.println("(should cause an ExportException)"); - AddrInUse obj = new AddrInUse(); - synchronized (obj) { - (new Thread(obj, "AddrInUse")).start(); + try (ServerSocket server = new ServerSocket(0)) { + int port = server.getLocalPort(); + System.err.println("Created a ServerSocket on port " + port + "..."); /* - * Don't wait forever (original bug is that the export - * hangs). + * Start a thread that creates a registry on the same port, + * and analyze the result. */ - obj.wait(TIMEOUT); + System.err.println("create a registry on the same port..."); + System.err.println("(should cause an ExportException)"); - if (obj.exportSucceeded) { - throw new RuntimeException( - "TEST FAILED: export on already-bound port succeeded"); - } else if (obj.exportException != null) { - obj.exportException.printStackTrace(); - if (obj.exportException instanceof ExportException) { - System.err.println("TEST PASSED"); - } else { - throw new RuntimeException( - "TEST FAILED: unexpected exception occurred", - obj.exportException); + Thread exportRegistryThread = new Thread(() -> { + /* + * Attempt to create (i.e. export) a registry on the port that + * has already been bound, and record the result. + */ + try { + LocateRegistry.createRegistry(port); + } catch (Throwable t) { + registryExportFailure = t; } - } else { - throw new RuntimeException("TEST FAILED: export timed out"); + }, "ExportRegistry-Thread"); + + exportRegistryThread.start(); + + /* + * Wait for the LocateRegistry.createRegistry() call to complete or + * if it blocks forever (due to the original bug), then let jtreg fail + * the test with a timeout + */ + exportRegistryThread.join(); + if (registryExportFailure == null) { + throw new RuntimeException( + "TEST FAILED: export on already-bound port succeeded"); + } + if (!(registryExportFailure instanceof ExportException)) { + throw new RuntimeException( + "TEST FAILED: unexpected exception occurred", registryExportFailure); } + System.err.println("TEST PASSED, received expected exception: " + registryExportFailure); } } } diff --git a/test/jdk/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java b/test/jdk/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java index 2370dcd35c4..4de6598a0f4 100644 --- a/test/jdk/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java +++ b/test/jdk/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,12 +54,11 @@ import java.rmi.*; import java.rmi.server.*; -import sun.rmi.transport.*; -import sun.rmi.*; import java.util.Map; import java.io.*; import java.lang.reflect.*; import java.rmi.registry.*; +import sun.rmi.transport.*; public class CheckLeaseLeak extends UnicastRemoteObject implements LeaseLeak { public CheckLeaseLeak() throws RemoteException { } @@ -102,8 +101,6 @@ public static void main (String[] args) { System.err.println("Created client: " + i); JavaVM jvm = new JavaVM("LeaseLeakClient", - " -Djava.security.policy=" + - TestParams.defaultPolicy + " -Drmi.registry.port=" + registryPort, ""); @@ -128,8 +125,8 @@ public static void main (String[] args) { } } - /* numLeft should be 2 - if 11 there is a problem. */ - if (numLeft > 2) { + /* numLeft should be 4 - if 11 there is a problem. */ + if (numLeft > 4) { TestLibrary.bomb("Too many objects in DGCImpl.leaseTable: "+ numLeft); } else { @@ -156,57 +153,51 @@ private static int getDGCLeaseTableSize () { Field f; try { - f = (Field) java.security.AccessController.doPrivileged - (new java.security.PrivilegedExceptionAction() { - public Object run() throws Exception { - - ObjID dgcID = new ObjID(DGC_ID); - - /* - * Construct an ObjectEndpoint containing DGC's - * ObjID. - */ - Class oeClass = - Class.forName("sun.rmi.transport.ObjectEndpoint"); - Class[] constrParams = - new Class[]{ ObjID.class, Transport.class }; - Constructor oeConstructor = - oeClass.getDeclaredConstructor(constrParams); - oeConstructor.setAccessible(true); - Object oe = - oeConstructor.newInstance( - new Object[]{ dgcID, null }); - - /* - * Get Target that contains DGCImpl in ObjectTable - */ - Class objTableClass = - Class.forName("sun.rmi.transport.ObjectTable"); - Class getTargetParams[] = new Class[] { oeClass }; - Method objTableGetTarget = - objTableClass.getDeclaredMethod("getTarget", - getTargetParams); - objTableGetTarget.setAccessible(true); - Target dgcTarget = (Target) - objTableGetTarget.invoke(null, new Object[]{ oe }); - - /* get the DGCImpl from its Target */ - Method targetGetImpl = - dgcTarget.getClass().getDeclaredMethod + ObjID dgcID = new ObjID(DGC_ID); + /* + * Construct an ObjectEndpoint containing DGC's + * ObjID. + */ + Class oeClass = + Class.forName("sun.rmi.transport.ObjectEndpoint"); + Class[] constrParams = + new Class[]{ ObjID.class, Transport.class }; + Constructor oeConstructor = + oeClass.getDeclaredConstructor(constrParams); + oeConstructor.setAccessible(true); + Object oe = + oeConstructor.newInstance( + new Object[]{ dgcID, null }); + + /* + * Get Target that contains DGCImpl in ObjectTable + */ + Class objTableClass = + Class.forName("sun.rmi.transport.ObjectTable"); + Class getTargetParams[] = new Class[] { oeClass }; + Method objTableGetTarget = + objTableClass.getDeclaredMethod("getTarget", + getTargetParams); + objTableGetTarget.setAccessible(true); + Target dgcTarget = (Target) + objTableGetTarget.invoke(null, new Object[]{ oe }); + + /* get the DGCImpl from its Target */ + Method targetGetImpl = + dgcTarget.getClass().getDeclaredMethod ("getImpl", null); - targetGetImpl.setAccessible(true); - dgcImpl[0] = - (Remote) targetGetImpl.invoke(dgcTarget, null); + targetGetImpl.setAccessible(true); + dgcImpl[0] = + (Remote) targetGetImpl.invoke(dgcTarget, null); - /* Get the lease table from the DGCImpl. */ - Field reflectedLeaseTable = - dgcImpl[0].getClass().getDeclaredField + /* Get the lease table from the DGCImpl. */ + Field reflectedLeaseTable = + dgcImpl[0].getClass().getDeclaredField ("leaseTable"); - reflectedLeaseTable.setAccessible(true); + reflectedLeaseTable.setAccessible(true); + + f = reflectedLeaseTable; - return reflectedLeaseTable; - } - }); /** * This is the leaseTable that will fill up with LeaseInfo @@ -217,9 +208,6 @@ public Object run() throws Exception { numLeaseInfosLeft = leaseTable.size(); } catch(Exception e) { - if (e instanceof java.security.PrivilegedActionException) - e = ((java.security.PrivilegedActionException) e). - getException(); TestLibrary.bomb(e); } diff --git a/test/jdk/java/rmi/transport/checkLeaseInfoLeak/LeaseLeakClient.java b/test/jdk/java/rmi/transport/checkLeaseInfoLeak/LeaseLeakClient.java index d9cf9fa9e96..dd24b819146 100644 --- a/test/jdk/java/rmi/transport/checkLeaseInfoLeak/LeaseLeakClient.java +++ b/test/jdk/java/rmi/transport/checkLeaseInfoLeak/LeaseLeakClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ public class LeaseLeakClient { public static void main(String args[]) { - TestLibrary.suggestSecurityManager("java.rmi.RMISecurityManager"); try { LeaseLeak leaseLeak = null; diff --git a/test/jdk/java/security/KeyStore/TestDisabledAlgorithms.java b/test/jdk/java/security/KeyStore/TestDisabledAlgorithms.java new file mode 100644 index 00000000000..0c060a45b7e --- /dev/null +++ b/test/jdk/java/security/KeyStore/TestDisabledAlgorithms.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8244336 + * @summary Test JCE layer algorithm restriction + * @library /test/lib + * @run main/othervm TestDisabledAlgorithms KEYSTORE.JKs true + * @run main/othervm TestDisabledAlgorithms keySTORE.what false + * @run main/othervm TestDisabledAlgorithms kEYstoRe.jceKS false + * @run main/othervm -Djdk.crypto.disabledAlgorithms="keystore.jkS" TestDisabledAlgorithms keySTORE.jceKs true + * @run main/othervm -Djdk.crypto.disabledAlgorithms="KEYstORE.what" TestDisabledAlgorithms KeYStore.JKs false + * @run main/othervm -Djdk.crypto.disabledAlgorithms="keystOre.jceKS" TestDisabledAlgorithms KEysTORE.JKS false + */ +import java.io.File; +import java.util.List; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.Provider; +import java.security.Security; +import jdk.test.lib.Utils; + +public class TestDisabledAlgorithms { + + private static final String PROP_NAME = "jdk.crypto.disabledAlgorithms"; + + // reuse existing JKS test keystore + private final static String DIR = System.getProperty("test.src", "."); + private static final char[] PASSWD = "passphrase".toCharArray(); + private static final String JKS_FN = "keystore.jks"; + + private static void test(List algos, Provider p, + boolean shouldThrow) throws Exception { + + for (String a : algos) { + System.out.println("Testing " + (p != null ? p.getName() : "") + + ": " + a + ", shouldThrow=" + shouldThrow); + if (shouldThrow) { + if (p == null) { + Utils.runAndCheckException(() -> KeyStore.getInstance(a), + KeyStoreException.class); + Utils.runAndCheckException( + () -> KeyStore.getInstance(new File(DIR, JKS_FN), + PASSWD), + KeyStoreException.class); + Utils.runAndCheckException( + () -> KeyStore.getInstance(new File(DIR, JKS_FN), + () -> { + return new KeyStore.PasswordProtection(PASSWD); + }), + KeyStoreException.class); + } else { + // with a provider argument + Utils.runAndCheckException(() -> KeyStore.getInstance(a, p), + KeyStoreException.class); + Utils.runAndCheckException(() -> KeyStore.getInstance(a, + p.getName()), KeyStoreException.class); + } + } else { + KeyStore k; + if (p == null) { + k = KeyStore.getInstance(a); + System.out.println("Got KeyStore w/ algo " + k.getType()); + k = KeyStore.getInstance(new File(DIR, JKS_FN), PASSWD); + System.out.println("Got KeyStore w/ algo " + k.getType()); + k = KeyStore.getInstance(new File(DIR, JKS_FN), + () -> { + return new KeyStore.PasswordProtection(PASSWD); + }); + System.out.println("Got KeyStore w/ algo " + k.getType()); + } else { + // with a provider argument + k = KeyStore.getInstance(a, p); + k = KeyStore.getInstance(a, p.getName()); + System.out.println("Got KeyStore w/ algo " + k.getType()); + } + } + } + } + + public static void main(String[] args) throws Exception { + String propValue = args[0]; + System.out.println("Setting Security Prop " + PROP_NAME + " = " + + propValue); + Security.setProperty(PROP_NAME, propValue); + + boolean shouldThrow = Boolean.valueOf(args[1]); + + List algos = List.of("JKS", "jkS"); + // test w/o provider + test(algos, null, shouldThrow); + + // test w/ provider + Provider[] providers = Security.getProviders("KeyStore.JKS"); + for (Provider p : providers) { + test(algos, p, shouldThrow); + } + } +} diff --git a/test/jdk/java/security/MessageDigest/TestDisabledAlgorithms.java b/test/jdk/java/security/MessageDigest/TestDisabledAlgorithms.java new file mode 100644 index 00000000000..413898e0c70 --- /dev/null +++ b/test/jdk/java/security/MessageDigest/TestDisabledAlgorithms.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8244336 + * @summary Test JCE layer algorithm restriction + * @library /test/lib + * @run main/othervm TestDisabledAlgorithms MESSAGEdigest.Sha-512 true + * @run main/othervm TestDisabledAlgorithms messageDIGest.what false + * @run main/othervm TestDisabledAlgorithms meSSagedIgest.sHA-512/224 false + */ +import java.util.List; +import java.security.NoSuchAlgorithmException; +import java.security.MessageDigest; +import java.security.Provider; +import java.security.Security; +import jdk.test.lib.Utils; + +public class TestDisabledAlgorithms { + + private static final String PROP_NAME = "jdk.crypto.disabledAlgorithms"; + + private static void test(List algos, Provider p, + boolean shouldThrow) throws Exception { + + for (String a : algos) { + System.out.println("Testing " + (p != null ? p.getName() : "") + + ": " + a + ", shouldThrow=" + shouldThrow); + if (shouldThrow) { + if (p == null) { + Utils.runAndCheckException(() -> MessageDigest.getInstance(a), + NoSuchAlgorithmException.class); + } else { + Utils.runAndCheckException(() -> MessageDigest.getInstance(a, p), + NoSuchAlgorithmException.class); + Utils.runAndCheckException(() -> MessageDigest.getInstance(a, + p.getName()), NoSuchAlgorithmException.class); + } + } else { + MessageDigest m; + if (p == null) { + m = MessageDigest.getInstance(a); + } else { + m = MessageDigest.getInstance(a, p); + m = MessageDigest.getInstance(a, p.getName()); + } + System.out.println("Got MessageDigest w/ algo " + + m.getAlgorithm()); + } + } + } + + public static void main(String[] args) throws Exception { + String propValue = args[0]; + System.out.println("Setting Security Prop " + PROP_NAME + " = " + + propValue); + Security.setProperty(PROP_NAME, propValue); + + boolean shouldThrow = Boolean.valueOf(args[1]); + + List algos = List.of("sHA-512", "shA-512", + "2.16.840.1.101.3.4.2.3"); + // test w/o provider + test(algos, null, shouldThrow); + + // test w/ provider + Provider[] providers = Security.getProviders("MessageDigest.SHA-512"); + for (Provider p : providers) { + test(algos, p, shouldThrow); + } + } +} diff --git a/test/jdk/java/security/Provider/NewInstance.java b/test/jdk/java/security/Provider/NewInstance.java index ad69f468925..547b9111682 100644 --- a/test/jdk/java/security/Provider/NewInstance.java +++ b/test/jdk/java/security/Provider/NewInstance.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,21 +26,34 @@ * @bug 8039853 * @summary Provider.Service.newInstance() does not work with current JDK JGSS Mechanisms + * @library /test/lib */ -import java.security.*; -import java.util.*; + +import jtreg.SkippedException; + +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.Security; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; public class NewInstance { public static void main(String[] args) throws Exception { - for (Provider p : Security.getProviders()) { + + System.out.println("Removing SunPCSC provider from the list (A smartcard might not be installed)."); + final List providers = Arrays.stream(Security.getProviders()) + .filter(provider -> !provider.getName().equals("SunPCSC")) + .collect(Collectors.toList()); + + for (Provider p : providers) { System.out.println("---------"); System.out.println(p.getName() + ":" + p.getInfo()); - if (p.getName().equals("SunPCSC")) { - System.out.println("A smartcard might not be installed. Skip test."); - continue; - } Set set = p.getServices(); Iterator i = set.iterator(); diff --git a/test/jdk/java/security/Signature/TestDisabledAlgorithms.java b/test/jdk/java/security/Signature/TestDisabledAlgorithms.java new file mode 100644 index 00000000000..cdecf113d80 --- /dev/null +++ b/test/jdk/java/security/Signature/TestDisabledAlgorithms.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8244336 + * @summary Test JCE layer algorithm restriction + * @library /test/lib + * @run main/othervm TestDisabledAlgorithms SIGNATURe.sha512withRSA true + * @run main/othervm TestDisabledAlgorithms signaturE.what false + * @run main/othervm TestDisabledAlgorithms SiGnAtUrE.SHa512/224withRSA false + */ +import java.util.List; +import java.security.NoSuchAlgorithmException; +import java.security.Signature; +import java.security.Provider; +import java.security.Security; +import jdk.test.lib.Utils; + +public class TestDisabledAlgorithms { + + private static final String PROP_NAME = "jdk.crypto.disabledAlgorithms"; + + private static void test(List algos, Provider p, + boolean shouldThrow) throws Exception { + + for (String a : algos) { + System.out.println("Testing " + (p != null ? p.getName() : "") + + ": " + a + ", shouldThrow=" + shouldThrow); + if (shouldThrow) { + if (p == null) { + Utils.runAndCheckException(() -> Signature.getInstance(a), + NoSuchAlgorithmException.class); + } else { + Utils.runAndCheckException(() -> Signature.getInstance(a, p), + NoSuchAlgorithmException.class); + Utils.runAndCheckException(() -> Signature.getInstance(a, + p.getName()), NoSuchAlgorithmException.class); + } + } else { + Signature s; + if (p == null) { + s = Signature.getInstance(a); + } else { + s = Signature.getInstance(a, p); + s = Signature.getInstance(a, p.getName()); + } + System.out.println("Got Signature w/ algo " + s.getAlgorithm()); + } + } + } + + public static void main(String[] args) throws Exception { + String propValue = args[0]; + System.out.println("Setting Security Prop " + PROP_NAME + " = " + + propValue); + Security.setProperty(PROP_NAME, propValue); + + boolean shouldThrow = Boolean.valueOf(args[1]); + + List algos = List.of("sha512withRsa", "1.2.840.113549.1.1.13"); + // test w/o provider + test(algos, null, shouldThrow); + + // test w/ provider + Provider[] providers = Security.getProviders("Signature.SHA512withRSA"); + for (Provider p : providers) { + test(algos, p, shouldThrow); + } + } +} diff --git a/test/jdk/java/security/SignedJar/spi-calendar-provider/TestSPISigned.java b/test/jdk/java/security/SignedJar/spi-calendar-provider/TestSPISigned.java index 83c2d85f6e4..fb54d468d18 100644 --- a/test/jdk/java/security/SignedJar/spi-calendar-provider/TestSPISigned.java +++ b/test/jdk/java/security/SignedJar/spi-calendar-provider/TestSPISigned.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2022, Red Hat, Inc. + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +31,7 @@ import java.util.Locale; import java.util.List; import java.util.ArrayList; +import java.net.URI; import java.nio.file.Paths; import java.nio.file.Path; import java.nio.file.Files; @@ -54,12 +56,9 @@ */ public class TestSPISigned { - private static final String TEST_CLASSES = System.getProperty("test.classes", "."); private static final String TEST_SRC = System.getProperty("test.src", "."); private static final Path META_INF_DIR = Paths.get(TEST_SRC, "provider", "meta"); - private static final Path PROVIDER_PARENT = Paths.get(TEST_CLASSES, ".."); - private static final Path PROVIDER_DIR = PROVIDER_PARENT.resolve("provider"); private static final Path MODS_DIR = Paths.get("mods"); private static final Path UNSIGNED_JAR = MODS_DIR.resolve("unsigned-with-locale.jar"); private static final Path SIGNED_JAR = MODS_DIR.resolve("signed-with-locale.jar"); @@ -81,7 +80,9 @@ public static void main(String[] args) throws Throwable { // Set up signed jar with custom calendar data provider // // 1. Create jar with custom CalendarDataProvider - JarUtils.createJarFile(UNSIGNED_JAR, PROVIDER_DIR); + var codeSource = baz.CalendarDataProviderImpl.class.getProtectionDomain().getCodeSource(); + var providerDir = Path.of(URI.create(codeSource.getLocation().toString())); + JarUtils.createJarFile(UNSIGNED_JAR, providerDir); JarUtils.updateJarFile(UNSIGNED_JAR, META_INF_DIR); // create signer's keypair SecurityTools.keytool("-genkeypair -keyalg RSA -keystore ks " + diff --git a/test/jdk/java/security/cert/CertStore/NoLDAP.java b/test/jdk/java/security/cert/CertStore/NoLDAP.java index 868411e63c4..812a978931d 100644 --- a/test/jdk/java/security/cert/CertStore/NoLDAP.java +++ b/test/jdk/java/security/cert/CertStore/NoLDAP.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,23 @@ * @bug 8004502 * @summary Sanity check that NoSuchAlgorithmException is thrown when requesting * a CertStore of type "LDAP" and LDAP is not available. + * @library /test/lib */ import java.security.NoSuchAlgorithmException; import java.security.cert.CertStore; import java.security.cert.LDAPCertStoreParameters; +import jtreg.SkippedException; public class NoLDAP { public static void main(String[] args) throws Exception { try { Class.forName("javax.naming.ldap.LdapName"); - System.out.println("LDAP is present, test skipped"); - return; - } catch (ClassNotFoundException ignore) { } + throw new SkippedException("LDAP is present"); + } catch (ClassNotFoundException ignore) { + System.err.println("Expected: class not found exception " + ignore.getMessage()); + } try { CertStore.getInstance("LDAP", new LDAPCertStoreParameters()); diff --git a/test/jdk/java/text/Format/CompactNumberFormat/TestClone.java b/test/jdk/java/text/Format/CompactNumberFormat/TestClone.java new file mode 100644 index 00000000000..42abc1be2ba --- /dev/null +++ b/test/jdk/java/text/Format/CompactNumberFormat/TestClone.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * @test + * @bug 8368328 + * @summary Tests if CompactNumberFormat.clone() creates an independent object + * @run junit/othervm --add-opens java.base/java.text=ALL-UNNAMED TestClone + */ + +import java.lang.invoke.MethodHandles; +import java.text.CompactNumberFormat; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; +import java.util.Locale; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotSame; + +public class TestClone { + // Concurrently parse numbers using cloned instances as originally + // reported in the bug. This test could produce false negative results, + // depending on the testing environment + @Test + void randomAccessTest() { + var original = + NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT); + var threads = IntStream.range(0, 10) + .mapToObj(num -> new Thread(() -> { + var clone = (NumberFormat) original.clone(); + for (int i = 0; i < 1000; i++) { + assertDoesNotThrow(() -> + assertEquals(num, clone.parse(String.valueOf(num)).intValue())); + } + })).toList(); + threads.forEach(Thread::start); + threads.forEach(t -> { + try { + t.join(); + } catch (InterruptedException ie) { + throw new RuntimeException(ie); + } + }); + } + + private static Stream referenceFields() throws ClassNotFoundException { + return Stream.of( + Arguments.of("compactPatterns", String[].class), + Arguments.of("symbols", DecimalFormatSymbols.class), + Arguments.of("decimalFormat", DecimalFormat.class), + Arguments.of("defaultDecimalFormat", DecimalFormat.class), + Arguments.of("digitList", Class.forName("java.text.DigitList")) + ); + } + // Explicitly checks if the cloned object has its own references for + // "compactPatterns", "symbols", "decimalFormat", "defaultDecimalFormat", + // and "digitList" + @ParameterizedTest + @MethodSource("referenceFields") + void whiteBoxTest(String fieldName, Class type) throws Throwable { + var original = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT); + var clone = original.clone(); + var lookup = MethodHandles.privateLookupIn(CompactNumberFormat.class, MethodHandles.lookup()); + + assertNotSame(lookup.findGetter(CompactNumberFormat.class, fieldName, type).invoke(original), + lookup.findGetter(CompactNumberFormat.class, fieldName, type).invoke(clone)); + } +} diff --git a/test/jdk/java/text/Format/DecimalFormat/RoundingTiesNearZeroTest.java b/test/jdk/java/text/Format/DecimalFormat/RoundingTiesNearZeroTest.java new file mode 100644 index 00000000000..9cbf572f368 --- /dev/null +++ b/test/jdk/java/text/Format/DecimalFormat/RoundingTiesNearZeroTest.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8369050 + * @summary Check rounding of DecimalFormat on tie cases when the maximum + * fraction digits allowed is one less than the position of the first + * significant digit in the double. + * @run junit RoundingTiesNearZeroTest + */ + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.math.RoundingMode; +import java.text.NumberFormat; +import java.util.Locale; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class RoundingTiesNearZeroTest { + + // Safe to re-use since we are not testing any fast-path cases + // so state is irrelevant + private static final NumberFormat format = NumberFormat.getInstance(Locale.US); + + @ParameterizedTest + @MethodSource("ties") + void roundingTieTest(RoundingMode rm, int maxDigits, double db, String expected) { + format.setRoundingMode(rm); + format.setMaximumFractionDigits(maxDigits); + assertEquals(expected, format.format(db), "Rounding failed under " + rm); + } + + static Stream ties() { + return Stream.of( + // 1) String is exact as binary + // 0.5 -> 0.5 + Arguments.of(RoundingMode.HALF_EVEN, 0, 0.5, "0"), + Arguments.of(RoundingMode.HALF_UP, 0, 0.5, "1"), + Arguments.of(RoundingMode.HALF_DOWN, 0, 0.5, "0"), + // 2) String is rounded up from binary + // 0.0000005 -> 4.999999999999999773740559129431293428069693618454039096832275390625E-7 + Arguments.of(RoundingMode.HALF_EVEN, 6, 0.0000005, "0"), + Arguments.of(RoundingMode.HALF_UP, 6, 0.0000005, "0"), + Arguments.of(RoundingMode.HALF_DOWN, 6, 0.0000005, "0"), + // 3) String is not rounded up from binary + // Non-exponential notation + // 0.05 -> 0.05000000000000000277555756156289135105907917022705078125 + Arguments.of(RoundingMode.HALF_EVEN, 1, 0.05, "0.1"), + Arguments.of(RoundingMode.HALF_UP, 1, 0.05, "0.1"), + Arguments.of(RoundingMode.HALF_DOWN, 1, 0.05, "0.1"), + // Exponential notation + // 0.00005 -> 0.0000500000000000000023960868011929647991564706899225711822509765625 + Arguments.of(RoundingMode.HALF_EVEN, 4, 0.00005, "0.0001"), + Arguments.of(RoundingMode.HALF_UP, 4, 0.00005, "0.0001"), + Arguments.of(RoundingMode.HALF_DOWN, 4, 0.00005, "0.0001") + ); + } +} diff --git a/test/jdk/java/text/Format/NumberFormat/Bug4944439.java b/test/jdk/java/text/Format/NumberFormat/Bug4944439.java index 561052e9a95..a13a36733e2 100644 --- a/test/jdk/java/text/Format/NumberFormat/Bug4944439.java +++ b/test/jdk/java/text/Format/NumberFormat/Bug4944439.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,22 +23,19 @@ /* * @test - * @bug 4944439 + * @bug 4944439 8372609 * @summary Confirm that numbers where all digits after the decimal separator are 0 * and which are between Long.MIN_VALUE and Long.MAX_VALUE are returned * as Long(not double). * @run junit Bug4944439 */ -import java.text.DecimalFormat; +import java.text.NumberFormat; import java.util.ArrayList; import java.util.Locale; import java.util.stream.Stream; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; @@ -47,21 +44,7 @@ public class Bug4944439 { - // Save JVM default locale - private static final Locale savedLocale = Locale.getDefault(); - private static final DecimalFormat df = new DecimalFormat(); - - // Set JVM default locale to US for testing - @BeforeAll - static void initAll() { - Locale.setDefault(Locale.US); - } - - // Restore JVM default locale - @AfterAll - static void tearDownAll() { - Locale.setDefault(savedLocale); - } + private static final NumberFormat df = NumberFormat.getInstance(Locale.US); // Check return type and value returned by DecimalFormat.parse() for longs @ParameterizedTest diff --git a/test/jdk/java/text/Format/NumberFormat/NumberRegression.java b/test/jdk/java/text/Format/NumberFormat/NumberRegression.java index 2ff111f0e4b..6aca6d3e477 100644 --- a/test/jdk/java/text/Format/NumberFormat/NumberRegression.java +++ b/test/jdk/java/text/Format/NumberFormat/NumberRegression.java @@ -30,7 +30,7 @@ * 4125885 4134034 4134300 4140009 4141750 4145457 4147295 4147706 4162198 * 4162852 4167494 4170798 4176114 4179818 4185761 4212072 4212073 4216742 * 4217661 4243011 4243108 4330377 4233840 4241880 4833877 8008577 8227313 - * 8174269 + * 8174269 8369050 * @summary Regression tests for NumberFormat and associated classes * @library /java/text/testlib * @build HexDumpReader TestUtils @@ -1853,7 +1853,7 @@ public void test4241880() { "2%", "1%", "2%", "2%", "1%", "0%", "0%", "1%", "1%", "1%", "0", "2", "0.2", "0.6", "0.04", - "0.04", "0.000", "0.002", + "0.04", "0.001", "0.002", }; for (int i = 0; i < input.length; i++) { DecimalFormat format = new DecimalFormat(pattern[i]); diff --git a/test/jdk/java/util/Calendar/JapaneseCalendarNameTest.java b/test/jdk/java/util/Calendar/JapaneseCalendarNameTest.java new file mode 100644 index 00000000000..6c8597c9404 --- /dev/null +++ b/test/jdk/java/util/Calendar/JapaneseCalendarNameTest.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8202088 8207152 8217609 8219890 8358819 + * @summary Test the localized Japanese calendar names, such as + * the Reiwa Era names (May 1st. 2019-), or the Gan-nen text + * @modules jdk.localedata + * @run junit JapaneseCalendarNameTest + */ + +import static java.util.Calendar.*; +import static java.util.Locale.*; + +import java.text.DateFormat; +import java.text.ParseException; +import java.util.Calendar; +import java.util.Locale; +import java.util.stream.Stream; + +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.assertEquals; + +public class JapaneseCalendarNameTest { + private static final Calendar c = new Calendar.Builder() + .setCalendarType("japanese") + .setFields(ERA, 5, YEAR, 1, MONTH, MAY, DAY_OF_MONTH, 1) + .build(); + private static final Locale JAJPJP = Locale.of("ja", "JP", "JP"); + private static final Locale JCAL = Locale.forLanguageTag("ja-u-ca-japanese"); + + private static Stream reiwaEraNames() { + return Stream.of( + // type, locale, name + Arguments.of(LONG, JAPAN, "令和"), + Arguments.of(LONG, US, "Reiwa"), + Arguments.of(LONG, CHINA, "令和"), + Arguments.of(SHORT, JAPAN, "令和"), + Arguments.of(SHORT, US, "Reiwa"), + Arguments.of(SHORT, CHINA, "令和") + ); + } + + @ParameterizedTest + @MethodSource("reiwaEraNames") + void testReiwaEraName(int type, Locale locale, String expected) { + assertEquals(expected, c.getDisplayName(ERA, type, locale)); + } + + private static Stream gannen() { + return Stream.of( + // format, + // formatted text + Arguments.of(DateFormat.getDateInstance(DateFormat.FULL, JAJPJP), + "令和元年5月1日水曜日"), + Arguments.of(DateFormat.getDateInstance(DateFormat.FULL, JCAL), + "令和元年5月1日水曜日"), + Arguments.of(DateFormat.getDateInstance(DateFormat.LONG, JAJPJP), + "令和元年5月1日"), + Arguments.of(DateFormat.getDateInstance(DateFormat.LONG, JCAL), + "令和元年5月1日"), + Arguments.of(DateFormat.getDateInstance(DateFormat.MEDIUM, JAJPJP), + "令和1年5月1日"), + Arguments.of(DateFormat.getDateInstance(DateFormat.MEDIUM, JCAL), + "令和1年5月1日"), + Arguments.of(DateFormat.getDateInstance(DateFormat.SHORT, JAJPJP), + "令和1/5/1"), + Arguments.of(DateFormat.getDateInstance(DateFormat.SHORT, JCAL), + "令和1/5/1") + ); + } + + @ParameterizedTest + @MethodSource("gannen") + void testGannenFormat(DateFormat df, String expected) { + assertEquals(expected, df.format(c.getTime())); + } + + @ParameterizedTest + @MethodSource("gannen") + void testGannenParse(DateFormat df, String formatted) throws ParseException { + assertEquals(c.getTime(), df.parse(formatted)); + } +} diff --git a/test/jdk/java/util/Calendar/JapaneseEraNameTest.java b/test/jdk/java/util/Calendar/JapaneseEraNameTest.java deleted file mode 100644 index 11e35927adf..00000000000 --- a/test/jdk/java/util/Calendar/JapaneseEraNameTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 8202088 8207152 8217609 8219890 - * @summary Test the localized Japanese new era name (May 1st. 2019-) - * is retrieved no matter CLDR provider contains the name or not. - * @modules jdk.localedata - * @run testng JapaneseEraNameTest - */ - -import static java.util.Calendar.*; -import static java.util.Locale.*; -import java.util.Calendar; -import java.util.Locale; - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import static org.testng.Assert.assertEquals; - -@Test -public class JapaneseEraNameTest { - static final Calendar c = new Calendar.Builder() - .setCalendarType("japanese") - .setFields(ERA, 5, YEAR, 1, MONTH, MAY, DAY_OF_MONTH, 1) - .build(); - - @DataProvider(name="names") - Object[][] names() { - return new Object[][] { - // type, locale, name - { LONG, JAPAN, "\u4ee4\u548c" }, - { LONG, US, "Reiwa" }, - { LONG, CHINA, "\u4ee4\u548c" }, - { SHORT, JAPAN, "\u4ee4\u548c" }, - { SHORT, US, "Reiwa" }, - { SHORT, CHINA, "\u4ee4\u548c" }, - }; - } - - @Test(dataProvider="names") - public void testJapaneseNewEraName(int type, Locale locale, String expected) { - assertEquals(c.getDisplayName(ERA, type, locale), expected); - } -} diff --git a/test/jdk/java/util/Calendar/RollHoursTest.java b/test/jdk/java/util/Calendar/RollHoursTest.java new file mode 100644 index 00000000000..2eb85caab85 --- /dev/null +++ b/test/jdk/java/util/Calendar/RollHoursTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8367901 + * @summary Ensure hour rolling is correct. Particularly, when the HOUR/HOUR_OF_DAY + * amount rolled would cause the calendar to originate on the same hour as before + * the call. + * @run junit RollHoursTest + */ + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.FieldSource; + +import java.text.DateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.List; +import java.util.TimeZone; +import java.util.stream.IntStream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class RollHoursTest { + + // Should trigger multiple full HOUR/HOUR_OF_DAY cycles + private static final List hours = + IntStream.rangeClosed(-55, 55).boxed().toList(); + // Various calendars to test against + private static final List calendars = List.of( + // GMT, independent of daylight saving time transitions + new GregorianCalendar(TimeZone.getTimeZone("GMT")), + // Daylight saving observing calendars + new GregorianCalendar(TimeZone.getTimeZone("America/Chicago")), + new GregorianCalendar(TimeZone.getTimeZone("America/Chicago")), + new GregorianCalendar(TimeZone.getTimeZone("America/Los_Angeles")), + new GregorianCalendar(TimeZone.getTimeZone("America/Los_Angeles")) + ); + + // Reset the times of each calendar. These calendars provide testing under + // daylight saving transitions (or the lack thereof) and different AM/PM hours. + @BeforeEach + void clear() { + // Reset all calendars each iteration for clean slate + calendars.forEach(Calendar::clear); + + // Basic test, independent of daylight saving transitions + calendars.get(0).set(2005, 8, 20, 12, 10, 25); + + // Transition to daylight saving time (CST/CDT) --- + // Day of transition: 03/13/2016 (Sunday) + // Most interesting test case due to 2 AM skip + calendars.get(1).set(2016, 2, 13, 3, 30, 55); + // Day before transition: 03/12/2016 (Saturday) + calendars.get(2).set(2016, 2, 12, 15, 20, 45); + + // Transition back to standard time (PST/PDT) ---- + // Day of transition: 11/06/2016 (Sunday) + calendars.get(3).set(2016, 10, 6, 4, 15, 20); + // Day before transition: 11/05/2016 (Saturday) + calendars.get(4).set(2016, 10, 5, 12, 25, 30); + } + + // Rolling the HOUR_OF_DAY field. + @ParameterizedTest + @FieldSource("hours") + void HourOfDayTest(int hoursToRoll) { + for (var cal : calendars) { + var savedTime = cal.getTime(); + var savedHour = cal.get(Calendar.HOUR_OF_DAY); + cal.roll(Calendar.HOUR_OF_DAY, hoursToRoll); + assertEquals(getExpectedHour(hoursToRoll, savedHour, 24, cal, savedTime), + cal.get(Calendar.HOUR_OF_DAY), + getMessage(cal.getTimeZone(), savedTime, hoursToRoll)); + } + } + + // Rolling the HOUR field. + @ParameterizedTest + @FieldSource("hours") + void HourTest(int hoursToRoll) { + for (var cal : calendars) { + var savedTime = cal.getTime(); + var savedHour = cal.get(Calendar.HOUR_OF_DAY); + cal.roll(Calendar.HOUR, hoursToRoll); + assertEquals(getExpectedHour(hoursToRoll, savedHour, 12, cal, savedTime), + cal.get(Calendar.HOUR), + getMessage(cal.getTimeZone(), savedTime, hoursToRoll)); + } + } + + // Gets the expected hour after rolling by X hours. Supports 12/24-hour cycle. + // Special handling for non-existent 2 AM case on transition day. + private static int getExpectedHour(int roll, int hour, int hourCycle, Calendar cal, Date oldDate) { + // For example with HOUR_OF_DAY at 15 and a 24-hour cycle + // For rolling forwards 50 hours -> (50 + 15) % 24 = 17 + // For hour backwards 50 hours -> (24 + (15 - 50) % 24) % 24 + // -> (24 - 11) % 24 = 13 + var result = (roll >= 0 ? (hour + roll) : (hourCycle + (hour + roll) % hourCycle)) % hourCycle; + + // 2 AM does not exist on transition day. Calculate normalized value accordingly + if (cal.getTimeZone().inDaylightTime(oldDate) && cal.get(Calendar.MONTH) == Calendar.MARCH && result == 2) { + return roll > 0 ? result + 1 : result - 1; + } else { + // Normal return value + return result; + } + } + + // Get a TimeZone adapted error message + private static String getMessage(TimeZone tz, Date date, int hoursToRoll) { + var fmt = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL); + fmt.setTimeZone(tz); + return fmt.format(date) + " incorrectly rolled " + hoursToRoll; + } +} diff --git a/test/jdk/java/util/Currency/ISO4217-list-one.txt b/test/jdk/java/util/Currency/ISO4217-list-one.txt index aa8c2725899..ca4bfd6dc94 100644 --- a/test/jdk/java/util/Currency/ISO4217-list-one.txt +++ b/test/jdk/java/util/Currency/ISO4217-list-one.txt @@ -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 @@ BV NOK 578 2 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 @@ CR CRC 188 2 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 @@ LK LKR 144 2 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 --git a/test/jdk/java/util/Currency/ValidateISO4217.java b/test/jdk/java/util/Currency/ValidateISO4217.java index 67793dcbecb..fa11a4b4fc4 100644 --- a/test/jdk/java/util/Currency/ValidateISO4217.java +++ b/test/jdk/java/util/Currency/ValidateISO4217.java @@ -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 - * 8354343 8354344 8356096 + * 8354343 8354344 8356096 8368308 * @summary Validate ISO 4217 data for Currency class. * @modules java.base/java.util:open * jdk.localedata @@ -116,7 +116,7 @@ public class ValidateISO4217 { private static final Set currenciesNotYetDefined = 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 --git a/test/jdk/java/util/Locale/PreserveTagCase.java b/test/jdk/java/util/Locale/PreserveTagCase.java index c5535e3a89f..3721067e831 100644 --- a/test/jdk/java/util/Locale/PreserveTagCase.java +++ b/test/jdk/java/util/Locale/PreserveTagCase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,7 +53,7 @@ public class PreserveTagCase { */ @ParameterizedTest @MethodSource("filterProvider") - public static void testFilterTags(String ranges, List tags, + public void testFilterTags(String ranges, List tags, List expected, FilteringMode mode) { List priorityList = LanguageRange.parse(ranges); List actual = Locale.filterTags(priorityList, tags, mode); @@ -67,7 +67,7 @@ public static void testFilterTags(String ranges, List tags, */ @ParameterizedTest @MethodSource("lookupProvider") - public static void testLookupTag(String ranges, List tags, + public void testLookupTag(String ranges, List tags, String expected) { List priorityList = LanguageRange.parse(ranges); String actual = Locale.lookupTag(priorityList, tags); diff --git a/test/jdk/java/util/TimeZone/DefaultTimeZoneTest.java b/test/jdk/java/util/TimeZone/DefaultTimeZoneTest.java index 4dd644d58b5..b386d39d499 100644 --- a/test/jdk/java/util/TimeZone/DefaultTimeZoneTest.java +++ b/test/jdk/java/util/TimeZone/DefaultTimeZoneTest.java @@ -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 @@ -38,6 +38,11 @@ import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; +import javax.swing.SwingConstants; +import javax.swing.BoxLayout; +import javax.swing.Box; +import java.awt.Dimension; +import java.awt.Component; import java.awt.BorderLayout; import java.awt.Window; import java.lang.reflect.InvocationTargetException; @@ -98,17 +103,36 @@ public static void main(String[] args) private static Window createTest() { var contents = new JFrame("DefaultTimeZoneTest"); - var label = new JLabel(SDF.format(new Date())); + contents.setSize(350, 250); + // Panel with vertical layout var panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS)); + // Time zone ID label + var timeZoneID = new JLabel("Time zone ID: " + SDF.getTimeZone().getID(), SwingConstants.CENTER); + timeZoneID.setAlignmentX(Component.CENTER_ALIGNMENT); + // Time label + var label = new JLabel(SDF.format(new Date()), SwingConstants.CENTER); + label.setAlignmentX(Component.CENTER_ALIGNMENT); + // Update button var button = new JButton("Update Time Zone"); + button.setAlignmentX(Component.CENTER_ALIGNMENT); + // Add components with spacing + panel.add(Box.createRigidArea(new Dimension(0, 10))); + panel.add(timeZoneID); + panel.add(Box.createRigidArea(new Dimension(0, 5))); + panel.add(label); + panel.add(Box.createRigidArea(new Dimension(0, 10))); panel.add(button); - contents.setSize(350, 250); - contents.add(label, BorderLayout.NORTH); - contents.add(panel, BorderLayout.CENTER); + contents.add(panel); + // Update default time zone on button click button.addActionListener(e -> { + // Clear JVM cached timezone and force reload from OS + TimeZone.setDefault(null); + System.setProperty("user.timezone", ""); TimeZone tz = TimeZone.getDefault(); SDF.setTimeZone(tz); + timeZoneID.setText("Time zone ID: " + tz.getID()); label.setText(SDF.format(new Date())); contents.repaint(); }); diff --git a/test/jdk/java/util/TimeZone/SimpleTimeZoneEqualsHashCodeTest.java b/test/jdk/java/util/TimeZone/SimpleTimeZoneEqualsHashCodeTest.java new file mode 100644 index 00000000000..586c7bdf5cc --- /dev/null +++ b/test/jdk/java/util/TimeZone/SimpleTimeZoneEqualsHashCodeTest.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8369184 + * @summary Checks if equals()/hashCode() of SimpleTimeZone works correctly + * @run junit SimpleTimeZoneEqualsHashCodeTest + */ + +import java.util.SimpleTimeZone; +import static java.util.Calendar.MARCH; +import static java.util.Calendar.NOVEMBER; +import static java.util.Calendar.SUNDAY; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class SimpleTimeZoneEqualsHashCodeTest { + private static final SimpleTimeZone STZ_WITH_DST = + new SimpleTimeZone(-288_000_000, "America/Los_Angeles", + MARCH, 8, -SUNDAY, 7_200_000, + NOVEMBER, 1, -SUNDAY, 7_200_000); + private static final SimpleTimeZone STZ_WITHOUT_DST = + new SimpleTimeZone(0, "foo"); + + @Test + void withDSTTest() { + var stz = (SimpleTimeZone)STZ_WITH_DST.clone(); + assertEquals(STZ_WITH_DST, stz); + assertEquals(STZ_WITH_DST.hashCode(), stz.hashCode()); + + stz.setEndRule(NOVEMBER, 8, -SUNDAY, 7_200_000); + assertNotEquals(STZ_WITH_DST, stz); + // From the contract point, hash codes may be the same. + // This tests the implementation which considers DST + // related fields for calculating the hash code. + assertNotEquals(STZ_WITH_DST.hashCode(), stz.hashCode()); + } + + @Test + void withoutDSTTest() { + var stz = (SimpleTimeZone)STZ_WITHOUT_DST.clone(); + + // Only setting start rule. Still considered non-DST zone + stz.setStartRule(MARCH, 8, -SUNDAY, 7_200_000); + assertTrue(!stz.useDaylightTime()); + assertEquals(STZ_WITHOUT_DST, stz); + assertEquals(STZ_WITHOUT_DST.hashCode(), stz.hashCode()); + + // Setting end rule as well. Now it is considered DST zone + stz.setEndRule(NOVEMBER, 8, -SUNDAY, 7_200_000); + assertTrue(stz.useDaylightTime()); + assertNotEquals(STZ_WITHOUT_DST, stz); + // From the contract point, hash codes may be the same. + // This tests the implementation which considers DST + // related fields for calculating the hash code. + assertNotEquals(STZ_WITHOUT_DST.hashCode(), stz.hashCode()); + } +} diff --git a/test/jdk/java/util/TimeZone/TimeZoneData/VERSION b/test/jdk/java/util/TimeZone/TimeZoneData/VERSION index 750d9fae2b1..76d146afc71 100644 --- a/test/jdk/java/util/TimeZone/TimeZoneData/VERSION +++ b/test/jdk/java/util/TimeZone/TimeZoneData/VERSION @@ -1 +1 @@ -tzdata2025b +tzdata2025c diff --git a/test/jdk/java/util/concurrent/CopyOnWriteArraySet/SerializationTest.java b/test/jdk/java/util/concurrent/CopyOnWriteArraySet/SerializationTest.java new file mode 100644 index 00000000000..7700eda6cd6 --- /dev/null +++ b/test/jdk/java/util/concurrent/CopyOnWriteArraySet/SerializationTest.java @@ -0,0 +1,84 @@ +/* + * 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 8365058 + * @summary Check basic correctness of de-serialization + * @run junit SerializationTest + */ + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class SerializationTest { + + // Ensure basic serialization round trip correctness + @ParameterizedTest + @MethodSource + void roundTripTest(CopyOnWriteArraySet expected) { + var bytes = ser(expected); + var actual = deSer(bytes); + assertEquals(CopyOnWriteArraySet.class, actual.getClass()); + assertEquals(expected, actual); + } + + private static Stream> roundTripTest() { + return Stream.of( + new CopyOnWriteArraySet<>(), + new CopyOnWriteArraySet<>(List.of(1, 2, 3)), + new CopyOnWriteArraySet<>(Set.of("Foo", "Bar", "Baz")) + ); + } + + private static byte[] ser(Object obj) { + return assertDoesNotThrow(() -> { + try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(byteArrayOutputStream)) { + oos.writeObject(obj); + return byteArrayOutputStream.toByteArray(); + } + }, "Unexpected error during serialization"); + } + + private static Object deSer(byte[] bytes) { + return assertDoesNotThrow(() -> { + try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(byteArrayInputStream)) { + return ois.readObject(); + } + }, "Unexpected error during de-serialization"); + } +} diff --git a/test/jdk/java/util/concurrent/DelayScheduler/AscendingOrderAfterReplace.java b/test/jdk/java/util/concurrent/DelayScheduler/AscendingOrderAfterReplace.java new file mode 100644 index 00000000000..fd72b8148d2 --- /dev/null +++ b/test/jdk/java/util/concurrent/DelayScheduler/AscendingOrderAfterReplace.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8370887 + * @summary Test that cancelling a delayed task doesn't impact the ordering that other + * delayed tasks execute + */ + +import java.time.Duration; +import java.time.Instant; +import java.util.Arrays; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.Future; +import java.util.concurrent.LinkedTransferQueue; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +public class AscendingOrderAfterReplace { + + private static final int[] DELAYS_IN_MS = { 3000, 3400, 3900, 3800, 3700, 3600, 3430, 3420, 3310, 3500, 3200 }; + + public static void main(String[] args) throws Exception { + for (int i = 1; i < DELAYS_IN_MS.length; i++) { + System.out.println("=== Test " + i + " ==="); + while (!testCancel(DELAYS_IN_MS, i)) { } + } + } + + /** + * Schedule the delayed tasks, cancel one of them, and check that the remaining tasks + * execute in the ascending order of delay. + * @return true if the test passed, false if a retry is needed + * @throws RuntimeException if the test fails + */ + private static boolean testCancel(int[] delays, int indexToCancel) throws Exception { + log("Delayed tasks: " + toString(delays)); + + // delayed tasks add to this queue when they execute + var queue = new LinkedTransferQueue(); + + // pool with one thread to ensure that delayed tasks don't execute concurrently + try (var pool = new ForkJoinPool(1)) { + long startNanos = System.nanoTime(); + Future[] futures = Arrays.stream(delays) + .mapToObj(d -> pool.schedule(() -> { + log("Triggered " + d); + queue.add(d); + }, d, MILLISECONDS)) + .toArray(Future[]::new); + long endNanos = System.nanoTime(); + log("Delayed tasks submitted"); + + // check submit took < min diffs between two delays + long submitTime = Duration.ofNanos(endNanos - startNanos).toMillis(); + long minDiff = minDifference(delays); + if (submitTime >= minDiff) { + log("Submit took >= " + minDiff + " ms, need to retry"); + pool.shutdownNow(); + return false; + } + + // give a bit of time for -delayScheduler thread to process pending tasks + Thread.sleep(minValue(delays) / 2); + log("Cancel " + delays[indexToCancel]); + futures[indexToCancel].cancel(true); + } + + // delayed tasks should have executed in ascending order of their delay + int[] executed = queue.stream().mapToInt(Integer::intValue).toArray(); + log("Executed: " + toString(executed)); + if (!isAscendingOrder(executed)) { + throw new RuntimeException("Not in ascending order!"); + } + return true; + } + + /** + * Return the minimum element. + */ + private static int minValue(int[] array) { + return IntStream.of(array).min().orElseThrow(); + } + + /** + * Return the minimum difference between any two elements. + */ + private static int minDifference(int[] array) { + int[] sorted = array.clone(); + Arrays.sort(sorted); + return IntStream.range(1, sorted.length) + .map(i -> sorted[i] - sorted[i - 1]) + .min() + .orElse(0); + } + + /** + * Return true if the array is in ascending order. + */ + private static boolean isAscendingOrder(int[] array) { + return IntStream.range(1, array.length) + .allMatch(i -> array[i - 1] <= array[i]); + } + + /** + * Returns a String containing the elements of an array in index order. + */ + private static String toString(int[] array) { + return IntStream.of(array) + .mapToObj(Integer::toString) + .collect(Collectors.joining(", ", "[", "]")); + } + + private static void log(String message) { + System.out.println(Instant.now() + " " + message); + } +} + diff --git a/test/jdk/java/util/concurrent/Executors/AutoShutdown.java b/test/jdk/java/util/concurrent/Executors/AutoShutdown.java index 2b7fa7b883f..ec58a472f7b 100644 --- a/test/jdk/java/util/concurrent/Executors/AutoShutdown.java +++ b/test/jdk/java/util/concurrent/Executors/AutoShutdown.java @@ -23,23 +23,32 @@ /* * @test - * @bug 6399443 8302899 + * @bug 6399443 8302899 8362123 * @summary Test that Executors.newSingleThreadExecutor wraps an ExecutorService that * automatically shuts down and terminates when the wrapper is GC'ed + * @library /test/lib/ * @modules java.base/java.util.concurrent:+open * @run junit AutoShutdown */ +import java.lang.ref.PhantomReference; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; import java.lang.reflect.Field; import java.time.Duration; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; import java.util.function.Supplier; import java.util.stream.Stream; import java.util.stream.IntStream; +import jdk.test.lib.Utils; +import jdk.test.lib.util.ForceGC; + import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -61,6 +70,13 @@ private static Stream executorAndQueuedTaskCounts() { .mapToObj(i -> Arguments.of(s, i))); } + private static Stream shutdownMethods() { + return Stream.>of( + e -> e.shutdown(), + e -> e.shutdownNow() + ).map(Arguments::of); + } + /** * SingleThreadExecutor with no worker threads. */ @@ -110,6 +126,28 @@ void testActiveWorker(Supplier supplier,int queuedTaskCount) th assertEquals(ntasks, completedTaskCount.get()); } + @ParameterizedTest + @MethodSource("shutdownMethods") + void testShutdownUnlinksCleaner(Consumer shutdown) throws Exception { + ClassLoader classLoader = + Utils.getTestClassPathURLClassLoader(ClassLoader.getPlatformClassLoader()); + + ReferenceQueue queue = new ReferenceQueue<>(); + Reference reference = new PhantomReference(classLoader, queue); + try { + Class isolatedClass = classLoader.loadClass("AutoShutdown$IsolatedClass"); + assertSame(isolatedClass.getClassLoader(), classLoader); + isolatedClass.getDeclaredMethod("shutdown", Consumer.class).invoke(null, shutdown); + + isolatedClass = null; + classLoader = null; + + assertTrue(ForceGC.wait(() -> queue.poll() != null)); + } finally { + Reference.reachabilityFence(reference); + } + } + /** * Returns the delegate for the given ExecutorService. The given ExecutorService * must be a Executors$DelegatedExecutorService. @@ -132,5 +170,22 @@ private void gcAndAwaitTermination(ExecutorService executor) throws Exception { terminated = executor.awaitTermination(100, TimeUnit.MILLISECONDS); } } -} + public static class IsolatedClass { + + private static final ExecutorService executor = + Executors.newSingleThreadExecutor(new IsolatedThreadFactory()); + + public static void shutdown(Consumer shutdown) { + shutdown.accept(executor); + } + } + + public static class IsolatedThreadFactory implements ThreadFactory { + + @Override + public Thread newThread(Runnable r) { + return new Thread(r); + } + } +} diff --git a/test/jdk/java/util/concurrent/forkjoin/ContextClassLoaderTest.java b/test/jdk/java/util/concurrent/forkjoin/ContextClassLoaderTest.java new file mode 100644 index 00000000000..eb6465e9619 --- /dev/null +++ b/test/jdk/java/util/concurrent/forkjoin/ContextClassLoaderTest.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8368500 + * @run junit/othervm ContextClassLoaderTest + * @summary Check the context classloader is reset + */ +import java.net.URL; +import java.net.URLClassLoader; +import java.util.concurrent.Future; +import java.util.concurrent.ForkJoinPool; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +class ContextClassLoaderTest { + + @Test + void testContextClassLoaderIsSetAndRestored() throws Exception { + Future future = ForkJoinPool.commonPool().submit(() -> { + Thread thread = Thread.currentThread(); + ClassLoader originalCCL = thread.getContextClassLoader(); + ClassLoader customCCL = new URLClassLoader(new URL[0], originalCCL); + // Set custom context classloader and verify it + thread.setContextClassLoader(customCCL); + assertSame(customCCL, thread.getContextClassLoader(), "Custom context class loader not set"); + + // Reset to original and verify restoration + thread.setContextClassLoader(originalCCL); + assertSame(originalCCL, thread.getContextClassLoader(), "Original context class loader not restored"); + }); + future.get(); + } +} + diff --git a/test/jdk/java/util/concurrent/tck/CompletableFutureTest.java b/test/jdk/java/util/concurrent/tck/CompletableFutureTest.java index de3d1dd1050..fc86936d5da 100644 --- a/test/jdk/java/util/concurrent/tck/CompletableFutureTest.java +++ b/test/jdk/java/util/concurrent/tck/CompletableFutureTest.java @@ -58,6 +58,7 @@ import java.util.concurrent.Executor; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.ForkJoinWorkerThread; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; @@ -5133,4 +5134,46 @@ public void testDefaultExceptionallyComposeAsyncExecutor_actionFailed() { checkCompletedWithWrappedException(g.toCompletableFuture(), r.ex); r.assertInvoked(); }} + + public void testOnlyHelpsIfInTheSamePool() throws Exception { + class Logic { + interface Extractor { ForkJoinPool pool(CompletableFuture cf) throws Exception; } + static final List executeInnerOuter( + ForkJoinPool outer, ForkJoinPool inner, Logic.Extractor extractor + ) throws Exception { + return CompletableFuture.supplyAsync(() -> + Stream.iterate(1, i -> i + 1) + .limit(64) + .map(i -> CompletableFuture.supplyAsync( + () -> Thread.currentThread() instanceof ForkJoinWorkerThread wt ? wt.getPool() : null, inner) + ) + .map(cf -> { + try { + return extractor.pool(cf); + } catch (Exception ex) { + throw new AssertionError("Unexpected", ex); + } + }) + .toList() + , outer).join(); + } + } + + List extractors = + List.of( + c -> c.get(60, SECONDS), + CompletableFuture::get, + CompletableFuture::join + ); + + try (var pool = new ForkJoinPool(2)) { + for (var extractor : extractors) { + for (var p : Logic.executeInnerOuter(pool, ForkJoinPool.commonPool(), extractor)) + assertTrue(p != pool); // The inners should have all been executed by commonPool + + for (var p : Logic.executeInnerOuter(pool, pool, extractor)) + assertTrue(p == pool); // The inners could have been helped by the outer + } + } + } } diff --git a/test/jdk/java/util/concurrent/tck/ForkJoinPoolTest.java b/test/jdk/java/util/concurrent/tck/ForkJoinPoolTest.java index 9422128511e..de1caaab2d9 100644 --- a/test/jdk/java/util/concurrent/tck/ForkJoinPoolTest.java +++ b/test/jdk/java/util/concurrent/tck/ForkJoinPoolTest.java @@ -31,9 +31,6 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static java.util.concurrent.TimeUnit.NANOSECONDS; - import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; import java.util.ArrayList; @@ -41,6 +38,7 @@ import java.util.Collections; import java.util.List; import java.util.concurrent.Callable; +import java.util.concurrent.CancellationException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; @@ -51,13 +49,19 @@ import java.util.concurrent.Future; import java.util.concurrent.RecursiveTask; import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.ReentrantLock; import junit.framework.Test; import junit.framework.TestSuite; +import static java.util.concurrent.TimeUnit.*; + public class ForkJoinPoolTest extends JSR166TestCase { public static void main(String[] args) { main(suite(), args); @@ -482,6 +486,57 @@ public void testSubmitRunnable() throws Throwable { } } + public void testCancellationExceptionInGet() throws Exception { + final ExecutorService e = new ForkJoinPool(1); + try (var cleaner = cleaner(e)) { + assertCancellationExceptionFrom( + e::submit, + f -> () -> f.get(1000, TimeUnit.SECONDS) + ); + assertCancellationExceptionFrom( + e::submit, + f -> f::get + ); + assertCancellationExceptionFrom( + c -> e.submit(() -> { try { c.call(); } catch (Exception ex) { throw new RuntimeException(ex); } }), + f -> () -> f.get(1000, TimeUnit.SECONDS) + ); + assertCancellationExceptionFrom( + c -> e.submit(() -> { try { c.call(); } catch (Exception ex) { throw new RuntimeException(ex); } }), + f -> f::get + ); + } + } + + private void assertCancellationExceptionFrom( + Function, Future> createTask, + Function, Callable> getResult) throws Exception { + final var t = new AtomicReference(); + final var c = new CountDownLatch(1); // Only used to induce WAITING state (never counted down) + final var task = createTask.apply(() -> { + try { + t.set(Thread.currentThread()); + c.await(); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt();; + } + return null; + }); + Thread taskThread; + while((taskThread = t.get()) == null || taskThread.getState() != Thread.State.WAITING) { + if (Thread.interrupted()) + throw new InterruptedException(); + Thread.onSpinWait(); + } + task.cancel(true); + try { + getResult.apply(task).call(); + } catch (CancellationException ce) { + return; // Success + } + shouldThrow(); + } + /** * Completed submit(runnable, result) returns result */ diff --git a/test/jdk/javax/crypto/Cipher/TestDisabledAlgorithms.java b/test/jdk/javax/crypto/Cipher/TestDisabledAlgorithms.java new file mode 100644 index 00000000000..3505552d1b1 --- /dev/null +++ b/test/jdk/javax/crypto/Cipher/TestDisabledAlgorithms.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8244336 + * @summary Test JCE layer algorithm restriction + * @library /test/lib + * @run main/othervm TestDisabledAlgorithms CIPHEr.Rsa/ECB/PKCS1Padding true + * @run main/othervm TestDisabledAlgorithms cipheR.rsA true + * @run main/othervm TestDisabledAlgorithms CIPher.what false + * @run main/othervm TestDisabledAlgorithms cipHER.RSA/ECB/PKCS1Padding2 false + */ +import java.util.List; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.Security; +import java.security.Signature; +import javax.crypto.Cipher; +import javax.crypto.NoSuchPaddingException; +import jdk.test.lib.Utils; + +public class TestDisabledAlgorithms { + + private static final String PROP_NAME = "jdk.crypto.disabledAlgorithms"; + + private static final String TARGET = "Cipher.RSA/ECB/PKCS1Padding"; + + private static void test(List algos, Provider p, + boolean shouldThrow) throws Exception { + + for (String a : algos) { + System.out.println("Testing " + (p != null ? p.getName() : "") + + ": " + a + ", shouldThrow=" + shouldThrow); + if (shouldThrow) { + if (p == null) { + Utils.runAndCheckException(() -> Cipher.getInstance(a), + NoSuchAlgorithmException.class); + } else { + Utils.runAndCheckException(() -> Cipher.getInstance(a, p), + NoSuchAlgorithmException.class); + Utils.runAndCheckException(() -> Cipher.getInstance(a, + p.getName()), NoSuchAlgorithmException.class); + + } + } else { + Cipher c; + if (p == null) { + c = Cipher.getInstance(a); + } else { + c = Cipher.getInstance(a, p); + c = Cipher.getInstance(a, p.getName()); + } + System.out.println("Got cipher w/ algo " + c.getAlgorithm()); + } + } + } + + public static void main(String[] args) throws Exception { + String propValue = args[0]; + System.out.println("Setting Security Prop " + PROP_NAME + " = " + + propValue); + Security.setProperty(PROP_NAME, propValue); + + boolean shouldThrow = Boolean.valueOf(args[1]); + + List algos = List.of("Rsa/ECB/PKCS1Padding", "rSA"); + + // test w/o provider + test(algos, null, shouldThrow); + + // test w/ provider + Provider[] providers = Security.getProviders(); + for (Provider p : providers) { + if (p.getService("Cipher", "RSA/ECB/PKCS1Padding") != null) { + test(algos, p, shouldThrow); + } + } + + // make sure NONEwithRSA signature is still available from SunJCE and + // SunMSCAPI (windows) + if (shouldThrow) { + System.out.println("Testing NONEwithRSA signature support"); + for (String pn : List.of("SunJCE", "SunMSCAPI")) { + Provider p = Security.getProvider(pn); + if (p != null) { + Signature s = Signature.getInstance("NONEwithRSA", p); + System.out.println(pn + "=> yes"); + } else { + System.out.println(pn + "=> skip; not found"); + } + } + } + System.out.println("Done"); + } +} diff --git a/test/jdk/javax/crypto/Cipher/TestDisabledWithOids.java b/test/jdk/javax/crypto/Cipher/TestDisabledWithOids.java new file mode 100644 index 00000000000..d1d9fa7a5bb --- /dev/null +++ b/test/jdk/javax/crypto/Cipher/TestDisabledWithOids.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8375549 + * @summary Test JCE layer algorithm restriction using algorithms w/ oids + * @library /test/lib + * @run main/othervm -Djdk.crypto.disabledAlgorithms=Cipher.DES,Cipher.RSA/ECB/PKCS1Padding TestDisabledWithOids + * @run main/othervm -Djdk.crypto.disabledAlgorithms=Cipher.RSA/ECB/PKCS1Padding,Cipher.DES TestDisabledWithOids + */ +import java.security.NoSuchAlgorithmException; +import javax.crypto.Cipher; +import jdk.test.lib.Utils; + +public class TestDisabledWithOids { + public static void main(String[] args) throws Exception { + String algo1 = "RSA/ECB/PKCS1Padding"; + String algo2 = "DES"; + + Utils.runAndCheckException(() -> Cipher.getInstance(algo1), + NoSuchAlgorithmException.class); + Utils.runAndCheckException(() -> Cipher.getInstance(algo2), + NoSuchAlgorithmException.class); + System.out.println("Done"); + } +} diff --git a/test/jdk/javax/crypto/Cipher/TestEmptyModePadding.java b/test/jdk/javax/crypto/Cipher/TestEmptyModePadding.java new file mode 100644 index 00000000000..56e35f2a72a --- /dev/null +++ b/test/jdk/javax/crypto/Cipher/TestEmptyModePadding.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025 IBM Corporation. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8359388 + * @summary test that the Cipher.getInstance() would reject improper + * transformations with empty mode and/or padding. + */ + +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.Security; +import javax.crypto.Cipher; + +public class TestEmptyModePadding { + + public static void main(String[] args) throws Exception { + Provider provider = Security.getProvider( + System.getProperty("test.provider.name", "SunJCE")); + + System.out.println("Testing against " + provider.getName()); + + String[] testTransformations = { + // transformations w/ only 1 component, i.e. algo + " ", + // transformations w/ only 2 components + "AES/", + "AES/ ", + "AES/CBC", + "PBEWithHmacSHA512/224AndAES_128/", + "PBEWithHmacSHA512/256AndAES_128/ ", + "PBEWithHmacSHA512/224AndAES_128/CBC", + // 3-component transformations w/ empty component(s) + "AES//", + "AES/ /", + "AES// ", + "AES/ / ", + "AES/CBC/", "AES/CBC/ ", + "AES//PKCS5Padding", "AES/ /NoPadding", + "PBEWithHmacSHA512/224AndAES_128//", + "PBEWithHmacSHA512/224AndAES_128/ /", + "PBEWithHmacSHA512/224AndAES_128// ", + "PBEWithHmacSHA512/224AndAES_128/ / ", + "PBEWithHmacSHA512/256AndAES_128/CBC/", + "PBEWithHmacSHA512/256AndAES_128/CBC/ ", + "PBEWithHmacSHA512/256AndAES_128//PKCS5Padding", + "PBEWithHmacSHA512/256AndAES_128/ /PKCS5Padding", + }; + + for (String t : testTransformations) { + test(t, provider); + } + } + + private static void test(String t, Provider p) throws Exception { + try { + Cipher c = Cipher.getInstance(t, p); + throw new RuntimeException("Should throw NSAE for \'" + t + "\'"); + } catch (NoSuchAlgorithmException nsae) { + // transformation info is already in the NSAE message + System.out.println("Expected NSAE: " + nsae.getMessage()); + } + } +} diff --git a/test/jdk/javax/management/security/SecurityTest.java b/test/jdk/javax/management/security/SecurityTest.java index 835c340dd99..b5af51b5028 100644 --- a/test/jdk/javax/management/security/SecurityTest.java +++ b/test/jdk/javax/management/security/SecurityTest.java @@ -399,6 +399,8 @@ private List buildCommandLine(String args[]) { opts.add(JDKToolFinder.getJDKTool("java")); opts.addAll(Arrays.asList(jdk.test.lib.Utils.getTestJavaOpts())); + opts.add("-Djdk.rmi.ssl.client.enableEndpointIdentification=false"); + // We need to forward some properties to the client side opts.add("-Dtest.src=" + System.getProperty("test.src")); diff --git a/test/jdk/javax/net/ssl/DTLS/DTLSNamedGroups.java b/test/jdk/javax/net/ssl/DTLS/DTLSNamedGroups.java index e9165fa391c..1fc4f962675 100644 --- a/test/jdk/javax/net/ssl/DTLS/DTLSNamedGroups.java +++ b/test/jdk/javax/net/ssl/DTLS/DTLSNamedGroups.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -140,4 +140,3 @@ private static void runTest(String[] serverNamedGroups, } } } - diff --git a/test/jdk/javax/net/ssl/DTLS/DTLSOverDatagram.java b/test/jdk/javax/net/ssl/DTLS/DTLSOverDatagram.java index 1820dbe5423..9780586cd57 100644 --- a/test/jdk/javax/net/ssl/DTLS/DTLSOverDatagram.java +++ b/test/jdk/javax/net/ssl/DTLS/DTLSOverDatagram.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,6 @@ */ public class DTLSOverDatagram { - private static final int SOCKET_TIMEOUT = 10 * 1000; // in millis private static final int BUFFER_SIZE = 1024; private static final int MAXIMUM_PACKET_SIZE = 1024; @@ -78,6 +77,7 @@ public class DTLSOverDatagram { private final AtomicBoolean exceptionOccurred = new AtomicBoolean(false); private final CountDownLatch serverStarted = new CountDownLatch(1); + private int socketTimeout = 10 * 1000; // in millis /* * ============================================================= * The test case @@ -476,6 +476,10 @@ static DatagramPacket getPacket( return null; } + public void setSocketTimeout(int socketTimeout) { + this.socketTimeout = socketTimeout; + } + // run delegated tasks void runDelegatedTasks(SSLEngine engine) throws Exception { Runnable runnable; @@ -529,8 +533,8 @@ public final void runTest(DTLSOverDatagram testCase) throws Exception { try (DatagramSocket serverSocket = new DatagramSocket(serverSocketAddress); DatagramSocket clientSocket = new DatagramSocket(clientSocketAddress)) { - serverSocket.setSoTimeout(SOCKET_TIMEOUT); - clientSocket.setSoTimeout(SOCKET_TIMEOUT); + serverSocket.setSoTimeout(socketTimeout); + clientSocket.setSoTimeout(socketTimeout); InetSocketAddress serverSocketAddr = new InetSocketAddress( InetAddress.getLoopbackAddress(), serverSocket.getLocalPort()); diff --git a/test/jdk/javax/net/ssl/DTLS/DTLSSignatureSchemes.java b/test/jdk/javax/net/ssl/DTLS/DTLSSignatureSchemes.java index 5dd897b1bd7..9c1c64f7fa0 100644 --- a/test/jdk/javax/net/ssl/DTLS/DTLSSignatureSchemes.java +++ b/test/jdk/javax/net/ssl/DTLS/DTLSSignatureSchemes.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -134,4 +134,3 @@ private static void runTest(String[] serverSignatureSchemes, } } } - diff --git a/test/jdk/javax/net/ssl/DTLS/FragmentedFinished.java b/test/jdk/javax/net/ssl/DTLS/FragmentedFinished.java new file mode 100644 index 00000000000..2b6fd16005c --- /dev/null +++ b/test/jdk/javax/net/ssl/DTLS/FragmentedFinished.java @@ -0,0 +1,72 @@ +/* + * 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. + */ + +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. + +/* + * @test + * @bug 8367133 + * @summary Verify that handshake succeeds when Finished message is fragmented + * @modules java.base/sun.security.util + * @library /test/lib + * @build DTLSOverDatagram + * @run main/othervm FragmentedFinished + */ + +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLParameters; +import java.net.DatagramPacket; +import java.net.SocketAddress; +import java.util.ArrayList; +import java.util.List; + +public class FragmentedFinished extends DTLSOverDatagram { + private SSLEngine serverSSLEngine; + public static void main(String[] args) throws Exception { + FragmentedFinished testCase = new FragmentedFinished(); + testCase.runTest(testCase); + } + + @Override + SSLEngine createSSLEngine(boolean isClient) throws Exception { + SSLEngine sslEngine = super.createSSLEngine(isClient); + if (!isClient) { + serverSSLEngine = sslEngine; + } + return sslEngine; + } + + @Override + DatagramPacket createHandshakePacket(byte[] ba, SocketAddress socketAddr) { + if (ba.length < 30) { // detect ChangeCipherSpec + // Reduce the maximumPacketSize to force fragmentation + // of the Finished message + SSLParameters params = serverSSLEngine.getSSLParameters(); + params.setMaximumPacketSize(53); + serverSSLEngine.setSSLParameters(params); + } + + return super.createHandshakePacket(ba, socketAddr); + } +} diff --git a/test/jdk/javax/net/ssl/DTLS/PacketLossRetransmission.java b/test/jdk/javax/net/ssl/DTLS/PacketLossRetransmission.java index 24a12600087..2dd0de830f1 100644 --- a/test/jdk/javax/net/ssl/DTLS/PacketLossRetransmission.java +++ b/test/jdk/javax/net/ssl/DTLS/PacketLossRetransmission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, 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 @@ -32,37 +32,16 @@ * @library /test/lib * @build DTLSOverDatagram * - * @run main/othervm PacketLossRetransmission client 0 hello_request * @run main/othervm PacketLossRetransmission client 1 client_hello - * @run main/othervm PacketLossRetransmission client 2 server_hello - * @run main/othervm PacketLossRetransmission client 3 hello_verify_request - * @run main/othervm -Djdk.tls.client.enableSessionTicketExtension=false PacketLossRetransmission client 4 new_session_ticket - * @run main/othervm PacketLossRetransmission client 11 certificate - * @run main/othervm PacketLossRetransmission client 12 server_key_exchange - * @run main/othervm PacketLossRetransmission client 13 certificate_request - * @run main/othervm PacketLossRetransmission client 14 server_hello_done - * @run main/othervm PacketLossRetransmission client 15 certificate_verify * @run main/othervm PacketLossRetransmission client 16 client_key_exchange * @run main/othervm PacketLossRetransmission client 20 finished - * @run main/othervm PacketLossRetransmission client 21 certificate_url - * @run main/othervm PacketLossRetransmission client 22 certificate_status - * @run main/othervm PacketLossRetransmission client 23 supplemental_data * @run main/othervm PacketLossRetransmission client -1 change_cipher_spec - * @run main/othervm PacketLossRetransmission server 0 hello_request - * @run main/othervm PacketLossRetransmission server 1 client_hello * @run main/othervm PacketLossRetransmission server 2 server_hello * @run main/othervm PacketLossRetransmission server 3 hello_verify_request - * @run main/othervm -Djdk.tls.client.enableSessionTicketExtension=false PacketLossRetransmission server 4 new_session_ticket * @run main/othervm PacketLossRetransmission server 11 certificate * @run main/othervm PacketLossRetransmission server 12 server_key_exchange - * @run main/othervm PacketLossRetransmission server 13 certificate_request * @run main/othervm PacketLossRetransmission server 14 server_hello_done - * @run main/othervm PacketLossRetransmission server 15 certificate_verify - * @run main/othervm PacketLossRetransmission server 16 client_key_exchange * @run main/othervm PacketLossRetransmission server 20 finished - * @run main/othervm PacketLossRetransmission server 21 certificate_url - * @run main/othervm PacketLossRetransmission server 22 certificate_status - * @run main/othervm PacketLossRetransmission server 23 supplemental_data * @run main/othervm PacketLossRetransmission server -1 change_cipher_spec */ @@ -79,6 +58,7 @@ public class PacketLossRetransmission extends DTLSOverDatagram { private static boolean isClient; private static byte handshakeType; + private static final int TIMEOUT = 500; private boolean needPacketLoss = true; @@ -87,6 +67,7 @@ public static void main(String[] args) throws Exception { handshakeType = Byte.parseByte(args[1]); PacketLossRetransmission testCase = new PacketLossRetransmission(); + testCase.setSocketTimeout(TIMEOUT); testCase.runTest(testCase); } @@ -102,7 +83,7 @@ boolean produceHandshakePackets(SSLEngine engine, SocketAddress socketAddr, if (packet != null) { needPacketLoss = false; - System.out.println("Loss a packet of handshake messahe"); + System.out.println("Loss a packet of handshake message"); packets.remove(packet); } } diff --git a/test/jdk/javax/net/ssl/SSLException/CheckSSLHandshakeException.java b/test/jdk/javax/net/ssl/SSLException/CheckSSLHandshakeException.java index 4c8aba3de44..4ba3e906597 100644 --- a/test/jdk/javax/net/ssl/SSLException/CheckSSLHandshakeException.java +++ b/test/jdk/javax/net/ssl/SSLException/CheckSSLHandshakeException.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/javax/net/ssl/SSLException/CheckSSLKeyException.java b/test/jdk/javax/net/ssl/SSLException/CheckSSLKeyException.java index dcd62fcf8e7..2d271236de1 100644 --- a/test/jdk/javax/net/ssl/SSLException/CheckSSLKeyException.java +++ b/test/jdk/javax/net/ssl/SSLException/CheckSSLKeyException.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/javax/net/ssl/SSLException/CheckSSLPeerUnverifiedException.java b/test/jdk/javax/net/ssl/SSLException/CheckSSLPeerUnverifiedException.java index 04184e99306..1d37271ed53 100644 --- a/test/jdk/javax/net/ssl/SSLException/CheckSSLPeerUnverifiedException.java +++ b/test/jdk/javax/net/ssl/SSLException/CheckSSLPeerUnverifiedException.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/javax/net/ssl/SSLException/CheckSSLProtocolException.java b/test/jdk/javax/net/ssl/SSLException/CheckSSLProtocolException.java index 3f62fac8f77..c1bd53e21e9 100644 --- a/test/jdk/javax/net/ssl/SSLException/CheckSSLProtocolException.java +++ b/test/jdk/javax/net/ssl/SSLException/CheckSSLProtocolException.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/javax/net/ssl/SSLParameters/NamedGroups.java b/test/jdk/javax/net/ssl/SSLParameters/NamedGroups.java index fc5001e89b8..25f73606b96 100644 --- a/test/jdk/javax/net/ssl/SSLParameters/NamedGroups.java +++ b/test/jdk/javax/net/ssl/SSLParameters/NamedGroups.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/javax/net/ssl/SSLParameters/NamedGroupsSpec.java b/test/jdk/javax/net/ssl/SSLParameters/NamedGroupsSpec.java index 9146e7b5f7b..0d910ccfb67 100644 --- a/test/jdk/javax/net/ssl/SSLParameters/NamedGroupsSpec.java +++ b/test/jdk/javax/net/ssl/SSLParameters/NamedGroupsSpec.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/javax/net/ssl/SSLParameters/SignatureSchemes.java b/test/jdk/javax/net/ssl/SSLParameters/SignatureSchemes.java index 7dadeff5703..7f41cb1af79 100644 --- a/test/jdk/javax/net/ssl/SSLParameters/SignatureSchemes.java +++ b/test/jdk/javax/net/ssl/SSLParameters/SignatureSchemes.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/javax/net/ssl/ServerName/EndingDotHostname.java b/test/jdk/javax/net/ssl/ServerName/EndingDotHostname.java index bac110aa033..5438f429455 100644 --- a/test/jdk/javax/net/ssl/ServerName/EndingDotHostname.java +++ b/test/jdk/javax/net/ssl/ServerName/EndingDotHostname.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -248,4 +248,3 @@ protected void runClientApplication(SSLSocket socket) throws Exception { sslIS.read(); } } - diff --git a/test/jdk/javax/net/ssl/Stapling/HttpsUrlConnClient.java b/test/jdk/javax/net/ssl/Stapling/HttpsUrlConnClient.java index b9829621d68..c34311f1689 100644 --- a/test/jdk/javax/net/ssl/Stapling/HttpsUrlConnClient.java +++ b/test/jdk/javax/net/ssl/Stapling/HttpsUrlConnClient.java @@ -33,7 +33,11 @@ * @run main/othervm HttpsUrlConnClient RSASSA-PSS RSASSA-PSS */ -import java.io.*; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; import java.math.BigInteger; import java.security.KeyPair; import java.security.KeyPairGenerator; @@ -41,7 +45,9 @@ import java.net.URL; import java.net.HttpURLConnection; import java.net.InetAddress; + import javax.net.ssl.*; + import java.security.KeyStore; import java.security.PublicKey; import java.security.Security; @@ -55,7 +61,16 @@ import java.security.cert.PKIXRevocationChecker; import java.security.spec.PKCS8EncodedKeySpec; import java.text.SimpleDateFormat; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import jdk.test.lib.security.SimpleOCSPServer; @@ -92,10 +107,6 @@ public class HttpsUrlConnClient { static String INT_ALIAS = "intermediate"; static String SSL_ALIAS = "ssl"; - /* - * Is the server ready to serve? - */ - volatile static boolean serverReady = false; volatile int serverPort = 0; volatile Exception serverException = null; @@ -164,7 +175,7 @@ static void testPKIXParametersRevEnabled(String[] allowedProts) ClientParameters cliParams = new ClientParameters(); cliParams.protocols = allowedProts; ServerParameters servParams = new ServerParameters(); - serverReady = false; + CountDownLatch serverReady = new CountDownLatch(1); System.out.println("====================================="); System.out.println("Stapling enabled, PKIXParameters with"); @@ -192,7 +203,7 @@ static void testPKIXParametersRevEnabled(String[] allowedProts) Security.setProperty("ocsp.enable", "false"); HttpsUrlConnClient sslTest = new HttpsUrlConnClient(cliParams, - servParams); + servParams, serverReady); TestResult tr = sslTest.getResult(); if (!checkClientValidationFailure(tr.clientExc, BasicReason.REVOKED)) { if (tr.clientExc != null) { @@ -219,10 +230,11 @@ static void testPKIXParametersRevEnabled(String[] allowedProts) /* * Define the server side of the test. * - * If the server prematurely exits, serverReady will be set to true + * If the server prematurely exits, serverReady will be counted down * to avoid infinite hangs. */ - void doServerSide(ServerParameters servParams) throws Exception { + void doServerSide(ServerParameters servParams, CountDownLatch serverReady) + throws Exception { // Selectively enable or disable the feature System.setProperty("jdk.tls.server.enableStatusRequestExtension", @@ -274,7 +286,7 @@ void doServerSide(ServerParameters servParams) throws Exception { /* * Signal Client, we're ready for his connect. */ - serverReady = true; + serverReady.countDown(); try (SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept(); BufferedReader in = new BufferedReader( @@ -306,18 +318,13 @@ void doServerSide(ServerParameters servParams) throws Exception { /* * Define the client side of the test. * - * If the server prematurely exits, serverReady will be set to true + * If the server prematurely exits, serverReady will be counted down * to avoid infinite hangs. */ - void doClientSide(ClientParameters cliParams) throws Exception { + void doClientSide(ClientParameters cliParams, CountDownLatch serverReady) + throws Exception { - // Wait 5 seconds for server ready - for (int i = 0; (i < 100 && !serverReady); i++) { - Thread.sleep(50); - } - if (!serverReady) { - throw new RuntimeException("Server not ready yet"); - } + serverReady.await(); // Selectively enable or disable the feature System.setProperty("jdk.tls.client.enableStatusRequestExtension", @@ -373,16 +380,16 @@ void doClientSide(ClientParameters cliParams) throws Exception { * * Fork off the other side, then do your work. */ - HttpsUrlConnClient(ClientParameters cliParams, - ServerParameters servParams) throws Exception { + HttpsUrlConnClient(ClientParameters cliParams, ServerParameters servParams, + CountDownLatch serverReady) throws Exception { Exception startException = null; try { if (separateServerThread) { - startServer(servParams, true); - startClient(cliParams, false); + startServer(servParams, true, serverReady); + startClient(cliParams, false, serverReady); } else { - startClient(cliParams, true); - startServer(servParams, false); + startClient(cliParams, true, serverReady); + startServer(servParams, false, serverReady); } } catch (Exception e) { startException = e; @@ -453,51 +460,53 @@ TestResult getResult() { return tr; } - final void startServer(ServerParameters servParams, boolean newThread) - throws Exception { + final void startServer(ServerParameters servParams, boolean newThread, + CountDownLatch serverReady) throws IOException { if (newThread) { serverThread = new Thread() { @Override public void run() { try { - doServerSide(servParams); + doServerSide(servParams, serverReady); } catch (Exception e) { /* * Our server thread just died. * * Release the client, if not active already... */ - System.err.println("Server died..."); - serverReady = true; + System.err.println("Server died: " + e); serverException = e; + } finally { + serverReady.countDown(); } } }; serverThread.start(); } else { try { - doServerSide(servParams); + doServerSide(servParams, serverReady); } catch (Exception e) { + System.err.println("Server died: " + e); serverException = e; } finally { - serverReady = true; + serverReady.countDown(); } } } - final void startClient(ClientParameters cliParams, boolean newThread) - throws Exception { + final void startClient(ClientParameters cliParams, boolean newThread, + CountDownLatch serverReady) throws Exception { if (newThread) { clientThread = new Thread() { @Override public void run() { try { - doClientSide(cliParams); + doClientSide(cliParams, serverReady); } catch (Exception e) { /* * Our client thread just died. */ - System.err.println("Client died..."); + System.err.println("Client died: " + e); clientException = e; } } @@ -505,9 +514,10 @@ public void run() { clientThread.start(); } else { try { - doClientSide(cliParams); + doClientSide(cliParams, serverReady); } catch (Exception e) { clientException = e; + System.err.println("Client died: " + e); } } } diff --git a/test/jdk/javax/net/ssl/TLSCommon/interop/AbstractPeer.java b/test/jdk/javax/net/ssl/TLSCommon/interop/AbstractPeer.java index 1bfc3ebcdbb..9950caf1921 100644 --- a/test/jdk/javax/net/ssl/TLSCommon/interop/AbstractPeer.java +++ b/test/jdk/javax/net/ssl/TLSCommon/interop/AbstractPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,13 +49,6 @@ protected void printLog() throws IOException { System.out.println(Utilities.readFile(logPath).orElse("")); } - /* - * Deletes log file if exists. - */ - protected void deleteLog() throws IOException { - Utilities.deleteFile(getLogPath()); - } - /* * The negotiated application protocol. */ diff --git a/test/jdk/javax/net/ssl/TLSCommon/interop/JdkProcClient.java b/test/jdk/javax/net/ssl/TLSCommon/interop/JdkProcClient.java index 91d1a8d1ead..7d3cb7d1665 100644 --- a/test/jdk/javax/net/ssl/TLSCommon/interop/JdkProcClient.java +++ b/test/jdk/javax/net/ssl/TLSCommon/interop/JdkProcClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -148,7 +148,6 @@ protected Path getLogPath() { @Override public void close() throws IOException { printLog(); - deleteLog(); } public static void main(String[] args) throws Exception { diff --git a/test/jdk/javax/net/ssl/TLSCommon/interop/JdkProcServer.java b/test/jdk/javax/net/ssl/TLSCommon/interop/JdkProcServer.java index b07a039203e..a6c8a13e0c6 100644 --- a/test/jdk/javax/net/ssl/TLSCommon/interop/JdkProcServer.java +++ b/test/jdk/javax/net/ssl/TLSCommon/interop/JdkProcServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -166,7 +166,6 @@ public void signalStop() { public void close() throws IOException { printLog(); deletePort(); - deleteLog(); } private static int readPort() { diff --git a/test/jdk/javax/net/ssl/templates/SSLExampleCert.java b/test/jdk/javax/net/ssl/templates/SSLExampleCert.java index 0b82aed3b7b..46f69a62e41 100644 --- a/test/jdk/javax/net/ssl/templates/SSLExampleCert.java +++ b/test/jdk/javax/net/ssl/templates/SSLExampleCert.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java b/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java index 0891523ac11..51706cec927 100644 --- a/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java +++ b/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java @@ -190,6 +190,7 @@ protected void doServerSide() throws Exception { try { sslServerSocket.setSoTimeout(30000); sslSocket = (SSLSocket)sslServerSocket.accept(); + System.out.println("Connection established on port : " +serverPort); } catch (SocketTimeoutException ste) { // Ignore the test case if no connection within 30 seconds. System.out.println( @@ -228,6 +229,7 @@ protected void doServerSide() throws Exception { } } finally { sslSocket.close(); + System.out.println("Connection closed on port : " +serverPort); } } diff --git a/test/jdk/javax/print/PrintServiceLookup/CountPrintServices.java b/test/jdk/javax/print/PrintServiceLookup/CountPrintServices.java index 5be9f0297d2..4da1ed59a27 100644 --- a/test/jdk/javax/print/PrintServiceLookup/CountPrintServices.java +++ b/test/jdk/javax/print/PrintServiceLookup/CountPrintServices.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,25 +25,21 @@ import java.io.InputStreamReader; import javax.print.PrintService; import javax.print.PrintServiceLookup; -import javax.print.attribute.AttributeSet; -import javax.print.attribute.HashAttributeSet; -import javax.print.attribute.standard.PrinterName; +import java.io.IOException; + +import jtreg.SkippedException; /* * @test * @bug 8032693 * @key printer + * @library /test/lib/ + * @requires (os.family == "linux") * @summary Test that lpstat and JDK agree whether there are printers. */ public class CountPrintServices { public static void main(String[] args) throws Exception { - String os = System.getProperty("os.name").toLowerCase(); - System.out.println("OS is " + os); - if (!os.equals("linux")) { - System.out.println("Linux specific test. No need to continue"); - return; - } PrintService services[] = PrintServiceLookup.lookupPrintServices(null, null); if (services.length > 0) { @@ -51,7 +47,16 @@ public static void main(String[] args) throws Exception { return; } String[] lpcmd = { "lpstat", "-a" }; - Process proc = Runtime.getRuntime().exec(lpcmd); + Process proc; + try { + proc = Runtime.getRuntime().exec(lpcmd); + } catch (IOException e) { + if (e.getMessage().contains("No such file or directory")) { + throw new SkippedException("Cannot find lpstat"); + } else { + throw e; + } + } proc.waitFor(); InputStreamReader ir = new InputStreamReader(proc.getInputStream()); BufferedReader br = new BufferedReader(ir); @@ -66,4 +71,3 @@ public static void main(String[] args) throws Exception { } } } - diff --git a/test/jdk/javax/rmi/ssl/SSLSocketParametersTest.java b/test/jdk/javax/rmi/ssl/SSLSocketParametersTest.java index 6da32894587..4aeaf399eed 100644 --- a/test/jdk/javax/rmi/ssl/SSLSocketParametersTest.java +++ b/test/jdk/javax/rmi/ssl/SSLSocketParametersTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2023, 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 @@ -134,6 +134,7 @@ public void runTest(int testNumber) throws Exception { } public static void main(String[] args) throws Exception { + System.setProperty("jdk.rmi.ssl.client.enableEndpointIdentification", "false"); // Set keystore properties (server-side) // final String keystore = System.getProperty("test.src") + @@ -153,4 +154,4 @@ public static void main(String[] args) throws Exception { SSLSocketParametersTest test = new SSLSocketParametersTest(); test.runTest(Integer.parseInt(args[0])); } -} \ No newline at end of file +} diff --git a/test/jdk/javax/security/auth/callback/PasswordCallback/CheckCleanerBound.java b/test/jdk/javax/security/auth/callback/PasswordCallback/CheckCleanerBound.java index 8f68773398c..6d500fea656 100644 --- a/test/jdk/javax/security/auth/callback/PasswordCallback/CheckCleanerBound.java +++ b/test/jdk/javax/security/auth/callback/PasswordCallback/CheckCleanerBound.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,4 +55,3 @@ public static void main(String[] args) throws Exception { } } } - diff --git a/test/jdk/javax/security/auth/callback/PasswordCallback/PasswordCleanup.java b/test/jdk/javax/security/auth/callback/PasswordCallback/PasswordCleanup.java index ea8b1d1c145..64db7de2b18 100644 --- a/test/jdk/javax/security/auth/callback/PasswordCallback/PasswordCleanup.java +++ b/test/jdk/javax/security/auth/callback/PasswordCallback/PasswordCleanup.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,4 +49,3 @@ public static void main(String[] args) throws Exception { } } } - diff --git a/test/jdk/javax/sound/midi/MidiDeviceConnectors/TestAllDevices.java b/test/jdk/javax/sound/midi/MidiDeviceConnectors/TestAllDevices.java index 27290738a0c..afac39b83fb 100644 --- a/test/jdk/javax/sound/midi/MidiDeviceConnectors/TestAllDevices.java +++ b/test/jdk/javax/sound/midi/MidiDeviceConnectors/TestAllDevices.java @@ -24,6 +24,7 @@ /** * @test * @bug 4933700 + * @key sound * @summary Tests that default devices return MidiDeviceTransmitter/Receiver and returned objects return correct MidiDevice * @compile TestAllDevices.java * @run main TestAllDevices diff --git a/test/jdk/javax/sound/midi/SysexMessage/SendRawSysexMessage.java b/test/jdk/javax/sound/midi/SysexMessage/SendRawSysexMessage.java index 00c57f46c98..7b8c4b0a3f2 100644 --- a/test/jdk/javax/sound/midi/SysexMessage/SendRawSysexMessage.java +++ b/test/jdk/javax/sound/midi/SysexMessage/SendRawSysexMessage.java @@ -35,6 +35,7 @@ /** * @test * @bug 8074211 8237495 8301310 + * @key sound * @summary fail with memory errors when asked to send a sysex message starting * with 0xF7 */ diff --git a/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/ExpectedNPEOnNull.java b/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/ExpectedNPEOnNull.java index efb57eeeae2..05ba16cded5 100644 --- a/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/ExpectedNPEOnNull.java +++ b/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/ExpectedNPEOnNull.java @@ -32,6 +32,7 @@ /** * @test * @bug 8143909 + * @key sound * @author Sergey Bylokhov */ public final class ExpectedNPEOnNull { diff --git a/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/FakeInfo.java b/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/FakeInfo.java index 8eabb992bca..71d27c4943c 100644 --- a/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/FakeInfo.java +++ b/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/FakeInfo.java @@ -35,6 +35,7 @@ /** * @test * @bug 8059743 + * @key sound * @summary MidiDeviceProvider shouldn't returns incorrect results in case of * some unknown MidiDevice.Info * @author Sergey Bylokhov diff --git a/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/UnsupportedInfo.java b/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/UnsupportedInfo.java index 685a5e8af62..5d37759fbad 100644 --- a/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/UnsupportedInfo.java +++ b/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/UnsupportedInfo.java @@ -30,6 +30,7 @@ /** * @test * @bug 8058115 + * @key sound * @summary MidiDeviceProvider shouldn't returns incorrect results in case of * unsupported MidiDevice.Info * @author Sergey Bylokhov diff --git a/test/jdk/javax/swing/ButtonGroup/TestButtonGroupFocusTraversal.java b/test/jdk/javax/swing/ButtonGroup/TestButtonGroupFocusTraversal.java index c115d44edbf..8dba2ae3e08 100644 --- a/test/jdk/javax/swing/ButtonGroup/TestButtonGroupFocusTraversal.java +++ b/test/jdk/javax/swing/ButtonGroup/TestButtonGroupFocusTraversal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,6 @@ * @run main TestButtonGroupFocusTraversal */ -import javax.swing.AbstractAction; import javax.swing.ButtonGroup; import javax.swing.JCheckBox; import javax.swing.JFrame; @@ -43,9 +42,7 @@ import java.awt.Container; import java.awt.FlowLayout; import java.awt.KeyboardFocusManager; -import java.awt.Point; import java.awt.Robot; -import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; public class TestButtonGroupFocusTraversal { @@ -53,25 +50,11 @@ public class TestButtonGroupFocusTraversal { private static JTextField textFieldFirst, textFieldLast; private static JToggleButton toggleButton1, toggleButton2; private static JCheckBox checkBox1, checkBox2; - private static boolean toggleButtonActionPerformed; - private static boolean checkboxActionPerformed; + private static volatile boolean toggleButtonActionPerformed; + private static volatile boolean checkboxActionPerformed; private static JRadioButton radioButton1, radioButton2; private static Robot robot; - private static void blockTillDisplayed(Component comp) { - Point p = null; - while (p == null) { - try { - p = comp.getLocationOnScreen(); - } catch (IllegalStateException e) { - try { - Thread.sleep(500); - } catch (InterruptedException ie) { - } - } - } - } - private static void createUI() throws Exception { SwingUtilities.invokeAndWait(new Runnable() { public void run() { @@ -84,33 +67,11 @@ public void run() { checkBox1 = new JCheckBox("1"); checkBox2 = new JCheckBox("2"); - toggleButton1.setAction(new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - toggleButtonActionPerformed = true; - } - }); - - toggleButton2.setAction(new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - toggleButtonActionPerformed = true; - } - }); - - checkBox1.setAction(new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - checkboxActionPerformed = true; - } - }); - - checkBox2.setAction(new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - checkboxActionPerformed = true; - } - }); + toggleButton1.addActionListener((_) -> toggleButtonActionPerformed = true); + toggleButton2.addActionListener((_) -> toggleButtonActionPerformed = true); + + checkBox1.addActionListener((_) -> checkboxActionPerformed = true); + checkBox2.addActionListener((_) -> checkboxActionPerformed = true); ButtonGroup toggleGroup = new ButtonGroup(); toggleGroup.add(toggleButton1); @@ -128,7 +89,7 @@ public void actionPerformed(ActionEvent e) { radioButton2.setSelected(true); checkBox2.setSelected(true); - frame = new JFrame("Test"); + frame = new JFrame("TestButtonGroupFocusTraversal"); frame.setLayout(new FlowLayout()); Container pane = frame.getContentPane(); @@ -178,7 +139,7 @@ private static void checkToggleButtonActionPerformed() { } private static void checkCheckboxActionPerformed() { - if (toggleButtonActionPerformed) { + if (checkboxActionPerformed) { throw new RuntimeException("Checkbox Action should not be" + "performed"); } @@ -196,19 +157,13 @@ public static void main(String[] args) throws Exception { createUI(); robot.waitForIdle(); - robot.delay(200); - - blockTillDisplayed(frame); + robot.delay(500); SwingUtilities.invokeAndWait(textFieldFirst::requestFocus); if (!textFieldFirst.equals(KeyboardFocusManager.getCurrentKeyboardFocusManager() .getFocusOwner())) { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } + robot.delay(300); SwingUtilities.invokeAndWait(textFieldFirst::requestFocus); } diff --git a/test/jdk/javax/swing/JCheckBox/4449413/bug4449413.java b/test/jdk/javax/swing/JCheckBox/4449413/bug4449413.java index 1efcfe58a31..d854961ea06 100644 --- a/test/jdk/javax/swing/JCheckBox/4449413/bug4449413.java +++ b/test/jdk/javax/swing/JCheckBox/4449413/bug4449413.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, 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 @@ -24,7 +24,6 @@ /* @test * @bug 4449413 * @summary Tests that checkbox and radiobuttons' check marks are visible when background is black - * @author Ilya Boyandin * @run main/manual bug4449413 */ @@ -56,8 +55,16 @@ public class bug4449413 extends JFrame { + private static boolean isWindowsLF; + + private static String INSTRUCTIONS_WINDOWSLF = + "There are eight controls, JCheckBox/JRadioButton with black background\n" + + "and JRadioButtonMenuItem/JCheckboxMenuItem with gray background\n"; + private static final String INSTRUCTIONS = - "There are eight controls with black backgrounds.\n" + + "There are eight controls with black backgrounds.\n"; + + private static final String INSTRUCTIONS_COMMON = "Four enabled (on the left side) and four disabled (on the right side)\n" + "checkboxes and radiobuttons.\n\n" + "1. If at least one of the controls' check marks is not visible:\n" + @@ -82,6 +89,8 @@ boolean isMetalLookAndFeel() { } public static void main(String[] args) throws Exception { + isWindowsLF = "Windows".equals(UIManager.getLookAndFeel().getID()); + SwingUtilities.invokeLater(() -> { instance = new bug4449413(); instance.createAndShowGUI(); @@ -150,8 +159,10 @@ public void addComponentsToPane() { JTextArea instructionArea = new JTextArea( isMetalLookAndFeel() - ? INSTRUCTIONS + INSTRUCTIONS_ADDITIONS_METAL - : INSTRUCTIONS + ? INSTRUCTIONS + INSTRUCTIONS_COMMON + INSTRUCTIONS_ADDITIONS_METAL + : isWindowsLF + ? (INSTRUCTIONS_WINDOWSLF + INSTRUCTIONS_COMMON) + : (INSTRUCTIONS + INSTRUCTIONS_COMMON) ); instructionArea.setEditable(false); @@ -189,7 +200,13 @@ static AbstractButton createButton(int enabled, int type) { }; b.setOpaque(true); - b.setBackground(Color.black); + if (isWindowsLF + && ((b instanceof JRadioButtonMenuItem) + || (b instanceof JCheckBoxMenuItem))) { + b.setBackground(Color.lightGray); + } else { + b.setBackground(Color.black); + } b.setForeground(Color.white); b.setEnabled(enabled == 1); b.setSelected(true); diff --git a/test/jdk/javax/swing/JFileChooser/HTMLFileName.java b/test/jdk/javax/swing/JFileChooser/HTMLFileName.java index 8783c388985..a8bc9525cca 100644 --- a/test/jdk/javax/swing/JFileChooser/HTMLFileName.java +++ b/test/jdk/javax/swing/JFileChooser/HTMLFileName.java @@ -41,7 +41,7 @@ /* * @test id=system - * @bug 8139228 + * @bug 8139228 8358532 * @summary JFileChooser should not render Directory names in HTML format * @library /java/awt/regtesthelpers * @build PassFailJFrame @@ -52,24 +52,35 @@ public class HTMLFileName { private static final String INSTRUCTIONS = """

      -
    1. FileChooser shows up a virtual directory and file with name -

      Swing Rocks!. -
    2. On "HTML disabled" frame : +
    3. JFileChooser shows a virtual directory. + The first file in the list has the following name: + <html><h1 color=#ff00ff><font + face="Serif">Swing Rocks! +
      +
      +
    4. In HTML disabled frame:
        -
      1. Verify that the folder and file name must be plain text. -
      2. If the name in file pane window and also in directory - ComboBox remains in plain text, then press Pass. - If it appears to be in HTML format with Pink color as - shown, then press Fail. +
      3. Verify that the first file name displays + as plain text, + that is you see the HTML tags in the file name. +
      4. If the file name in the file pane and + in the navigation combo box above is displayed + as HTML, that is in large font and magenta color, + then press Fail.
      -
    5. On "HTML enabled" frame : +
    6. In HTML enabled frame:
        -
      1. Verify that the folder and file name remains in HTML - format with name "Swing Rocks!" pink in color as shown. -
      2. If the name in file pane window and also in directory - ComboBox remains in HTML format string, then press Pass. - If it appears to be in plain text, then press Fail. +
      3. Verify that the first file name displays as HTML, + that is Swing Rocks! in large font + and magenta color.
        + Note: On macOS in Aqua L&F, the file name with + HTML displays as an empty file name. It is not an error. +
      4. If the file name in the file pane and + in the navigation combo box above is displayed + as HTML, then press Pass.
        + If it is in plain text, then press Fail.
    @@ -99,6 +110,7 @@ public static void main(String[] args) throws Exception { PassFailJFrame.builder() .instructions(INSTRUCTIONS) .columns(45) + .rows(20) .testUI(HTMLFileName::initialize) .positionTestUIBottomRowCentered() .build() @@ -110,18 +122,25 @@ private static List initialize() { return List.of(createFileChooser(true), createFileChooser(false)); } - private static JFrame createFileChooser(boolean htmlEnabled) { + private static JFrame createFileChooser(boolean htmlDisabled) { JFileChooser jfc = new JFileChooser(new VirtualFileSystemView()); - jfc.putClientProperty("html.disable", htmlEnabled); + jfc.putClientProperty("html.disable", htmlDisabled); jfc.setControlButtonsAreShown(false); - JFrame frame = new JFrame((htmlEnabled) ? "HTML enabled" : "HTML disabled"); + JFrame frame = new JFrame(htmlDisabled ? "HTML disabled" : "HTML enabled"); frame.add(jfc); frame.pack(); return frame; } private static class VirtualFileSystemView extends FileSystemView { + private final File[] files = { + new File("/", "

    Swing Rocks!"), + new File("/", "virtualFile1.txt"), + new File("/", "virtualFile2.log") + }; + @Override public File createNewFolder(File containingDir) { return null; @@ -129,12 +148,7 @@ public File createNewFolder(File containingDir) { @Override public File[] getRoots() { - return new File[]{ - new File("/", "

    Swing Rocks!"), - new File("/", "virtualFile2.txt"), - new File("/", "virtualFolder") - }; + return files; } @Override @@ -150,12 +164,7 @@ public File getDefaultDirectory() { @Override public File[] getFiles(File dir, boolean useFileHiding) { // Simulate a virtual folder structure - return new File[]{ - new File("/", "

    Swing Rocks!"), - new File(dir, "virtualFile2.txt"), - new File(dir, "virtualFolder") - }; + return files; } @Override diff --git a/test/jdk/javax/swing/JInternalFrame/8160248/JInternalFrameDraggingTest.java b/test/jdk/javax/swing/JInternalFrame/8160248/JInternalFrameDraggingTest.java index 81f5e0d0802..7c3732925be 100644 --- a/test/jdk/javax/swing/JInternalFrame/8160248/JInternalFrameDraggingTest.java +++ b/test/jdk/javax/swing/JInternalFrame/8160248/JInternalFrameDraggingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,6 +21,7 @@ * questions. */ +import java.io.File; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Point; @@ -28,6 +29,7 @@ import java.awt.Robot; import java.awt.event.InputEvent; import java.awt.image.BufferedImage; +import javax.imageio.ImageIO; import javax.swing.JDesktopPane; import javax.swing.JFrame; import javax.swing.JInternalFrame; @@ -51,6 +53,7 @@ public class JInternalFrameDraggingTest { private static JInternalFrame internalFrame; private static int FRAME_SIZE = 500; private static Color BACKGROUND_COLOR = Color.ORANGE; + private static final int tolerance = 10; public static void main(String[] args) throws Exception { try { @@ -69,14 +72,24 @@ public static void main(String[] args) throws Exception { BufferedImage img = robot.createScreenCapture(rect); int testRGB = BACKGROUND_COLOR.getRGB(); + Color testColor = new Color(testRGB); for (int i = 1; i < size; i++) { int rgbCW = img.getRGB(i, size / 2); int rgbCH = img.getRGB(size / 2, i); - if (rgbCW != testRGB || rgbCH != testRGB) { + Color rgbCWColor = new Color(rgbCW); + Color rgbCHColor = new Color(rgbCH); + + if (Math.abs(rgbCWColor.getRed() - testColor.getRed()) > tolerance + || Math.abs(rgbCWColor.getGreen() - testColor.getGreen()) > tolerance + || Math.abs(rgbCWColor.getBlue() - testColor.getBlue()) > tolerance + || Math.abs(rgbCHColor.getRed() - testColor.getRed()) > tolerance + || Math.abs(rgbCHColor.getGreen() - testColor.getGreen()) > tolerance + || Math.abs(rgbCHColor.getBlue() - testColor.getBlue()) > tolerance) { System.out.println("i " + i + " rgbCW " + Integer.toHexString(rgbCW) + " testRGB " + Integer.toHexString(testRGB) + " rgbCH " + Integer.toHexString(rgbCH)); + ImageIO.write(img, "png", new File("JInternalFrameDraggingTest.png")); throw new RuntimeException("Background color is wrong!"); } } diff --git a/test/jdk/javax/swing/JMenuBar/RightLeftOrientation.java b/test/jdk/javax/swing/JMenuBar/RightLeftOrientation.java index 80779c9ce1d..8308034d060 100644 --- a/test/jdk/javax/swing/JMenuBar/RightLeftOrientation.java +++ b/test/jdk/javax/swing/JMenuBar/RightLeftOrientation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -20,75 +20,76 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + /* * @test * @bug 4211731 4214512 * @summary * This test checks if menu bars lay out correctly when their - * ComponentOrientation property is set to RIGHT_TO_LEFT. This test is - * manual. The tester is asked to compare left-to-right and - * right-to-left menu bars and judge whether they are mirror images of each - * other. + * ComponentOrientation property is set to RIGHT_TO_LEFT. + * The tester is asked to compare left-to-right and + * right-to-left menu bars and decide whether they are mirror + * images of each other. * @library /test/jdk/java/awt/regtesthelpers * @build PassFailJFrame * @run main/manual RightLeftOrientation */ import java.awt.ComponentOrientation; -import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.List; + import javax.swing.ButtonGroup; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; +import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.SwingUtilities; import javax.swing.UIManager; -public class RightLeftOrientation { +public final class RightLeftOrientation { - static JFrame ltrFrame; - static JFrame rtlFrame; + private static List frames; private static final String INSTRUCTIONS = """ - This test checks menu bars for correct Right-To-Left Component Orientation. - - You should see two frames, each containing a menu bar. + This test checks menu bars for correct Right-To-Left component orientation. - One frame will be labelled "Left To Right" and will contain + You should see two frames, each contains a menu bar. + One frame is labelled "Left To Right" and contains a menu bar with menus starting on its left side. - The other frame will be labelled "Right To Left" and will - contain a menu bar with menus starting on its right side. + The other frame is labelled "Right To Left" and + contains a menu bar with menus starting on its right side. - The test will also contain radio buttons that can be used to set - the look and feel of the menu bars. - For each look and feel, you should compare the two menu - bars and make sure they are mirror images of each other. """; + The test also displays a frame with radio buttons + to change the look and feel of the menu bars. + For each look and feel, compare the two menu bars + in LTR and RTL orientation and make sure they are mirror + images of each other."""; public static void main(String[] args) throws Exception { PassFailJFrame.builder() - .title("RTL test Instructions") + .title("Menu Bar RTL Instructions") .instructions(INSTRUCTIONS) - .rows((int) INSTRUCTIONS.lines().count() + 2) .columns(30) .testUI(RightLeftOrientation::createTestUI) + .positionTestUIRightColumn() .build() .awaitAndCheck(); } - private static JFrame createTestUI() { - JFrame frame = new JFrame("RightLeftOrientation"); + private static JFrame createPlafChangerFrame() { + JFrame frame = new JFrame("Change Look and Feel"); JPanel panel = new JPanel(); ButtonGroup group = new ButtonGroup(); - JRadioButton rb; ActionListener plafChanger = new PlafChanger(); UIManager.LookAndFeelInfo[] lafInfos = UIManager.getInstalledLookAndFeels(); for (int i = 0; i < lafInfos.length; i++) { - rb = new JRadioButton(lafInfos[i].getName()); + JRadioButton rb = new JRadioButton(lafInfos[i].getName()); rb.setActionCommand(lafInfos[i].getClassName()); rb.addActionListener(plafChanger); group.add(rb); @@ -99,33 +100,39 @@ private static JFrame createTestUI() { } frame.add(panel); + frame.pack(); + return frame; + } - ltrFrame = new JFrame("Left To Right"); + private static List createTestUI() { + JFrame plafFrame = createPlafChangerFrame(); + + JFrame ltrFrame = new JFrame("Left To Right"); ltrFrame.setJMenuBar(createMenuBar(ComponentOrientation.LEFT_TO_RIGHT)); ltrFrame.setSize(400, 100); - ltrFrame.setLocation(new Point(10, 10)); - ltrFrame.setVisible(true); - rtlFrame = new JFrame("Right To Left"); + JFrame rtlFrame = new JFrame("Right To Left"); rtlFrame.setJMenuBar(createMenuBar(ComponentOrientation.RIGHT_TO_LEFT)); rtlFrame.setSize(400, 100); - rtlFrame.setLocation(new Point(10, 120)); - rtlFrame.setVisible(true); - frame.pack(); - return frame; + + return (frames = List.of(plafFrame, ltrFrame, rtlFrame)); } - static class PlafChanger implements ActionListener { + private static final class PlafChanger implements ActionListener { + @Override public void actionPerformed(ActionEvent e) { String lnfName = e.getActionCommand(); try { UIManager.setLookAndFeel(lnfName); - SwingUtilities.updateComponentTreeUI(ltrFrame); - SwingUtilities.updateComponentTreeUI(rtlFrame); - } - catch (Exception exc) { - System.err.println("Could not load LookAndFeel: " + lnfName); + frames.forEach(SwingUtilities::updateComponentTreeUI); + } catch (Exception exc) { + String message = "Could not set Look and Feel to " + lnfName; + System.err.println(message); + JOptionPane.showMessageDialog(frames.get(0), + message, + "Look and Feel Error", + JOptionPane.ERROR_MESSAGE); } } diff --git a/test/jdk/javax/swing/JMenuItem/RightLeftOrientation.java b/test/jdk/javax/swing/JMenuItem/RightLeftOrientation.java index 6c7185b547a..247d8b52541 100644 --- a/test/jdk/javax/swing/JMenuItem/RightLeftOrientation.java +++ b/test/jdk/javax/swing/JMenuItem/RightLeftOrientation.java @@ -22,18 +22,36 @@ */ /* - * @test + * @test id=metal * @bug 4211052 * @requires (os.family == "windows") - * @summary - * This test checks if menu items lay out correctly when their + * @summary Verifies if menu items lay out correctly when their * ComponentOrientation property is set to RIGHT_TO_LEFT. - * The tester is asked to compare left-to-right and - * right-to-left menus and judge whether they are mirror images of each - * other. * @library /java/awt/regtesthelpers * @build PassFailJFrame - * @run main/manual RightLeftOrientation + * @run main/manual RightLeftOrientation metal + */ + +/* + * @test id=motif + * @bug 4211052 + * @requires (os.family == "windows") + * @summary Verifies if menu items lay out correctly when their + * ComponentOrientation property is set to RIGHT_TO_LEFT. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual RightLeftOrientation motif + */ + +/* + * @test id=windows + * @bug 4211052 8370465 + * @requires (os.family == "windows") + * @summary Verifies if menu items lay out correctly when their + * ComponentOrientation property is set to RIGHT_TO_LEFT. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual RightLeftOrientation windows */ import java.awt.Color; @@ -52,29 +70,47 @@ import javax.swing.JMenuItem; import javax.swing.JRadioButtonMenuItem; import javax.swing.KeyStroke; -import javax.swing.LookAndFeel; import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; import javax.swing.UIManager; public class RightLeftOrientation { private static final String INSTRUCTIONS = """ - A menu bar is shown containing a menu for each look and feel. - A disabled menu means that the look and feel is not available for - testing in this environment. - Every effort should be made to run this test - in an environment that covers all look and feels. + A menu bar is shown with a menu. - Each menu is divided into two halves. The upper half is oriented + The menu is divided into two halves. The upper half is oriented left-to-right and the lower half is oriented right-to-left. - For each menu, ensure that the lower half mirrors the upper half. + Ensure that the lower half mirrors the upper half. Note that when checking the positioning of the sub-menus, it helps to position the frame away from the screen edges."""; public static void main(String[] args) throws Exception { + if (args.length < 1) { + throw new IllegalArgumentException("Look-and-Feel keyword is required"); + } + + final String lafClassName; + switch (args[0]) { + case "metal" -> lafClassName = UIManager.getCrossPlatformLookAndFeelClassName(); + case "motif" -> lafClassName = "com.sun.java.swing.plaf.motif.MotifLookAndFeel"; + case "windows" -> lafClassName = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"; + default -> throw new IllegalArgumentException( + "Unsupported Look-and-Feel keyword for this test: " + args[0]); + } + + SwingUtilities.invokeAndWait(() -> { + try { + UIManager.setLookAndFeel(lafClassName); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + + System.out.println("Test for LookAndFeel " + lafClassName); + PassFailJFrame.builder() - .title("RightLeftOrientation Instructions") .instructions(INSTRUCTIONS) .columns(35) .testUI(RightLeftOrientation::createTestUI) @@ -86,32 +122,19 @@ private static JFrame createTestUI() { JFrame frame = new JFrame("RightLeftOrientation"); JMenuBar menuBar = new JMenuBar(); - menuBar.add(createMenu("javax.swing.plaf.metal.MetalLookAndFeel", - "Metal")); - menuBar.add(createMenu("com.sun.java.swing.plaf.motif.MotifLookAndFeel", - "Motif")); - menuBar.add(createMenu("com.sun.java.swing.plaf.windows.WindowsLookAndFeel", - "Windows")); + menuBar.add(createMenu()); frame.setJMenuBar(menuBar); - frame.pack(); + frame.setSize(250, 70); return frame; } - static JMenu createMenu(String laf, String name) { - JMenu menu = new JMenu(name); - try { - LookAndFeel save = UIManager.getLookAndFeel(); - UIManager.setLookAndFeel(laf); - addMenuItems(menu, ComponentOrientation.LEFT_TO_RIGHT); - menu.addSeparator(); - addMenuItems(menu, ComponentOrientation.RIGHT_TO_LEFT); - UIManager.setLookAndFeel(save); - } catch (Exception e) { - menu = new JMenu(name); - menu.setEnabled(false); - } + static JMenu createMenu() { + JMenu menu = new JMenu(UIManager.getLookAndFeel().getID()); + addMenuItems(menu, ComponentOrientation.LEFT_TO_RIGHT); + menu.addSeparator(); + addMenuItems(menu, ComponentOrientation.RIGHT_TO_LEFT); return menu; } @@ -132,6 +155,16 @@ static void addMenuItems(JMenu menu, ComponentOrientation o) { menuItem.setHorizontalTextPosition(SwingConstants.LEADING); menu.add(menuItem); + menuItem = new JMenuItem("Text to the left", new MyMenuItemIcon()); + menuItem.setComponentOrientation(o); + menuItem.setHorizontalTextPosition(SwingConstants.LEFT); + menu.add(menuItem); + + menuItem = new JMenuItem("Text to the right", new MyMenuItemIcon()); + menuItem.setComponentOrientation(o); + menuItem.setHorizontalTextPosition(SwingConstants.RIGHT); + menu.add(menuItem); + menuItem = new JRadioButtonMenuItem("Radio Button Menu Item"); menuItem.setComponentOrientation(o); menuItem.setSelected(true); diff --git a/test/jdk/javax/swing/JOptionPane/TestJOptionHTMLTag.java b/test/jdk/javax/swing/JOptionPane/TestJOptionHTMLTag.java deleted file mode 100644 index 94318492bd9..00000000000 --- a/test/jdk/javax/swing/JOptionPane/TestJOptionHTMLTag.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -/* @test - * @bug 5074006 - * @key headful - * @library /java/awt/regtesthelpers - * @build PassFailJFrame - * @summary Swing JOptionPane shows tag as a string after newline - * @run main/manual TestJOptionHTMLTag -*/ - -import javax.swing.JDialog; -import javax.swing.JOptionPane; -import javax.swing.SwingUtilities; - -public class TestJOptionHTMLTag { - static String instructions - = """ - INSTRUCTIONS: - A dialog will be shown. - If it does not contain string, press Pass else press Fail. - """; - static PassFailJFrame passFailJFrame; - - public static void main(String[] args) throws Exception { - - SwingUtilities.invokeAndWait(() -> { - try { - String message = "" + "This is a test\n" + ""; - JOptionPane optionPane = new JOptionPane(); - optionPane.setMessage(message); - optionPane.setMessageType(JOptionPane.INFORMATION_MESSAGE); - JDialog dialog = new JDialog(); - dialog.setContentPane(optionPane); - dialog.pack(); - dialog.setVisible(true); - - passFailJFrame = new PassFailJFrame(instructions); - PassFailJFrame.addTestWindow(dialog); - PassFailJFrame.positionTestWindow(dialog, PassFailJFrame.Position.HORIZONTAL); - } catch (Exception e) { - e.printStackTrace(); - } - }); - passFailJFrame.awaitAndCheck(); - } -} - diff --git a/test/jdk/javax/swing/JPasswordField/PasswordFieldInputMapWordTest.java b/test/jdk/javax/swing/JPasswordField/PasswordFieldInputMapWordTest.java new file mode 100644 index 00000000000..c49e9f7083c --- /dev/null +++ b/test/jdk/javax/swing/JPasswordField/PasswordFieldInputMapWordTest.java @@ -0,0 +1,118 @@ +/* + * 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 + * @key headful + * @bug 8358813 + * @summary Password fields' InputMap should not include any word-related action. + * + * @run main PasswordFieldInputMapWordTest + */ + +import java.util.Collection; +import java.util.Set; + +import javax.swing.InputMap; +import javax.swing.JComponent; +import javax.swing.JPasswordField; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.text.DefaultEditorKit; + +public class PasswordFieldInputMapWordTest { + public static void main(String[] args) throws Exception { + for (UIManager.LookAndFeelInfo laf : + UIManager.getInstalledLookAndFeels()) { + System.out.println("Testing LAF: " + laf.getClassName()); + SwingUtilities.invokeAndWait(() -> { + if (setLookAndFeel(laf)) { + runTest(); + } + }); + } + } + + private static boolean setLookAndFeel(UIManager.LookAndFeelInfo laf) { + try { + UIManager.setLookAndFeel(laf.getClassName()); + return true; + } catch (UnsupportedLookAndFeelException e) { + System.err.println("Skipping unsupported look and feel:"); + e.printStackTrace(); + return false; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + static int[] inputMapConditions = new int[] { + JComponent.WHEN_IN_FOCUSED_WINDOW, + JComponent.WHEN_FOCUSED, + JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT + }; + + /** + * These are all the actions with "word" in their field name. + */ + static Collection wordActions = Set.of( + DefaultEditorKit.deleteNextWordAction, + DefaultEditorKit.deletePrevWordAction, + DefaultEditorKit.beginWordAction, + DefaultEditorKit.endWordAction, + DefaultEditorKit.selectionBeginWordAction, + DefaultEditorKit.selectionEndWordAction, + DefaultEditorKit.previousWordAction, + DefaultEditorKit.nextWordAction, + DefaultEditorKit.selectionPreviousWordAction, + DefaultEditorKit.selectionNextWordAction + ); + + private static void runTest() { + JPasswordField field = new JPasswordField(); + + boolean testPassed = true; + for (int condition : inputMapConditions) { + InputMap inputMap = field.getInputMap(condition); + if (inputMap.allKeys() == null) { + continue; + } + for (KeyStroke keyStroke : inputMap.allKeys()) { + Object actionBinding = inputMap.get(keyStroke); + if (wordActions.contains(actionBinding)) { + if (testPassed) { + System.err.println("The following inputs/actions should not be available in a JPasswordField:"); + } + System.err.println(inputMap.get(keyStroke) + " (try typing " + keyStroke + ")"); + testPassed = false; + } + } + } + + if (!testPassed) { + throw new RuntimeException("One or more input/action binding was observed for a JPasswordField."); + } + } +} diff --git a/test/jdk/javax/swing/JProgressBar/TestProgressBarBorder.java b/test/jdk/javax/swing/JProgressBar/TestProgressBarBorder.java deleted file mode 100644 index 06ccfc3b9bf..00000000000 --- a/test/jdk/javax/swing/JProgressBar/TestProgressBarBorder.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.awt.Graphics; -import java.awt.image.BufferedImage; -import javax.imageio.ImageIO; -import javax.swing.JComponent; -import javax.swing.JProgressBar; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; -import javax.swing.UnsupportedLookAndFeelException; - -import static java.awt.image.BufferedImage.TYPE_INT_RGB; - -/* - * @test - * @bug 8224261 - * @key headful - * @library ../regtesthelpers - * @build Util - * @summary Verifies JProgressBar border is not painted when border - * painting is set to false - * @run main TestProgressBarBorder - */ - -public class TestProgressBarBorder { - public static void main(String[] args) throws Exception { - for (UIManager.LookAndFeelInfo laf : - UIManager.getInstalledLookAndFeels()) { - if (!laf.getName().contains("Nimbus") && !laf.getName().contains("GTK")) { - continue; - } - System.out.println("Testing LAF: " + laf.getName()); - SwingUtilities.invokeAndWait(() -> test(laf)); - } - } - - private static void test(UIManager.LookAndFeelInfo laf) { - setLookAndFeel(laf); - JProgressBar progressBar = createProgressBar(); - progressBar.setBorderPainted(true); - BufferedImage withBorder = paintToImage(progressBar); - progressBar.setBorderPainted(false); - BufferedImage withoutBorder = paintToImage(progressBar); - - boolean equal = Util.compareBufferedImages(withBorder, withoutBorder); - if (equal) { - try { - ImageIO.write(withBorder, "png", new File("withBorder.png")); - ImageIO.write(withoutBorder, "png", new File("withoutBorder.png")); - } catch (IOException ignored) {} - - throw new RuntimeException("JProgressBar border is painted when border " + - "painting is set to false"); - } - } - - private static void setLookAndFeel(UIManager.LookAndFeelInfo laf) { - try { - UIManager.setLookAndFeel(laf.getClassName()); - } catch (UnsupportedLookAndFeelException ignored) { - System.out.println("Unsupported LAF: " + laf.getClassName()); - } catch (ClassNotFoundException | InstantiationException - | IllegalAccessException e) { - throw new RuntimeException(e); - } - } - - private static JProgressBar createProgressBar() { - JProgressBar progressBar = new JProgressBar(); - progressBar.setSize(100, 50); - progressBar.setValue(0); - progressBar.setStringPainted(true); - return progressBar; - } - - private static BufferedImage paintToImage(JComponent content) { - BufferedImage im = new BufferedImage(content.getWidth(), content.getHeight(), - TYPE_INT_RGB); - Graphics g = im.getGraphics(); - content.paint(g); - g.dispose(); - return im; - } -} diff --git a/test/jdk/javax/swing/JTabbedPane/bug4499556.java b/test/jdk/javax/swing/JTabbedPane/bug4499556.java index fe9d7dbbfde..f9150b339e2 100644 --- a/test/jdk/javax/swing/JTabbedPane/bug4499556.java +++ b/test/jdk/javax/swing/JTabbedPane/bug4499556.java @@ -89,9 +89,10 @@ public static void main(String[] args) throws Exception { } static volatile JTabbedPane pane; + static volatile JFrame frame; static JFrame createUI() { - JFrame frame = new JFrame("bug4499556"); + frame = new JFrame("bug4499556"); pane = getTabbedPane(); frame.add(pane); frame.add(getRightPanel(), BorderLayout.EAST); @@ -262,7 +263,7 @@ static boolean setLAF(String laf) { e.printStackTrace(); return false; } - SwingUtilities.updateComponentTreeUI(pane); + SwingUtilities.updateComponentTreeUI(frame); return true; } diff --git a/test/jdk/javax/swing/SwingUtilities/bug4967768.java b/test/jdk/javax/swing/SwingUtilities/bug4967768.java index 43f9f7cabfb..6ce1f5c787b 100644 --- a/test/jdk/javax/swing/SwingUtilities/bug4967768.java +++ b/test/jdk/javax/swing/SwingUtilities/bug4967768.java @@ -37,13 +37,19 @@ public class bug4967768 { private static final String INSTRUCTIONS = """ - When the test starts you'll see a button "Oops" - with the "p" letter underlined at the bottom - of the instruction frame. + When the test starts you'll see a button "Oops". + + For Windows and GTK Look and Feel, you will need to + press the ALT key to make the mnemonic visible. + Once the ALT key is pressed, the letter "p" will be + underlined at the bottom of the instruction frame. Ensure the underline cuts through the descender of letter "p", i.e. the underline is painted not below the letter but below the baseline. + + Press Pass if you see the expected behaviour else + press Fail. """; public static void main(String[] args) throws Exception { diff --git a/test/jdk/javax/swing/border/LineBorder/ScaledLineBorderTest.java b/test/jdk/javax/swing/border/LineBorder/ScaledLineBorderTest.java index fc83b49597d..80faeed460e 100644 --- a/test/jdk/javax/swing/border/LineBorder/ScaledLineBorderTest.java +++ b/test/jdk/javax/swing/border/LineBorder/ScaledLineBorderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * 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,15 +42,18 @@ import javax.swing.JPanel; import javax.swing.SwingUtilities; +import static sun.java2d.pipe.Region.clipRound; + /* * @test - * @bug 8282958 + * @bug 8282958 8349188 * @summary Verify LineBorder edges have the same width * @requires (os.family == "windows") + * @modules java.desktop/sun.java2d.pipe * @run main ScaledLineBorderTest */ public class ScaledLineBorderTest { - private static final Dimension SIZE = new Dimension(120, 25); + private static final Dimension SIZE = new Dimension(250, 50); private static final Color OUTER_COLOR = Color.BLACK; private static final Color BORDER_COLOR = Color.RED; @@ -59,12 +62,19 @@ public class ScaledLineBorderTest { private static final double[] scales = {1.00, 1.25, 1.50, 1.75, 2.00, 2.50, 3.00}; + private static final int[] thickness = {1, 4, 10, 15}; + + private record TestImage(BufferedImage image, + List panelLocations, + double scale, + int thickness) { + } - private static final List images = - new ArrayList<>(scales.length); + private record TestUI(JComponent content, + List panelLocations, + int thickness) { + } - private static final List panelLocations = - new ArrayList<>(4); public static void main(String[] args) throws Exception { Collection params = Arrays.asList(args); @@ -74,29 +84,38 @@ public static void main(String[] args) throws Exception { } private static void testScaling(boolean showFrame, boolean saveImages) { - JComponent content = createUI(); - if (showFrame) { - showFrame(content); + for (int thickness : thickness) { + TestUI testUI = createUI(thickness); + if (showFrame) { + showFrame(testUI.content); + } + + List images = paintToImages(testUI, saveImages); + verifyBorderRendering(images, saveImages); + } + + if (errorCount > 0) { + throw new Error("Test failed: " + + errorCount + " error(s) detected - " + + errorMessage); } - paintToImages(content, saveImages); - verifyBorderRendering(saveImages); } - private static void verifyBorderRendering(final boolean saveImages) { - String errorMessage = null; - int errorCount = 0; - for (int i = 0; i < images.size(); i++) { - BufferedImage img = images.get(i); - double scaling = scales[i]; - try { - int thickness = (int) Math.floor(scaling); + private static String errorMessage = null; + private static int errorCount = 0; - checkVerticalBorders(SIZE.width / 2, thickness, img); + private static void verifyBorderRendering(final List images, + final boolean saveImages) { + for (TestImage test : images) { + final BufferedImage img = test.image; + final int effectiveThickness = clipRound(test.thickness * test.scale); + try { + checkVerticalBorders((int) (SIZE.width * test.scale / 2), effectiveThickness, img); - for (Point p : panelLocations) { - int y = (int) (p.y * scaling) + SIZE.height / 2; - checkHorizontalBorder(y, thickness, img); + for (Point p : test.panelLocations) { + int y = (int) ((p.y + (SIZE.height / 2)) * test.scale); + checkHorizontalBorder(y, effectiveThickness, img); } } catch (Error e) { if (errorMessage == null) { @@ -104,21 +123,13 @@ private static void verifyBorderRendering(final boolean saveImages) { } errorCount++; - System.err.printf("Scaling: %.2f\n", scaling); + System.err.printf("Scale: %.2f; thickness: %d, effective: %d\n", + test.scale, test.thickness, effectiveThickness); e.printStackTrace(); - // Save the image if it wasn't already saved - if (!saveImages) { - saveImage(img, getImageFileName(scaling)); - } + saveImage(img, getImageFileName(test.scale, test.thickness)); } } - - if (errorCount > 0) { - throw new Error("Test failed: " - + errorCount + " error(s) detected - " - + errorMessage); - } } private static void checkVerticalBorders(final int x, @@ -220,17 +231,19 @@ private static void throwUnexpectedColor(int x, int y, int color) { x, y, color)); } - private static JComponent createUI() { + private static TestUI createUI(int thickness) { Box contentPanel = Box.createVerticalBox(); contentPanel.setBackground(OUTER_COLOR); + List panelLocations = new ArrayList<>(4); + Dimension childSize = null; for (int i = 0; i < 4; i++) { JComponent filler = new JPanel(null); filler.setBackground(INSIDE_COLOR); filler.setPreferredSize(SIZE); filler.setBounds(i, 0, SIZE.width, SIZE.height); - filler.setBorder(BorderFactory.createLineBorder(BORDER_COLOR)); + filler.setBorder(BorderFactory.createLineBorder(BORDER_COLOR, thickness)); JPanel childPanel = new JPanel(new BorderLayout()); childPanel.setBorder(BorderFactory.createEmptyBorder(0, i, 4, 4)); @@ -248,7 +261,7 @@ private static JComponent createUI() { contentPanel.setSize(childSize.width, childSize.height * 4); - return contentPanel; + return new TestUI(contentPanel, panelLocations, thickness); } private static void showFrame(JComponent content) { @@ -260,28 +273,33 @@ private static void showFrame(JComponent content) { frame.setVisible(true); } - private static void paintToImages(final JComponent content, - final boolean saveImages) { - for (double scaling : scales) { + private static List paintToImages(final TestUI testUI, + final boolean saveImages) { + final List images = new ArrayList<>(scales.length); + final JComponent content = testUI.content; + for (double scale : scales) { BufferedImage image = - new BufferedImage((int) Math.ceil(content.getWidth() * scaling), - (int) Math.ceil(content.getHeight() * scaling), + new BufferedImage((int) Math.ceil(content.getWidth() * scale), + (int) Math.ceil(content.getHeight() * scale), BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = image.createGraphics(); - g2d.scale(scaling, scaling); + g2d.scale(scale, scale); content.paint(g2d); g2d.dispose(); if (saveImages) { - saveImage(image, getImageFileName(scaling)); + saveImage(image, getImageFileName(scale, testUI.thickness)); } - images.add(image); + images.add(new TestImage(image, testUI.panelLocations, + scale, testUI.thickness)); } + return images; } - private static String getImageFileName(final double scaling) { - return String.format("test%.2f.png", scaling); + private static String getImageFileName(final double scaling, + final int thickness) { + return String.format("test%02d@%.2f.png", thickness, scaling); } private static void saveImage(BufferedImage image, String filename) { diff --git a/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java b/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java index 4b076977313..2a732812e38 100644 --- a/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java +++ b/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,12 +44,15 @@ import javax.swing.SwingUtilities; import javax.swing.border.LineBorder; +import static sun.java2d.pipe.Region.clipRound; + /* * @test - * @bug 8282958 + * @bug 8282958 8349188 * @summary Verify all the borders are rendered consistently for a JTextField * in Windows LaF which uses LineBorder * @requires (os.family == "windows") + * @modules java.desktop/sun.java2d.pipe * @run main ScaledTextFieldBorderTest */ public class ScaledTextFieldBorderTest { @@ -92,7 +95,7 @@ private static void verifyBorderRendering(final boolean saveImages) { BufferedImage img = images.get(i); double scaling = scales[i]; try { - int thickness = (int) Math.floor(scaling); + int thickness = clipRound(scaling); checkVerticalBorders(textFieldSize.width / 2, thickness, img); diff --git a/test/jdk/javax/swing/plaf/basic/BasicTextUI/PasswordSelectionWordTest.java b/test/jdk/javax/swing/plaf/basic/BasicTextUI/PasswordSelectionWordTest.java new file mode 100644 index 00000000000..695d8a83c70 --- /dev/null +++ b/test/jdk/javax/swing/plaf/basic/BasicTextUI/PasswordSelectionWordTest.java @@ -0,0 +1,94 @@ +/* + * 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 + * @key headful + * @bug 4231444 8354646 + * @summary Password fields' ActionMap needs to replace + * DefaultEditorKit.selectWordAction with + * DefaultEditorKit.selectLineAction. + * + * @run main PasswordSelectionWordTest + */ + +import javax.swing.Action; +import javax.swing.JPasswordField; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.plaf.basic.BasicTextUI; +import javax.swing.text.DefaultEditorKit; +import java.awt.event.ActionEvent; + +public class PasswordSelectionWordTest { + public static void main(String[] args) throws Exception { + for (UIManager.LookAndFeelInfo laf : + UIManager.getInstalledLookAndFeels()) { + System.out.println("Testing LAF: " + laf.getClassName()); + SwingUtilities.invokeAndWait(() -> { + if (setLookAndFeel(laf)) { + runTest(); + } + }); + } + } + + private static boolean setLookAndFeel(UIManager.LookAndFeelInfo laf) { + try { + UIManager.setLookAndFeel(laf.getClassName()); + return true; + } catch (UnsupportedLookAndFeelException e) { + System.err.println("Skipping unsupported look and feel:"); + e.printStackTrace(); + return false; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static void runTest() { + String str = "one two three"; + JPasswordField field = new JPasswordField(str); + if (!(field.getUI() instanceof BasicTextUI)) { + throw new RuntimeException("Unexpected condition: JPasswordField UI was " + field.getUI()); + } + System.out.println("Testing " + field.getUI()); + + // do something (anything) to initialize the Views: + field.setSize(100, 100); + field.addNotify(); + + Action action = field.getActionMap().get( + DefaultEditorKit.selectWordAction); + action.actionPerformed(new ActionEvent(field, 0, "")); + int selectionStart = field.getSelectionStart(); + int selectionEnd = field.getSelectionEnd(); + System.out.println("selectionStart = " + selectionStart); + System.out.println("selectionEnd = " + selectionEnd); + if (selectionStart != 0 || selectionEnd != str.length()) { + throw new RuntimeException("selectionStart = " + selectionStart + + " and selectionEnd = " + selectionEnd); + } + } +} diff --git a/test/jdk/javax/swing/plaf/nimbus/TestNimbusProgressBarBorder.java b/test/jdk/javax/swing/plaf/nimbus/TestNimbusProgressBarBorder.java new file mode 100644 index 00000000000..f9aade1d24d --- /dev/null +++ b/test/jdk/javax/swing/plaf/nimbus/TestNimbusProgressBarBorder.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8192888 + * @key headful + * @summary Verifies ProgressBar in Synth L&F renders background + * when border is not painted + * @run main TestNimbusProgressBarBorder + */ + +import java.io.File; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.GridBagLayout; +import java.awt.image.BufferedImage; +import java.awt.Rectangle; +import java.awt.Robot; + +import javax.imageio.ImageIO; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.UIManager; +import javax.swing.SwingUtilities; + +public class TestNimbusProgressBarBorder { + + private static JFrame frame; + private static JProgressBar progressBar; + private static boolean failure = true; + private static volatile Rectangle rect; + + public static void main(String[] args) throws Exception { + int width = 200; + int height = 100; + try { + Robot robot = new Robot(); + SwingUtilities.invokeAndWait(() -> { + try { + // Set Nimbus L&F + UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel"); + } catch (Exception e) { + throw new RuntimeException(e); + } + frame = new JFrame("Nimbus JProgressBar Test"); + frame.setSize(width, height); + + // ProgressBar setup + progressBar = new JProgressBar(0, 100); + progressBar.setValue(0); + progressBar.setBorderPainted(false); + + JPanel center = new JPanel(new GridBagLayout()); + center.setBackground(Color.WHITE); + center.add(progressBar); + + frame.add(center, BorderLayout.CENTER); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + robot.waitForIdle(); + robot.delay(1000); + SwingUtilities.invokeAndWait(() -> { + rect = progressBar.getBounds(); + }); + + BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g2d = (Graphics2D) img.getGraphics(); + g2d.setColor(Color.WHITE); + g2d.fillRect(0, 0, rect.width, rect.height); + progressBar.paint(g2d); + g2d.dispose(); + + robot.waitForIdle(); + robot.delay(100); + + for (int x = 10; x < (10 + rect.width / 2); x++) { + for (int y = 10; y < (10 + rect.height / 2); y++) { + Color col = new Color(img.getRGB(x, y)); + if (!col.equals(Color.WHITE)) { + failure = false; + break; + } + } + } + if (failure) { + ImageIO.write(img, "png", new File("ProgressBarTest.png")); + throw new RuntimeException("ProgressBar background not drawn"); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } +} diff --git a/test/jdk/javax/swing/regtesthelpers/Util.java b/test/jdk/javax/swing/regtesthelpers/Util.java index 5f81384028e..ddbf32f938d 100644 --- a/test/jdk/javax/swing/regtesthelpers/Util.java +++ b/test/jdk/javax/swing/regtesthelpers/Util.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,14 +21,32 @@ * questions. */ -import javax.swing.*; -import java.awt.*; -import java.awt.event.*; +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.concurrent.Callable; +import java.util.function.Predicate; + +import javax.swing.Box; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.SwingUtilities; + +import static javax.swing.SwingUtilities.isEventDispatchThread; /** *

    This class contains utilities useful for regression testing. @@ -123,26 +141,44 @@ public static void generateOOME() { } /** - * Find a sub component by class name. - * Always run this method on the EDT thread + * Find a subcomponent by class name. */ public static Component findSubComponent(Component parent, String className) { - String parentClassName = parent.getClass().getName(); + return findComponent((Container) parent, + c -> c.getClass() + .getName() + .contains(className)); + } - if (parentClassName.contains(className)) { - return parent; + /** + * Find a component based on predicate. + */ + public static Component findComponent(final Container container, + final Predicate predicate) { + try { + if (isEventDispatchThread()) { + return findComponentImpl(container, predicate); + } else { + return Util.invokeOnEDT(() -> findComponentImpl(container, predicate)); + } + } catch (Exception e) { + throw new RuntimeException("Error occurred while finding component", e); } + } - if (parent instanceof Container) { - for (Component child : ((Container) parent).getComponents()) { - Component subComponent = findSubComponent(child, className); - - if (subComponent != null) { - return subComponent; + private static Component findComponentImpl(final Container container, + final Predicate predicate) { + for (Component child : container.getComponents()) { + if (predicate.test(child)) { + return child; + } + if (child instanceof Container cont && cont.getComponentCount() > 0) { + Component result = findComponentImpl(cont, predicate); + if (result != null) { + return result; } } } - return null; } diff --git a/test/jdk/javax/swing/text/GlyphView/bug4188841.java b/test/jdk/javax/swing/text/GlyphView/bug4188841.java index 1b3cc0bcdd4..9935712bd49 100644 --- a/test/jdk/javax/swing/text/GlyphView/bug4188841.java +++ b/test/jdk/javax/swing/text/GlyphView/bug4188841.java @@ -69,7 +69,7 @@ static JFrame createUI() { JFrame frame = new JFrame("bug4188841"); NoWrapTextPane nwp = new NoWrapTextPane(); - nwp.setText("the\tslow\tbrown\tfox\tjumps\tover\tthe\tlazy\tdog!"); + nwp.setText("the\tquick\tbrown\tfox\tjumps\tover\tthe\tlazy\tdog!"); nwp.setCaretPosition(nwp.getText().length()); JScrollPane scrollPane = new JScrollPane(nwp, diff --git a/test/jdk/jdk/incubator/vector/BasicFloat16ArithTests.java b/test/jdk/jdk/incubator/vector/BasicFloat16ArithTests.java index 4ed95f698cf..0c08099031a 100644 --- a/test/jdk/jdk/incubator/vector/BasicFloat16ArithTests.java +++ b/test/jdk/jdk/incubator/vector/BasicFloat16ArithTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8329817 8334432 8339076 8341260 + * @bug 8329817 8334432 8339076 8341260 8362207 * @modules jdk.incubator.vector * @summary Basic tests of Float16 arithmetic and similar operations */ @@ -186,7 +186,7 @@ private static void checkNegate() { for(var testCase : testCases) { float arg = testCase[0]; float expected = testCase[1]; - Float16 result = negate(valueOf(arg)); + Float16 result = negate(valueOfExact(arg)); if (Float.compare(expected, result.floatValue()) != 0) { checkFloat16(result, expected, "negate(" + arg + ")"); @@ -213,7 +213,7 @@ private static void checkAbs() { for(var testCase : testCases) { float arg = testCase[0]; float expected = testCase[1]; - Float16 result = abs(valueOf(arg)); + Float16 result = abs(valueOfExact(arg)); if (Float.compare(expected, result.floatValue()) != 0) { checkFloat16(result, expected, "abs(" + arg + ")"); @@ -238,7 +238,7 @@ private static void checkIsNaN() { }; for(var testCase : testCases) { - boolean result = isNaN(valueOf(testCase)); + boolean result = isNaN(valueOfExact(testCase)); if (result) { throwRE("isNaN returned true for " + testCase); } @@ -254,8 +254,8 @@ private static void checkFiniteness() { }; for(var infinity : infinities) { - boolean result1 = isFinite(valueOf(infinity)); - boolean result2 = isInfinite(valueOf(infinity)); + boolean result1 = isFinite(valueOfExact(infinity)); + boolean result2 = isInfinite(valueOfExact(infinity)); if (result1) { throwRE("Float16.isFinite returned true for " + infinity); @@ -282,8 +282,8 @@ private static void checkFiniteness() { }; for(var finity : finities) { - boolean result1 = isFinite(valueOf(finity)); - boolean result2 = isInfinite(valueOf(finity)); + boolean result1 = isFinite(valueOfExact(finity)); + boolean result2 = isInfinite(valueOfExact(finity)); if (!result1) { throwRE("Float16.isFinite returned true for " + finity); @@ -301,12 +301,12 @@ private static void checkMinMax() { float small = 1.0f; float large = 2.0f; - if (min(valueOf(small), valueOf(large)).floatValue() != small) { + if (min(valueOfExact(small), valueOfExact(large)).floatValue() != small) { throwRE(String.format("min(%g, %g) not equal to %g)", small, large, small)); } - if (max(valueOf(small), valueOf(large)).floatValue() != large) { + if (max(valueOfExact(small), valueOfExact(large)).floatValue() != large) { throwRE(String.format("max(%g, %g) not equal to %g)", small, large, large)); } @@ -318,10 +318,10 @@ private static void checkMinMax() { */ private static void checkArith() { float a = 1.0f; - Float16 a16 = valueOf(a); + Float16 a16 = valueOfExact(a); float b = 2.0f; - Float16 b16 = valueOf(b); + Float16 b16 = valueOfExact(b); if (add(a16, b16).floatValue() != (a + b)) { throwRE("failure with " + a16 + " + " + b16); @@ -371,7 +371,7 @@ private static void checkSqrt() { for(var testCase : testCases) { float arg = testCase[0]; float expected = testCase[1]; - Float16 result = sqrt(valueOf(arg)); + Float16 result = sqrt(valueOfExact(arg)); if (Float.compare(expected, result.floatValue()) != 0) { checkFloat16(result, expected, "sqrt(" + arg + ")"); @@ -409,7 +409,7 @@ private static void checkGetExponent() { float arg = testCase[0]; float expected = testCase[1]; // Exponents are in-range for Float16 - Float16 result = valueOf(getExponent(valueOf(arg))); + Float16 result = valueOfExact(getExponent(valueOfExact(arg))); if (Float.compare(expected, result.floatValue()) != 0) { checkFloat16(result, expected, "getExponent(" + arg + ")"); @@ -445,7 +445,7 @@ private static void checkUlp() { float arg = testCase[0]; float expected = testCase[1]; // Exponents are in-range for Float16 - Float16 result = ulp(valueOf(arg)); + Float16 result = ulp(valueOfExact(arg)); if (Float.compare(expected, result.floatValue()) != 0) { checkFloat16(result, expected, "ulp(" + arg + ")"); @@ -602,7 +602,7 @@ private static void checkValueOfString() { String input = testCase.input(); float expected = testCase.expected(); Float16 result = Float16.valueOf(input); - checkFloat16(result, expected, "Float16.valueOf(String) " + input); + checkFloat16(result, expected, "Float16.valueOfExact(String) " + input); } List negativeCases = List.of("0x1", @@ -747,7 +747,7 @@ private static void testZeroes() { } private static void testSimple() { - final float ulpOneFp16 = ulp(valueOf(1.0f)).floatValue(); + final float ulpOneFp16 = ulp(valueOfExact(1.0f)).floatValue(); float [][] testCases = { {1.0f, 2.0f, 3.0f, @@ -781,7 +781,7 @@ private static void testSimple() { } private static void testRounding() { - final float ulpOneFp16 = ulp(valueOf(1.0f)).floatValue(); + final float ulpOneFp16 = ulp(valueOfExact(1.0f)).floatValue(); float [][] testCases = { // The product is equal to @@ -816,6 +816,11 @@ private static void testRounding() { {0x1.ffcp-14f, 0x1.0p-24f, 0x1.0p14f, // *Cannot* be held exactly 0x1.0p14f}, + // Arguments where using float fma or uniform float + // arithmetic gives the wrong result + {0x1.08p7f, 0x1.04p7f, 0x1.0p-24f, + 0x1.0c4p14f}, + // Check values where the exact result cannot be // exactly stored in a double. {0x1.0p-24f, 0x1.0p-24f, 0x1.0p10f, @@ -839,10 +844,10 @@ private static void testRounding() { } private static void testFusedMacCase(float input1, float input2, float input3, float expected) { - Float16 a = valueOf(input1); - Float16 b = valueOf(input2); - Float16 c = valueOf(input3); - Float16 d = valueOf(expected); + Float16 a = valueOfExact(input1); + Float16 b = valueOfExact(input2); + Float16 c = valueOfExact(input3); + Float16 d = valueOfExact(expected); test("Float16.fma(float)", a, b, c, Float16.fma(a, b, c), d); @@ -865,4 +870,20 @@ private static void test(String testName, throw new RuntimeException(); } } + + /** + * {@return a Float16 value converted from the {@code float} + * argument throwing an {@code ArithmeticException} if the + * conversion is inexact}. + * + * @param f the {@code float} value to convert exactly + * @throws ArithmeticException + */ + private static Float16 valueOfExact(float f) { + Float16 f16 = valueOf(f); + if (Float.compare(f16.floatValue(), f) != 0) { + throw new ArithmeticException("Inexact conversion to Float16 of float value " + f); + } + return f16; + } } diff --git a/test/jdk/jdk/internal/jline/JLineConsoleProviderTest.java b/test/jdk/jdk/internal/jline/JLineConsoleProviderTest.java index 71590040685..445da167c5f 100644 --- a/test/jdk/jdk/internal/jline/JLineConsoleProviderTest.java +++ b/test/jdk/jdk/internal/jline/JLineConsoleProviderTest.java @@ -23,16 +23,19 @@ /** * @test - * @bug 8331535 8351435 8347050 + * @bug 8331535 8351435 8347050 8361613 * @summary Verify the jdk.internal.le's console provider works properly. - * @modules jdk.internal.le + * @modules java.base/jdk.internal.io + * jdk.internal.le/jdk.internal.org.jline * @library /test/lib - * @run main/othervm -Djdk.console=jdk.internal.le JLineConsoleProviderTest + * @run main JLineConsoleProviderTest */ import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; import java.util.Objects; +import jdk.internal.org.jline.JdkConsoleProviderImpl; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; @@ -66,8 +69,13 @@ void doRunConsoleTest(String testName, String input, String expectedOut) throws Exception { ProcessBuilder builder = - ProcessTools.createTestJavaProcessBuilder("-Djdk.console=jdk.internal.le", ConsoleTest.class.getName(), - testName); + ProcessTools.createTestJavaProcessBuilder( + "--add-exports", + "java.base/jdk.internal.io=ALL-UNNAMED", + "--add-exports", + "jdk.internal.le/jdk.internal.org.jline=ALL-UNNAMED", + ConsoleTest.class.getName(), + testName); OutputAnalyzer output = ProcessTools.executeProcess(builder, input); output.waitFor(); @@ -98,16 +106,18 @@ void doRunConsoleTest(String testName, public static class ConsoleTest { public static void main(String... args) { + // directly instantiate JLine JdkConsole, simulating isTTY=true + var impl = new JdkConsoleProviderImpl().console(true, StandardCharsets.UTF_8, StandardCharsets.UTF_8); switch (args[0]) { case "testCorrectOutputReadLine" -> - System.console().readLine("%%s"); + impl.readLine(null, "%%s"); case "testCorrectOutputReadPassword" -> - System.console().readPassword("%%s"); + impl.readPassword(null, "%%s"); case "readAndPrint" -> - System.out.println("'" + System.console().readLine() + "'"); + System.out.println("'" + impl.readLine() + "'"); case "readAndPrint2" -> { - System.out.println("1: '" +System.console().readLine() + "'"); - System.out.println("2: '" + System.console().readLine() + "'"); + System.out.println("1: '" + impl.readLine() + "'"); + System.out.println("2: '" + impl.readLine() + "'"); } default -> throw new UnsupportedOperationException(args[0]); } diff --git a/test/jdk/jdk/internal/jline/LazyJdkConsoleProvider.java b/test/jdk/jdk/internal/jline/LazyJdkConsoleProvider.java index acf0c848b43..a7533796b7c 100644 --- a/test/jdk/jdk/internal/jline/LazyJdkConsoleProvider.java +++ b/test/jdk/jdk/internal/jline/LazyJdkConsoleProvider.java @@ -23,15 +23,19 @@ /** * @test - * @bug 8333086 8344706 + * @bug 8333086 8344706 8361613 * @summary Verify the JLine backend is not initialized for simple printing. - * @enablePreview - * @modules jdk.internal.le/jdk.internal.org.jline.reader + * @modules java.base/jdk.internal.io + * jdk.internal.le/jdk.internal.org.jline + * jdk.internal.le/jdk.internal.org.jline.reader * jdk.internal.le/jdk.internal.org.jline.terminal * @library /test/lib * @run main LazyJdkConsoleProvider */ +import java.nio.charset.StandardCharsets; + +import jdk.internal.org.jline.JdkConsoleProviderImpl; import jdk.internal.org.jline.reader.LineReader; import jdk.internal.org.jline.terminal.Terminal; @@ -41,19 +45,18 @@ public class LazyJdkConsoleProvider { public static void main(String... args) throws Throwable { + // directly instantiate JLine JdkConsole, simulating isTTY=true switch (args.length > 0 ? args[0] : "default") { case "write" -> { - System.console().printf("Hello!\n"); - System.console().printf("Hello!"); - System.console().format("\nHello!\n"); - System.console().flush(); - IO.println("Hello!"); - IO.print("Hello!"); - } - case "read" -> System.console().readLine("Hello!"); - case "IO-read" -> { - IO.readln("Hello!"); + var impl = new JdkConsoleProviderImpl().console(true, StandardCharsets.UTF_8, StandardCharsets.UTF_8); + impl.println("Hello!\n"); + impl.println("Hello!"); + impl.format(null, "\nHello!\n"); + impl.flush(); } + case "read" -> new JdkConsoleProviderImpl() + .console(true, StandardCharsets.UTF_8, StandardCharsets.UTF_8) + .readLine(null, "Hello!"); case "default" -> { new LazyJdkConsoleProvider().runTest(); } @@ -64,14 +67,15 @@ void runTest() throws Exception { record TestCase(String testKey, String expected, String notExpected) {} TestCase[] testCases = new TestCase[] { new TestCase("write", null, Terminal.class.getName()), - new TestCase("read", LineReader.class.getName(), null), - new TestCase("IO-read", null, Terminal.class.getName()) + new TestCase("read", LineReader.class.getName(), null) }; for (TestCase tc : testCases) { ProcessBuilder builder = - ProcessTools.createTestJavaProcessBuilder("--enable-preview", - "-verbose:class", - "-Djdk.console=jdk.internal.le", + ProcessTools.createTestJavaProcessBuilder("-verbose:class", + "--add-exports", + "java.base/jdk.internal.io=ALL-UNNAMED", + "--add-exports", + "jdk.internal.le/jdk.internal.org.jline=ALL-UNNAMED", LazyJdkConsoleProvider.class.getName(), tc.testKey()); OutputAnalyzer output = ProcessTools.executeProcess(builder, ""); diff --git a/test/jdk/jdk/internal/jline/RedirectedStdOut.java b/test/jdk/jdk/internal/jline/RedirectedStdOut.java deleted file mode 100644 index 71419f96c73..00000000000 --- a/test/jdk/jdk/internal/jline/RedirectedStdOut.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * @test - * @bug 8330998 8351435 - * @summary Verify that even if the stdout is redirected java.io.Console will - * use it for writing. - * @modules jdk.internal.le - * @library /test/lib - * @run main RedirectedStdOut runRedirectAllTest - * @run main/othervm --enable-native-access=ALL-UNNAMED RedirectedStdOut runRedirectOutOnly - */ - -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import java.lang.foreign.Arena; -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.Linker; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SymbolLookup; -import java.lang.foreign.ValueLayout; -import java.lang.invoke.MethodHandle; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Objects; -import java.util.Optional; - -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.process.ProcessTools; - -public class RedirectedStdOut { - private static final String OUTPUT = "Hello!"; - - public static void main(String... args) throws Throwable { - RedirectedStdOut.class.getDeclaredMethod(args[0]) - .invoke(new RedirectedStdOut()); - } - - //verify the case where neither stdin/out/err is attached to a terminal, - //this test is weaker, but more reliable: - void runRedirectAllTest() throws Exception { - ProcessBuilder builder = - ProcessTools.createTestJavaProcessBuilder("-Djdk.console=jdk.internal.le", ConsoleTest.class.getName()); - OutputAnalyzer output = ProcessTools.executeProcess(builder); - - output.waitFor(); - - if (output.getExitValue() != 0) { - throw new AssertionError("Unexpected return value: " + output.getExitValue() + - ", actualOut: " + output.getStdout() + - ", actualErr: " + output.getStderr()); - } - - String expectedOut = OUTPUT; - String actualOut = output.getStdout(); - - if (!Objects.equals(expectedOut, actualOut)) { - throw new AssertionError("Unexpected stdout content. " + - "Expected: '" + expectedOut + "'" + - ", got: '" + actualOut + "'"); - } - - String expectedErr = ""; - String actualErr = output.getStderr(); - - if (!Objects.equals(expectedErr, actualErr)) { - throw new AssertionError("Unexpected stderr content. " + - "Expected: '" + expectedErr + "'" + - ", got: '" + actualErr + "'"); - } - } - - //verify the case where stdin is attached to a terminal, - //this test allocates pty, and it might be skipped, if the appropriate - //native functions cannot be found - //it also leaves the VM in a broken state (with a pty attached), and so - //should run in a separate VM instance - void runRedirectOutOnly() throws Throwable { - Path stdout = Path.of(".", "stdout.txt").toAbsolutePath(); - - Files.deleteIfExists(stdout); - - Linker linker = Linker.nativeLinker(); - SymbolLookup stdlib = linker.defaultLookup(); - MemorySegment parent = Arena.global().allocate(ValueLayout.ADDRESS); - MemorySegment child = Arena.global().allocate(ValueLayout.ADDRESS); - Optional openptyAddress = stdlib.find("openpty"); - - if (openptyAddress.isEmpty()) { - System.out.println("Cannot lookup openpty."); - //does not have forkpty, ignore - return ; - } - - Optional loginttyAddress = stdlib.find("login_tty"); - - if (loginttyAddress.isEmpty()) { - System.out.println("Cannot lookup login_tty."); - //does not have forkpty, ignore - return ; - } - - FunctionDescriptor openttyDescriptor = - FunctionDescriptor.of(ValueLayout.JAVA_INT, - ValueLayout.ADDRESS, - ValueLayout.ADDRESS, - ValueLayout.ADDRESS, - ValueLayout.ADDRESS, - ValueLayout.ADDRESS); - MethodHandle forkpty = linker.downcallHandle(openptyAddress.get(), - openttyDescriptor); - int res = (int) forkpty.invoke(parent, - child, - MemorySegment.NULL, - MemorySegment.NULL, - MemorySegment.NULL); - - if (res != 0) { - throw new AssertionError(); - } - - //set the current VM's in/out to the terminal: - FunctionDescriptor loginttyDescriptor = - FunctionDescriptor.of(ValueLayout.JAVA_INT, - ValueLayout.JAVA_INT); - MethodHandle logintty = linker.downcallHandle(loginttyAddress.get(), - loginttyDescriptor); - logintty.invoke(child.get(ValueLayout.JAVA_INT, 0)); - - //createTestJavaProcessBuilder logs to (current process') System.out, but - //that may not work since the redirect. Setting System.out to a scratch value: - System.setOut(new PrintStream(new ByteArrayOutputStream())); - - ProcessBuilder builder = - ProcessTools.createTestJavaProcessBuilder("-Djdk.console=jdk.internal.le", ConsoleTest.class.getName()); - - builder.inheritIO(); - builder.redirectOutput(stdout.toFile()); - - OutputAnalyzer output = ProcessTools.executeProcess(builder); - - output.waitFor(); - - String expectedOut = OUTPUT; - String actualOut = Files.readString(stdout); - - if (!Objects.equals(expectedOut, actualOut)) { - throw new AssertionError("Unexpected stdout content. " + - "Expected: '" + expectedOut + "'" + - ", got: '" + actualOut + "'"); - } - } - - public static class ConsoleTest { - public static void main(String... args) { - System.console().printf(OUTPUT); - System.exit(0); - } - } -} diff --git a/test/jdk/jdk/internal/platform/docker/GetFreeSwapSpaceSize.java b/test/jdk/jdk/internal/platform/docker/GetFreeSwapSpaceSize.java index 92b8cf282b7..b7721899ea3 100644 --- a/test/jdk/jdk/internal/platform/docker/GetFreeSwapSpaceSize.java +++ b/test/jdk/jdk/internal/platform/docker/GetFreeSwapSpaceSize.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020, 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2020, 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/jdk/internal/platform/docker/MetricsMemoryTester.java b/test/jdk/jdk/internal/platform/docker/MetricsMemoryTester.java index 8069965e8d8..c27a1c7480f 100644 --- a/test/jdk/jdk/internal/platform/docker/MetricsMemoryTester.java +++ b/test/jdk/jdk/internal/platform/docker/MetricsMemoryTester.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, 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 @@ -70,7 +70,7 @@ private static void testMemoryFailCount() { // We need swap to execute this test or will SEGV if (memAndSwapLimit <= memLimit) { - System.out.println("No swap memory limits, test case skipped"); + System.out.println("No swap memory limits. Ignoring test!"); } else { long count = Metrics.systemMetrics().getMemoryFailCount(); diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java b/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java index e236292de98..9a531d692ed 100644 --- a/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java +++ b/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java @@ -28,6 +28,7 @@ * @summary Verify that -XshowSettings:system works * @key cgroups * @requires container.support + * @requires !vm.asan * @library /test/lib * @run main/timeout=360 TestDockerBasic */ diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java b/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java index 4d452f20eef..ff039913b8f 100644 --- a/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java +++ b/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java @@ -35,6 +35,7 @@ * @key cgroups * @summary Test JDK Metrics class when running inside docker container * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform * @build MetricsCpuTester diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java index e8dc616b5e7..2afb5ed93b1 100644 --- a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java +++ b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, 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 @@ -27,12 +27,14 @@ import jdk.test.lib.containers.docker.DockerRunOptions; import jdk.test.lib.containers.docker.DockerTestUtils; import jdk.test.lib.process.OutputAnalyzer; +import jtreg.SkippedException; /* * @test * @key cgroups * @summary Test JDK Metrics class when running inside docker container * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform * @build MetricsMemoryTester @@ -111,18 +113,22 @@ private static void testMemoryFailCount(String value) throws Exception { // Check whether swapping really works for this test // On some systems there is no swap space enabled. And running - // 'java -Xms{mem-limit} -Xmx{mem-limit} -version' would fail due to swap space size being 0. + // 'java -Xms{mem-limit} -Xmx{mem-limit} -XX:+AlwaysPreTouch -version' + // would fail due to swap space size being 0. Note that when swap is + // properly enabled on the system the container gets the same amount + // of swap as is configured for memory. Thus, 2x{mem-limit} is the actual + // memory and swap bound for this pre-test. DockerRunOptions preOpts = new DockerRunOptions(imageName, "/jdk/bin/java", "-version"); preOpts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/") .addDockerOpts("--memory=" + value) + .addJavaOpts("-XX:+AlwaysPreTouch") .addJavaOpts("-Xms" + value) .addJavaOpts("-Xmx" + value); OutputAnalyzer oa = DockerTestUtils.dockerRunJava(preOpts); String output = oa.getOutput(); if (!output.contains("version")) { - System.out.println("Swapping doesn't work for this test."); - return; + throw new SkippedException("Swapping doesn't work for this test."); } DockerRunOptions opts = @@ -136,8 +142,7 @@ private static void testMemoryFailCount(String value) throws Exception { oa = DockerTestUtils.dockerRunJava(opts); output = oa.getOutput(); if (output.contains("Ignoring test")) { - System.out.println("Ignored by the tester"); - return; + throw new SkippedException("Ignored by the tester"); } oa.shouldHaveExitValue(0).shouldContain("TEST PASSED!!!"); } diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java index c6b94370807..da23acbf8b7 100644 --- a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java +++ b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java @@ -40,6 +40,7 @@ * @key cgroups * @summary Cgroup v1 subsystem fails to set subsystem path * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform * @build MetricsMemoryTester @@ -51,19 +52,6 @@ public class TestDockerMemoryMetricsSubgroup { DockerfileConfig.getBaseImageName() + ":" + DockerfileConfig.getBaseImageVersion(); - static String getEngineInfo(String format) throws Exception { - return DockerTestUtils.execute(Container.ENGINE_COMMAND, "info", "-f", format) - .getStdout(); - } - - static boolean isRootless() throws Exception { - // Docker and Podman have different INFO structures. - // The node path for Podman is .Host.Security.Rootless, that also holds for - // Podman emulating Docker CLI. The node path for Docker is .SecurityOptions. - return (getEngineInfo("{{.Host.Security.Rootless}}").contains("true") || - getEngineInfo("{{.SecurityOptions}}").contains("name=rootless")); - } - public static void main(String[] args) throws Exception { Metrics metrics = Metrics.systemMetrics(); if (metrics == null) { @@ -77,7 +65,7 @@ public static void main(String[] args) throws Exception { ContainerRuntimeVersionTestUtils.checkContainerVersionSupported(); - if (isRootless()) { + if (DockerTestUtils.isRootless()) { throw new SkippedException("Test skipped in rootless mode"); } diff --git a/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java b/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java index 204d7a215d8..b9d031f0309 100644 --- a/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java +++ b/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020, 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2020, 2022, Tencent. 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. * @@ -27,6 +27,7 @@ * @key cgroups * @bug 8242480 * @requires container.support + * @requires !vm.asan * @library /test/lib * @build GetFreeSwapSpaceSize * @run driver TestGetFreeSwapSpaceSize diff --git a/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java b/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java index 1544088f688..31e90e8802a 100644 --- a/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java +++ b/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java @@ -30,6 +30,7 @@ * @key cgroups * @summary Test container limits updating as they get updated at runtime without restart * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform * @build LimitUpdateChecker diff --git a/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java b/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java index 9fedeb55234..6b19bb475f1 100644 --- a/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java +++ b/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java @@ -28,6 +28,7 @@ * @summary Test JDK Metrics class when running inside a docker container with limited pids * @bug 8266490 * @requires container.support + * @requires !vm.asan * @library /test/lib * @build TestPidsLimit * @run driver TestPidsLimit diff --git a/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java b/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java index 93efff64cc4..49ec5663478 100644 --- a/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java +++ b/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java @@ -26,6 +26,7 @@ * @key cgroups * @summary Test JDK Metrics class when running inside docker container * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform * @run main TestSystemMetrics diff --git a/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java b/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java index 6a96514771c..d8d300401a0 100644 --- a/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java +++ b/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java @@ -26,6 +26,7 @@ * @test * @summary UseContainerSupport flag should reflect Metrics being available * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform * @build CheckUseContainerSupport diff --git a/test/jdk/jdk/internal/vm/Continuation/Fuzz.java b/test/jdk/jdk/internal/vm/Continuation/Fuzz.java index 52730c9523b..e5ed3566cd5 100644 --- a/test/jdk/jdk/internal/vm/Continuation/Fuzz.java +++ b/test/jdk/jdk/internal/vm/Continuation/Fuzz.java @@ -97,6 +97,9 @@ public static void main(String[] args) { if (Platform.isPPC()) { COMPILATION_TIMEOUT = COMPILATION_TIMEOUT * 2; } + if (Platform.isDebugBuild()) { + COMPILATION_TIMEOUT = COMPILATION_TIMEOUT * 2; + } warmup(); for (int compileLevel : new int[]{4}) { for (boolean compileRun : new boolean[]{true}) { diff --git a/test/jdk/jdk/internal/vm/Continuation/OSRWithManyLocals.java b/test/jdk/jdk/internal/vm/Continuation/OSRWithManyLocals.java new file mode 100644 index 00000000000..2a8d4e91001 --- /dev/null +++ b/test/jdk/jdk/internal/vm/Continuation/OSRWithManyLocals.java @@ -0,0 +1,90 @@ +/* +* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* This code is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +* version 2 for more details (a copy is included in the LICENSE file that +* accompanied this code). +* +* You should have received a copy of the GNU General Public License version +* 2 along with this work; if not, write to the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +* +* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +* or visit www.oracle.com if you need additional information or have any +* questions. +*/ + +/** +* @test +* @bug 8372591 +* @summary Test freeze/thaw of OSR frame from method with many locals +* @requires vm.continuations +* @requires vm.compMode != "Xint" & vm.compMode != "Xcomp" +* @modules java.base/jdk.internal.vm +* @library /test/lib /test/hotspot/jtreg +* @build jdk.test.whitebox.WhiteBox +* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox +* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI OSRWithManyLocals +*/ + +import jdk.internal.vm.Continuation; +import jdk.internal.vm.ContinuationScope; + +import jdk.test.lib.Asserts; +import java.lang.reflect.Method; +import jdk.test.whitebox.WhiteBox; + +public class OSRWithManyLocals { + static final WhiteBox wb = WhiteBox.getWhiteBox(); + static final ContinuationScope FOO = new ContinuationScope() {}; + static final Method foo = getMethod("foo"); + + public static void main(String[] args) throws Exception { + runCont(new Continuation(FOO, () -> warmUp())); + runCont(new Continuation(FOO, () -> foo())); + } + + public static void runCont(Continuation cont) { + while (!cont.isDone()) { + cont.run(); + } + } + + public static void warmUp() { + // Trigger compilation of Continuation.yield/yield0 + for (int i = 0; i < 10_000; i++) { + Continuation.yield(FOO); + } + } + + public static void foo() { + // Declare lots of locals so that size of OSR foo + Continuation.yield/yield0 + // frames is less than (foo_sender.unextended_sp() - foo_sender.sp()). + double d1=1,d2=2,d3=3,d4=4,d5=5,d6=6,d7=7,d8=8,d9=9,d10=10,d11=11,d12=12,d13=13,d14=14,d15=15,d16=16,d17=17,d18=18; + double d19=19,d20=20,d21=21,d22=22,d23=23,d24=24,d25=25,d26=26,d27=27,d28=28,d29=29,d30=30,d31=31,d32=32,d33=33,d34=34; + double d35=35,d36=36,d37=37,d38=38,d39=39,d40=40,d41=41,d42=42,d43=43,d44=44,d45=45,d46=46,d47=47,d48=48,d49=49,d50=50; + double d51=51,d52=52,d53=53,d54=54,d55=55,d56=56,d57=57,d58=58,d59=59,d60=60,d61=61,d62=62,d63=63,d64=64,d65=65,d66=66; + double d67=67,d68=68,d69=69,d70=70,d71=71,d72=72,d73=73,d74=74,d75=75,d76=76,d77=77,d78=78,d79=79,d80=80,d81=81,d82=82; + + // Provoke OSR compilation. After we verified the method was compiled keep looping + // until we trigger the _backedge_counter overflow to actually trigger OSR. + for (int i = 0; !wb.isMethodCompiled(foo, true) || i++ < 2_000;) { + } + Continuation.yield(FOO); + } + + static Method getMethod(String method) { + try { + return OSRWithManyLocals.class.getMethod(method); + } catch (Exception e) { + throw new RuntimeException("Exception: couldn't found method " + method + ". " + e.getMessage()); + } + } +} diff --git a/test/jdk/jdk/jfr/api/flightrecorder/TestSettingsControl.java b/test/jdk/jdk/jfr/api/flightrecorder/TestSettingsControl.java index e186db41bc2..e0e7e8b09c6 100644 --- a/test/jdk/jdk/jfr/api/flightrecorder/TestSettingsControl.java +++ b/test/jdk/jdk/jfr/api/flightrecorder/TestSettingsControl.java @@ -28,6 +28,7 @@ import java.util.Set; import jdk.jfr.Event; +import jdk.jfr.Name; import jdk.jfr.Recording; import jdk.jfr.SettingControl; import jdk.jfr.SettingDefinition; @@ -42,7 +43,7 @@ public class TestSettingsControl { static class MySettingsControl extends SettingControl { - public static boolean setWasCalled; + public static boolean myvalueSet; private String value = "default"; @@ -57,7 +58,9 @@ public String combine(Set values) { @Override public void setValue(String value) { - setWasCalled = true; + if ("myvalue".equals(value)) { + myvalueSet = true; + } this.value = value; } @@ -67,9 +70,10 @@ public String getValue() { } } - + @Name("M") static class MyCustomSettingEvent extends Event { @SettingDefinition + @Name("m") boolean mySetting(MySettingsControl msc) { return true; } @@ -77,13 +81,13 @@ boolean mySetting(MySettingsControl msc) { public static void main(String[] args) throws Throwable { Recording r = new Recording(); - r.enable(MyCustomSettingEvent.class).with("mySetting", "myvalue"); + r.enable("M").with("m", "myvalue"); r.start(); MyCustomSettingEvent e = new MyCustomSettingEvent(); e.commit(); r.stop(); r.close(); - assertTrue(MySettingsControl.setWasCalled, "SettingControl.setValue was not called"); + assertTrue(MySettingsControl.myvalueSet, "SettingControl.setValue(\"myvalue\") was not called"); } } diff --git a/test/jdk/jdk/jfr/event/gc/configuration/TestGCHeapConfigurationEventWith32BitOops.java b/test/jdk/jdk/jfr/event/gc/configuration/TestGCHeapConfigurationEventWith32BitOops.java index 9ef90afb063..c98f055aa72 100644 --- a/test/jdk/jdk/jfr/event/gc/configuration/TestGCHeapConfigurationEventWith32BitOops.java +++ b/test/jdk/jdk/jfr/event/gc/configuration/TestGCHeapConfigurationEventWith32BitOops.java @@ -35,6 +35,8 @@ * @requires vm.gc == "Parallel" | vm.gc == null * @requires os.family == "linux" | os.family == "windows" * @requires sun.arch.data.model == "64" + * @comment Asan changes memory layout and we get a different coops mode + * @requires !vm.asan * @library /test/lib /test/jdk * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox diff --git a/test/jdk/jdk/jfr/event/gc/configuration/TestGCHeapConfigurationEventWithZeroBasedOops.java b/test/jdk/jdk/jfr/event/gc/configuration/TestGCHeapConfigurationEventWithZeroBasedOops.java index 62d858eef98..f69d192ca5f 100644 --- a/test/jdk/jdk/jfr/event/gc/configuration/TestGCHeapConfigurationEventWithZeroBasedOops.java +++ b/test/jdk/jdk/jfr/event/gc/configuration/TestGCHeapConfigurationEventWithZeroBasedOops.java @@ -33,6 +33,8 @@ * @requires vm.gc == "Parallel" | vm.gc == null * @requires os.family == "linux" | os.family == "windows" * @requires sun.arch.data.model == "64" + * @comment Asan changes memory layout and we get a different coops mode + * @requires !vm.asan * @library /test/lib /test/jdk * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:-UseFastUnorderedTimeStamps -XX:+UseParallelGC -XX:+UseCompressedOops -Xmx4g jdk.jfr.event.gc.configuration.TestGCHeapConfigurationEventWithZeroBasedOops */ diff --git a/test/jdk/jdk/jfr/event/gc/detailed/TestGCHeapMemoryUsageEvent.java b/test/jdk/jdk/jfr/event/gc/detailed/TestGCHeapMemoryUsageEvent.java index d54ca7a723d..706dc45b6b7 100644 --- a/test/jdk/jdk/jfr/event/gc/detailed/TestGCHeapMemoryUsageEvent.java +++ b/test/jdk/jdk/jfr/event/gc/detailed/TestGCHeapMemoryUsageEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,7 +49,7 @@ public static void main(String[] args) throws Exception { List events = Events.fromRecording(recording); System.out.println(events); assertFalse(events.isEmpty()); - RecordedEvent event = events.getFirst(); + RecordedEvent event = events.getLast(); Events.assertField(event, "used").above(0L); Events.assertField(event, "committed").above(0L); Events.assertField(event, "max").above(0L); diff --git a/test/jdk/jdk/jfr/event/io/TestIOTopFrame.java b/test/jdk/jdk/jfr/event/io/TestIOTopFrame.java index 1184692b723..29d509b9147 100644 --- a/test/jdk/jdk/jfr/event/io/TestIOTopFrame.java +++ b/test/jdk/jdk/jfr/event/io/TestIOTopFrame.java @@ -52,6 +52,7 @@ import java.util.Map; import java.util.TreeMap; import java.util.concurrent.Callable; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -246,8 +247,10 @@ private static void testSocketChannels() throws Exception { r.enable(EVENT_SOCKET_READ).withStackTrace(); r.enable(EVENT_SOCKET_WRITE).withStackTrace(); r.start(); - Thread readerThread = Thread.ofPlatform().start(() -> readSocketChannel(ssc)); + CountDownLatch latch = new CountDownLatch(1); + Thread readerThread = Thread.ofPlatform().start(() -> readSocketChannel(ssc, latch)); writeSocketChannel(ssc); + latch.countDown(); readerThread.join(); r.stop(); assertTopFrames(r, "readSocket", 6, "readSocketChannel", 2, "writeSocket", 3, "writeSocketChannel", 2); @@ -255,13 +258,14 @@ private static void testSocketChannels() throws Exception { } } - private static void readSocketChannel(ServerSocketChannel ssc) { + private static void readSocketChannel(ServerSocketChannel ssc, CountDownLatch latch) { ByteBuffer[] buffers = createBuffers(); try (SocketChannel sc = ssc.accept()) { sc.read(buffers[0]); // 1 sc.read(buffers); // 2 try (InputStream is = sc.socket().getInputStream()) { readSocket(is); + latch.await(); } } catch (Exception ioe) { throw new RuntimeException(ioe); diff --git a/test/jdk/jdk/jfr/event/oldobject/TestEmergencyDumpAtOOM.java b/test/jdk/jdk/jfr/event/oldobject/TestEmergencyDumpAtOOM.java new file mode 100644 index 00000000000..213cacb3b33 --- /dev/null +++ b/test/jdk/jdk/jfr/event/oldobject/TestEmergencyDumpAtOOM.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, NTT DATA. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jfr.event.oldobject; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; +import jdk.jfr.consumer.EventStream; +import jdk.jfr.consumer.RecordingFile; + +import jdk.test.lib.Asserts; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +/** +* @test +* @bug 8364090 +* @summary Tests Dump reason and OldObjectSample events at OOME. +* @requires vm.flagless +* @requires vm.hasJFR +* @library /test/lib +* @run main/othervm jdk.jfr.event.oldobject.TestEmergencyDumpAtOOM +*/ +public class TestEmergencyDumpAtOOM { + + public static List DEFAULT_LEAKER_ARGS = List.of( + "-Xmx64m", + "-XX:TLABSize=2k", + "-XX:StartFlightRecording:dumponexit=true,filename=oom.jfr", + Leaker.class.getName() + ); + + public static class Leaker { + public static void main(String... args) { + List list = new ArrayList<>(); + while (true) { + list.add(new byte[1024]); + } + } + } + + private static void test(boolean shouldCrash) throws Exception { + List args = new ArrayList<>(DEFAULT_LEAKER_ARGS); + if (shouldCrash) { + args.add(0, "-XX:+CrashOnOutOfMemoryError"); + } + + while (true) { + Process p = ProcessTools.createTestJavaProcessBuilder(args).start(); + p.waitFor(); + OutputAnalyzer output = new OutputAnalyzer(p); + if (!output.contains("java.lang.OutOfMemoryError")) { + throw new RuntimeException("OutOfMemoryError did not happen."); + } + + // Check recording file + String jfrFileName = shouldCrash ? String.format("hs_err_pid%d.jfr", p.pid()) : "oom.jfr"; + Path jfrPath = Path.of(jfrFileName); + Asserts.assertTrue(Files.exists(jfrPath), "No jfr recording file " + jfrFileName + " exists"); + + // Check events + AtomicLong oldObjects = new AtomicLong(); + AtomicReference shutdownReason = new AtomicReference<>(); + AtomicReference dumpReason = new AtomicReference<>(); + try (EventStream stream = EventStream.openFile(jfrPath)) { + stream.onEvent("jdk.OldObjectSample", e -> oldObjects.incrementAndGet()); + stream.onEvent("jdk.Shutdown", e -> shutdownReason.set(e.getString("reason"))); + stream.onEvent("jdk.DumpReason", e -> dumpReason.set(e.getString("reason"))); + stream.start(); + } + + // Check OldObjectSample events + if (oldObjects.get() > 0L) { + if (shouldCrash) { + Asserts.assertEquals("CrashOnOutOfMemoryError", shutdownReason.get()); + Asserts.assertEquals("CrashOnOutOfMemoryError", dumpReason.get()); + } else { + Asserts.assertEquals("No remaining non-daemon Java threads", shutdownReason.get()); + } + // Passed this test + return; + } + + System.out.println("Could not find OldObjectSample events. Retrying."); + } + } + + public static void main(String... args) throws Exception { + test(true); + test(false); + } +} diff --git a/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleMultipleRecordings.java b/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleMultipleRecordings.java index 133df36684c..c88b0368597 100644 --- a/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleMultipleRecordings.java +++ b/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleMultipleRecordings.java @@ -39,20 +39,15 @@ * @run main jdk.jfr.event.profiling.TestCPUTimeSampleMultipleRecordings */ public class TestCPUTimeSampleMultipleRecordings { - - static String nativeEvent = EventNames.CPUTimeSample; - static volatile boolean alive = true; public static void main(String[] args) throws Exception { Thread t = new Thread(TestCPUTimeSampleMultipleRecordings::nativeMethod); - t.setDaemon(true); t.start(); for (int i = 0; i < 2; i++) { try (RecordingStream rs = new RecordingStream()) { - rs.enable(nativeEvent).with("throttle", "1ms"); - rs.onEvent(nativeEvent, e -> { - alive = false; + rs.enable(EventNames.CPUTimeSample).with("throttle", "1ms"); + rs.onEvent(EventNames.CPUTimeSample, e -> { rs.close(); }); @@ -60,6 +55,7 @@ public static void main(String[] args) throws Exception { } } alive = false; + t.join(); } public static void nativeMethod() { diff --git a/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleQueueAutoSizes.java b/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleQueueAutoSizes.java new file mode 100644 index 00000000000..1ea96e3bad3 --- /dev/null +++ b/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleQueueAutoSizes.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2025 SAP SE. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jfr.event.profiling; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.stream.Collectors; +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; + +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordingStream; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.internal.JVM; +import jdk.test.lib.Asserts; +import jdk.test.lib.jfr.EventNames; +import jdk.test.whitebox.WhiteBox; + + +/* + * Tests the sample queues increase in size as needed, when loss is recorded. + * @test + * @requires vm.hasJFR & os.family == "linux" & vm.debug + * @library /test/lib + * @modules jdk.jfr/jdk.jfr.internal + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -Xbatch -XX:StartFlightRecording:dumponexit=true jdk.jfr.event.profiling.TestCPUTimeSampleQueueAutoSizes + */ +public class TestCPUTimeSampleQueueAutoSizes { + + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + + private static final String BURST_THREAD_NAME = "Burst-Thread-1"; + + static volatile boolean alive = true; + + record LossEvent(long relativeTimeMillis, long lostSamples) {} + + /** A data collection from the CPUTimeSampleLost events for the burst thread */ + static class LossEventCollection { + private final List events = new ArrayList<>(); + + public synchronized void addEvent(LossEvent event) { + events.add(event); + } + + public synchronized List getSortedEvents() { + return events.stream() + .sorted(Comparator.comparingLong(e -> e.relativeTimeMillis)) + .collect(Collectors.toList()); + } + + public List getEventsPerInterval(long widthMillis, long stopTimeMillis) { + List ret = new ArrayList<>(); + for (long start = 0; start < stopTimeMillis; start += widthMillis) { + long actualStart = Math.min(start, stopTimeMillis - widthMillis); + long lostSamples = events.stream() + .filter(e -> e.relativeTimeMillis >= actualStart && e.relativeTimeMillis < actualStart + widthMillis) + .mapToLong(e -> e.lostSamples) + .sum(); + ret.add(new LossEvent(actualStart, lostSamples)); + } + return ret; + } + + } + + public static void main(String[] args) throws Exception { + try (RecordingStream rs = new RecordingStream()) { + // setup recording + AtomicLong firstSampleTimeMillis = new AtomicLong(0); + AtomicLong lastSampleTimeMillis = new AtomicLong(0); + LossEventCollection lossEvents = new LossEventCollection(); + rs.enable(EventNames.CPUTimeSample).with("throttle", "1ms"); + rs.onEvent(EventNames.CPUTimeSample, e -> { + if (firstSampleTimeMillis.get() == 0 && e.getThread("eventThread").getJavaName().equals(BURST_THREAD_NAME)) { + firstSampleTimeMillis.set(e.getStartTime().toEpochMilli()); + } + if (e.getThread("eventThread").getJavaName().equals(BURST_THREAD_NAME)) { + lastSampleTimeMillis.set(e.getStartTime().toEpochMilli()); + } + }); + rs.enable(EventNames.CPUTimeSamplesLost); + rs.onEvent(EventNames.CPUTimeSamplesLost, e -> { + if (e.getThread("eventThread").getJavaName().equals(BURST_THREAD_NAME)) { + long eventTime = e.getStartTime().toEpochMilli(); + long relativeTime = firstSampleTimeMillis.get() > 0 ? (eventTime - firstSampleTimeMillis.get()) : eventTime; + System.out.println("Lost samples: " + e.getLong("lostSamples") + " at " + relativeTime); + lossEvents.addEvent(new LossEvent(relativeTime, e.getLong("lostSamples"))); + } + }); + WHITE_BOX.cpuSamplerSetOutOfStackWalking(false); + rs.startAsync(); + // this thread runs all along + Thread burstThread = new Thread(() -> WHITE_BOX.busyWait(11000)); + burstThread.setName(BURST_THREAD_NAME); + burstThread.start(); + // now we toggle out-of-stack-walking off, wait 1 second and then turn it on for 500ms a few times + for (int i = 0; i < 5; i++) { + boolean supported = WHITE_BOX.cpuSamplerSetOutOfStackWalking(false); + if (!supported) { + System.out.println("Out-of-stack-walking not supported, skipping test"); + Asserts.assertFalse(true); + return; + } + Thread.sleep(700); + long iterations = WHITE_BOX.cpuSamplerOutOfStackWalkingIterations(); + WHITE_BOX.cpuSamplerSetOutOfStackWalking(true); + Thread.sleep(300); + while (WHITE_BOX.cpuSamplerOutOfStackWalkingIterations() == iterations) { + Thread.sleep(50); // just to make sure the stack walking really ran + } + } + rs.close(); + checkThatLossDecreased(lossEvents, lastSampleTimeMillis.get() - firstSampleTimeMillis.get()); + } + } + + static void checkThatLossDecreased(LossEventCollection lossEvents, long lastSampleTimeMillis) { + List intervalLosses = lossEvents.getEventsPerInterval(1000, lastSampleTimeMillis); + for (LossEvent interval : intervalLosses) { + System.out.println("Lost samples in interval " + interval.relativeTimeMillis + ": " + interval.lostSamples); + } + // check that there are at least 3 intervals + Asserts.assertTrue(intervalLosses.size() > 2); + // check that the second to last interval has far fewer lost samples than the first + Asserts.assertTrue(intervalLosses.get(intervalLosses.size() - 2).lostSamples < + intervalLosses.get(0).lostSamples / 2); + } +} diff --git a/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleThrottling.java b/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleThrottling.java index b0b9d6d2be7..ef2c73514a3 100644 --- a/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleThrottling.java +++ b/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleThrottling.java @@ -23,6 +23,7 @@ package jdk.jfr.event.profiling; import java.lang.management.ManagementFactory; +import java.lang.management.ThreadMXBean; import java.time.Duration; import java.time.Instant; import java.util.List; @@ -71,7 +72,7 @@ float rate() { } /** - * Counting the events that are emitted for a given throttle in a given time. + * Counting the events that are emitted for a given throttle in a given (CPU) time. *

    * The result is wall-clock independent; it only records the CPU-time and the number of * emitted events. The result, therefore, does not depend on the load of the machine. @@ -83,15 +84,9 @@ private static EventCount countEvents(int timeMs, String throttle) throws Except recording.enable(EventNames.CPUTimeSample) .with("throttle", throttle); - var bean = ManagementFactory.getThreadMXBean(); - recording.start(); - long startThreadCpuTime = bean.getCurrentThreadCpuTime(); - - wasteCPU(timeMs); - - long spendCPUTime = bean.getCurrentThreadCpuTime() - startThreadCpuTime; + long spendCPUTime = wasteCPU(timeMs); recording.stop(); @@ -99,19 +94,20 @@ private static EventCount countEvents(int timeMs, String throttle) throws Except .filter(e -> e.getThread().getJavaName() .equals(Thread.currentThread().getName())) .count(); - return new EventCount(eventCount, spendCPUTime / 1_000_000_000f); } } - private static void wasteCPU(int durationMs) { - long start = System.currentTimeMillis(); + private static long wasteCPU(int durationMs) { + ThreadMXBean bean = ManagementFactory.getThreadMXBean(); + long start = bean.getCurrentThreadCpuTime(); double i = 0; - while (System.currentTimeMillis() - start < durationMs) { + while (bean.getCurrentThreadCpuTime() - start < durationMs * 1_000_000) { for (int j = 0; j < 100000; j++) { i = Math.sqrt(i * Math.pow(Math.sqrt(Math.random()), Math.random())); } } + return bean.getCurrentThreadCpuTime() - start; } } diff --git a/test/jdk/jdk/jfr/event/profiling/TestFullStackTrace.java b/test/jdk/jdk/jfr/event/profiling/TestFullStackTrace.java index c337a8128ab..bfffb5e6f1d 100644 --- a/test/jdk/jdk/jfr/event/profiling/TestFullStackTrace.java +++ b/test/jdk/jdk/jfr/event/profiling/TestFullStackTrace.java @@ -32,6 +32,7 @@ * @library /test/lib * @build jdk.jfr.event.profiling.BaseTestFullStackTrace * @run main/othervm jdk.jfr.event.profiling.TestFullStackTrace + * @run main/othervm -XX:CompileCommand=compileonly,jdk.test.lib.jfr.RecurseThread::recurse* -XX:+PreserveFramePointer jdk.jfr.event.profiling.TestFullStackTrace */ public class TestFullStackTrace { diff --git a/test/jdk/jdk/jfr/event/runtime/TestBackToBackSensitive.java b/test/jdk/jdk/jfr/event/runtime/TestBackToBackSensitive.java new file mode 100644 index 00000000000..fbef91e73aa --- /dev/null +++ b/test/jdk/jdk/jfr/event/runtime/TestBackToBackSensitive.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jfr.event.runtime; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Instant; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; + +import jdk.jfr.Configuration; +import jdk.jfr.Event; +import jdk.jfr.Recording; +import jdk.jfr.StackTrace; +import jdk.jfr.consumer.EventStream; +import jdk.jfr.consumer.RecordedClassLoader; +import jdk.test.lib.jfr.TestClassLoader; + +/** + * @test + * @summary The test verifies that jdk.ClassLoaderStatistics and + * jdk.ThreadThreadDump are not emitted at the beginning of a chunk + * when the period is everyChunk, as is the case in default.jfc + * @requires vm.flagless + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @run main/othervm jdk.jfr.event.runtime.TestBackToBackSensitive + */ +public class TestBackToBackSensitive { + @StackTrace(false) + static class FillEvent extends Event { + String message; + } + public static Object OBJECT; + + public static void main(String... arg) throws Exception { + TestClassLoader loader = new TestClassLoader(); + Class clazz = loader.loadClass(TestBackToBackSensitive.class.getName()); + String classLoaderName = loader.getClass().getName(); + OBJECT = clazz.getDeclaredConstructor().newInstance(); + Configuration configuration = Configuration.getConfiguration("default"); + try (Recording r1 = new Recording(configuration)) { + // Start chunk 1 + r1.start(); + try (Recording r2 = new Recording()) { + // Start chunk 2 + r2.start(); + // Starts chunk 3 + r2.stop(); + } + // Start chunk 4 by filling up chunk 3 + for (int i = 0; i < 1_500_000; i++) { + FillEvent f = new FillEvent(); + f.commit(); + } + r1.stop(); + Path file = Path.of("file.jfr"); + r1.dump(file); + Set threadDumps = new LinkedHashSet<>(); + Set classLoaderStatistics = new LinkedHashSet<>(); + Set physicalMemory = new LinkedHashSet<>(); + try (EventStream es = EventStream.openFile(file)) { + es.onEvent("jdk.ThreadDump", e -> threadDumps.add(e.getStartTime())); + es.onEvent("jdk.ClassLoaderStatistics", e -> { + RecordedClassLoader cl = e.getValue("classLoader"); + if (cl != null) { + if (cl.getType().getName().equals(classLoaderName)) { + classLoaderStatistics.add(e.getStartTime()); + System.out.println("Class loader" + e); + } + } + }); + es.onEvent("jdk.PhysicalMemory", e -> physicalMemory.add(e.getStartTime())); + es.start(); + } + long chunkFiles = filesInRepository(); + System.out.println("Number of chunk files: " + chunkFiles); + // When jdk.PhysicalMemory is expected to be emitted: + // Chunk 1: begin, end + // Chunk 2: begin, end + // Chunk 3: begin, end + // Chunk 4: begin, end + assertCount("jdk.PhysicalMemory", physicalMemory, 2 * chunkFiles); + // When jdk.ClassLoaderStatistics and jdk.ThreadThreadDump are expected to be + // emitted: + // Chunk 1: begin, end + // Chunk 2: begin, end + // Chunk 3: end + // Chunk 4: end + assertCount("jdk.ThreadDump", threadDumps, 2 + 2 + (chunkFiles - 2)); + assertCount("jdk.ClassLoaderStatistics", classLoaderStatistics, 2 + 2 + (chunkFiles - 2)); + } + } + + private static long filesInRepository() throws IOException { + Path repository = Path.of(System.getProperty("jdk.jfr.repository")); + return Files.list(repository).filter(p -> p.toString().endsWith(".jfr")).count(); + } + + private static void assertCount(String eventName, Set timestamps, long expected) throws Exception { + System.out.println("Timestamps for " + eventName + ":"); + for (Instant timestamp : timestamps) { + System.out.println(timestamp); + } + int count = timestamps.size(); + if (count != expected) { + throw new Exception("Expected " + expected + " timestamps for event " + eventName + ", but got " + count); + } + } +} diff --git a/test/jdk/jdk/jfr/event/tracing/TestMethodTrace.java b/test/jdk/jdk/jfr/event/tracing/TestMethodTrace.java index a5fd1430627..5f26e5588f3 100644 --- a/test/jdk/jdk/jfr/event/tracing/TestMethodTrace.java +++ b/test/jdk/jdk/jfr/event/tracing/TestMethodTrace.java @@ -22,6 +22,8 @@ */ package jdk.jfr.event.tracing; +import java.time.Duration; +import java.util.List; import java.util.concurrent.atomic.AtomicReference; import jdk.jfr.Event; @@ -29,7 +31,9 @@ import jdk.jfr.consumer.RecordedEvent; import jdk.jfr.consumer.RecordedMethod; import jdk.jfr.consumer.RecordingStream; +import jdk.jfr.Recording; +import jdk.test.lib.jfr.Events; /** * @test * @summary Basic test of the MethodTrace event. @@ -52,6 +56,31 @@ private static class InnerMeasurement extends Event { } public static void main(String... args) throws Exception { + testWithoutThreshold(); + testWithThreshold(); + } + + private static void testWithThreshold() throws Exception { + try (Recording r = new Recording()) { + r.enable(EVENT_NAME) + .with("filter", CLASS_NAME + "::printHello") + .withThreshold(Duration.ofHours(1)); + r.start(); + printHello(); + r.stop(); + List events = Events.fromRecording(r); + if (!events.isEmpty()) { + System.out.println(events); + throw new Exception("Unexpected MethodTrace event"); + } + } + } + + public static void printHello() { + System.out.println("Hello!"); + } + + private static void testWithoutThreshold() throws Exception { AtomicReference o = new AtomicReference<>(); AtomicReference i = new AtomicReference<>(); AtomicReference e = new AtomicReference<>(); diff --git a/test/jdk/jdk/jfr/jmx/streaming/TestEnableDisable.java b/test/jdk/jdk/jfr/jmx/streaming/TestEnableDisable.java index 06e9691cfa2..5b1435c9d9d 100644 --- a/test/jdk/jdk/jfr/jmx/streaming/TestEnableDisable.java +++ b/test/jdk/jdk/jfr/jmx/streaming/TestEnableDisable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ /** * @test * @requires vm.flagless - * @summary Tests that event settings for a RemoteRecordingStream can be changed + * @summary Tests that the enabled setting can be configured for a RemoteRecordingStream * @requires vm.hasJFR * @library /test/lib /test/jdk * @run main/othervm jdk.jfr.jmx.streaming.TestEnableDisable diff --git a/test/jdk/jdk/jfr/jmx/streaming/TestWithers.java b/test/jdk/jdk/jfr/jmx/streaming/TestWithers.java new file mode 100644 index 00000000000..933337ef76b --- /dev/null +++ b/test/jdk/jdk/jfr/jmx/streaming/TestWithers.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jfr.jmx.streaming; + +import java.lang.management.ManagementFactory; +import java.time.Duration; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.function.Consumer; +import java.util.function.Predicate; + +import javax.management.MBeanServerConnection; + +import jdk.jfr.Event; +import jdk.jfr.EventSettings; +import jdk.jfr.FlightRecorder; +import jdk.jfr.Name; +import jdk.jfr.Period; +import jdk.jfr.StackTrace; +import jdk.jfr.Threshold; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordedStackTrace; +import jdk.management.jfr.RemoteRecordingStream; + +/** + * @test + * @requires vm.flagless + * @summary Tests that event settings for a RemoteRecordingStream can be changed + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @run main/othervm jdk.jfr.jmx.streaming.TestWithers + */ +public class TestWithers { + private static final Set RESULT = Collections.synchronizedSet(new HashSet<>()); + + @Name("AA") + @StackTrace(false) + static class A extends Event { + } + + @Name("BB") + @StackTrace(true) + static class B extends Event { + } + + @Name("CC") + @Threshold("10 h") + static class C extends Event { + } + + @Name("DD") + @Threshold("10 h") + static class D extends Event { + } + + @Name("EE") + @StackTrace(false) + static class E extends Event { + } + + @Name("FF") + @Period("10 h") + static class F extends Event { + } + + public static void main(String... args) throws Exception { + MBeanServerConnection conn = ManagementFactory.getPlatformMBeanServer(); + try (RemoteRecordingStream stream = new RemoteRecordingStream(conn)) { + addCheck(stream, es -> es.withStackTrace(), "AA", TestWithers::hasStackTrace); + addCheck(stream, es -> es.withoutStackTrace(), "BB", e -> !hasStackTrace(e)); + addCheck(stream, es -> es.withThreshold(Duration.ofMillis(0)), "CC", e -> true); + addCheck(stream, es -> es.withoutThreshold(), "DD", e -> true); + addCheck(stream, es -> es.with("stackTrace", "true"), "EE", TestWithers::hasStackTrace); + addCheck(stream, es -> es.withPeriod(Duration.ofMillis(700)), "FF", e -> true); + FlightRecorder.addPeriodicEvent(F.class, () -> { + F f = new F(); + f.commit(); + }); + stream.onFlush(() -> { + System.out.println(RESULT); + if (RESULT.size() == 6) { + stream.close(); + } + }); + + stream.startAsync(); + A a = new A(); + a.commit(); + + B b = new B(); + b.commit(); + + C c = new C(); + c.commit(); + + D d = new D(); + d.commit(); + + E e = new E(); + e.commit(); + + stream.awaitTermination(); + } + } + + private static void addCheck(RemoteRecordingStream stream, Consumer es, String eventName, Predicate validator) { + es.accept(stream.enable(eventName)); + stream.onEvent(eventName, e -> { + System.out.println(e); + if (validator.test(e)) { + RESULT.add(eventName); + } + }); + } + + private static boolean hasStackTrace(RecordedEvent e) { + RecordedStackTrace rs = e.getStackTrace(); + return rs != null && !rs.getFrames().isEmpty(); + } +} \ No newline at end of file diff --git a/test/jdk/jdk/jfr/tool/TestPrintContextual.java b/test/jdk/jdk/jfr/tool/TestPrintContextual.java index efecc31cb16..15486148b9c 100644 --- a/test/jdk/jdk/jfr/tool/TestPrintContextual.java +++ b/test/jdk/jdk/jfr/tool/TestPrintContextual.java @@ -410,6 +410,7 @@ private static List parseEvents(List lines) { private static List readPrintedLines(Path file, String... options) throws Exception { JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jfr"); launcher.addToolArg("print"); + launcher.addToolArg("--exact"); for (String option : options) { launcher.addToolArg(option); } diff --git a/test/jdk/jdk/nio/zipfs/NewFileSystemTests.java b/test/jdk/jdk/nio/zipfs/NewFileSystemTests.java index d15988176e3..d9da79be126 100644 --- a/test/jdk/jdk/nio/zipfs/NewFileSystemTests.java +++ b/test/jdk/jdk/nio/zipfs/NewFileSystemTests.java @@ -25,6 +25,7 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import org.testng.SkipException; import java.io.IOException; import java.net.URI; @@ -35,6 +36,7 @@ import java.nio.file.Path; import java.util.Iterator; import java.util.Map; +import jdk.test.lib.Platform; import static java.nio.charset.StandardCharsets.UTF_8; import static org.testng.Assert.assertEquals; @@ -48,6 +50,7 @@ * @bug 8218875 * @summary ZIP File System tests that leverage Files.newFileSystem * @modules jdk.zipfs + * @library /test/lib * @compile NewFileSystemTests.java * @run testng NewFileSystemTests */ @@ -219,6 +222,9 @@ public void multiReleaseJarReadWriteSuccess() throws IOException { */ @Test public void readOnlyZipFileFailure() throws IOException { + if (Platform.isRoot()) { + throw new SkipException("Test skipped when executed by root user."); + } // Underlying file is read-only. Path readOnlyZip = Utils.createJarFile("read_only.zip", Map.of("file.txt", "Hello World")); // In theory this can fail, and we should avoid unwanted false-negatives. diff --git a/test/jdk/jdk/nio/zipfs/TestPosix.java b/test/jdk/jdk/nio/zipfs/TestPosix.java index ff6f9c4920f..526acca8a9e 100644 --- a/test/jdk/jdk/nio/zipfs/TestPosix.java +++ b/test/jdk/jdk/nio/zipfs/TestPosix.java @@ -60,7 +60,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; -/** +/* * @test * @bug 8213031 8273935 8324635 * @summary Test POSIX ZIP file operations. @@ -756,7 +756,7 @@ public void testJarFile() throws IOException { delTree(UNZIP_DIR); Files.createDirectory(UNZIP_DIR); File targetDir = UNZIP_DIR.toFile(); - try (JarFile jf = new JarFile(ZIP_FILE.toFile())) { + try (JarFile jf = new JarFile(JAR_FILE.toFile())) { Enumeration zenum = jf.entries(); while (zenum.hasMoreElements()) { JarEntry ze = zenum.nextElement(); diff --git a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java index 0822205bbaf..8754f2c6e64 100644 --- a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java +++ b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java @@ -416,50 +416,6 @@ * @run main/othervm/manual -Djava.security.debug=certpath CAInterop certignarootca CRL */ -/* - * @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 @@ -726,20 +682,6 @@ private CATestURLs getTestURLs(String alias) { 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 --git a/test/jdk/sun/awt/font/TestDevTransform.java b/test/jdk/sun/awt/font/TestDevTransform.java index 2783401c0f2..39d4255f154 100644 --- a/test/jdk/sun/awt/font/TestDevTransform.java +++ b/test/jdk/sun/awt/font/TestDevTransform.java @@ -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 @@ -22,9 +22,31 @@ */ /* - * @test + * @test id=dialog_double * @bug 4269775 8341535 * @summary Check that different text rendering APIs agree + * @run main/othervm TestDevTransform DIALOG DOUBLE + */ + +/* + * @test id=dialog_float + * @bug 4269775 8341535 + * @summary Check that different text rendering APIs agree + * @run main/othervm TestDevTransform DIALOG FLOAT + */ + +/* + * @test id=monospaced_double + * @bug 4269775 8341535 + * @summary Check that different text rendering APIs agree + * @run main/othervm TestDevTransform MONOSPACED DOUBLE + */ + +/* + * @test id=monospaced_float + * @bug 4269775 8341535 + * @summary Check that different text rendering APIs agree + * @run main/othervm TestDevTransform MONOSPACED FLOAT */ /** @@ -66,6 +88,8 @@ public class TestDevTransform { static String test = "This is only a test"; static double angle = Math.PI / 6.0; // Rotate 30 degrees static final int W = 400, H = 400; + static boolean useDialog; + static boolean useDouble; static void draw(Graphics2D g2d, TextLayout layout, float x, float y, float scalex) { @@ -101,9 +125,19 @@ static void init(Graphics2D g2d) { g2d.setColor(Color.white); g2d.fillRect(0, 0, W, H); g2d.setColor(Color.black); - g2d.scale(1.481f, 1.481); // Convert to 108 dpi + if (useDouble) { + g2d.scale(1.481, 1.481); // Convert to 108 dpi + } else { + g2d.scale(1.481f, 1.481f); // Convert to 108 dpi + } g2d.addRenderingHints(hints); - Font font = new Font(Font.DIALOG, Font.PLAIN, 12); + String name; + if (useDialog) { + name = Font.DIALOG; + } else { + name = Font.MONOSPACED; + } + Font font = new Font(name, Font.PLAIN, 12); g2d.setFont(font); } @@ -135,6 +169,12 @@ static void compare(BufferedImage bi1, String name1, BufferedImage bi2, String n } public static void main(String args[]) throws Exception { + if (args[0].equals("DIALOG")) { + useDialog = true; + } + if (args[1].equals("DOUBLE")) { + useDouble = true; + } BufferedImage tl_Image = new BufferedImage(W, H, BufferedImage.TYPE_INT_RGB); { diff --git a/test/jdk/sun/java2d/cmm/ColorConvertOp/FilterSemiCustomImages.java b/test/jdk/sun/java2d/cmm/ColorConvertOp/FilterSemiCustomImages.java new file mode 100644 index 00000000000..ff3fcde7482 --- /dev/null +++ b/test/jdk/sun/java2d/cmm/ColorConvertOp/FilterSemiCustomImages.java @@ -0,0 +1,162 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Point; +import java.awt.color.ColorSpace; +import java.awt.image.BufferedImage; +import java.awt.image.ColorConvertOp; +import java.awt.image.ColorModel; +import java.awt.image.SampleModel; +import java.awt.image.WritableRaster; +import java.io.File; + +import javax.imageio.ImageIO; + +import static java.awt.image.BufferedImage.TYPE_3BYTE_BGR; +import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR; +import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR_PRE; +import static java.awt.image.BufferedImage.TYPE_INT_ARGB; +import static java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE; +import static java.awt.image.BufferedImage.TYPE_INT_BGR; +import static java.awt.image.BufferedImage.TYPE_INT_RGB; +import static java.awt.image.BufferedImage.TYPE_USHORT_GRAY; + +/** + * @test + * @bug 8366208 + * @summary Verifies ColorConvertOp works correctly with BufferedImage and + * semi-custom raster + */ +public final class FilterSemiCustomImages { + + private static final int W = 144; + private static final int H = 123; + + private static final int[] TYPES = { + TYPE_INT_RGB, TYPE_INT_ARGB, TYPE_INT_ARGB_PRE, TYPE_INT_BGR, + TYPE_3BYTE_BGR, TYPE_4BYTE_ABGR, TYPE_4BYTE_ABGR_PRE, + TYPE_USHORT_GRAY + }; + + private static final int[] CSS = { + ColorSpace.CS_CIEXYZ, ColorSpace.CS_GRAY, ColorSpace.CS_LINEAR_RGB, + ColorSpace.CS_PYCC, ColorSpace.CS_sRGB + }; + + private static final class CustomRaster extends WritableRaster { + CustomRaster(SampleModel sampleModel, Point origin) { + super(sampleModel, origin); + } + } + + public static void main(String[] args) throws Exception { + for (int fromIndex : CSS) { + for (int toIndex : CSS) { + if (fromIndex != toIndex) { + for (int type : TYPES) { + test(fromIndex, toIndex, type); + } + } + } + } + } + + private static void test(int fromIndex, int toIndex, int type) + throws Exception + { + ColorSpace fromCS = ColorSpace.getInstance(fromIndex); + ColorSpace toCS = ColorSpace.getInstance(toIndex); + ColorConvertOp op = new ColorConvertOp(fromCS, toCS, null); + + // standard source -> standard dst + BufferedImage srcGold = new BufferedImage(W, H, type); + fill(srcGold); + BufferedImage dstGold = new BufferedImage(W, H, type); + op.filter(srcGold, dstGold); + + // custom source -> standard dst + BufferedImage srcCustom = makeCustomBI(srcGold); + fill(srcCustom); + BufferedImage dst = new BufferedImage(W, H, type); + op.filter(srcCustom, dst); + verify(dstGold, dst); + + // standard source -> custom dst + BufferedImage src = new BufferedImage(W, H, type); + fill(src); + BufferedImage dstCustom = makeCustomBI(dstGold); + op.filter(src, dstCustom); + verify(dstGold, dstCustom); + + // custom source -> custom dst + srcCustom = makeCustomBI(srcGold); + fill(srcCustom); + dstCustom = makeCustomBI(dstGold); + op.filter(srcCustom, dstCustom); + verify(dstGold, dstCustom); + } + + private static BufferedImage makeCustomBI(BufferedImage bi) { + ColorModel cm = bi.getColorModel(); + SampleModel sm = bi.getSampleModel(); + CustomRaster cr = new CustomRaster(sm, new Point()); + return new BufferedImage(cm, cr, bi.isAlphaPremultiplied(), null) { + @Override + public int getType() { + return bi.getType(); + } + }; + } + + private static void fill(BufferedImage image) { + int width = image.getWidth(); + int height = image.getHeight(); + for (int x = 0; x < width; ++x) { + for (int y = 0; y < height; ++y) { + // alpha channel may be calculated slightly differently on + // different code paths, so only check fully transparent and + // fully opaque pixels + Color c = new Color(y * 255 / (height - 1), + x * 255 / (width - 1), + x % 255, + (x % 2 == 0) ? 0 : 255); + image.setRGB(x, y, c.getRGB()); + } + } + } + + private static void verify(BufferedImage dstGold, BufferedImage dst) + throws Exception + { + for (int x = 0; x < W; ++x) { + for (int y = 0; y < H; ++y) { + if (dst.getRGB(x, y) != dstGold.getRGB(x, y)) { + ImageIO.write(dst, "png", new File("custom.png")); + ImageIO.write(dstGold, "png", new File("gold.png")); + throw new RuntimeException("Test failed."); + } + } + } + } +} diff --git a/test/jdk/sun/java2d/marlin/ClipShapeTest.java b/test/jdk/sun/java2d/marlin/ClipShapeTest.java index 3bdbd416e63..e77fca6924d 100644 --- a/test/jdk/sun/java2d/marlin/ClipShapeTest.java +++ b/test/jdk/sun/java2d/marlin/ClipShapeTest.java @@ -154,13 +154,12 @@ static enum ShapeMode { static final AtomicBoolean isMarlin = new AtomicBoolean(); static final AtomicBoolean isClipRuntime = new AtomicBoolean(); + static final Logger log = Logger.getLogger("sun.java2d.marlin"); + static { Locale.setDefault(Locale.US); // FIRST: Get Marlin runtime state from its log: - - // initialize j.u.l Looger: - final Logger log = Logger.getLogger("sun.java2d.marlin"); log.addHandler(new Handler() { @Override public void publish(LogRecord record) { diff --git a/test/jdk/sun/management/jmxremote/bootstrap/AbstractFilePermissionTest.java b/test/jdk/sun/management/jmxremote/bootstrap/AbstractFilePermissionTest.java index ddbca2c444d..7d1756be062 100644 --- a/test/jdk/sun/management/jmxremote/bootstrap/AbstractFilePermissionTest.java +++ b/test/jdk/sun/management/jmxremote/bootstrap/AbstractFilePermissionTest.java @@ -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 @@ -35,7 +35,6 @@ import java.nio.file.attribute.PosixFilePermission; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -47,7 +46,6 @@ * @author Taras Ledkov */ public abstract class AbstractFilePermissionTest { - private final String TEST_CLASS_PATH = System.getProperty("test.class.path"); protected final String TEST_CLASSES = System.getProperty("test.classes"); protected final FileSystem FS = FileSystems.getDefault(); private int MAX_GET_FREE_PORT_TRIES = 10; @@ -169,11 +167,8 @@ private int doTest() throws Exception { final String pp = "-Dcom.sun.management.jmxremote.port=" + jdk.test.lib.Utils.getFreePort(); List command = new ArrayList<>(); - Collections.addAll(command, jdk.test.lib.Utils.getTestJavaOpts()); command.add(mp); command.add(pp); - command.add("-cp"); - command.add(TEST_CLASSES); command.add(className); ProcessBuilder processBuilder = ProcessTools.createTestJavaProcessBuilder(command); diff --git a/test/jdk/sun/management/jmxremote/bootstrap/JMXInterfaceBindingTest.java b/test/jdk/sun/management/jmxremote/bootstrap/JMXInterfaceBindingTest.java index 61359084297..1f4707fab3b 100644 --- a/test/jdk/sun/management/jmxremote/bootstrap/JMXInterfaceBindingTest.java +++ b/test/jdk/sun/management/jmxremote/bootstrap/JMXInterfaceBindingTest.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2015, Red Hat Inc + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -205,6 +206,7 @@ private Process createTestProcess() { // This is needed for testing on loopback args.add("-Djava.rmi.server.hostname=" + address); if (useSSL) { + args.add("-Djdk.rmi.ssl.client.enableEndpointIdentification=false"); args.add("-Dcom.sun.management.jmxremote.registry.ssl=true"); args.add("-Djavax.net.ssl.keyStore=" + KEYSTORE_LOC); args.add("-Djavax.net.ssl.trustStore=" + TRUSTSTORE_LOC); diff --git a/test/jdk/sun/management/jmxremote/bootstrap/LocalManagementTest.java b/test/jdk/sun/management/jmxremote/bootstrap/LocalManagementTest.java index 0a7c735e2e0..b6e478528d9 100644 --- a/test/jdk/sun/management/jmxremote/bootstrap/LocalManagementTest.java +++ b/test/jdk/sun/management/jmxremote/bootstrap/LocalManagementTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,12 +24,10 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicReference; import jdk.test.lib.process.ProcessTools; -import jdk.test.lib.Utils; /** * @test @@ -48,7 +46,6 @@ * @run main/othervm/timeout=300 LocalManagementTest */ public class LocalManagementTest { - private static final String TEST_CLASSPATH = System.getProperty("test.class.path"); public static void main(String[] args) throws Exception { int failures = 0; @@ -99,16 +96,13 @@ private static boolean test5() throws Exception { private static boolean doTest(String testId, String arg) throws Exception { List args = new ArrayList<>(); args.add("-XX:+UsePerfData"); - Collections.addAll(args, Utils.getTestJavaOpts()); - args.add("-cp"); - args.add(TEST_CLASSPATH); if (arg != null) { args.add(arg); } args.add("TestApplication"); ProcessBuilder server = ProcessTools.createTestJavaProcessBuilder( - args.toArray(new String[args.size()]) + args.toArray(new String[0]) ); Process serverPrc = null, clientPrc = null; @@ -134,8 +128,6 @@ private static boolean doTest(String testId, String arg) throws Exception { System.out.println(" shutdown port : " + port.get()); ProcessBuilder client = ProcessTools.createTestJavaProcessBuilder( - "-cp", - TEST_CLASSPATH, "--add-exports", "jdk.management.agent/jdk.internal.agent=ALL-UNNAMED", "TestManager", String.valueOf(serverPrc.pid()), diff --git a/test/jdk/sun/management/jmxremote/bootstrap/RmiBootstrapTest.java b/test/jdk/sun/management/jmxremote/bootstrap/RmiBootstrapTest.java index 2a99c5e7d52..b62d3f1bbd7 100644 --- a/test/jdk/sun/management/jmxremote/bootstrap/RmiBootstrapTest.java +++ b/test/jdk/sun/management/jmxremote/bootstrap/RmiBootstrapTest.java @@ -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 @@ -169,6 +169,7 @@ public static void main(String args[]) throws Exception { final List credentialFiles = prepareTestFiles(args[0]); Security.setProperty("jdk.tls.disabledAlgorithms", ""); + System.setProperty("jdk.rmi.ssl.client.enableEndpointIdentification", "false"); try { MAX_GET_FREE_PORT_TRIES = Integer.parseInt(System.getProperty("test.getfreeport.max.tries", "10")); diff --git a/test/jdk/sun/management/jmxremote/bootstrap/RmiRegistrySslTest.java b/test/jdk/sun/management/jmxremote/bootstrap/RmiRegistrySslTest.java index 6cc5708b385..3c9508e74f3 100644 --- a/test/jdk/sun/management/jmxremote/bootstrap/RmiRegistrySslTest.java +++ b/test/jdk/sun/management/jmxremote/bootstrap/RmiRegistrySslTest.java @@ -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 @@ -28,7 +28,6 @@ import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; -import java.net.BindException; import java.nio.charset.Charset; import java.nio.file.FileSystem; import java.nio.file.FileSystems; @@ -180,6 +179,7 @@ private int doTest(String... args) throws Exception { initTestEnvironment(); List command = new ArrayList<>(); + command.add("-Djdk.rmi.ssl.client.enableEndpointIdentification=false"); Collections.addAll(command, Utils.getTestJavaOpts()); command.add("-Dtest.src=" + TEST_SRC); command.add("-Dtest.rmi.port=" + port); diff --git a/test/jdk/sun/net/www/protocol/file/FileURLTest.java b/test/jdk/sun/net/www/protocol/file/FileURLTest.java index 135274a9504..e111a538aca 100644 --- a/test/jdk/sun/net/www/protocol/file/FileURLTest.java +++ b/test/jdk/sun/net/www/protocol/file/FileURLTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 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,6 +25,7 @@ * @test * @bug 4474391 * @summary url: file:///D|/Projects/tmp/test.html: urlConnection.getInputStream() broken. + * @requires os.family == "windows" */ import java.io.*; import java.net.*; @@ -33,10 +34,7 @@ public class FileURLTest { public static void main(String [] args) { - String name = System.getProperty("os.name"); - if (name.startsWith("Windows")) { String urlStr = "file:///C|/nonexisted.txt"; - try { URL url = new URL(urlStr); URLConnection urlConnection = url.openConnection(); @@ -49,6 +47,5 @@ public static void main(String [] args) throw new RuntimeException("Can't handle '|' in place of ':' in file urls"); } } - } } } diff --git a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java index 6ea62526566..9ce71064b54 100644 --- a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java +++ b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java @@ -34,379 +34,41 @@ * @author Xuelei Fan */ -import java.net.*; -import java.util.*; -import java.io.*; -import javax.net.ssl.*; -import java.security.Security; + +import java.io.PrintStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.URL; +import java.security.KeyPair; +import java.security.KeyPairGenerator; import java.security.KeyStore; -import java.security.KeyFactory; +import java.security.SecureRandom; +import java.security.Security; +import java.security.cert.X509Certificate; + import java.security.cert.Certificate; -import java.security.cert.CertificateFactory; -import java.security.spec.*; -import java.security.interfaces.*; import java.math.BigInteger; import jdk.test.lib.net.URIBuilder; - -/* - * Certificates and key used in the test. - * - * TLS server certificate: - * server private key: - * -----BEGIN RSA PRIVATE KEY----- - * Proc-Type: 4,ENCRYPTED - * DEK-Info: DES-EDE3-CBC,D9AE407F6D0E389A - * - * WPrA7TFol/cQCcp9oHnXWNpYlvRbbIcQj0m+RKT2Iuzfus+DHt3Zadf8nJpKfX2e - * h2rnhlzCN9M7djRDooZKDOPCsdBn51Au7HlZF3S3Opgo7D8XFM1a8t1Je4ke14oI - * nw6QKYsBblRziPnP2PZ0zvX24nOv7bbY8beynlJHGs00VWSFdoH2DS0aE1p6D+3n - * ptJuJ75dVfZFK4X7162APlNXevX8D6PEQpSiRw1rjjGGcnvQ4HdWk3BxDVDcCNJb - * Y1aGNRxsjTDvPi3R9Qx2M+W03QzEPx4SR3ZHVskeSJHaetM0TM/w/45Paq4GokXP - * ZeTnbEx1xmjkA7h+t4doLL4watx5F6yLsJzu8xB3lt/1EtmkYtLz1t7X4BetPAXz - * zS69X/VwhKfsOI3qXBWuL2oHPyhDmT1gcaUQwEPSV6ogHEEQEDXdiUS8heNK13KF - * TCQYFkETvV2BLxUhV1hypPzRQ6tUpJiAbD5KmoK2lD9slshG2QtvKQq0/bgkDY5J - * LhDHV2dtcZ3kDPkkZXpbcJQvoeH3d09C5sIsuTFo2zgNR6oETHUc5TzP6FY2YYRa - * QcK5HcmtsRRiXFm01ac+aMejJUIujjFt84SiKWT/73vC8AmY4tYcJBLjCg4XIxSH - * fdDFLL1YZENNO5ivlp8mdiHqcawx+36L7DrEZQ8RZt6cqST5t/+XTdM74s6k81GT - * pNsa82P2K2zmIUZ/DL2mKjW1vfRByw1NQFEBkN3vdyZxYfM/JyUzX4hbjXBEkh9Q - * QYrcwLKLjis2QzSvK04B3bvRzRb+4ocWiso8ZPAXAIxZFBWDpTMM2A== - * -----END RSA PRIVATE KEY----- - * - * -----BEGIN RSA PRIVATE KEY----- - * MIICXAIBAAKBgQClrFscN6LdmYktsnm4j9VIpecchBeNaZzGrG358h0fORna03Ie - * buxEzHCk3LoAMPagTz1UemFqzFfQCn+VKBg/mtmU8hvIJIh+/p0PPftXUwizIDPU - * PxdHFNHN6gjYDnVOr77M0uyvqXpJ38LZrLgkQJCmA1Yq0DAFQCxPq9l0iQIDAQAB - * AoGAbqcbg1E1mkR99uOJoNeQYKFOJyGiiXTMnXV1TseC4+PDfQBU7Dax35GcesBi - * CtapIpFKKS5D+ozY6b7ZT8ojxuQ/uHLPAvz0WDR3ds4iRF8tyu71Q1ZHcQsJa17y - * yO7UbkSSKn/Mp9Rb+/dKqftUGNXVFLqgHBOzN2s3We3bbbECQQDYBPKOg3hkaGHo - * OhpHKqtQ6EVkldihG/3i4WejRonelXN+HRh1KrB2HBx0M8D/qAzP1i3rNSlSHer4 - * 59YRTJnHAkEAxFX/sVYSn07BHv9Zhn6XXct/Cj43z/tKNbzlNbcxqQwQerw3IH51 - * 8UH2YOA+GD3lXbKp+MytoFLWv8zg4YT/LwJAfqan75Z1R6lLffRS49bIiq8jwE16 - * rTrUJ+kv8jKxMqc9B3vXkxpsS1M/+4E8bqgAmvpgAb8xcsvHsBd9ErdukQJBAKs2 - * j67W75BrPjBI34pQ1LEfp56IGWXOrq1kF8IbCjxv3+MYRT6Z6UJFkpRymNPNDjsC - * dgUYgITiGJHUGXuw3lMCQHEHqo9ZtXz92yFT+VhsNc29B8m/sqUJdtCcMd/jGpAF - * u6GHufjqIZBpQsk63wbwESAPZZ+kk1O1kS5GIRLX608= - * -----END RSA PRIVATE KEY----- - * - * Private-Key: (1024 bit) - * modulus: - * 00:a5:ac:5b:1c:37:a2:dd:99:89:2d:b2:79:b8:8f: - * d5:48:a5:e7:1c:84:17:8d:69:9c:c6:ac:6d:f9:f2: - * 1d:1f:39:19:da:d3:72:1e:6e:ec:44:cc:70:a4:dc: - * ba:00:30:f6:a0:4f:3d:54:7a:61:6a:cc:57:d0:0a: - * 7f:95:28:18:3f:9a:d9:94:f2:1b:c8:24:88:7e:fe: - * 9d:0f:3d:fb:57:53:08:b3:20:33:d4:3f:17:47:14: - * d1:cd:ea:08:d8:0e:75:4e:af:be:cc:d2:ec:af:a9: - * 7a:49:df:c2:d9:ac:b8:24:40:90:a6:03:56:2a:d0: - * 30:05:40:2c:4f:ab:d9:74:89 - * publicExponent: 65537 (0x10001) - * privateExponent: - * 6e:a7:1b:83:51:35:9a:44:7d:f6:e3:89:a0:d7:90: - * 60:a1:4e:27:21:a2:89:74:cc:9d:75:75:4e:c7:82: - * e3:e3:c3:7d:00:54:ec:36:b1:df:91:9c:7a:c0:62: - * 0a:d6:a9:22:91:4a:29:2e:43:fa:8c:d8:e9:be:d9: - * 4f:ca:23:c6:e4:3f:b8:72:cf:02:fc:f4:58:34:77: - * 76:ce:22:44:5f:2d:ca:ee:f5:43:56:47:71:0b:09: - * 6b:5e:f2:c8:ee:d4:6e:44:92:2a:7f:cc:a7:d4:5b: - * fb:f7:4a:a9:fb:54:18:d5:d5:14:ba:a0:1c:13:b3: - * 37:6b:37:59:ed:db:6d:b1 - * prime1: - * 00:d8:04:f2:8e:83:78:64:68:61:e8:3a:1a:47:2a: - * ab:50:e8:45:64:95:d8:a1:1b:fd:e2:e1:67:a3:46: - * 89:de:95:73:7e:1d:18:75:2a:b0:76:1c:1c:74:33: - * c0:ff:a8:0c:cf:d6:2d:eb:35:29:52:1d:ea:f8:e7: - * d6:11:4c:99:c7 - * prime2: - * 00:c4:55:ff:b1:56:12:9f:4e:c1:1e:ff:59:86:7e: - * 97:5d:cb:7f:0a:3e:37:cf:fb:4a:35:bc:e5:35:b7: - * 31:a9:0c:10:7a:bc:37:20:7e:75:f1:41:f6:60:e0: - * 3e:18:3d:e5:5d:b2:a9:f8:cc:ad:a0:52:d6:bf:cc: - * e0:e1:84:ff:2f - * exponent1: - * 7e:a6:a7:ef:96:75:47:a9:4b:7d:f4:52:e3:d6:c8: - * 8a:af:23:c0:4d:7a:ad:3a:d4:27:e9:2f:f2:32:b1: - * 32:a7:3d:07:7b:d7:93:1a:6c:4b:53:3f:fb:81:3c: - * 6e:a8:00:9a:fa:60:01:bf:31:72:cb:c7:b0:17:7d: - * 12:b7:6e:91 - * exponent2: - * 00:ab:36:8f:ae:d6:ef:90:6b:3e:30:48:df:8a:50: - * d4:b1:1f:a7:9e:88:19:65:ce:ae:ad:64:17:c2:1b: - * 0a:3c:6f:df:e3:18:45:3e:99:e9:42:45:92:94:72: - * 98:d3:cd:0e:3b:02:76:05:18:80:84:e2:18:91:d4: - * 19:7b:b0:de:53 - * coefficient: - * 71:07:aa:8f:59:b5:7c:fd:db:21:53:f9:58:6c:35: - * cd:bd:07:c9:bf:b2:a5:09:76:d0:9c:31:df:e3:1a: - * 90:05:bb:a1:87:b9:f8:ea:21:90:69:42:c9:3a:df: - * 06:f0:11:20:0f:65:9f:a4:93:53:b5:91:2e:46:21: - * 12:d7:eb:4f - * - * - * server certificate: - * Data: - * Version: 3 (0x2) - * Serial Number: 7 (0x7) - * Signature Algorithm: md5WithRSAEncryption - * Issuer: C=US, ST=Some-State, L=Some-City, O=Some-Org - * Validity - * Not Before: Dec 8 03:27:57 2008 GMT - * Not After : Aug 25 03:27:57 2028 GMT - * Subject: C=US, ST=Some-State, L=Some-City, O=Some-Org, OU=SSL-Server, CN=localhost - * Subject Public Key Info: - * Public Key Algorithm: rsaEncryption - * RSA Public Key: (1024 bit) - * Modulus (1024 bit): - * 00:a5:ac:5b:1c:37:a2:dd:99:89:2d:b2:79:b8:8f: - * d5:48:a5:e7:1c:84:17:8d:69:9c:c6:ac:6d:f9:f2: - * 1d:1f:39:19:da:d3:72:1e:6e:ec:44:cc:70:a4:dc: - * ba:00:30:f6:a0:4f:3d:54:7a:61:6a:cc:57:d0:0a: - * 7f:95:28:18:3f:9a:d9:94:f2:1b:c8:24:88:7e:fe: - * 9d:0f:3d:fb:57:53:08:b3:20:33:d4:3f:17:47:14: - * d1:cd:ea:08:d8:0e:75:4e:af:be:cc:d2:ec:af:a9: - * 7a:49:df:c2:d9:ac:b8:24:40:90:a6:03:56:2a:d0: - * 30:05:40:2c:4f:ab:d9:74:89 - * Exponent: 65537 (0x10001) - * X509v3 extensions: - * X509v3 Basic Constraints: - * CA:FALSE - * X509v3 Key Usage: - * Digital Signature, Non Repudiation, Key Encipherment - * X509v3 Subject Key Identifier: - * ED:6E:DB:F4:B5:56:C8:FB:1A:06:61:3F:0F:08:BB:A6:04:D8:16:54 - * X509v3 Authority Key Identifier: - * keyid:FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14 - * - * X509v3 Subject Alternative Name: critical - * IP Address:127.0.0.1 - * Signature Algorithm: md5WithRSAEncryption - * - * -----BEGIN CERTIFICATE----- - * MIICnzCCAgigAwIBAgIBBzANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET - * MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK - * EwhTb21lLU9yZzAeFw0wODEyMDgwMzI3NTdaFw0yODA4MjUwMzI3NTdaMHIxCzAJ - * BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp - * dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtU2VydmVyMRIwEAYD - * VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKWsWxw3 - * ot2ZiS2yebiP1Uil5xyEF41pnMasbfnyHR85GdrTch5u7ETMcKTcugAw9qBPPVR6 - * YWrMV9AKf5UoGD+a2ZTyG8gkiH7+nQ89+1dTCLMgM9Q/F0cU0c3qCNgOdU6vvszS - * 7K+peknfwtmsuCRAkKYDVirQMAVALE+r2XSJAgMBAAGjbjBsMAkGA1UdEwQCMAAw - * CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTtbtv0tVbI+xoGYT8PCLumBNgWVDAfBgNV - * HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDASBgNVHREBAf8ECDAGhwR/AAAB - * MA0GCSqGSIb3DQEBBAUAA4GBAFJjItCtCBZcjD69wdqfIbKmRFa6eJAjR6LcoDva - * cKC/sDOLelpspiZ66Zb0Xdv5qQ7QrfOXt3K8QqJKRMdZLF9WfUfy0gJDM32ub91h - * pu+TmcGPs+6RdrAQcuvU1ZDV9X8SMj7BtKaim4d5sqFw1npncKiA5xFn8vOYwdun - * nZif - * -----END CERTIFICATE----- - * - * - * TLS client certificate: - * client private key: - * ----BEGIN RSA PRIVATE KEY----- - * Proc-Type: 4,ENCRYPTED - * DEK-Info: DES-EDE3-CBC,FA2A435CD35A9390 - * - * Z+Y2uaETbsUWIyJUyVu1UV2G4rgFYJyACZT6Tp1KjRtxflSh2kXkJ9MpuXMXA0V4 - * Yy3fDzPqCL9NJmQAYRlAx/W/+j4F5EyMWDIx8fUxzONRZyoiwF7jLm+KscAfv6Pf - * q7ItWOdj3z7IYrwlB8YIGd3F2cDKT3S+lYRk7rKb/qT7itbuHnY4Ardh3yl+MZak - * jBp+ELUlRsUqSr1V0LoM+0rCCykarpyfhpxEcqsrl0v9Cyi5uhU50/oKv5zql3SH - * l2ImgDjp3batAs8+Bd4NF2aqi0a7Hy44JUHxRm4caZryU/i/D9N1MbuM6882HLat - * 5N0G+NaIUfywa8mjwq2D5aiit18HqKA6XeRRYeJ5Dvu9DCO4GeFSwcUFIBMI0L46 - * 7s114+oDodg57pMgITi+04vmUxvqlN9aiyd7f5Fgd7PeHGeOdbMz1NaJLJaPI9++ - * NakK8eK9iwT/Gdq0Uap5/CHW7vCT5PO+h3HY0STH0lWStXhdWnFO04zTdywsbSp+ - * DLpHeFT66shfeUlxR0PsCbG9vPRt/QmGLeYQZITppWo/ylSq4j+pRIuXvuWHdBRN - * rTZ8QF4Y7AxQUXVz1j1++s6ZMHTzaK2i9HrhmDs1MbJl+QwWre3Xpv3LvTVz3k5U - * wX8kuY1m3STt71QCaRWENq5sRaMImLxZbxc/ivFl9RAzUqo4NCxLod/QgA4iLqtO - * ztnlpzwlC/F8HbQ1oqYWwnZAPhzU/cULtstl+Yrws2c2atO323LbPXZqbASySgig - * sNpFXQMObdfP6LN23bY+1SvtK7V4NUTNhpdIc6INQAQ= - * -----END RSA PRIVATE KEY----- - * - * -----BEGIN RSA PRIVATE KEY----- - * MIICWwIBAAKBgQC78EA2rCZUTvSjWgAvaSFvuXo6k+yi9uGOx2PYLxIwmS6w8o/4 - * Jy0keCiE9wG/jUR53TvSVfPOPLJbIX3v/TNKsaP/xsibuQ98QTWX+ds6BWAFFa9Z - * F5KjEK0WHOQHU6+odqJWKpLT+SjgeM9eH0irXBnd4WdDunWN9YKsQ5JEGwIDAQAB - * AoGAEbdqNj0wN85hnWyEi/ObJU8UyKTdL9eaF72QGfcF/fLSxfd3vurihIeXOkGW - * tpn4lIxYcVGM9CognhqgJpl11jFTQzn1KqZ+NEJRKkCHA4hDabKJbSC9fXHvRwrf - * BsFpZqgiNxp3HseUTiwnaUVeyPgMt/jAj5nB5Sib+UyUxrECQQDnNQBiF2aifEg6 - * zbJOOC7he5CHAdkFxSxWVFVHL6EfXfqdLVkUohMbgZv+XxyIeU2biOExSg49Kds3 - * FOKgTau1AkEA0Bd1haj6QuCo8I0AXm2WO+MMTZMTvtHD/bGjKNM+fT4I8rKYnQRX - * 1acHdqS9Xx2rNJqZgkMmpESIdPR2fc4yjwJALFeM6EMmqvj8/VIf5UJ/Mz14fXwM - * PEARfckUxd9LnnFutCBTWlKvKXJVEZb6KO5ixPaegc57Jp3Vbh3yTN44lQJADD/1 - * SSMDaIB1MYP7a5Oj7m6VQNPRq8AJe5vDcRnOae0G9dKRrVyeFxO4GsHj6/+BHp2j - * P8nYMn9eURQ7DXjf/QJAAQzMlWnKGSO8pyTDtnQx3hRMoUkOEhmNq4bQhLkYqtnY - * FcqpUQ2qMjW+NiNWk5HnTrMS3L9EdJobMUzaNZLy4w== - * -----END RSA PRIVATE KEY----- - * - * Private-Key: (1024 bit) - * modulus: - * 00:bb:f0:40:36:ac:26:54:4e:f4:a3:5a:00:2f:69: - * 21:6f:b9:7a:3a:93:ec:a2:f6:e1:8e:c7:63:d8:2f: - * 12:30:99:2e:b0:f2:8f:f8:27:2d:24:78:28:84:f7: - * 01:bf:8d:44:79:dd:3b:d2:55:f3:ce:3c:b2:5b:21: - * 7d:ef:fd:33:4a:b1:a3:ff:c6:c8:9b:b9:0f:7c:41: - * 35:97:f9:db:3a:05:60:05:15:af:59:17:92:a3:10: - * ad:16:1c:e4:07:53:af:a8:76:a2:56:2a:92:d3:f9: - * 28:e0:78:cf:5e:1f:48:ab:5c:19:dd:e1:67:43:ba: - * 75:8d:f5:82:ac:43:92:44:1b - * publicExponent: 65537 (0x10001) - * privateExponent: - * 11:b7:6a:36:3d:30:37:ce:61:9d:6c:84:8b:f3:9b: - * 25:4f:14:c8:a4:dd:2f:d7:9a:17:bd:90:19:f7:05: - * fd:f2:d2:c5:f7:77:be:ea:e2:84:87:97:3a:41:96: - * b6:99:f8:94:8c:58:71:51:8c:f4:2a:20:9e:1a:a0: - * 26:99:75:d6:31:53:43:39:f5:2a:a6:7e:34:42:51: - * 2a:40:87:03:88:43:69:b2:89:6d:20:bd:7d:71:ef: - * 47:0a:df:06:c1:69:66:a8:22:37:1a:77:1e:c7:94: - * 4e:2c:27:69:45:5e:c8:f8:0c:b7:f8:c0:8f:99:c1: - * e5:28:9b:f9:4c:94:c6:b1 - * prime1: - * 00:e7:35:00:62:17:66:a2:7c:48:3a:cd:b2:4e:38: - * 2e:e1:7b:90:87:01:d9:05:c5:2c:56:54:55:47:2f: - * a1:1f:5d:fa:9d:2d:59:14:a2:13:1b:81:9b:fe:5f: - * 1c:88:79:4d:9b:88:e1:31:4a:0e:3d:29:db:37:14: - * e2:a0:4d:ab:b5 - * prime2: - * 00:d0:17:75:85:a8:fa:42:e0:a8:f0:8d:00:5e:6d: - * 96:3b:e3:0c:4d:93:13:be:d1:c3:fd:b1:a3:28:d3: - * 3e:7d:3e:08:f2:b2:98:9d:04:57:d5:a7:07:76:a4: - * bd:5f:1d:ab:34:9a:99:82:43:26:a4:44:88:74:f4: - * 76:7d:ce:32:8f - * exponent1: - * 2c:57:8c:e8:43:26:aa:f8:fc:fd:52:1f:e5:42:7f: - * 33:3d:78:7d:7c:0c:3c:40:11:7d:c9:14:c5:df:4b: - * 9e:71:6e:b4:20:53:5a:52:af:29:72:55:11:96:fa: - * 28:ee:62:c4:f6:9e:81:ce:7b:26:9d:d5:6e:1d:f2: - * 4c:de:38:95 - * exponent2: - * 0c:3f:f5:49:23:03:68:80:75:31:83:fb:6b:93:a3: - * ee:6e:95:40:d3:d1:ab:c0:09:7b:9b:c3:71:19:ce: - * 69:ed:06:f5:d2:91:ad:5c:9e:17:13:b8:1a:c1:e3: - * eb:ff:81:1e:9d:a3:3f:c9:d8:32:7f:5e:51:14:3b: - * 0d:78:df:fd - * coefficient: - * 01:0c:cc:95:69:ca:19:23:bc:a7:24:c3:b6:74:31: - * de:14:4c:a1:49:0e:12:19:8d:ab:86:d0:84:b9:18: - * aa:d9:d8:15:ca:a9:51:0d:aa:32:35:be:36:23:56: - * 93:91:e7:4e:b3:12:dc:bf:44:74:9a:1b:31:4c:da: - * 35:92:f2:e3 - * - * client certificate: - * Data: - * Version: 3 (0x2) - * Serial Number: 6 (0x6) - * Signature Algorithm: md5WithRSAEncryption - * Issuer: C=US, ST=Some-State, L=Some-City, O=Some-Org - * Validity - * Not Before: Dec 8 03:27:34 2008 GMT - * Not After : Aug 25 03:27:34 2028 GMT - * Subject: C=US, ST=Some-State, L=Some-City, O=Some-Org, OU=SSL-Client, CN=localhost - * Subject Public Key Info: - * Public Key Algorithm: rsaEncryption - * RSA Public Key: (1024 bit) - * Modulus (1024 bit): - * 00:bb:f0:40:36:ac:26:54:4e:f4:a3:5a:00:2f:69: - * 21:6f:b9:7a:3a:93:ec:a2:f6:e1:8e:c7:63:d8:2f: - * 12:30:99:2e:b0:f2:8f:f8:27:2d:24:78:28:84:f7: - * 01:bf:8d:44:79:dd:3b:d2:55:f3:ce:3c:b2:5b:21: - * 7d:ef:fd:33:4a:b1:a3:ff:c6:c8:9b:b9:0f:7c:41: - * 35:97:f9:db:3a:05:60:05:15:af:59:17:92:a3:10: - * ad:16:1c:e4:07:53:af:a8:76:a2:56:2a:92:d3:f9: - * 28:e0:78:cf:5e:1f:48:ab:5c:19:dd:e1:67:43:ba: - * 75:8d:f5:82:ac:43:92:44:1b - * Exponent: 65537 (0x10001) - * X509v3 extensions: - * X509v3 Basic Constraints: - * CA:FALSE - * X509v3 Key Usage: - * Digital Signature, Non Repudiation, Key Encipherment - * X509v3 Subject Key Identifier: - * CD:BB:C8:85:AA:91:BD:FD:1D:BE:CD:67:7C:FF:B3:E9:4C:A8:22:E6 - * X509v3 Authority Key Identifier: - * keyid:FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14 - * - * X509v3 Subject Alternative Name: critical - * IP Address:127.0.0.1 - * Signature Algorithm: md5WithRSAEncryption - * - * -----BEGIN CERTIFICATE----- - * MIICnzCCAgigAwIBAgIBBjANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET - * MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK - * EwhTb21lLU9yZzAeFw0wODEyMDgwMzI3MzRaFw0yODA4MjUwMzI3MzRaMHIxCzAJ - * BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp - * dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtQ2xpZW50MRIwEAYD - * VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALvwQDas - * JlRO9KNaAC9pIW+5ejqT7KL24Y7HY9gvEjCZLrDyj/gnLSR4KIT3Ab+NRHndO9JV - * 8848slshfe/9M0qxo//GyJu5D3xBNZf52zoFYAUVr1kXkqMQrRYc5AdTr6h2olYq - * ktP5KOB4z14fSKtcGd3hZ0O6dY31gqxDkkQbAgMBAAGjbjBsMAkGA1UdEwQCMAAw - * CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTNu8iFqpG9/R2+zWd8/7PpTKgi5jAfBgNV - * HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDASBgNVHREBAf8ECDAGhwR/AAAB - * MA0GCSqGSIb3DQEBBAUAA4GBACjj9PS+W6XOF7toFMwMOv/AemZeBOpcEF1Ei1Hx - * HjvB6EOHkMY8tFm5OPzkiWiK3+s3awpSW0jWdzMYwrQJ3/klMsPDpI7PEuirqwHP - * i5Wyl/vk7jmfWVcBO9MVhPUo4BYl4vS9aj6JA5QbkbkB95LOgT/BowY0WmHeVsXC - * I9aw - * -----END CERTIFICATE----- - * - * - * - * Trusted CA certificate: - * Certificate: - * Data: - * Version: 3 (0x2) - * Serial Number: 0 (0x0) - * Signature Algorithm: md5WithRSAEncryption - * Issuer: C=US, ST=Some-State, L=Some-City, O=Some-Org - * Validity - * Not Before: Dec 8 02:43:36 2008 GMT - * Not After : Aug 25 02:43:36 2028 GMT - * Subject: C=US, ST=Some-State, L=Some-City, O=Some-Org - * Subject Public Key Info: - * Public Key Algorithm: rsaEncryption - * RSA Public Key: (1024 bit) - * Modulus (1024 bit): - * 00:cb:c4:38:20:07:be:88:a7:93:b0:a1:43:51:2d: - * d7:8e:85:af:54:dd:ad:a2:7b:23:5b:cf:99:13:53: - * 99:45:7d:ee:6d:ba:2d:bf:e3:ad:6e:3d:9f:1a:f9: - * 03:97:e0:17:55:ae:11:26:57:de:01:29:8e:05:3f: - * 21:f7:e7:36:e8:2e:37:d7:48:ac:53:d6:60:0e:c7: - * 50:6d:f6:c5:85:f7:8b:a6:c5:91:35:72:3c:94:ee: - * f1:17:f0:71:e3:ec:1b:ce:ca:4e:40:42:b0:6d:ee: - * 6a:0e:d6:e5:ad:3c:0f:c9:ba:82:4f:78:f8:89:97: - * 89:2a:95:12:4c:d8:09:2a:e9 - * Exponent: 65537 (0x10001) - * X509v3 extensions: - * X509v3 Subject Key Identifier: - * FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14 - * X509v3 Authority Key Identifier: - * keyid:FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14 - * DirName:/C=US/ST=Some-State/L=Some-City/O=Some-Org - * serial:00 - * - * X509v3 Basic Constraints: - * CA:TRUE - * Signature Algorithm: md5WithRSAEncryption - * - * -----BEGIN CERTIFICATE----- - * MIICrDCCAhWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET - * MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK - * EwhTb21lLU9yZzAeFw0wODEyMDgwMjQzMzZaFw0yODA4MjUwMjQzMzZaMEkxCzAJ - * BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp - * dHkxETAPBgNVBAoTCFNvbWUtT3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB - * gQDLxDggB76Ip5OwoUNRLdeOha9U3a2ieyNbz5kTU5lFfe5tui2/461uPZ8a+QOX - * 4BdVrhEmV94BKY4FPyH35zboLjfXSKxT1mAOx1Bt9sWF94umxZE1cjyU7vEX8HHj - * 7BvOyk5AQrBt7moO1uWtPA/JuoJPePiJl4kqlRJM2Akq6QIDAQABo4GjMIGgMB0G - * A1UdDgQWBBT6uVG/TOfZhpgz+efLHvEzSfeoFDBxBgNVHSMEajBogBT6uVG/TOfZ - * hpgz+efLHvEzSfeoFKFNpEswSTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUt - * U3RhdGUxEjAQBgNVBAcTCVNvbWUtQ2l0eTERMA8GA1UEChMIU29tZS1PcmeCAQAw - * DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQBcIm534U123Hz+rtyYO5uA - * ofd81G6FnTfEAV8Kw9fGyyEbQZclBv34A9JsFKeMvU4OFIaixD7nLZ/NZ+IWbhmZ - * LovmJXyCkOufea73pNiZ+f/4/ScZaIlM/PRycQSqbFNd4j9Wott+08qxHPLpsf3P - * 6Mvf0r1PNTY2hwTJLJmKtg== - * -----END CERTIFICATE--- - */ +import jdk.test.lib.security.CertificateBuilder; +import jdk.test.lib.security.CertificateBuilder.KeyUsage; +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; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLServerSocketFactory; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.TrustManagerFactory; public class IPIdentities { - static Map cookies; - ServerSocket ss; /* * ============================================================= @@ -421,208 +83,14 @@ public class IPIdentities { */ static boolean separateServerThread = true; - /* - * Where do we find the keystores? - */ - static String trusedCertStr = - "-----BEGIN CERTIFICATE-----\n" + - "MIICrDCCAhWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET\n" + - "MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK\n" + - "EwhTb21lLU9yZzAeFw0wODEyMDgwMjQzMzZaFw0yODA4MjUwMjQzMzZaMEkxCzAJ\n" + - "BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp\n" + - "dHkxETAPBgNVBAoTCFNvbWUtT3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\n" + - "gQDLxDggB76Ip5OwoUNRLdeOha9U3a2ieyNbz5kTU5lFfe5tui2/461uPZ8a+QOX\n" + - "4BdVrhEmV94BKY4FPyH35zboLjfXSKxT1mAOx1Bt9sWF94umxZE1cjyU7vEX8HHj\n" + - "7BvOyk5AQrBt7moO1uWtPA/JuoJPePiJl4kqlRJM2Akq6QIDAQABo4GjMIGgMB0G\n" + - "A1UdDgQWBBT6uVG/TOfZhpgz+efLHvEzSfeoFDBxBgNVHSMEajBogBT6uVG/TOfZ\n" + - "hpgz+efLHvEzSfeoFKFNpEswSTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUt\n" + - "U3RhdGUxEjAQBgNVBAcTCVNvbWUtQ2l0eTERMA8GA1UEChMIU29tZS1PcmeCAQAw\n" + - "DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQBcIm534U123Hz+rtyYO5uA\n" + - "ofd81G6FnTfEAV8Kw9fGyyEbQZclBv34A9JsFKeMvU4OFIaixD7nLZ/NZ+IWbhmZ\n" + - "LovmJXyCkOufea73pNiZ+f/4/ScZaIlM/PRycQSqbFNd4j9Wott+08qxHPLpsf3P\n" + - "6Mvf0r1PNTY2hwTJLJmKtg==\n" + - "-----END CERTIFICATE-----"; - - static String serverCertStr = - "-----BEGIN CERTIFICATE-----\n" + - "MIICnzCCAgigAwIBAgIBBzANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET\n" + - "MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK\n" + - "EwhTb21lLU9yZzAeFw0wODEyMDgwMzI3NTdaFw0yODA4MjUwMzI3NTdaMHIxCzAJ\n" + - "BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp\n" + - "dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtU2VydmVyMRIwEAYD\n" + - "VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKWsWxw3\n" + - "ot2ZiS2yebiP1Uil5xyEF41pnMasbfnyHR85GdrTch5u7ETMcKTcugAw9qBPPVR6\n" + - "YWrMV9AKf5UoGD+a2ZTyG8gkiH7+nQ89+1dTCLMgM9Q/F0cU0c3qCNgOdU6vvszS\n" + - "7K+peknfwtmsuCRAkKYDVirQMAVALE+r2XSJAgMBAAGjbjBsMAkGA1UdEwQCMAAw\n" + - "CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTtbtv0tVbI+xoGYT8PCLumBNgWVDAfBgNV\n" + - "HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDASBgNVHREBAf8ECDAGhwR/AAAB\n" + - "MA0GCSqGSIb3DQEBBAUAA4GBAFJjItCtCBZcjD69wdqfIbKmRFa6eJAjR6LcoDva\n" + - "cKC/sDOLelpspiZ66Zb0Xdv5qQ7QrfOXt3K8QqJKRMdZLF9WfUfy0gJDM32ub91h\n" + - "pu+TmcGPs+6RdrAQcuvU1ZDV9X8SMj7BtKaim4d5sqFw1npncKiA5xFn8vOYwdun\n" + - "nZif\n" + - "-----END CERTIFICATE-----"; - - static String clientCertStr = - "-----BEGIN CERTIFICATE-----\n" + - "MIICnzCCAgigAwIBAgIBBjANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET\n" + - "MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK\n" + - "EwhTb21lLU9yZzAeFw0wODEyMDgwMzI3MzRaFw0yODA4MjUwMzI3MzRaMHIxCzAJ\n" + - "BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp\n" + - "dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtQ2xpZW50MRIwEAYD\n" + - "VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALvwQDas\n" + - "JlRO9KNaAC9pIW+5ejqT7KL24Y7HY9gvEjCZLrDyj/gnLSR4KIT3Ab+NRHndO9JV\n" + - "8848slshfe/9M0qxo//GyJu5D3xBNZf52zoFYAUVr1kXkqMQrRYc5AdTr6h2olYq\n" + - "ktP5KOB4z14fSKtcGd3hZ0O6dY31gqxDkkQbAgMBAAGjbjBsMAkGA1UdEwQCMAAw\n" + - "CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTNu8iFqpG9/R2+zWd8/7PpTKgi5jAfBgNV\n" + - "HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDASBgNVHREBAf8ECDAGhwR/AAAB\n" + - "MA0GCSqGSIb3DQEBBAUAA4GBACjj9PS+W6XOF7toFMwMOv/AemZeBOpcEF1Ei1Hx\n" + - "HjvB6EOHkMY8tFm5OPzkiWiK3+s3awpSW0jWdzMYwrQJ3/klMsPDpI7PEuirqwHP\n" + - "i5Wyl/vk7jmfWVcBO9MVhPUo4BYl4vS9aj6JA5QbkbkB95LOgT/BowY0WmHeVsXC\n" + - "I9aw\n" + - "-----END CERTIFICATE-----"; - - - static byte serverPrivateExponent[] = { - (byte)0x6e, (byte)0xa7, (byte)0x1b, (byte)0x83, - (byte)0x51, (byte)0x35, (byte)0x9a, (byte)0x44, - (byte)0x7d, (byte)0xf6, (byte)0xe3, (byte)0x89, - (byte)0xa0, (byte)0xd7, (byte)0x90, (byte)0x60, - (byte)0xa1, (byte)0x4e, (byte)0x27, (byte)0x21, - (byte)0xa2, (byte)0x89, (byte)0x74, (byte)0xcc, - (byte)0x9d, (byte)0x75, (byte)0x75, (byte)0x4e, - (byte)0xc7, (byte)0x82, (byte)0xe3, (byte)0xe3, - (byte)0xc3, (byte)0x7d, (byte)0x00, (byte)0x54, - (byte)0xec, (byte)0x36, (byte)0xb1, (byte)0xdf, - (byte)0x91, (byte)0x9c, (byte)0x7a, (byte)0xc0, - (byte)0x62, (byte)0x0a, (byte)0xd6, (byte)0xa9, - (byte)0x22, (byte)0x91, (byte)0x4a, (byte)0x29, - (byte)0x2e, (byte)0x43, (byte)0xfa, (byte)0x8c, - (byte)0xd8, (byte)0xe9, (byte)0xbe, (byte)0xd9, - (byte)0x4f, (byte)0xca, (byte)0x23, (byte)0xc6, - (byte)0xe4, (byte)0x3f, (byte)0xb8, (byte)0x72, - (byte)0xcf, (byte)0x02, (byte)0xfc, (byte)0xf4, - (byte)0x58, (byte)0x34, (byte)0x77, (byte)0x76, - (byte)0xce, (byte)0x22, (byte)0x44, (byte)0x5f, - (byte)0x2d, (byte)0xca, (byte)0xee, (byte)0xf5, - (byte)0x43, (byte)0x56, (byte)0x47, (byte)0x71, - (byte)0x0b, (byte)0x09, (byte)0x6b, (byte)0x5e, - (byte)0xf2, (byte)0xc8, (byte)0xee, (byte)0xd4, - (byte)0x6e, (byte)0x44, (byte)0x92, (byte)0x2a, - (byte)0x7f, (byte)0xcc, (byte)0xa7, (byte)0xd4, - (byte)0x5b, (byte)0xfb, (byte)0xf7, (byte)0x4a, - (byte)0xa9, (byte)0xfb, (byte)0x54, (byte)0x18, - (byte)0xd5, (byte)0xd5, (byte)0x14, (byte)0xba, - (byte)0xa0, (byte)0x1c, (byte)0x13, (byte)0xb3, - (byte)0x37, (byte)0x6b, (byte)0x37, (byte)0x59, - (byte)0xed, (byte)0xdb, (byte)0x6d, (byte)0xb1 - }; - - static byte serverModulus[] = { - (byte)0x00, - (byte)0xa5, (byte)0xac, (byte)0x5b, (byte)0x1c, - (byte)0x37, (byte)0xa2, (byte)0xdd, (byte)0x99, - (byte)0x89, (byte)0x2d, (byte)0xb2, (byte)0x79, - (byte)0xb8, (byte)0x8f, (byte)0xd5, (byte)0x48, - (byte)0xa5, (byte)0xe7, (byte)0x1c, (byte)0x84, - (byte)0x17, (byte)0x8d, (byte)0x69, (byte)0x9c, - (byte)0xc6, (byte)0xac, (byte)0x6d, (byte)0xf9, - (byte)0xf2, (byte)0x1d, (byte)0x1f, (byte)0x39, - (byte)0x19, (byte)0xda, (byte)0xd3, (byte)0x72, - (byte)0x1e, (byte)0x6e, (byte)0xec, (byte)0x44, - (byte)0xcc, (byte)0x70, (byte)0xa4, (byte)0xdc, - (byte)0xba, (byte)0x00, (byte)0x30, (byte)0xf6, - (byte)0xa0, (byte)0x4f, (byte)0x3d, (byte)0x54, - (byte)0x7a, (byte)0x61, (byte)0x6a, (byte)0xcc, - (byte)0x57, (byte)0xd0, (byte)0x0a, (byte)0x7f, - (byte)0x95, (byte)0x28, (byte)0x18, (byte)0x3f, - (byte)0x9a, (byte)0xd9, (byte)0x94, (byte)0xf2, - (byte)0x1b, (byte)0xc8, (byte)0x24, (byte)0x88, - (byte)0x7e, (byte)0xfe, (byte)0x9d, (byte)0x0f, - (byte)0x3d, (byte)0xfb, (byte)0x57, (byte)0x53, - (byte)0x08, (byte)0xb3, (byte)0x20, (byte)0x33, - (byte)0xd4, (byte)0x3f, (byte)0x17, (byte)0x47, - (byte)0x14, (byte)0xd1, (byte)0xcd, (byte)0xea, - (byte)0x08, (byte)0xd8, (byte)0x0e, (byte)0x75, - (byte)0x4e, (byte)0xaf, (byte)0xbe, (byte)0xcc, - (byte)0xd2, (byte)0xec, (byte)0xaf, (byte)0xa9, - (byte)0x7a, (byte)0x49, (byte)0xdf, (byte)0xc2, - (byte)0xd9, (byte)0xac, (byte)0xb8, (byte)0x24, - (byte)0x40, (byte)0x90, (byte)0xa6, (byte)0x03, - (byte)0x56, (byte)0x2a, (byte)0xd0, (byte)0x30, - (byte)0x05, (byte)0x40, (byte)0x2c, (byte)0x4f, - (byte)0xab, (byte)0xd9, (byte)0x74, (byte)0x89 - }; - - static byte clientPrivateExponent[] = { - (byte)0x11, (byte)0xb7, (byte)0x6a, (byte)0x36, - (byte)0x3d, (byte)0x30, (byte)0x37, (byte)0xce, - (byte)0x61, (byte)0x9d, (byte)0x6c, (byte)0x84, - (byte)0x8b, (byte)0xf3, (byte)0x9b, (byte)0x25, - (byte)0x4f, (byte)0x14, (byte)0xc8, (byte)0xa4, - (byte)0xdd, (byte)0x2f, (byte)0xd7, (byte)0x9a, - (byte)0x17, (byte)0xbd, (byte)0x90, (byte)0x19, - (byte)0xf7, (byte)0x05, (byte)0xfd, (byte)0xf2, - (byte)0xd2, (byte)0xc5, (byte)0xf7, (byte)0x77, - (byte)0xbe, (byte)0xea, (byte)0xe2, (byte)0x84, - (byte)0x87, (byte)0x97, (byte)0x3a, (byte)0x41, - (byte)0x96, (byte)0xb6, (byte)0x99, (byte)0xf8, - (byte)0x94, (byte)0x8c, (byte)0x58, (byte)0x71, - (byte)0x51, (byte)0x8c, (byte)0xf4, (byte)0x2a, - (byte)0x20, (byte)0x9e, (byte)0x1a, (byte)0xa0, - (byte)0x26, (byte)0x99, (byte)0x75, (byte)0xd6, - (byte)0x31, (byte)0x53, (byte)0x43, (byte)0x39, - (byte)0xf5, (byte)0x2a, (byte)0xa6, (byte)0x7e, - (byte)0x34, (byte)0x42, (byte)0x51, (byte)0x2a, - (byte)0x40, (byte)0x87, (byte)0x03, (byte)0x88, - (byte)0x43, (byte)0x69, (byte)0xb2, (byte)0x89, - (byte)0x6d, (byte)0x20, (byte)0xbd, (byte)0x7d, - (byte)0x71, (byte)0xef, (byte)0x47, (byte)0x0a, - (byte)0xdf, (byte)0x06, (byte)0xc1, (byte)0x69, - (byte)0x66, (byte)0xa8, (byte)0x22, (byte)0x37, - (byte)0x1a, (byte)0x77, (byte)0x1e, (byte)0xc7, - (byte)0x94, (byte)0x4e, (byte)0x2c, (byte)0x27, - (byte)0x69, (byte)0x45, (byte)0x5e, (byte)0xc8, - (byte)0xf8, (byte)0x0c, (byte)0xb7, (byte)0xf8, - (byte)0xc0, (byte)0x8f, (byte)0x99, (byte)0xc1, - (byte)0xe5, (byte)0x28, (byte)0x9b, (byte)0xf9, - (byte)0x4c, (byte)0x94, (byte)0xc6, (byte)0xb1 - }; - - static byte clientModulus[] = { - (byte)0x00, - (byte)0xbb, (byte)0xf0, (byte)0x40, (byte)0x36, - (byte)0xac, (byte)0x26, (byte)0x54, (byte)0x4e, - (byte)0xf4, (byte)0xa3, (byte)0x5a, (byte)0x00, - (byte)0x2f, (byte)0x69, (byte)0x21, (byte)0x6f, - (byte)0xb9, (byte)0x7a, (byte)0x3a, (byte)0x93, - (byte)0xec, (byte)0xa2, (byte)0xf6, (byte)0xe1, - (byte)0x8e, (byte)0xc7, (byte)0x63, (byte)0xd8, - (byte)0x2f, (byte)0x12, (byte)0x30, (byte)0x99, - (byte)0x2e, (byte)0xb0, (byte)0xf2, (byte)0x8f, - (byte)0xf8, (byte)0x27, (byte)0x2d, (byte)0x24, - (byte)0x78, (byte)0x28, (byte)0x84, (byte)0xf7, - (byte)0x01, (byte)0xbf, (byte)0x8d, (byte)0x44, - (byte)0x79, (byte)0xdd, (byte)0x3b, (byte)0xd2, - (byte)0x55, (byte)0xf3, (byte)0xce, (byte)0x3c, - (byte)0xb2, (byte)0x5b, (byte)0x21, (byte)0x7d, - (byte)0xef, (byte)0xfd, (byte)0x33, (byte)0x4a, - (byte)0xb1, (byte)0xa3, (byte)0xff, (byte)0xc6, - (byte)0xc8, (byte)0x9b, (byte)0xb9, (byte)0x0f, - (byte)0x7c, (byte)0x41, (byte)0x35, (byte)0x97, - (byte)0xf9, (byte)0xdb, (byte)0x3a, (byte)0x05, - (byte)0x60, (byte)0x05, (byte)0x15, (byte)0xaf, - (byte)0x59, (byte)0x17, (byte)0x92, (byte)0xa3, - (byte)0x10, (byte)0xad, (byte)0x16, (byte)0x1c, - (byte)0xe4, (byte)0x07, (byte)0x53, (byte)0xaf, - (byte)0xa8, (byte)0x76, (byte)0xa2, (byte)0x56, - (byte)0x2a, (byte)0x92, (byte)0xd3, (byte)0xf9, - (byte)0x28, (byte)0xe0, (byte)0x78, (byte)0xcf, - (byte)0x5e, (byte)0x1f, (byte)0x48, (byte)0xab, - (byte)0x5c, (byte)0x19, (byte)0xdd, (byte)0xe1, - (byte)0x67, (byte)0x43, (byte)0xba, (byte)0x75, - (byte)0x8d, (byte)0xf5, (byte)0x82, (byte)0xac, - (byte)0x43, (byte)0x92, (byte)0x44, (byte)0x1b - }; + static X509Certificate trustedCert; + + static X509Certificate serverCert; + + static X509Certificate clientCert; + + static KeyPair serverKeys; + static KeyPair clientKeys; static char passphrase[] = "passphrase".toCharArray(); @@ -639,7 +107,7 @@ public class IPIdentities { /* * Turn on SSL debugging? */ - static boolean debug = false; + static boolean debug = Boolean.getBoolean("test.debug"); private SSLServerSocket sslServerSocket = null; @@ -650,8 +118,8 @@ public class IPIdentities { * to avoid infinite hangs. */ void doServerSide() throws Exception { - SSLContext context = getSSLContext(trusedCertStr, serverCertStr, - serverModulus, serverPrivateExponent, passphrase); + SSLContext context = getSSLContext(trustedCert, serverCert, + serverKeys, passphrase); SSLServerSocketFactory sslssf = context.getServerSocketFactory(); // doClientSide() connects to the loopback address @@ -706,8 +174,8 @@ void doServerSide() throws Exception { void doClientSide() throws Exception { SSLContext reservedSSLContext = SSLContext.getDefault(); try { - SSLContext context = getSSLContext(trusedCertStr, clientCertStr, - clientModulus, clientPrivateExponent, passphrase); + SSLContext context = getSSLContext(trustedCert, clientCert, + clientKeys, passphrase); SSLContext.setDefault(context); /* @@ -755,6 +223,65 @@ void doClientSide() throws Exception { volatile Exception serverException = null; volatile Exception clientException = null; + 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 CertificateBuilder.newCertificateBuilder( + "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) + .setOneHourValidity() + .build(null, caKeys.getPrivate(), "MD5WithRSA"); + } + + private static void setupCertificates() throws Exception { + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); + KeyPair caKeys = kpg.generateKeyPair(); + serverKeys = kpg.generateKeyPair(); + clientKeys = kpg.generateKeyPair(); + + trustedCert = createTrustedCert(caKeys); + if (debug) { + System.out.println("----------- Trusted Cert -----------"); + CertificateBuilder.printCertificate(trustedCert, System.out); + } + + serverCert = CertificateBuilder.newCertificateBuilder( + "O=Some-Org, L=Some-City, ST=Some-State, C=US", + serverKeys.getPublic(), caKeys.getPublic(), + KeyUsage.DIGITAL_SIGNATURE, KeyUsage.NONREPUDIATION, KeyUsage.KEY_ENCIPHERMENT) + .addBasicConstraintsExt(false, false, -1) + .addExtension(CertificateBuilder.createIPSubjectAltNameExt(true, "127.0.0.1")) + .setOneHourValidity() + .build(trustedCert, caKeys.getPrivate(), "MD5WithRSA"); + if (debug) { + System.out.println("----------- Server Cert -----------"); + CertificateBuilder.printCertificate(serverCert, System.out); + } + + clientCert = CertificateBuilder.newCertificateBuilder( + "CN=localhost, OU=SSL-Client, O=Some-Org, L=Some-City, ST=Some-State, C=US", + clientKeys.getPublic(), caKeys.getPublic(), + KeyUsage.DIGITAL_SIGNATURE, KeyUsage.NONREPUDIATION, KeyUsage.KEY_ENCIPHERMENT) + .addExtension(CertificateBuilder.createIPSubjectAltNameExt(true, "127.0.0.1")) + .addBasicConstraintsExt(false, false, -1) + .setOneHourValidity() + .build(trustedCert, caKeys.getPrivate(), "MD5WithRSA"); + if (debug) { + System.out.println("----------- Client Cert -----------"); + CertificateBuilder.printCertificate(clientCert, System.out); + } + } + public static void main(String args[]) throws Exception { // MD5 is used in this test case, don't disable MD5 algorithm. Security.setProperty("jdk.certpath.disabledAlgorithms", @@ -762,8 +289,11 @@ public static void main(String args[]) throws Exception { Security.setProperty("jdk.tls.disabledAlgorithms", "SSLv3, RC4, DH keySize < 768"); - if (debug) + if (debug) { System.setProperty("javax.net.debug", "all"); + } + + setupCertificates(); /* * Start the tests. @@ -855,45 +385,23 @@ public void run() { } // get the ssl context - private static SSLContext getSSLContext(String trusedCertStr, - String keyCertStr, byte[] modulus, - byte[] privateExponent, char[] passphrase) throws Exception { - - // generate certificate from cert string - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - - ByteArrayInputStream is = - new ByteArrayInputStream(trusedCertStr.getBytes()); - Certificate trusedCert = cf.generateCertificate(is); - is.close(); + private static SSLContext getSSLContext(X509Certificate trustedCert, + X509Certificate keyCert, KeyPair key, char[] passphrase) throws Exception { // create a key store - KeyStore ks = KeyStore.getInstance("JKS"); + KeyStore ks = KeyStore.getInstance("PKCS12"); ks.load(null, null); // import the trused cert - ks.setCertificateEntry("RSA Export Signer", trusedCert); - - if (keyCertStr != null) { - // generate the private key. - RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec( - new BigInteger(modulus), - new BigInteger(privateExponent)); - KeyFactory kf = KeyFactory.getInstance("RSA"); - RSAPrivateKey priKey = - (RSAPrivateKey)kf.generatePrivate(priKeySpec); - - // generate certificate chain - is = new ByteArrayInputStream(keyCertStr.getBytes()); - Certificate keyCert = cf.generateCertificate(is); - is.close(); + ks.setCertificateEntry("RSA Export Signer", trustedCert); + if (keyCert != null) { Certificate[] chain = new Certificate[2]; chain[0] = keyCert; - chain[1] = trusedCert; + chain[1] = trustedCert; // import the key entry. - ks.setKeyEntry("Whatever", priKey, passphrase, chain); + ks.setKeyEntry("Whatever", key.getPrivate(), passphrase, chain); } // create SSL context @@ -902,7 +410,7 @@ private static SSLContext getSSLContext(String trusedCertStr, SSLContext ctx = SSLContext.getInstance("TLSv1.2"); - if (keyCertStr != null) { + if (keyCert != null) { KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, passphrase); diff --git a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/TEST.properties b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/TEST.properties new file mode 100644 index 00000000000..e1ed216f21d --- /dev/null +++ b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/TEST.properties @@ -0,0 +1,3 @@ +modules = \ + java.base/sun.security.util \ + java.base/sun.security.x509 diff --git a/test/jdk/sun/security/ec/ECDHKeyAgreementParamValidation.java b/test/jdk/sun/security/ec/ECDHKeyAgreementParamValidation.java index 0864d650162..3a77030f259 100644 --- a/test/jdk/sun/security/ec/ECDHKeyAgreementParamValidation.java +++ b/test/jdk/sun/security/ec/ECDHKeyAgreementParamValidation.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024, THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2024, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/sun/security/jgss/GssContextCleanup.java b/test/jdk/sun/security/jgss/GssContextCleanup.java index 00d84e8a70e..1e992df97d5 100644 --- a/test/jdk/sun/security/jgss/GssContextCleanup.java +++ b/test/jdk/sun/security/jgss/GssContextCleanup.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,4 +59,3 @@ public static void main(String[] args) throws Exception { } } } - diff --git a/test/jdk/sun/security/jgss/GssNameCleanup.java b/test/jdk/sun/security/jgss/GssNameCleanup.java index be68c46087d..ef19479b6a0 100644 --- a/test/jdk/sun/security/jgss/GssNameCleanup.java +++ b/test/jdk/sun/security/jgss/GssNameCleanup.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * 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,4 +66,3 @@ public static void main(String[] args) throws Exception { } } } - diff --git a/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java b/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java index 86a612ac3ba..1d28c3494e7 100644 --- a/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java +++ b/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java @@ -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 @@ public class VerifyCACerts { + 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 @@ public class VerifyCACerts { "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 --git a/test/jdk/sun/security/pkcs11/Cipher/KeyWrap/NISTWrapKAT.java b/test/jdk/sun/security/pkcs11/Cipher/KeyWrap/NISTWrapKAT.java index e1f32ea8076..e8f637e0b0c 100644 --- a/test/jdk/sun/security/pkcs11/Cipher/KeyWrap/NISTWrapKAT.java +++ b/test/jdk/sun/security/pkcs11/Cipher/KeyWrap/NISTWrapKAT.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * 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,13 +29,19 @@ * @summary Verify that the AES-Key-Wrap and AES-Key-Wrap-Pad ciphers * work as expected using NIST test vectors. */ +import jtreg.SkippedException; + import java.security.Key; import java.security.AlgorithmParameters; import java.security.Provider; -import javax.crypto.*; -import javax.crypto.spec.*; +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.util.ArrayList; import java.util.Arrays; import java.math.BigInteger; +import java.util.List; // adapted from com/sun/crypto/provider/Cipher/KeyWrap/NISTWrapKAT.java public class NISTWrapKAT extends PKCS11Test { @@ -73,8 +79,11 @@ public class NISTWrapKAT extends PKCS11Test { "308D49692B5F8CF638D54BB4B985633504237329964C76EBB3F669870A708DBC"; private static String KWP_AES256_224 = "0942747DB07032A3F04CDB2E7DE1CBA038F92BC355393AE9A0E4AE8C901912AC3D3AF0F16D240607"; - // from RFC 5649 sec6 - private static String KEK2 = "5840DF6E29B02AF1AB493B705BF16EA1AE8338F4DCC176A8"; + // from RFC 5649 sec6 + private static String KEK2 = + "5840DF6E29B02AF1AB493B705BF16EA1AE8338F4DCC176A8"; + + private static final List skippedList = new ArrayList <>(); private static byte[] toBytes(String hex, int hexLen) { if (hexLen < hex.length()) { @@ -91,10 +100,18 @@ private static byte[] toBytes(String hex, int hexLen) { byte[] out = new byte[outLen]; if (val.length < outLen) { // enlarge - System.arraycopy(val, 0, out, outLen - val.length, val.length); + System.arraycopy(val, + 0, + out, + outLen - val.length, + val.length); } else { // truncate - System.arraycopy(val, val.length - outLen, out, 0, outLen); + System.arraycopy(val, + val.length - outLen, + out, + 0, + outLen); } return out; } @@ -143,7 +160,8 @@ public Object[][] testData() { "AFBEB0F07DFBF5419200F2CCB50BB24F" }, { "AES/KWP/NoPadding", KEK2, 24, "C37B7E6492584340BED12207808941155068F738", 20, - "138BDEAA9B8FA7FC61F97742E72248EE5AE6AE5360D1AE6A5F54F373FA543B6A" }, + "138BDEAA9B8FA7FC61F97742E72248EE5AE6AE5360D1AE6A5F54F373FA543B6A" + }, // some more test vectors for KW and KWP // from csrc.nist.gov/groups/STM/cavp/documents/mac/kwtestvectors.zip { "AES/KW/NoPadding", "7575da3a93607cc2bfd8cec7aadfd9a6", 16, @@ -257,6 +275,9 @@ public void testKeyWrap(String algo, String key, int keyLen, int allowed = Cipher.getMaxAllowedKeyLength("AES"); if (keyLen > allowed) { System.out.println("=> skip, exceeds max allowed size " + allowed); + skippedList.add(algo + " Cipher with wrapping " + + dataLen + "-byte key with " + 8 * keyLen + + "-bit KEK exceeds max allowed size " + allowed); return; } Cipher c1 = Cipher.getInstance(algo, @@ -275,7 +296,8 @@ public void testKeyWrap(String algo, String key, int keyLen, c1.init(Cipher.WRAP_MODE, cipherKey); IvParameterSpec ivSpec = new IvParameterSpec(c1.getIV()); c2.init(Cipher.WRAP_MODE, cipherKey, ivSpec); - AlgorithmParameters params = AlgorithmParameters.getInstance("AES"); + AlgorithmParameters params = + AlgorithmParameters.getInstance("AES"); params.init(ivSpec); c3.init(Cipher.WRAP_MODE, cipherKey, params); @@ -300,9 +322,12 @@ public void testKeyWrap(String algo, String key, int keyLen, params.init(ivSpec); c3.init(Cipher.UNWRAP_MODE, cipherKey, params); - Key unwrapped = c1.unwrap(wrapped, "AES", Cipher.SECRET_KEY); - Key unwrapped2 = c2.unwrap(wrapped, "AES", Cipher.SECRET_KEY); - Key unwrapped3 = c3.unwrap(wrapped, "AES", Cipher.SECRET_KEY); + Key unwrapped = + c1.unwrap(wrapped, "AES", Cipher.SECRET_KEY); + Key unwrapped2 = + c2.unwrap(wrapped, "AES", Cipher.SECRET_KEY); + Key unwrapped3 = + c3.unwrap(wrapped, "AES", Cipher.SECRET_KEY); if (!Arrays.equals(unwrapped.getEncoded(), dataVal) || !Arrays.equals(unwrapped2.getEncoded(), dataVal) || @@ -320,6 +345,9 @@ public void testEnc(String algo, String key, int keyLen, String data, int allowed = Cipher.getMaxAllowedKeyLength("AES"); if (keyLen > allowed) { System.out.println("=> skip, exceeds max allowed size " + allowed); + skippedList.add(algo + " Cipher with enc " + + dataLen + "-byte data with " + 8 * keyLen + + "-bit KEK exceeds max allowed size " + allowed); return; } Cipher c1 = Cipher.getInstance(algo, @@ -336,7 +364,8 @@ public void testEnc(String algo, String key, int keyLen, String data, c1.init(Cipher.ENCRYPT_MODE, cipherKey); IvParameterSpec ivSpec = new IvParameterSpec(c1.getIV()); c2.init(Cipher.ENCRYPT_MODE, cipherKey, ivSpec); - AlgorithmParameters params = AlgorithmParameters.getInstance("AES"); + AlgorithmParameters params = + AlgorithmParameters.getInstance("AES"); params.init(ivSpec); c3.init(Cipher.ENCRYPT_MODE, cipherKey, params); @@ -384,18 +413,22 @@ public static void main(String[] args) throws Exception { @Override public void main(Provider p) throws Exception { Object[][] testDatum = testData(); - for (int i = 0; i < testDatum.length; i++) { - Object[] td = testDatum[i]; + for (Object[] td : testDatum) { String algo = (String) td[0]; if (p.getService("Cipher", algo) == null) { - System.out.println("Skip, due to no support: " + algo); - continue; + skippedList.add("No support for " + algo); } - testKeyWrap(algo, (String)td[1], (int)td[2], (String)td[3], - (int)td[4], (String)td[5], p); - testEnc(algo, (String)td[1], (int)td[2], (String)td[3], - (int)td[4], (String)td[5], p); + testKeyWrap(algo, (String) td[1], (int) td[2], (String) td[3], + (int) td[4], (String) td[5], p); + testEnc(algo, (String) td[1], (int) td[2], (String) td[3], + (int) td[4], (String) td[5], p); + } + + if (!skippedList.isEmpty()) { + throw new SkippedException("One or more tests skipped " + + skippedList); + } else { + System.out.println("All Tests Passed"); } - System.out.println("Test Passed"); } } diff --git a/test/jdk/sun/security/pkcs11/Cipher/KeyWrap/TestGeneral.java b/test/jdk/sun/security/pkcs11/Cipher/KeyWrap/TestGeneral.java index 0cfb4557572..f5e4494fc59 100644 --- a/test/jdk/sun/security/pkcs11/Cipher/KeyWrap/TestGeneral.java +++ b/test/jdk/sun/security/pkcs11/Cipher/KeyWrap/TestGeneral.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,18 +29,30 @@ * @library /test/lib ../.. * @run main/othervm TestGeneral */ +import jtreg.SkippedException; + import java.nio.ByteBuffer; +import java.security.AlgorithmParameters; +import java.security.InvalidAlgorithmParameterException; +import java.security.Key; +import java.security.KeyPairGenerator; +import java.security.PrivateKey; +import java.security.Provider; +import java.util.ArrayList; import java.util.Arrays; import java.util.HexFormat; -import java.security.*; -import javax.crypto.*; -import javax.crypto.spec.*; +import java.util.List; +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; // adapted from com/sun/crypto/provider/Cipher/KeyWrap/TestGeneral.java public class TestGeneral extends PKCS11Test { private static final byte[] DATA_32 = - Arrays.copyOf("1234567890123456789012345678901234".getBytes(), 32); + Arrays.copyOf("1234567890123456789012345678901234".getBytes(), + 32); private static final SecretKey KEY = new SecretKeySpec(DATA_32, 0, 16, "AES"); private static final int KW_IV_LEN = 8; @@ -49,7 +61,8 @@ public class TestGeneral extends PKCS11Test { private static final int MAX_KWP_PAD_LEN = 7; // 0-7 public static void testEnc(Cipher c, byte[] in, int startLen, int inc, - IvParameterSpec[] ivs, int maxPadLen) throws Exception { + IvParameterSpec[] ivs, int maxPadLen) + throws Exception { System.out.println("testEnc, input len=" + startLen + " w/ inc=" + inc); @@ -96,7 +109,7 @@ public static void testEnc(Cipher c, byte[] in, int startLen, int inc, } public static void testKAT(Cipher c, String keyStr, String inStr, - String expectedStr) throws Exception { + String expectedStr) throws Exception { System.out.println("testKAT, input len: " + inStr.length()/2); @@ -245,16 +258,21 @@ public void main(Provider p) throws Exception { SecretKey aes256 = new SecretKeySpec(DATA_32, "AES"); SecretKey any256 = new SecretKeySpec(DATA_32, "ANY"); PrivateKey priv = KeyPairGenerator.getInstance - ("RSA", System.getProperty("test.provider.name","SunRsaSign")) + ("RSA", + System.getProperty( + "test.provider.name", + "SunRsaSign")) .generateKeyPair().getPrivate(); String[] algos = { "AES/KW/PKCS5Padding", "AES/KW/NoPadding", "AES/KWP/NoPadding" }; + + final List skippedList = new ArrayList<>(); + for (String a : algos) { if (p.getService("Cipher", a) == null) { - System.out.println("Skip, due to no support: " + a); - continue; + skippedList.add(a); } System.out.println("Testing " + a); @@ -329,6 +347,12 @@ public void main(Provider p) throws Exception { testWrap(c, keys, ivs, padLen); testIv(c, ivLen, allowCustomIv); } - System.out.println("All Tests Passed"); + + if (!skippedList.isEmpty()) { + throw new SkippedException("One or more tests skipped " + + "due to no support " + skippedList); + } else { + System.out.println("All Tests Passed"); + } } } diff --git a/test/jdk/sun/security/pkcs11/Cipher/KeyWrap/XMLEncKAT.java b/test/jdk/sun/security/pkcs11/Cipher/KeyWrap/XMLEncKAT.java index 1857e619cc6..5ba02416c8b 100644 --- a/test/jdk/sun/security/pkcs11/Cipher/KeyWrap/XMLEncKAT.java +++ b/test/jdk/sun/security/pkcs11/Cipher/KeyWrap/XMLEncKAT.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,14 +28,16 @@ * @library /test/lib ../.. * @run main/othervm XMLEncKAT */ +import jtreg.SkippedException; + import java.util.Base64; import java.security.Key; -import java.security.AlgorithmParameters; import java.security.Provider; -import javax.crypto.*; -import javax.crypto.spec.*; +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; -import java.io.IOException; // adapted from com/sun/crypto/provider/Cipher/KeyWrap/XMLEncKAT.java public class XMLEncKAT extends PKCS11Test { @@ -105,7 +107,9 @@ private void testKeyWrap(Provider p, String cAlg, byte[] cKeyVal, // first test UNWRAP with known values for (int i = 0; i < base64Wrapped.length; i++) { byte[] wrappedKey = base64D.decode(base64Wrapped[i]); - key[i] = c.unwrap(wrappedKey, "AES", Cipher.SECRET_KEY); + key[i] = c.unwrap(wrappedKey, + "AES", + Cipher.SECRET_KEY); if (c.getIV() != null) { params[i] = new IvParameterSpec(c.getIV()); } @@ -131,8 +135,7 @@ public void main(Provider p) throws Exception { String wrapAlg = "AESWrap"; if (p.getService("Cipher", wrapAlg) == null) { - System.out.println("Skip, due to no support: " + wrapAlg); - return; + throw new SkippedException("No support " + wrapAlg); } String keyAlg = "AES"; diff --git a/test/jdk/sun/security/pkcs11/Cipher/ReinitCipher.java b/test/jdk/sun/security/pkcs11/Cipher/ReinitCipher.java index fe93dff5050..c54889fbdc4 100644 --- a/test/jdk/sun/security/pkcs11/Cipher/ReinitCipher.java +++ b/test/jdk/sun/security/pkcs11/Cipher/ReinitCipher.java @@ -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 @@ -32,6 +32,8 @@ * @run main/othervm ReinitCipher */ +import jtreg.SkippedException; + import java.security.Provider; import java.util.Random; import javax.crypto.Cipher; @@ -46,8 +48,7 @@ public static void main(String[] args) throws Exception { @Override public void main(Provider p) throws Exception { if (p.getService("Cipher", "ARCFOUR") == null) { - System.out.println("Not supported by provider, skipping"); - return; + throw new SkippedException("Algorithm ARCFOUR is not supported by provider, skipping"); } Random random = new Random(); byte[] data1 = new byte[10 * 1024]; diff --git a/test/jdk/sun/security/pkcs11/Cipher/Test4512704.java b/test/jdk/sun/security/pkcs11/Cipher/Test4512704.java index ddca64ecb69..7aafa4fd70f 100644 --- a/test/jdk/sun/security/pkcs11/Cipher/Test4512704.java +++ b/test/jdk/sun/security/pkcs11/Cipher/Test4512704.java @@ -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,14 +29,16 @@ * @run main Test4512704 * @summary Verify that AES cipher can generate default IV in encrypt mode */ -import java.io.PrintStream; -import java.security.*; -import java.security.spec.*; -import java.util.Random; +import jtreg.SkippedException; -import javax.crypto.*; -import javax.crypto.spec.*; +import java.security.GeneralSecurityException; +import java.security.InvalidAlgorithmParameterException; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; import java.security.Provider; +import java.security.spec.AlgorithmParameterSpec; public class Test4512704 extends PKCS11Test { @@ -48,9 +50,8 @@ public void test(String mode, Provider p) throws Exception { transformation = "AES/" + mode + "/NoPadding"; c = Cipher.getInstance(transformation, p); } catch (GeneralSecurityException e) { - System.out.println("Skip testing " + p.getName() + - ", no support for " + mode); - return; + throw new SkippedException("Skip testing " + p.getName() + + ", no support for " + mode); } SecretKey key = new SecretKeySpec(new byte[16], "AES"); diff --git a/test/jdk/sun/security/pkcs11/Cipher/TestCICOWithGCM.java b/test/jdk/sun/security/pkcs11/Cipher/TestCICOWithGCM.java index 06c1e84392c..f6b6157cefa 100644 --- a/test/jdk/sun/security/pkcs11/Cipher/TestCICOWithGCM.java +++ b/test/jdk/sun/security/pkcs11/Cipher/TestCICOWithGCM.java @@ -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 @@ -31,13 +31,21 @@ * @key randomness */ -import java.security.*; -import javax.crypto.*; -import javax.crypto.spec.*; -import java.math.*; -import java.io.*; +import jtreg.SkippedException; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import javax.crypto.Cipher; +import javax.crypto.CipherInputStream; +import javax.crypto.CipherOutputStream; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; + +import java.security.GeneralSecurityException; +import java.security.Provider; +import java.util.Arrays; +import java.util.Random; -import java.util.*; public class TestCICOWithGCM extends PKCS11Test { public static void main(String[] args) throws Exception { @@ -55,9 +63,8 @@ public void test(String mode, Provider p) throws Exception { String transformation = "AES/" + mode + "/NoPadding"; c = Cipher.getInstance(transformation, p); } catch (GeneralSecurityException e) { - System.out.println("Skip testing " + p.getName() + - ", no support for " + mode); - return; + throw new SkippedException("Skip testing " + p.getName() + + ", no support for " + mode); } SecretKey key = new SecretKeySpec(new byte[16], "AES"); diff --git a/test/jdk/sun/security/pkcs11/Cipher/TestCICOWithGCMAndAAD.java b/test/jdk/sun/security/pkcs11/Cipher/TestCICOWithGCMAndAAD.java index be2b1d18c8f..13ab8541351 100644 --- a/test/jdk/sun/security/pkcs11/Cipher/TestCICOWithGCMAndAAD.java +++ b/test/jdk/sun/security/pkcs11/Cipher/TestCICOWithGCMAndAAD.java @@ -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 @@ -30,6 +30,8 @@ * @summary Test CipherInputStream/OutputStream with AES GCM mode with AAD. * @key randomness */ +import jtreg.SkippedException; + import java.io.*; import java.security.*; import java.util.*; @@ -44,7 +46,6 @@ public static void main(String[] args) throws Exception { @Override public void main(Provider p) throws Exception { test("GCM", p); -// test("CCM", p); } public void test(String mode, Provider p) throws Exception { @@ -53,9 +54,8 @@ public void test(String mode, Provider p) throws Exception { String transformation = "AES/" + mode + "/NoPadding"; c = Cipher.getInstance(transformation, p); } catch (GeneralSecurityException e) { - System.out.println("Skip testing " + p.getName() + - ", no support for " + mode); - return; + throw new SkippedException("Skip testing " + p.getName() + + ", no support for " + mode); } SecretKey key = new SecretKeySpec(new byte[16], "AES"); diff --git a/test/jdk/sun/security/pkcs11/Cipher/TestChaChaPoly.java b/test/jdk/sun/security/pkcs11/Cipher/TestChaChaPoly.java index 26853ae3ee6..da351bc7493 100644 --- a/test/jdk/sun/security/pkcs11/Cipher/TestChaChaPoly.java +++ b/test/jdk/sun/security/pkcs11/Cipher/TestChaChaPoly.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,7 @@ import javax.crypto.spec.SecretKeySpec; import javax.crypto.NoSuchPaddingException; -import jdk.test.lib.Utils; +import jtreg.SkippedException; public class TestChaChaPoly extends PKCS11Test { @@ -70,8 +70,7 @@ public void main(Provider p) throws Exception { try { Cipher.getInstance(ALGO, p); } catch (NoSuchAlgorithmException nsae) { - System.out.println("Skip; no support for " + ALGO); - return; + throw new SkippedException("Skip; no support for " + ALGO); } this.p = p; testTransformations(); diff --git a/test/jdk/sun/security/pkcs11/Cipher/TestChaChaPolyKAT.java b/test/jdk/sun/security/pkcs11/Cipher/TestChaChaPolyKAT.java index 5649ed013ef..d2590b2c3cb 100644 --- a/test/jdk/sun/security/pkcs11/Cipher/TestChaChaPolyKAT.java +++ b/test/jdk/sun/security/pkcs11/Cipher/TestChaChaPolyKAT.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,22 +26,25 @@ * @bug 8255410 * @library /test/lib .. * @modules jdk.crypto.cryptoki - * @build jdk.test.lib.Convert * @run main/othervm TestChaChaPolyKAT * @summary ChaCha20-Poly1305 Cipher Implementation (KAT) */ -import java.util.*; +import jtreg.SkippedException; + import java.security.GeneralSecurityException; import java.security.Provider; import java.security.NoSuchAlgorithmException; import javax.crypto.Cipher; -import javax.crypto.spec.ChaCha20ParameterSpec; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import javax.crypto.AEADBadTagException; import java.nio.ByteBuffer; -import jdk.test.lib.Convert; +import java.util.Arrays; +import java.util.HexFormat; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; public class TestChaChaPolyKAT extends PKCS11Test { public static class TestData { @@ -126,8 +129,7 @@ public void main(Provider p) throws Exception { try { Cipher.getInstance(ALGO, p); } catch (NoSuchAlgorithmException nsae) { - System.out.println("Skip; no support for " + ALGO); - return; + throw new SkippedException("Skip; no support for " + ALGO); } int testsPassed = 0; diff --git a/test/jdk/sun/security/pkcs11/Cipher/TestChaChaPolyNoReuse.java b/test/jdk/sun/security/pkcs11/Cipher/TestChaChaPolyNoReuse.java index 94272367caa..60d80b9e365 100644 --- a/test/jdk/sun/security/pkcs11/Cipher/TestChaChaPolyNoReuse.java +++ b/test/jdk/sun/security/pkcs11/Cipher/TestChaChaPolyNoReuse.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,18 +30,22 @@ * (key/nonce reuse check) */ -import java.util.*; +import jtreg.SkippedException; + import javax.crypto.Cipher; import java.security.spec.AlgorithmParameterSpec; import java.security.Provider; import java.security.NoSuchAlgorithmException; -import javax.crypto.spec.ChaCha20ParameterSpec; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; -import javax.crypto.AEADBadTagException; import javax.crypto.SecretKey; import java.security.InvalidKeyException; import java.security.InvalidAlgorithmParameterException; +import java.util.Arrays; +import java.util.HexFormat; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; public class TestChaChaPolyNoReuse extends PKCS11Test { @@ -238,8 +242,7 @@ public void main(Provider p) throws Exception { try { Cipher.getInstance(CIPHER_ALGO, p); } catch (NoSuchAlgorithmException nsae) { - System.out.println("Skip; no support for " + CIPHER_ALGO); - return; + throw new SkippedException("Skip; no support for " + CIPHER_ALGO); } int testsPassed = 0; diff --git a/test/jdk/sun/security/pkcs11/Cipher/TestChaChaPolyOutputSize.java b/test/jdk/sun/security/pkcs11/Cipher/TestChaChaPolyOutputSize.java index 57a7b9a4606..f68340658fa 100644 --- a/test/jdk/sun/security/pkcs11/Cipher/TestChaChaPolyOutputSize.java +++ b/test/jdk/sun/security/pkcs11/Cipher/TestChaChaPolyOutputSize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,14 +30,14 @@ * @run main TestChaChaPolyOutputSize */ +import jtreg.SkippedException; + import java.nio.ByteBuffer; import java.security.GeneralSecurityException; -import java.security.Key; import java.security.SecureRandom; import java.security.Provider; import java.security.NoSuchAlgorithmException; import javax.crypto.Cipher; -import javax.crypto.spec.ChaCha20ParameterSpec; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; @@ -60,8 +60,7 @@ public void main(Provider p) throws GeneralSecurityException { try { Cipher.getInstance(ALGO, p); } catch (NoSuchAlgorithmException nsae) { - System.out.println("Skip; no support for " + ALGO); - return; + throw new SkippedException("Skip; no support for " + ALGO); } testGetOutSize(p); testMultiPartAEADDec(p); diff --git a/test/jdk/sun/security/pkcs11/Cipher/TestCipherMode.java b/test/jdk/sun/security/pkcs11/Cipher/TestCipherMode.java index 76f0c9dc412..cf3d948be17 100644 --- a/test/jdk/sun/security/pkcs11/Cipher/TestCipherMode.java +++ b/test/jdk/sun/security/pkcs11/Cipher/TestCipherMode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,8 @@ * @run main/othervm TestCipherMode */ +import jtreg.SkippedException; + import java.security.Provider; import java.security.Key; import java.security.KeyPair; @@ -38,20 +40,22 @@ import java.security.PublicKey; import java.security.InvalidParameterException; import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; public class TestCipherMode extends PKCS11Test { - private static String[] TRANSFORMATIONS = { - "AES/ECB/PKCS5Padding", "AES/GCM/NoPadding", - "RSA/ECB/PKCS1Padding" + private static final String[] TRANSFORMATIONS = { + "AES/ECB/PKCS5Padding", "AES/GCM/NoPadding", + "RSA/ECB/PKCS1Padding" }; - private static byte[] BYTES16 = - Arrays.copyOf(TRANSFORMATIONS[0].getBytes(), 16); + private static final byte[] BYTES16 = + Arrays.copyOf("AES/ECB/PKCS5Padding".getBytes(), 16); private static SecretKey AES_KEY = new SecretKeySpec(BYTES16, "AES"); private static PublicKey RSA_PUBKEY = null; private static PrivateKey RSA_PRIVKEY = null; @@ -97,18 +101,29 @@ public void main(Provider p) throws Exception { // test all cipher impls, e.g. P11Cipher, P11AEADCipher, and // P11RSACipher - for (String t : TRANSFORMATIONS) { - checkModes(t, p); + List skipped = new ArrayList<>(); + for (final String t : TRANSFORMATIONS) { + try { + checkModes(t, p); + } catch (SkippedException skippedException) { + // printing to System.out, so it's easier to see which test it relates to + skippedException.printStackTrace(System.out); + skipped.add(t); + } + } + + if (!skipped.isEmpty()) { + throw new SkippedException("Some tests skipped: " + skipped); + } else { + System.out.println("All tests passed"); } - System.out.println("All tests passed"); } private static void checkModes(String t, Provider p) throws Exception { try { Cipher.getInstance(t, p); } catch (Exception e) { - System.out.println("Skip " + t + " due to " + e.getMessage()); - return; + throw new SkippedException("Skip " + t + " due to " + e.getMessage()); } for (CipherMode m : CipherMode.values()) { diff --git a/test/jdk/sun/security/pkcs11/Cipher/TestDisabledAlgorithms.java b/test/jdk/sun/security/pkcs11/Cipher/TestDisabledAlgorithms.java new file mode 100644 index 00000000000..7d489cd2bb4 --- /dev/null +++ b/test/jdk/sun/security/pkcs11/Cipher/TestDisabledAlgorithms.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8244336 + * @summary Test JCE layer algorithm restriction + * @library /test/lib .. + * @run main/othervm TestDisabledAlgorithms CiPhEr.RSA/ECB/PKCS1Padding true + * @run main/othervm TestDisabledAlgorithms cIpHeR.rsA true + * @run main/othervm TestDisabledAlgorithms Cipher.what false + * @run main/othervm TestDisabledAlgorithms CiPhER.RSA/ECB/PKCS1Padding2 false + */ +import java.util.List; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.Security; +import javax.crypto.Cipher; +import javax.crypto.NoSuchPaddingException; +import jdk.test.lib.Utils; + +public class TestDisabledAlgorithms extends PKCS11Test { + + boolean shouldThrow; + + TestDisabledAlgorithms(boolean shouldThrow) { + this.shouldThrow = shouldThrow; + } + + private static final String PROP_NAME = "jdk.crypto.disabledAlgorithms"; + + private static void test(String alg, Provider p, boolean shouldThrow) + throws Exception { + System.out.println("Testing " + p.getName() + ": " + alg + + ", shouldThrow=" + shouldThrow); + if (shouldThrow) { + Utils.runAndCheckException(() -> Cipher.getInstance(alg, p), + NoSuchAlgorithmException.class); + } else { + Cipher c = Cipher.getInstance(alg, p); + System.out.println("Got cipher w/ algo " + c.getAlgorithm()); + } + } + + @Override + public void main(Provider p) throws Exception { + for (String a : List.of("RSA/ECB/PKCS1Padding", "RSA")) { + test(a, p, shouldThrow); + } + System.out.println("Done"); + } + + public static void main(String[] args) throws Exception { + String propValue = args[0]; + System.out.println("Setting Security Prop " + PROP_NAME + " = " + + propValue); + Security.setProperty(PROP_NAME, propValue); + boolean shouldThrow = Boolean.valueOf(args[1]); + main(new TestDisabledAlgorithms(shouldThrow), args); + } +} diff --git a/test/jdk/sun/security/pkcs11/Cipher/TestGCMKeyAndIvCheck.java b/test/jdk/sun/security/pkcs11/Cipher/TestGCMKeyAndIvCheck.java index adabcc571aa..4e78d8d39d7 100644 --- a/test/jdk/sun/security/pkcs11/Cipher/TestGCMKeyAndIvCheck.java +++ b/test/jdk/sun/security/pkcs11/Cipher/TestGCMKeyAndIvCheck.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,13 +31,21 @@ */ -import java.security.*; +import jtreg.SkippedException; + +import java.security.AlgorithmParameters; +import java.security.GeneralSecurityException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.Provider; import java.security.spec.AlgorithmParameterSpec; -import javax.crypto.*; -import javax.crypto.spec.*; -import java.math.*; +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; -import java.util.*; +import java.util.Arrays; public class TestGCMKeyAndIvCheck extends PKCS11Test { @@ -77,9 +85,8 @@ public void test(String mode, Provider p) throws Exception { String transformation = "AES/" + mode + "/NoPadding"; c = Cipher.getInstance(transformation, p); } catch (GeneralSecurityException e) { - System.out.println("Skip testing " + p.getName() + - ", no support for " + mode); - return; + throw new SkippedException("Skip testing " + p.getName() + + ", no support for " + mode); } System.out.println("Testing against " + p.getName()); SecretKey key = new SecretKeySpec(new byte[16], "AES"); diff --git a/test/jdk/sun/security/pkcs11/Cipher/TestKATForGCM.java b/test/jdk/sun/security/pkcs11/Cipher/TestKATForGCM.java index 95e6e5b1a0a..e5e8284e6f4 100644 --- a/test/jdk/sun/security/pkcs11/Cipher/TestKATForGCM.java +++ b/test/jdk/sun/security/pkcs11/Cipher/TestKATForGCM.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,8 @@ * @summary Known Answer Test for AES cipher with GCM mode support in * PKCS11 provider. */ +import jtreg.SkippedException; + import java.security.GeneralSecurityException; import java.security.Provider; import java.util.Arrays; @@ -311,23 +313,27 @@ public void main(Provider p) throws Exception { try { c = Cipher.getInstance(transformation, p); } catch (GeneralSecurityException e) { - System.out.println("Skip testing " + p.getName() + - ", no support for " + transformation); - return; + throw new SkippedException("Skip testing " + p.getName() + + ", no support for " + transformation); } try { if (execute(testValues, c)) { System.out.println("Test Passed!"); } } catch (Exception e) { - System.out.println("Exception occured using " + p.getName() + " version " + p.getVersionStr()); + System.out.println("Exception occured using " + p.getName() + + " version " + p.getVersionStr()); if (isNSS(p)) { - double ver = getNSSInfo("nss"); + Version ver = getNSSInfo("nss"); String osName = System.getProperty("os.name"); - if (ver > 3.139 && ver < 3.15 && osName.equals("Linux")) { + + if (osName.equals("Linux") && + ver.major() == 3 && ver.minor() < 15 + && (ver.minor() > 13 && ver.patch() >= 9)) { // warn about buggy behaviour on Linux with nss 3.14 - System.out.println("Warning: old NSS " + ver + " might be problematic, consider upgrading it"); + System.out.println("Warning: old NSS " + ver + + " might be problematic, consider upgrading it"); } } throw e; diff --git a/test/jdk/sun/security/pkcs11/Cipher/TestRSACipher.java b/test/jdk/sun/security/pkcs11/Cipher/TestRSACipher.java index 73039ba2f65..204b852e4d6 100644 --- a/test/jdk/sun/security/pkcs11/Cipher/TestRSACipher.java +++ b/test/jdk/sun/security/pkcs11/Cipher/TestRSACipher.java @@ -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 @@ -44,6 +44,7 @@ import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import jdk.test.lib.security.SecurityUtils; +import jtreg.SkippedException; public class TestRSACipher extends PKCS11Test { @@ -55,8 +56,7 @@ public void main(Provider p) throws Exception { try { Cipher.getInstance(RSA_ALGOS[0], p); } catch (GeneralSecurityException e) { - System.out.println("Not supported by provider, skipping"); - return; + throw new SkippedException("Algorithm " + RSA_ALGOS[0] + " is not supported by provider, skipping"); } String kpgAlgorithm = "RSA"; int keySize = SecurityUtils.getTestKeySize(kpgAlgorithm); diff --git a/test/jdk/sun/security/pkcs11/Cipher/TestRSACipherWrap.java b/test/jdk/sun/security/pkcs11/Cipher/TestRSACipherWrap.java index 559c7680c06..01d30934049 100644 --- a/test/jdk/sun/security/pkcs11/Cipher/TestRSACipherWrap.java +++ b/test/jdk/sun/security/pkcs11/Cipher/TestRSACipherWrap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, 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 @@ -43,6 +43,7 @@ import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import jdk.test.lib.security.SecurityUtils; +import jtreg.SkippedException; public class TestRSACipherWrap extends PKCS11Test { @@ -54,8 +55,7 @@ public void main(Provider p) throws Exception { try { Cipher.getInstance(RSA_ALGOS[0], p); } catch (GeneralSecurityException e) { - System.out.println(RSA_ALGOS[0] + " unsupported, skipping"); - return; + throw new SkippedException(RSA_ALGOS[0] + " unsupported, skipping"); } String kpgAlgorithm = "RSA"; KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgorithm, p); diff --git a/test/jdk/sun/security/pkcs11/Cipher/TestRawRSACipher.java b/test/jdk/sun/security/pkcs11/Cipher/TestRawRSACipher.java index 2c553f7e452..8989e951b09 100644 --- a/test/jdk/sun/security/pkcs11/Cipher/TestRawRSACipher.java +++ b/test/jdk/sun/security/pkcs11/Cipher/TestRawRSACipher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,7 @@ import java.util.Random; import javax.crypto.Cipher; import jdk.test.lib.security.SecurityUtils; +import jtreg.SkippedException; public class TestRawRSACipher extends PKCS11Test { @@ -49,8 +50,7 @@ public void main(Provider p) throws Exception { try { Cipher.getInstance("RSA/ECB/NoPadding", p); } catch (GeneralSecurityException e) { - System.out.println("Not supported by provider, skipping"); - return; + throw new SkippedException("Algorithm RSA/ECB/NoPadding is not supported by provider, skipping"); } String kpgAlgorithm = "RSA"; diff --git a/test/jdk/sun/security/pkcs11/Cipher/TestSymmCiphers.java b/test/jdk/sun/security/pkcs11/Cipher/TestSymmCiphers.java index b818adfe589..2e66370b807 100644 --- a/test/jdk/sun/security/pkcs11/Cipher/TestSymmCiphers.java +++ b/test/jdk/sun/security/pkcs11/Cipher/TestSymmCiphers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, 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 @@ -32,11 +32,15 @@ * @run main/othervm TestSymmCiphers */ +import jtreg.SkippedException; + import java.io.ByteArrayOutputStream; import java.nio.ByteBuffer; import java.security.AlgorithmParameters; import java.security.NoSuchAlgorithmException; import java.security.Provider; +import java.util.ArrayList; +import java.util.List; import java.util.Random; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; @@ -44,43 +48,33 @@ public class TestSymmCiphers extends PKCS11Test { - private static class CI { // class for holding Cipher Information - - String transformation; - String keyAlgo; - int dataSize; + private record CI (String transformation, String keyAlgo, int dataSize){} // record for holding Cipher Information - CI(String transformation, String keyAlgo, int dataSize) { - this.transformation = transformation; - this.keyAlgo = keyAlgo; - this.dataSize = dataSize; - } - } private static final CI[] TEST_LIST = { - new CI("ARCFOUR", "ARCFOUR", 400), - new CI("RC4", "RC4", 401), - new CI("DES/CBC/NoPadding", "DES", 400), - new CI("DESede/CBC/NoPadding", "DESede", 160), - new CI("AES/CBC/NoPadding", "AES", 4800), - new CI("Blowfish/CBC/NoPadding", "Blowfish", 24), - new CI("DES/cbc/PKCS5Padding", "DES", 6401), - new CI("DESede/CBC/PKCS5Padding", "DESede", 402), - new CI("AES/CBC/PKCS5Padding", "AES", 30), - new CI("Blowfish/CBC/PKCS5Padding", "Blowfish", 19), - new CI("DES/ECB/NoPadding", "DES", 400), - new CI("DESede/ECB/NoPadding", "DESede", 160), - new CI("AES/ECB/NoPadding", "AES", 4800), - new CI("DES/ECB/PKCS5Padding", "DES", 32), - new CI("DES/ECB/PKCS5Padding", "DES", 6400), - new CI("DESede/ECB/PKCS5Padding", "DESede", 400), - new CI("AES/ECB/PKCS5Padding", "AES", 64), - - new CI("DES", "DES", 6400), - new CI("DESede", "DESede", 408), - new CI("AES", "AES", 128), - - new CI("AES/CTR/NoPadding", "AES", 3200), - new CI("AES/CTS/NoPadding", "AES", 3200), + new CI("ARCFOUR", "ARCFOUR", 400), + new CI("RC4", "RC4", 401), + new CI("DES/CBC/NoPadding", "DES", 400), + new CI("DESede/CBC/NoPadding", "DESede", 160), + new CI("AES/CBC/NoPadding", "AES", 4800), + new CI("Blowfish/CBC/NoPadding", "Blowfish", 24), + new CI("DES/cbc/PKCS5Padding", "DES", 6401), + new CI("DESede/CBC/PKCS5Padding", "DESede", 402), + new CI("AES/CBC/PKCS5Padding", "AES", 30), + new CI("Blowfish/CBC/PKCS5Padding", "Blowfish", 19), + new CI("DES/ECB/NoPadding", "DES", 400), + new CI("DESede/ECB/NoPadding", "DESede", 160), + new CI("AES/ECB/NoPadding", "AES", 4800), + new CI("DES/ECB/PKCS5Padding", "DES", 32), + new CI("DES/ECB/PKCS5Padding", "DES", 6400), + new CI("DESede/ECB/PKCS5Padding", "DESede", 400), + new CI("AES/ECB/PKCS5Padding", "AES", 64), + + new CI("DES", "DES", 6400), + new CI("DESede", "DESede", 408), + new CI("AES", "AES", 128), + + new CI("AES/CTR/NoPadding", "AES", 3200), + new CI("AES/CTS/NoPadding", "AES", 3200), }; private static final StringBuffer debugBuf = new StringBuffer(); @@ -90,11 +84,10 @@ public void main(Provider p) throws Exception { // NSS reports CKR_DEVICE_ERROR when the data passed to // its EncryptUpdate/DecryptUpdate is not multiple of blocks int firstBlkSize = 16; - boolean status = true; + List skippedList = new ArrayList<>(); Random random = new Random(); try { - for (int i = 0; i < TEST_LIST.length; i++) { - CI currTest = TEST_LIST[i]; + for (CI currTest : TEST_LIST) { System.out.println("===" + currTest.transformation + "==="); try { KeyGenerator kg = @@ -123,7 +116,8 @@ public void main(Provider p) throws Exception { System.out.println("Decryption tests: DONE"); } catch (NoSuchAlgorithmException nsae) { System.out.println("Skipping unsupported algorithm: " + - nsae); + nsae); + skippedList.add(currTest); } } } catch (Exception ex) { @@ -131,11 +125,15 @@ public void main(Provider p) throws Exception { System.out.println(debugBuf); throw ex; } + + if (!skippedList.isEmpty()){ + throw new SkippedException("Some tests skipped: " + skippedList); + } } private static void test(Cipher cipher, int mode, SecretKey key, - AlgorithmParameters params, int firstBlkSize, - byte[] in, byte[] answer) throws Exception { + AlgorithmParameters params, int firstBlkSize, + byte[] in, byte[] answer) throws Exception { // test setup long startTime, endTime; cipher.init(mode, key, params); diff --git a/test/jdk/sun/security/pkcs11/Cipher/TestSymmCiphersNoPad.java b/test/jdk/sun/security/pkcs11/Cipher/TestSymmCiphersNoPad.java index 9290fe8d6eb..973da3b0c55 100644 --- a/test/jdk/sun/security/pkcs11/Cipher/TestSymmCiphersNoPad.java +++ b/test/jdk/sun/security/pkcs11/Cipher/TestSymmCiphersNoPad.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,8 @@ * @run main/othervm TestSymmCiphersNoPad */ +import jtreg.SkippedException; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; @@ -39,6 +41,8 @@ import java.security.AlgorithmParameters; import java.security.NoSuchAlgorithmException; import java.security.Provider; +import java.util.ArrayList; +import java.util.List; import java.util.Random; import javax.crypto.Cipher; import javax.crypto.CipherInputStream; @@ -47,48 +51,37 @@ public class TestSymmCiphersNoPad extends PKCS11Test { - private static class CI { // class for holding Cipher Information - String transformation; - String keyAlgo; - int dataSize; + private record CI (String transformation, String keyAlgo, int dataSize){} // record for holding Cipher Information - CI(String transformation, String keyAlgo, int dataSize) { - this.transformation = transformation; - this.keyAlgo = keyAlgo; - this.dataSize = dataSize; - } - } + private static final StringBuffer debugBuf = new StringBuffer(); - private static final CI TEST_LIST[] = { - new CI("ARCFOUR", "ARCFOUR", 400), - new CI("RC4", "RC4", 401), - new CI("DES/CBC/NoPadding", "DES", 400), - new CI("DESede/CBC/NoPadding", "DESede", 160), - new CI("AES/CBC/NoPadding", "AES", 4800), - new CI("Blowfish/CBC/NoPadding", "Blowfish", 24), - new CI("AES/CTR/NoPadding", "AES", 1600), - new CI("AES/CTR/NoPadding", "AES", 65), - new CI("AES/CTS/NoPadding", "AES", 1600), - new CI("AES/CTS/NoPadding", "AES", 65), + private static final CI[] TEST_LIST = { + new CI("ARCFOUR", "ARCFOUR", 400), + new CI("RC4", "RC4", 401), + new CI("DES/CBC/NoPadding", "DES", 400), + new CI("DESede/CBC/NoPadding", "DESede", 160), + new CI("AES/CBC/NoPadding", "AES", 4800), + new CI("Blowfish/CBC/NoPadding", "Blowfish", 24), + new CI("AES/CTR/NoPadding", "AES", 1600), + new CI("AES/CTR/NoPadding", "AES", 65), + new CI("AES/CTS/NoPadding", "AES", 1600), + new CI("AES/CTS/NoPadding", "AES", 65), }; - private static final StringBuffer debugBuf = new StringBuffer(); - @Override public void main(Provider p) throws Exception { - boolean status = true; + List skippedList = new ArrayList<>(); Random random = new Random(); try { - for (int i = 0; i < TEST_LIST.length; i++) { - CI currTest = TEST_LIST[i]; + for (CI currTest : TEST_LIST) { System.out.println("===" + currTest.transformation + "==="); try { KeyGenerator kg = - KeyGenerator.getInstance(currTest.keyAlgo, p); + KeyGenerator.getInstance(currTest.keyAlgo, p); SecretKey key = kg.generateKey(); Cipher c1 = Cipher.getInstance(currTest.transformation, p); Cipher c2 = Cipher.getInstance(currTest.transformation, - System.getProperty("test.provider.name", "SunJCE")); + System.getProperty("test.provider.name", "SunJCE")); byte[] plainTxt = new byte[currTest.dataSize]; random.nextBytes(plainTxt); @@ -98,16 +91,17 @@ public void main(Provider p) throws Exception { AlgorithmParameters params = c2.getParameters(); byte[] answer = c2.doFinal(plainTxt); test(c1, Cipher.ENCRYPT_MODE, key, params, - plainTxt, answer); + plainTxt, answer); System.out.println("Encryption tests: DONE"); c2.init(Cipher.DECRYPT_MODE, key, params); byte[] answer2 = c2.doFinal(answer); test(c1, Cipher.DECRYPT_MODE, key, params, - answer, answer2); + answer, answer2); System.out.println("Decryption tests: DONE"); } catch (NoSuchAlgorithmException nsae) { System.out.println("Skipping unsupported algorithm: " + nsae); + skippedList.add(currTest); } } } catch (Exception ex) { @@ -115,6 +109,10 @@ public void main(Provider p) throws Exception { System.out.println(debugBuf); throw ex; } + + if (!skippedList.isEmpty()){ + throw new SkippedException("Some tests skipped: " + skippedList); + } } private static void test(Cipher cipher, int mode, SecretKey key, diff --git a/test/jdk/sun/security/pkcs11/KeyAgreement/SupportedDHKeys.java b/test/jdk/sun/security/pkcs11/KeyAgreement/SupportedDHKeys.java index c4f8e189937..d044934fb59 100644 --- a/test/jdk/sun/security/pkcs11/KeyAgreement/SupportedDHKeys.java +++ b/test/jdk/sun/security/pkcs11/KeyAgreement/SupportedDHKeys.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,8 @@ * @run main/othervm SupportedDHKeys */ +import jtreg.SkippedException; + import java.math.BigInteger; import java.security.KeyPair; import java.security.KeyPairGenerator; @@ -62,8 +64,7 @@ private enum SupportedKeySize { @Override public void main(Provider provider) throws Exception { if (provider.getService("KeyPairGenerator", "DiffieHellman") == null) { - System.out.println("No support of DH KeyPairGenerator, skipping"); - return; + throw new SkippedException("No support of DH KeyPairGenerator, skipping"); } for (SupportedKeySize keySize : SupportedKeySize.values()) { diff --git a/test/jdk/sun/security/pkcs11/KeyAgreement/TestDH.java b/test/jdk/sun/security/pkcs11/KeyAgreement/TestDH.java index 560459c2b09..1140ba75e12 100644 --- a/test/jdk/sun/security/pkcs11/KeyAgreement/TestDH.java +++ b/test/jdk/sun/security/pkcs11/KeyAgreement/TestDH.java @@ -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 @@ -38,14 +38,14 @@ import javax.crypto.KeyAgreement; import javax.crypto.SecretKey; import jdk.test.lib.security.SecurityUtils; +import jtreg.SkippedException; public class TestDH extends PKCS11Test { @Override public void main(Provider p) throws Exception { if (p.getService("KeyAgreement", "DH") == null) { - System.out.println("DH not supported, skipping"); - return; + throw new SkippedException("DH not supported, skipping"); } String kpgAlgorithm = "DH"; KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgorithm, p); diff --git a/test/jdk/sun/security/pkcs11/KeyAgreement/TestInterop.java b/test/jdk/sun/security/pkcs11/KeyAgreement/TestInterop.java index 810814ebd5d..da15c41132a 100644 --- a/test/jdk/sun/security/pkcs11/KeyAgreement/TestInterop.java +++ b/test/jdk/sun/security/pkcs11/KeyAgreement/TestInterop.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, 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 @@ -40,6 +40,7 @@ import javax.crypto.spec.DHPublicKeySpec; import jdk.test.lib.security.DiffieHellmanGroup; import jdk.test.lib.security.SecurityUtils; +import jtreg.SkippedException; public class TestInterop extends PKCS11Test { @@ -76,8 +77,7 @@ public class TestInterop extends PKCS11Test { @Override public void main(Provider prov) throws Exception { if (prov.getService("KeyAgreement", "DH") == null) { - System.out.println("DH not supported, skipping"); - return; + throw new SkippedException("DH not supported, skipping"); } try { System.out.println("testing generateSecret()"); diff --git a/test/jdk/sun/security/pkcs11/KeyAgreement/TestShort.java b/test/jdk/sun/security/pkcs11/KeyAgreement/TestShort.java index 27e6bcbc8a3..d0e03c21f36 100644 --- a/test/jdk/sun/security/pkcs11/KeyAgreement/TestShort.java +++ b/test/jdk/sun/security/pkcs11/KeyAgreement/TestShort.java @@ -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 @@ -31,6 +31,8 @@ * @run main/othervm TestShort */ +import jtreg.SkippedException; + import java.math.BigInteger; import java.security.KeyFactory; import java.security.PrivateKey; @@ -90,12 +92,10 @@ public class TestShort extends PKCS11Test { @Override public void main(Provider provider) throws Exception { if (provider.getService("KeyAgreement", "DH") == null) { - System.out.println("DH not supported, skipping"); - return; + throw new SkippedException("DH not supported, skipping"); } + try { - DHPublicKeySpec publicSpec; - DHPrivateKeySpec privateSpec; KeyFactory kf = KeyFactory.getInstance("DH", provider); KeyAgreement ka = KeyAgreement.getInstance("DH", provider); @@ -106,7 +106,7 @@ public void main(Provider provider) throws Exception { ka.init(pr1); ka.doPhase(pu2, true); byte[] n2 = ka.generateSecret(); - if (Arrays.equals(s2, n2) == false) { + if (!Arrays.equals(s2, n2)) { throw new Exception("mismatch 2"); } System.out.println("short ok"); @@ -114,7 +114,7 @@ public void main(Provider provider) throws Exception { ka.init(pr1); ka.doPhase(pu3, true); byte[] n3 = ka.generateSecret(); - if (Arrays.equals(s3, n3) == false) { + if (!Arrays.equals(s3, n3)) { throw new Exception("mismatch 3"); } System.out.println("normal ok"); @@ -123,27 +123,6 @@ public void main(Provider provider) throws Exception { ex.printStackTrace(); throw ex; } - -/* - KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH", provider); - kpg.initialize(512); -// KeyPair kp1 = kpg.generateKeyPair(); -// System.out.println(kp1.getPublic()); -// System.out.println(kp1.getPrivate()); - while (true) { - KeyAgreement ka = KeyAgreement.getInstance("DH", provider); - ka.init(pr1); - KeyPair kp2 = kpg.generateKeyPair(); - ka.doPhase(kp2.getPublic(), true); - byte[] sec = ka.generateSecret(); - if (sec.length == 64) { - System.out.println(kp2.getPrivate()); - System.out.println(kp2.getPublic()); - System.out.println(toString(sec)); - break; - } - } -/**/ } public static void main(String[] args) throws Exception { diff --git a/test/jdk/sun/security/pkcs11/KeyAgreement/UnsupportedDHKeys.java b/test/jdk/sun/security/pkcs11/KeyAgreement/UnsupportedDHKeys.java index b2a2c29e8af..1cd224c2362 100644 --- a/test/jdk/sun/security/pkcs11/KeyAgreement/UnsupportedDHKeys.java +++ b/test/jdk/sun/security/pkcs11/KeyAgreement/UnsupportedDHKeys.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,8 @@ * @run main/othervm UnsupportedDHKeys */ +import jtreg.SkippedException; + import java.security.InvalidParameterException; import java.security.KeyPairGenerator; import java.security.Provider; @@ -59,8 +61,7 @@ private enum UnsupportedKeySize { @Override public void main(Provider provider) throws Exception { if (provider.getService("KeyPairGenerator", "DiffieHellman") == null) { - System.out.println("No supported of DH KeyPairGenerator, skipping"); - return; + throw new SkippedException("DH (DiffieHellman) is not supported in KeyPairGenerator, skipping"); } for (UnsupportedKeySize keySize : UnsupportedKeySize.values()) { diff --git a/test/jdk/sun/security/pkcs11/KeyGenerator/DESParity.java b/test/jdk/sun/security/pkcs11/KeyGenerator/DESParity.java index 59f58ca525e..f9da78df0e2 100644 --- a/test/jdk/sun/security/pkcs11/KeyGenerator/DESParity.java +++ b/test/jdk/sun/security/pkcs11/KeyGenerator/DESParity.java @@ -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 @@ -32,6 +32,8 @@ * @run main/othervm DESParity */ +import jtreg.SkippedException; + import java.security.Provider; import java.util.Random; import javax.crypto.SecretKey; @@ -45,8 +47,7 @@ public class DESParity extends PKCS11Test { @Override public void main(Provider p) throws Exception { if (p.getService("SecretKeyFactory", "DES") == null) { - System.out.println("Not supported by provider, skipping"); - return; + throw new SkippedException("Not supported by provider, skipping"); } Random random = new Random(); SecretKeyFactory kf; @@ -57,7 +58,7 @@ public void main(Provider p) throws Exception { random.nextBytes(b); SecretKeySpec spec = new SecretKeySpec(b, "DES"); SecretKey key = kf.generateSecret(spec); - if (DESKeySpec.isParityAdjusted(key.getEncoded(), 0) == false) { + if (!DESKeySpec.isParityAdjusted(key.getEncoded(), 0)) { throw new Exception("DES key not parity adjusted"); } } @@ -68,7 +69,7 @@ public void main(Provider p) throws Exception { random.nextBytes(b); SecretKeySpec spec = new SecretKeySpec(b, "DESede"); SecretKey key = kf.generateSecret(spec); - if (DESedeKeySpec.isParityAdjusted(key.getEncoded(), 0) == false) { + if (!DESedeKeySpec.isParityAdjusted(key.getEncoded(), 0)) { throw new Exception("DESede key not parity adjusted"); } } diff --git a/test/jdk/sun/security/pkcs11/KeyGenerator/TestAES.java b/test/jdk/sun/security/pkcs11/KeyGenerator/TestAES.java index e74007a65e3..66078be30bd 100644 --- a/test/jdk/sun/security/pkcs11/KeyGenerator/TestAES.java +++ b/test/jdk/sun/security/pkcs11/KeyGenerator/TestAES.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,13 +30,14 @@ * @library /test/lib .. * @run main TestAES */ +import jtreg.SkippedException; +import sun.security.util.SecurityProviderConstants; + import java.security.Provider; -import java.security.InvalidAlgorithmParameterException; import java.security.InvalidParameterException; import java.security.NoSuchAlgorithmException; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; -import static sun.security.util.SecurityProviderConstants.*; public class TestAES extends PKCS11Test { @@ -53,17 +54,16 @@ public void main(Provider p) throws Exception { try { kg = KeyGenerator.getInstance(ALGO, p); } catch (NoSuchAlgorithmException nsae) { - System.out.println("Skip; no support for " + ALGO); - return; + throw new SkippedException("Skip; no support for " + ALGO, nsae); } // first try w/o setting a key length and check if the generated key // length matches SecretKey key = kg.generateKey(); byte[] keyValue = key.getEncoded(); - if (key.getEncoded().length != getDefAESKeySize() >> 3) { + if (key.getEncoded().length != SecurityProviderConstants.getDefAESKeySize() >> 3) { throw new RuntimeException("Default AES key length should be " + - getDefAESKeySize()); + SecurityProviderConstants.getDefAESKeySize()); } for (int keySize : new int[] { 16, 32, 64, 128, 256, 512, 1024 }) { diff --git a/test/jdk/sun/security/pkcs11/KeyGenerator/TestChaCha20.java b/test/jdk/sun/security/pkcs11/KeyGenerator/TestChaCha20.java index a21571cd957..0eaab538655 100644 --- a/test/jdk/sun/security/pkcs11/KeyGenerator/TestChaCha20.java +++ b/test/jdk/sun/security/pkcs11/KeyGenerator/TestChaCha20.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,8 @@ * @library /test/lib .. * @run main/othervm TestChaCha20 */ +import jtreg.SkippedException; + import java.security.Provider; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidParameterException; @@ -54,8 +56,7 @@ public void main(Provider p) throws Exception { try { kg = KeyGenerator.getInstance(ALGO, p); } catch (NoSuchAlgorithmException nsae) { - System.out.println("Skip; no support for " + ALGO); - return; + throw new SkippedException("Skip; no support for " + ALGO, nsae); } try { diff --git a/test/jdk/sun/security/pkcs11/KeyGenerator/TestKeyGenerator.java b/test/jdk/sun/security/pkcs11/KeyGenerator/TestKeyGenerator.java index 15d0ee87fe4..50886a7aba3 100644 --- a/test/jdk/sun/security/pkcs11/KeyGenerator/TestKeyGenerator.java +++ b/test/jdk/sun/security/pkcs11/KeyGenerator/TestKeyGenerator.java @@ -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 diff --git a/test/jdk/sun/security/pkcs11/KeyPairGenerator/TestDH2048.java b/test/jdk/sun/security/pkcs11/KeyPairGenerator/TestDH2048.java index b05861ff3ae..06a9fa67afe 100644 --- a/test/jdk/sun/security/pkcs11/KeyPairGenerator/TestDH2048.java +++ b/test/jdk/sun/security/pkcs11/KeyPairGenerator/TestDH2048.java @@ -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 @@ -31,6 +31,8 @@ * @run main/othervm TestDH2048 */ +import jtreg.SkippedException; + import java.security.InvalidParameterException; import java.security.KeyPair; import java.security.KeyPairGenerator; @@ -50,8 +52,7 @@ private static void checkUnsupportedKeySize(KeyPairGenerator kpg, int ks) @Override public void main(Provider p) throws Exception { if (p.getService("KeyPairGenerator", "DH") == null) { - System.out.println("KPG for DH not supported, skipping"); - return; + throw new SkippedException("KPG for DH not supported, skipping"); } KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH", p); kpg.initialize(512); diff --git a/test/jdk/sun/security/pkcs11/KeyPairGenerator/TestDefaultDHPrivateExpSize.java b/test/jdk/sun/security/pkcs11/KeyPairGenerator/TestDefaultDHPrivateExpSize.java index cb93a96fdd2..3f19a59423b 100644 --- a/test/jdk/sun/security/pkcs11/KeyPairGenerator/TestDefaultDHPrivateExpSize.java +++ b/test/jdk/sun/security/pkcs11/KeyPairGenerator/TestDefaultDHPrivateExpSize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,12 +21,12 @@ * questions. */ -import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.Provider; -import java.security.PrivateKey; import javax.crypto.spec.DHParameterSpec; import javax.crypto.interfaces.DHPrivateKey; + +import jtreg.SkippedException; import sun.security.util.SecurityProviderConstants; import sun.security.provider.ParameterCache; @@ -47,8 +47,7 @@ public void main(Provider p) throws Exception { System.out.println("Testing " + p.getName()); if (p.getService("KeyPairGenerator", "DH") == null) { - System.out.println("Skip, no support for DH KeyPairGenerator"); - return; + throw new SkippedException("Skip, no support for DH KeyPairGenerator"); } KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH", p); diff --git a/test/jdk/sun/security/pkcs11/KeyStore/CertChainRemoval.java b/test/jdk/sun/security/pkcs11/KeyStore/CertChainRemoval.java index 0158da0da36..31efbccaeab 100644 --- a/test/jdk/sun/security/pkcs11/KeyStore/CertChainRemoval.java +++ b/test/jdk/sun/security/pkcs11/KeyStore/CertChainRemoval.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,15 +28,17 @@ * @run testng/othervm CertChainRemoval */ import jdk.test.lib.SecurityTools; -import java.io.*; +import java.io.File; +import java.io.FileInputStream; import java.nio.file.Path; -import java.util.*; import java.security.Key; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.Provider; import java.security.cert.Certificate; +import java.util.Arrays; +import java.util.Enumeration; import jtreg.SkippedException; import org.testng.SkipException; @@ -125,8 +127,7 @@ public void main(Provider p) throws Exception { p11ks.load(null, PKCS11KS.passwd); printKeyStore("Initial PKCS11 KeyStore: ", p11ks); } catch (Exception e) { - System.out.println("Skip test, due to " + e); - return; + throw new SkippedException("Skip test, due to " + e, e); } // get the necessary keys from the temp keystore diff --git a/test/jdk/sun/security/pkcs11/KeyStore/ClientAuth.java b/test/jdk/sun/security/pkcs11/KeyStore/ClientAuth.java index 1af1258d173..5d50015880d 100644 --- a/test/jdk/sun/security/pkcs11/KeyStore/ClientAuth.java +++ b/test/jdk/sun/security/pkcs11/KeyStore/ClientAuth.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -260,8 +260,7 @@ public void main(Provider p) throws Exception { try { javax.crypto.Cipher.getInstance("RSA/ECB/PKCS1Padding", p); } catch (GeneralSecurityException e) { - System.out.println("Not supported by provider, skipping"); - return; + throw new SkippedException("Not supported by provider, skipping"); } this.provider = p; diff --git a/test/jdk/sun/security/pkcs11/KeyStore/SecretKeysBasic.java b/test/jdk/sun/security/pkcs11/KeyStore/SecretKeysBasic.java index 4d876604c01..1ff80fcaf07 100644 --- a/test/jdk/sun/security/pkcs11/KeyStore/SecretKeysBasic.java +++ b/test/jdk/sun/security/pkcs11/KeyStore/SecretKeysBasic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, 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 @@ -116,11 +116,14 @@ private static boolean checkSecretKeyEntry(String alias, // A bug in NSS 3.12 (Mozilla bug 471665) causes AES key lengths // to be read incorrectly. Checking for improper 16 byte length // in key string. - if (isNSS(provider) && expected.getAlgorithm().equals("AES") && - (getNSSVersion() >= 3.12 && getNSSVersion() <= 3.122)) { - System.out.println("NSS 3.12 bug returns incorrect AES key "+ - "length breaking key storage. Aborting..."); - return true; + if (isNSS(provider) && expected.getAlgorithm().equals("AES")) { + Version version = getNSSVersion(); + if (version.major() == 3 && version.minor() == 12 + && version.patch() <= 2) { + System.out.println("NSS 3.12 bug returns incorrect AES key " + + "length breaking key storage. Aborting..."); + return true; + } } if (saveBeforeCheck) { @@ -168,7 +171,7 @@ private static void dumpKey(String info, SecretKey key) { private static void doTest() throws Exception { // Make sure both NSS libraries are the same version. if (isNSS(provider) && - (getLibsoftokn3Version() != getLibnss3Version())) { + (!getLibsoftokn3Version().equals(getLibnss3Version()))) { System.out.println("libsoftokn3 and libnss3 versions do not match. Aborting test..."); return; } diff --git a/test/jdk/sun/security/pkcs11/PKCS11Test.java b/test/jdk/sun/security/pkcs11/PKCS11Test.java index efae619314d..bbc8a760131 100644 --- a/test/jdk/sun/security/pkcs11/PKCS11Test.java +++ b/test/jdk/sun/security/pkcs11/PKCS11Test.java @@ -80,21 +80,21 @@ public abstract class PKCS11Test { // Version of the NSS artifact. This coincides with the version of // the NSS version - private static final String NSS_BUNDLE_VERSION = "3.107"; + private static final String NSS_BUNDLE_VERSION = "3.111"; private static final String NSSLIB = "jpg.tests.jdk.nsslib"; - static double nss_version = -1; + static Version nss_version = null; static ECCState nss_ecc_status = ECCState.Basic; // The NSS library we need to search for in getNSSLibDir() // Default is "libsoftokn3.so", listed as "softokn3" // The other is "libnss3.so", listed as "nss3". - static String nss_library = "softokn3"; + static String nss_library = System.getProperty("CUSTOM_P11_LIBRARY_NAME", "softokn3"); // NSS versions of each library. It is simpler to keep nss_version // for quick checking for generic testing than many if-else statements. - static double softoken3_version = -1; - static double nss3_version = -1; + static Version softoken3_version = null; + static Version nss3_version = null; static Provider pkcs11 = newPKCS11Provider(); private static String PKCS11_BASE; private static Map osMap; @@ -199,6 +199,17 @@ public static String getBase() throws Exception { if (PKCS11_BASE != null) { return PKCS11_BASE; } + String customBaseDir = System.getProperty("CUSTOM_P11_CONFIG_BASE_DIR"); + if (customBaseDir != null) { + File base = new File(customBaseDir); + if (!base.exists()) { + throw new RuntimeException( + "Directory specified by CUSTOM_P11_CONFIG_BASE_DIR does not exist: " + + base.getAbsolutePath()); + } + PKCS11_BASE = base.getAbsolutePath(); + return PKCS11_BASE; + } File cwd = new File(System.getProperty("test.src", ".")).getCanonicalFile(); while (true) { File file = new File(cwd, "TEST.ROOT"); @@ -258,13 +269,29 @@ private static String getOsId() { } static boolean isBadNSSVersion(Provider p) { - double nssVersion = getNSSVersion(); - if (isNSS(p) && nssVersion >= 3.11 && nssVersion < 3.12) { - System.out.println("NSS 3.11 has a DER issue that recent " + - "version do not, skipping"); - return true; + Version nssVersion = getNSSVersion(); + if (isNSS(p)) { + // bad version is just between [3.11,3.12) + return nssVersion.major == 3 && 11 == nssVersion.minor; + } else { + return false; } - return false; + } + + public record Version(int major, int minor, int patch) {} + + protected static Version parseVersionString(String version) { + String [] parts = version.split("\\."); + int major = Integer.parseInt(parts[0]); + int minor = 0; + int patch = 0; + if (parts.length >= 2) { + minor = Integer.parseInt(parts[1]); + } + if (parts.length >= 3) { + patch = Integer.parseInt(parts[2]); + } + return new Version(major, minor, patch); } protected static void safeReload(String lib) { @@ -293,26 +320,26 @@ public static boolean isNSS(Provider p) { return p.getName().equalsIgnoreCase("SUNPKCS11-NSS"); } - static double getNSSVersion() { - if (nss_version == -1) + static Version getNSSVersion() { + if (nss_version == null) getNSSInfo(); return nss_version; } static ECCState getNSSECC() { - if (nss_version == -1) + if (nss_version == null) getNSSInfo(); return nss_ecc_status; } - public static double getLibsoftokn3Version() { - if (softoken3_version == -1) + public static Version getLibsoftokn3Version() { + if (softoken3_version == null) return getNSSInfo("softokn3"); return softoken3_version; } - public static double getLibnss3Version() { - if (nss3_version == -1) + public static Version getLibnss3Version() { + if (nss3_version == null) return getNSSInfo("nss3"); return nss3_version; } @@ -327,7 +354,7 @@ static void getNSSInfo() { // $Header: NSS // Version: NSS // Here, stands for NSS version. - static double getNSSInfo(String library) { + static Version getNSSInfo(String library) { // look for two types of headers in NSS libraries String nssHeader1 = "$Header: NSS"; String nssHeader2 = "Version: NSS"; @@ -336,15 +363,15 @@ static double getNSSInfo(String library) { int i = 0; Path libfile = null; - if (library.compareTo("softokn3") == 0 && softoken3_version > -1) + if (library.compareTo("softokn3") == 0 && softoken3_version != null) return softoken3_version; - if (library.compareTo("nss3") == 0 && nss3_version > -1) + if (library.compareTo("nss3") == 0 && nss3_version != null) return nss3_version; try { libfile = getNSSLibPath(); if (libfile == null) { - return 0.0; + return parseVersionString("0.0"); } try (InputStream is = Files.newInputStream(libfile)) { byte[] data = new byte[1000]; @@ -380,7 +407,7 @@ static double getNSSInfo(String library) { if (!found) { System.out.println("lib" + library + " version not found, set to 0.0: " + libfile); - nss_version = 0.0; + nss_version = parseVersionString("0.0"); return nss_version; } @@ -393,26 +420,7 @@ static double getNSSInfo(String library) { version.append(c); } - // If a "dot dot" release, strip the extra dots for double parsing - String[] dot = version.toString().split("\\."); - if (dot.length > 2) { - version = new StringBuilder(dot[0] + "." + dot[1]); - for (int j = 2; dot.length > j; j++) { - version.append(dot[j]); - } - } - - // Convert to double for easier version value checking - try { - nss_version = Double.parseDouble(version.toString()); - } catch (NumberFormatException e) { - System.out.println("===== Content start ====="); - System.out.println(s); - System.out.println("===== Content end ====="); - System.out.println("Failed to parse lib" + library + - " version. Set to 0.0"); - e.printStackTrace(); - } + nss_version = parseVersionString(version.toString()); System.out.print("library: " + library + ", version: " + version + ". "); @@ -454,6 +462,40 @@ public static void testNSS(PKCS11Test test) throws Exception { System.out.println("testNSS: Completed"); } + /** + * Prepares the NSS configuration file hierarchy, then returns the + * path of the configuration file that should be used to configure + * the PKCS11 provider. + * + * By default, the contents of the directory + * "test/jdk/sun/security/pkcs11/nss" are copied to the jtreg + * scratch directory ("."), and "./nss/p11-nss.txt" is returned. + * + * The following system properties modify the default behavior: + * + * CUSTOM_P11_CONFIG_BASE_DIR: The path of a custom configuration + * file hierarchy; overrides the default, + * "test/jdk/sun/security/pkcs11". + * + * CUSTOM_P11_CONFIG_NAME: The name of a custom configuration + * file; overrides the default, "p11-nss.txt". Note that some + * test cases set CUSTOM_P11_CONFIG_NAME using -D in jtreg @run + * tags; for those test cases, setting this property on the + * top-level jtreg command line has no effect. + * + * CUSTOM_P11_CONFIG: The path of a custom configuration file; + * overrides the default "./nss/p11-nss.txt". This takes + * precedence over CUSTOM_P11_CONFIG_NAME. Tests that hard-code + * CUSTOM_P11_CONFIG_NAME in jtreg @run tags may not work + * correctly when CUSTOM_P11_CONFIG is set on the top-level jtreg + * command line. + * + * CUSTOM_DB_DIR: The path of a custom database directory; + * overrides the default, "./nss/db". + * + * CUSTOM_P11_LIBRARY_NAME: The name of a custom provider library + * to load; overrides the default, "softokn3". + */ public static String getNssConfig() throws Exception { String libdir = getNSSLibDir(); if (libdir == null) { diff --git a/test/jdk/sun/security/pkcs11/Provider/Absolute.java b/test/jdk/sun/security/pkcs11/Provider/Absolute.java index c298c076b30..07a934030db 100644 --- a/test/jdk/sun/security/pkcs11/Provider/Absolute.java +++ b/test/jdk/sun/security/pkcs11/Provider/Absolute.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, 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 @@ -28,6 +28,8 @@ * @summary load DLLs and launch executables using fully qualified path */ +import jtreg.SkippedException; + import java.security.InvalidParameterException; import java.security.Provider; @@ -40,12 +42,11 @@ public static void main(String[] args) throws Exception { try { Provider p = PKCS11Test.getSunPKCS11(config); if (p == null) { - System.out.println("Skipping test - no PKCS11 provider available"); + throw new SkippedException("Skipping test - no PKCS11 provider available"); } } catch (InvalidParameterException ipe) { Throwable ex = ipe.getCause(); - if (ex.getMessage().indexOf( - "Absolute path required for library value:") != -1) { + if (ex.getMessage().contains("Absolute path required for library value:")) { System.out.println("Test Passed: expected exception thrown"); } else { // rethrow diff --git a/test/jdk/sun/security/pkcs11/Provider/ConfigShortPath.java b/test/jdk/sun/security/pkcs11/Provider/ConfigShortPath.java index f229360f1af..120f289d211 100644 --- a/test/jdk/sun/security/pkcs11/Provider/ConfigShortPath.java +++ b/test/jdk/sun/security/pkcs11/Provider/ConfigShortPath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2020, 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 @@ -25,11 +25,17 @@ * @bug 6581254 6986789 7196009 8062170 * @summary Allow '~', '+', and quoted paths in config file * @author Valerie Peng + * @library /test/lib */ -import java.security.*; -import java.io.*; -import java.lang.reflect.*; +import jtreg.SkippedException; + +import java.io.File; +import java.io.IOException; +import java.security.InvalidParameterException; +import java.security.Provider; +import java.security.ProviderException; +import java.security.Security; public class ConfigShortPath { @@ -43,8 +49,7 @@ public class ConfigShortPath { public static void main(String[] args) throws Exception { Provider p = Security.getProvider("SunPKCS11"); if (p == null) { - System.out.println("Skipping test - no PKCS11 provider available"); - return; + throw new SkippedException("Skipping test - no PKCS11 provider available"); } String osInfo = System.getProperty("os.name", ""); @@ -65,7 +70,7 @@ public static void main(String[] args) throws Exception { if (cause.getClass().getName().equals ("sun.security.pkcs11.ConfigurationException")) { // Error occurred during parsing - if (cause.getMessage().indexOf("Unexpected") != -1) { + if (cause.getMessage().contains("Unexpected")) { throw (ProviderException) cause; } } diff --git a/test/jdk/sun/security/pkcs11/Provider/LoginISE.java b/test/jdk/sun/security/pkcs11/Provider/LoginISE.java index 5027770c5e6..d131a857216 100644 --- a/test/jdk/sun/security/pkcs11/Provider/LoginISE.java +++ b/test/jdk/sun/security/pkcs11/Provider/LoginISE.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 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 @@ -21,16 +21,22 @@ * questions. */ -import java.io.*; -import java.util.*; -import java.security.*; -import javax.security.auth.callback.*; +import jtreg.SkippedException; + +import java.io.IOException; +import java.security.AuthProvider; +import java.security.Provider; +import java.security.Security; +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.UnsupportedCallbackException; /** * @test * @bug 8130648 * @summary make sure IllegalStateException is thrown for uninitialized * SunPKCS11 provider instance + * @library /test/lib */ public class LoginISE { @@ -38,8 +44,7 @@ public static void main(String[] args) throws Exception { Provider p = Security.getProvider("SunPKCS11"); if (p == null) { - System.out.println("No un-initialized PKCS11 provider available; skip"); - return; + throw new SkippedException("No un-initialized PKCS11 provider available; skip"); } if (!(p instanceof AuthProvider)) { throw new RuntimeException("Error: expect AuthProvider!"); diff --git a/test/jdk/sun/security/pkcs11/Secmod/AddTrustedCert.java b/test/jdk/sun/security/pkcs11/Secmod/AddTrustedCert.java index 880adc954ea..7b4a5075da8 100644 --- a/test/jdk/sun/security/pkcs11/Secmod/AddTrustedCert.java +++ b/test/jdk/sun/security/pkcs11/Secmod/AddTrustedCert.java @@ -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 @@ -121,10 +121,10 @@ public static void main(String[] args) throws Exception { } private static boolean improperNSSVersion(Provider p) { - double nssVersion = getNSSVersion(); - if (p.getName().equalsIgnoreCase("SunPKCS11-NSSKeyStore") - && nssVersion >= 3.28 && nssVersion < 3.35) { - return true; + Version nssVersion = getNSSVersion(); + if (p.getName().equalsIgnoreCase("SunPKCS11-NSSKeyStore")) { + return nssVersion.major() == 3 && + (nssVersion.minor() >= 28 && nssVersion.minor() < 35); } return false; diff --git a/test/jdk/sun/security/pkcs11/SecretKeyFactory/TestGeneral.java b/test/jdk/sun/security/pkcs11/SecretKeyFactory/TestGeneral.java index bca594c66bd..e59d0b4a1ca 100644 --- a/test/jdk/sun/security/pkcs11/SecretKeyFactory/TestGeneral.java +++ b/test/jdk/sun/security/pkcs11/SecretKeyFactory/TestGeneral.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,10 +30,14 @@ * @run main/othervm TestGeneral */ +import jtreg.SkippedException; + import java.security.NoSuchAlgorithmException; import java.security.Provider; import java.security.SecureRandom; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import javax.crypto.SecretKeyFactory; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; @@ -57,8 +61,11 @@ private void test(String algorithm, SecretKey key, Provider p, try { skf = SecretKeyFactory.getInstance(algorithm, p); } catch (NoSuchAlgorithmException e) { - System.out.println("Not supported, skipping: " + e); - return; + throw new SkippedException("[algorithm: " + algorithm + + ", key: " + key.getAlgorithm() + "]" + + ", provider: " + p.getName() + "]" + + ", expectedTestResult: " + expected + "]" + + "Not supported, skipping: " + e); } try { SecretKey key2 = skf.translateKey(key); @@ -99,21 +106,31 @@ public void main(Provider p) throws Exception { SecretKey bf_128Key = new SecretKeySpec(rawBytes, 0, 16, "Blowfish"); SecretKey cc20Key = new SecretKeySpec(rawBytes, 0, 32, "ChaCha20"); - // fixed key length - test("AES", aes_128Key, p, TestResult.PASS); - test("AES", aes_256Key, p, TestResult.PASS); - test("AES", cc20Key, p, TestResult.FAIL); + List skippedList = new ArrayList<>(); + try { + // fixed key length + test("AES", aes_128Key, p, TestResult.PASS); + test("AES", aes_256Key, p, TestResult.PASS); + test("AES", cc20Key, p, TestResult.FAIL); - test("ChaCha20", aes_128Key, p, TestResult.FAIL); - test("ChaCha20", aes_256Key, p, TestResult.FAIL); - test("ChaCha20", cc20Key, p, TestResult.PASS); + test("ChaCha20", aes_128Key, p, TestResult.FAIL); + test("ChaCha20", aes_256Key, p, TestResult.FAIL); + test("ChaCha20", cc20Key, p, TestResult.PASS); - // variable key length - // Different PKCS11 impls may have different ranges - // of supported key sizes for variable-key-length - // algorithms. - test("Blowfish", aes_128Key, p, TestResult.FAIL); - test("Blowfish", cc20Key, p, TestResult.FAIL); - test("Blowfish", bf_128Key, p, TestResult.PASS); + // variable key length + // Different PKCS11 impls may have different ranges + // of supported key sizes for variable-key-length + // algorithms. + test("Blowfish", aes_128Key, p, TestResult.FAIL); + test("Blowfish", cc20Key, p, TestResult.FAIL); + test("Blowfish", bf_128Key, p, TestResult.PASS); + } catch (SkippedException skippedException){ + skippedException.printStackTrace(); + skippedList.add(skippedException.getMessage()); + } + + if (!skippedList.isEmpty()) { + throw new SkippedException("One or more tests skipped " + skippedList); + } } } diff --git a/test/jdk/sun/security/pkcs11/SecureRandom/Basic.java b/test/jdk/sun/security/pkcs11/SecureRandom/Basic.java index 091b906171c..1b3aed50d7c 100644 --- a/test/jdk/sun/security/pkcs11/SecureRandom/Basic.java +++ b/test/jdk/sun/security/pkcs11/SecureRandom/Basic.java @@ -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 @@ -32,6 +32,8 @@ * @run main/othervm Basic */ +import jtreg.SkippedException; + import java.security.NoSuchAlgorithmException; import java.security.Provider; import java.security.SecureRandom; @@ -44,9 +46,8 @@ public void main(Provider p) throws Exception { try { random = SecureRandom.getInstance("PKCS11"); } catch (NoSuchAlgorithmException e) { - System.out.println("Provider " + p + " does not support SecureRandom, skipping"); e.printStackTrace(); - return; + throw new SkippedException("Provider " + p + " does not support SecureRandom, skipping", e); } byte[] b = new byte[32]; random.nextBytes(b); diff --git a/test/jdk/sun/security/pkcs11/SecureRandom/TestDeserialization.java b/test/jdk/sun/security/pkcs11/SecureRandom/TestDeserialization.java index f54ae95f36d..b8d37e2a00e 100644 --- a/test/jdk/sun/security/pkcs11/SecureRandom/TestDeserialization.java +++ b/test/jdk/sun/security/pkcs11/SecureRandom/TestDeserialization.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2018, 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 @@ -29,6 +29,8 @@ * @modules jdk.crypto.cryptoki */ +import jtreg.SkippedException; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; @@ -43,18 +45,16 @@ public class TestDeserialization extends PKCS11Test { public void main(Provider p) throws Exception { // Skip this test for providers not found by java.security.Security if (Security.getProvider(p.getName()) != p) { - System.out.println("Skip test for provider " + p.getName()); - return; + throw new SkippedException("Skip test for provider " + p.getName()); } SecureRandom r; try { r = SecureRandom.getInstance("PKCS11", p); System.out.println("SecureRandom instance " + r); } catch (NoSuchAlgorithmException e) { - System.out.println("Provider " + p + - " does not support SecureRandom, skipping"); e.printStackTrace(); - return; + throw new SkippedException("Provider " + p + + " does not support SecureRandom, skipping"); } r.setSeed(System.currentTimeMillis()); byte[] buf = new byte[16]; diff --git a/test/jdk/sun/security/pkcs11/Signature/InitAgainPSS.java b/test/jdk/sun/security/pkcs11/Signature/InitAgainPSS.java index a2fa7294977..1acf6c250ef 100644 --- a/test/jdk/sun/security/pkcs11/Signature/InitAgainPSS.java +++ b/test/jdk/sun/security/pkcs11/Signature/InitAgainPSS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, 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 @@ -20,8 +20,15 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -import java.security.*; -import java.security.spec.*; +import jtreg.SkippedException; + +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.Signature; +import java.security.spec.MGF1ParameterSpec; +import java.security.spec.PSSParameterSpec; /** * @test @@ -46,9 +53,7 @@ private void test(String sigAlg, Provider p) throws Exception { try { s1 = Signature.getInstance(sigAlg, p); } catch (NoSuchAlgorithmException e) { - System.out.println("Skip testing " + sigAlg + - " due to no support"); - return; + throw new SkippedException("No support " + sigAlg); } byte[] msg = "hello".getBytes(); diff --git a/test/jdk/sun/security/pkcs11/Signature/KeyAndParamCheckForPSS.java b/test/jdk/sun/security/pkcs11/Signature/KeyAndParamCheckForPSS.java index adf7a08908e..45e26ec3930 100644 --- a/test/jdk/sun/security/pkcs11/Signature/KeyAndParamCheckForPSS.java +++ b/test/jdk/sun/security/pkcs11/Signature/KeyAndParamCheckForPSS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -20,9 +20,18 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -import java.security.*; -import java.security.interfaces.*; -import java.security.spec.*; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.Provider; +import java.security.PublicKey; +import java.security.Signature; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.MGF1ParameterSpec; +import java.security.spec.PSSParameterSpec; +import java.util.ArrayList; +import java.util.List; import jtreg.SkippedException; @@ -43,7 +52,7 @@ public static void main(String[] args) throws Exception { main(new KeyAndParamCheckForPSS(), args); } - private static boolean skipTest = true; + private static final List skippedAlgs = new ArrayList<>(); @Override public void main(Provider p) throws Exception { @@ -73,8 +82,8 @@ public void main(Provider p) throws Exception { runTest(p, 1040, "SHA3-512", "SHA3-384"); runTest(p, 1040, "SHA3-512", "SHA3-512"); - if (skipTest) { - throw new SkippedException("Test Skipped"); + if (!skippedAlgs.isEmpty()) { + throw new SkippedException("Tests Skipped: " + skippedAlgs); } } @@ -84,7 +93,17 @@ private static void runTest(Provider p, int keySize, String hashAlg, System.out.println("Testing " + hashAlg + " and MGF1" + mgfHashAlg); PSSUtil.AlgoSupport s = PSSUtil.isHashSupported(p, hashAlg, mgfHashAlg); if (s == PSSUtil.AlgoSupport.NO) { - System.out.println("=> Skip; no support"); + System.out.printf("=> Skip; no support keysize: %d, hash alg: %s, mgf Hash Alg: %s%n", + keySize, + hashAlg, + mgfHashAlg); + skippedAlgs.add( + String.format( + "[keysize: %s, hash alg: %s, mgf Hash Alg: %s]", + keySize, + hashAlg, + mgfHashAlg) + ); return; } @@ -108,7 +127,6 @@ private static void runTest(Provider p, int keySize, String hashAlg, sig.setParameter(paramsGood); sig.initSign(priv); // algorithm support confirmed - skipTest = false; } catch (Exception ex) { if (s == PSSUtil.AlgoSupport.MAYBE) { // confirmed to be unsupported; skip the rest of the test diff --git a/test/jdk/sun/security/pkcs11/Signature/SigInteropPSS.java b/test/jdk/sun/security/pkcs11/Signature/SigInteropPSS.java index d5b22400bff..c9efa8fdf76 100644 --- a/test/jdk/sun/security/pkcs11/Signature/SigInteropPSS.java +++ b/test/jdk/sun/security/pkcs11/Signature/SigInteropPSS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,9 +21,15 @@ * questions. */ -import java.security.*; -import java.security.spec.*; -import java.security.interfaces.*; +import jtreg.SkippedException; + +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.Signature; +import java.security.spec.MGF1ParameterSpec; +import java.security.spec.PSSParameterSpec; /* * @test @@ -53,9 +59,7 @@ public void main(Provider p) throws Exception { try { sigPkcs11 = Signature.getInstance("RSASSA-PSS", p); } catch (NoSuchAlgorithmException e) { - System.out.println("Skip testing RSASSA-PSS" + - " due to no support"); - return; + throw new SkippedException("No support for RSASSA-PSS"); } Signature sigSunRsaSign = diff --git a/test/jdk/sun/security/pkcs11/Signature/SigInteropPSS2.java b/test/jdk/sun/security/pkcs11/Signature/SigInteropPSS2.java index dfe56167848..ca0368841c5 100644 --- a/test/jdk/sun/security/pkcs11/Signature/SigInteropPSS2.java +++ b/test/jdk/sun/security/pkcs11/Signature/SigInteropPSS2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,9 +21,16 @@ * questions. */ -import java.security.*; -import java.security.spec.*; -import java.security.interfaces.*; +import jtreg.SkippedException; + +import java.security.AlgorithmParameters; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.Security; +import java.security.Signature; +import java.security.spec.PSSParameterSpec; /* * @test @@ -67,9 +74,7 @@ public void main(Provider p) throws Exception { try { sigPkcs11 = Signature.getInstance(digest + "withRSASSA-PSS", p); } catch (NoSuchAlgorithmException e) { - System.out.println("Skip testing " + digest + "withRSASSA-PSS" + - " due to no support"); - continue; + throw new SkippedException("No support for " + digest + "withRSASSA-PSS"); } runTest(sigPkcs11, sigSunRsaSign, kp); diff --git a/test/jdk/sun/security/pkcs11/Signature/SignatureTestPSS.java b/test/jdk/sun/security/pkcs11/Signature/SignatureTestPSS.java index c87554a51b1..778a7758562 100644 --- a/test/jdk/sun/security/pkcs11/Signature/SignatureTestPSS.java +++ b/test/jdk/sun/security/pkcs11/Signature/SignatureTestPSS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -20,29 +20,55 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -import java.security.*; -import java.security.interfaces.*; -import java.security.spec.*; -import java.util.stream.IntStream; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.KeyPair; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.Provider; +import java.security.PublicKey; +import java.security.Signature; +import java.security.SignatureException; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.MGF1ParameterSpec; +import java.security.spec.PSSParameterSpec; +import java.util.ArrayList; +import java.util.List; + import jtreg.SkippedException; /** - * @test + * @test id=sha * @bug 8080462 8226651 8242332 * @summary Generate a RSASSA-PSS signature and verify it using PKCS11 provider * @library /test/lib .. * @modules jdk.crypto.cryptoki * @run main SignatureTestPSS */ + +/** + * @test id=sha3 + * @bug 8080462 8226651 8242332 + * @summary Generate a RSASSA-PSS signature and verify it using PKCS11 provider + * @library /test/lib .. + * @modules jdk.crypto.cryptoki + * @run main SignatureTestPSS sha3 + */ public class SignatureTestPSS extends PKCS11Test { private static final String SIGALG = "RSASSA-PSS"; private static final int[] KEYSIZES = { 2048, 3072 }; - private static final String[] DIGESTS = { + + private static String[] DIGESTS = null; + + private static final String[] SHA_DIGESTS = { "SHA-224", "SHA-256", "SHA-384" , "SHA-512", - "SHA3-224", "SHA3-256", "SHA3-384" , "SHA3-512", }; + private static final String[] SHA3_DIGESTS = { + "SHA3-224", "SHA3-256", "SHA3-384" , "SHA3-512" + }; + private static final byte[] DATA = generateData(100); /** @@ -55,9 +81,12 @@ public class SignatureTestPSS extends PKCS11Test { */ private static final int UPDATE_TIMES_HUNDRED = 100; - private static boolean skipTest = true; + private static final List skippedAlgs = new ArrayList<>(); public static void main(String[] args) throws Exception { + DIGESTS = (args.length > 0 && "sha3".equals(args[0])) ? + SHA3_DIGESTS : SHA_DIGESTS; + main(new SignatureTestPSS(), args); } @@ -80,6 +109,8 @@ public void main(Provider p) throws Exception { PSSUtil.isHashSupported(p, hash, mgfHash); if (s == PSSUtil.AlgoSupport.NO) { System.out.println(" => Skip; no support"); + skippedAlgs.add("[Hash = " + hash + + ", MGF1 Hash = " + mgfHash + "]"); continue; } checkSignature(p, DATA, pubKey, privKey, hash, mgfHash, s); @@ -87,17 +118,15 @@ public void main(Provider p) throws Exception { }; } - // start testing below - if (skipTest) { - throw new SkippedException("Test Skipped"); + if (!skippedAlgs.isEmpty()) { + throw new SkippedException("Test Skipped :" + skippedAlgs); } } private static void checkSignature(Provider p, byte[] data, PublicKey pub, PrivateKey priv, String hash, String mgfHash, PSSUtil.AlgoSupport s) throws NoSuchAlgorithmException, InvalidKeyException, - SignatureException, NoSuchProviderException, - InvalidAlgorithmParameterException { + SignatureException { // only test RSASSA-PSS signature against the supplied hash/mgfHash // if they are supported; otherwise PKCS11 library will throw @@ -112,14 +141,27 @@ private static void checkSignature(Provider p, byte[] data, PublicKey pub, } catch (InvalidAlgorithmParameterException iape) { if (s == PSSUtil.AlgoSupport.MAYBE) { // confirmed to be unsupported; skip the rest of the test - System.out.println(" => Skip; no PSS support"); + System.out.printf(" => Skip; no PSS support public key: %s, private key: %s, " + + "hash: %s, mgf hash: %s, Algo Support: %s%n", + pub, + priv, + hash, + mgfHash, + s); + skippedAlgs.add(String.format( + "[public key: %s, private key: %s, " + + "hash: %s, mgf hash: %s, Algo Support: %s]", + pub, + priv, + hash, + mgfHash, + s) + ); return; } else { throw new RuntimeException("Unexpected Exception", iape); } } - // start testing below - skipTest = false; for (int i = 0; i < UPDATE_TIMES_HUNDRED; i++) { sig.update(data); diff --git a/test/jdk/sun/security/pkcs11/Signature/SignatureTestPSS2.java b/test/jdk/sun/security/pkcs11/Signature/SignatureTestPSS2.java index 516b17972e5..ac6c13523a2 100644 --- a/test/jdk/sun/security/pkcs11/Signature/SignatureTestPSS2.java +++ b/test/jdk/sun/security/pkcs11/Signature/SignatureTestPSS2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -20,13 +20,23 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -import java.security.*; -import java.security.interfaces.*; -import java.security.spec.*; +import jtreg.SkippedException; + +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.Provider; +import java.security.PublicKey; +import java.security.Signature; +import java.security.SignatureException; import java.util.stream.IntStream; /** - * @test + * @test id=sha * @bug 8244154 8242332 * @summary Generate a withRSASSA-PSS signature and verify it using * PKCS11 provider @@ -34,13 +44,28 @@ * @modules jdk.crypto.cryptoki * @run main SignatureTestPSS2 */ + +/** + * @test id=sha3 + * @bug 8244154 8242332 + * @summary Generate a withRSASSA-PSS signature and verify it using + * PKCS11 provider + * @library /test/lib .. + * @modules jdk.crypto.cryptoki + * @run main SignatureTestPSS2 sha3 + */ public class SignatureTestPSS2 extends PKCS11Test { // PKCS11 does not support RSASSA-PSS keys yet private static final String KEYALG = "RSA"; - private static final String[] SIGALGS = { + + private static String[] SIGALGS = null; + + private static final String[] SHA_SIGALGS = { "SHA224withRSASSA-PSS", "SHA256withRSASSA-PSS", - "SHA384withRSASSA-PSS", "SHA512withRSASSA-PSS", + "SHA384withRSASSA-PSS", "SHA512withRSASSA-PSS" + }; + private static final String[] SHA3_SIGALGS = { "SHA3-224withRSASSA-PSS", "SHA3-256withRSASSA-PSS", "SHA3-384withRSASSA-PSS", "SHA3-512withRSASSA-PSS" }; @@ -53,6 +78,8 @@ public class SignatureTestPSS2 extends PKCS11Test { private static final int UPDATE_TIMES = 2; public static void main(String[] args) throws Exception { + SIGALGS = (args.length > 0 && "sha3".equals(args[0])) ? SHA3_SIGALGS : SHA_SIGALGS; + main(new SignatureTestPSS2(), args); } @@ -63,9 +90,7 @@ public void main(Provider p) throws Exception { try { sig = Signature.getInstance(sa, p); } catch (NoSuchAlgorithmException e) { - System.out.println("Skip testing " + sa + - " due to no support"); - return; + throw new SkippedException("No support for " + sa); } for (int i : KEYSIZES) { runTest(sig, i); @@ -94,7 +119,7 @@ private static void test(Signature sig, PrivateKey privKey, SignatureException | NoSuchProviderException ex) { throw new RuntimeException(ex); } catch (InvalidAlgorithmParameterException ex2) { - System.out.println("Skip test due to " + ex2); + throw new SkippedException(ex2.toString()); } } diff --git a/test/jdk/sun/security/pkcs11/Signature/TestDSA.java b/test/jdk/sun/security/pkcs11/Signature/TestDSA.java index e7b937d6190..0a086bd2ed0 100644 --- a/test/jdk/sun/security/pkcs11/Signature/TestDSA.java +++ b/test/jdk/sun/security/pkcs11/Signature/TestDSA.java @@ -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 @@ -32,6 +32,8 @@ * @run main/othervm TestDSA */ +import jtreg.SkippedException; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.StringReader; @@ -122,8 +124,7 @@ public void main(Provider provider) throws Exception { System.out.println("Testing provider " + provider + "..."); if (provider.getService("Signature", "SHA1withDSA") == null) { - System.out.println("DSA not supported, skipping"); - return; + throw new SkippedException("DSA not supported"); } KeyFactory kf = KeyFactory.getInstance("DSA", provider); diff --git a/test/jdk/sun/security/pkcs11/Signature/TestDSAKeyLength.java b/test/jdk/sun/security/pkcs11/Signature/TestDSAKeyLength.java index a9b43a647a9..ffd7b9e3ee0 100644 --- a/test/jdk/sun/security/pkcs11/Signature/TestDSAKeyLength.java +++ b/test/jdk/sun/security/pkcs11/Signature/TestDSAKeyLength.java @@ -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 @@ -47,13 +47,15 @@ public static void main(String[] args) throws Exception { @Override protected boolean skipTest(Provider provider) { - double version = getNSSVersion(); - String[] versionStrs = Double.toString(version).split("\\."); - int major = Integer.parseInt(versionStrs[0]); - int minor = Integer.parseInt(versionStrs[1]); - if (isNSS(provider) && (version == 0.0 || (major >= 3 && minor >= 14))) { - System.out.println("Skip testing NSS " + version); - return true; + if (isNSS(provider)) { + Version version = getNSSVersion(); + if (version == null) { + return true; + } + if (version.major() >= 3 && version.minor() >= 14){ + System.out.println("Skip testing NSS " + version); + return true; + } } return false; diff --git a/test/jdk/sun/security/pkcs11/Signature/TestNONEwithRSA.java b/test/jdk/sun/security/pkcs11/Signature/TestNONEwithRSA.java new file mode 100644 index 00000000000..8274602c09f --- /dev/null +++ b/test/jdk/sun/security/pkcs11/Signature/TestNONEwithRSA.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.security.*; +import java.security.interfaces.*; +import java.security.spec.*; +import java.util.stream.IntStream; +import jtreg.SkippedException; + +/** + * @test + * @bug 8244336 + * @summary Test the NONEwithRSA signature refactoring for JCE layer + * algorithm restriction + * @library /test/lib .. + * @modules jdk.crypto.cryptoki + */ +public class TestNONEwithRSA extends PKCS11Test { + + private static final String SIGALG = "NONEwithRSA"; + + private static final int[] KEYSIZES = { 2048, 3072 }; + private static final byte[] DATA = generateData(100); + + public static void main(String[] args) throws Exception { + main(new TestNONEwithRSA(), args); + } + + @Override + public void main(Provider p) throws Exception { + try { + Signature.getInstance(SIGALG, p); + } catch (NoSuchAlgorithmException nsae) { + throw new SkippedException("Skip due to no support for " + SIGALG); + } + + for (int kSize : KEYSIZES) { + System.out.println("[KEYSIZE = " + kSize + "]"); + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", p); + kpg.initialize(kSize); + KeyPair kp = kpg.generateKeyPair(); + PrivateKey privKey = kp.getPrivate(); + PublicKey pubKey = kp.getPublic(); + checkSignature(p, DATA, pubKey, privKey); + } + } + + private static void checkSignature(Provider p, byte[] data, PublicKey pub, + PrivateKey priv) + throws NoSuchAlgorithmException, InvalidKeyException, + SignatureException, NoSuchProviderException, + InvalidAlgorithmParameterException { + + Signature sig = Signature.getInstance(SIGALG, p); + sig.initSign(priv); + + sig.update(data); + byte[] signedData = sig.sign(); + + // Make sure signature verifies with original data + sig.initVerify(pub); + sig.update(data); + if (!sig.verify(signedData)) { + throw new RuntimeException("Failed to verify signature"); + } + + // Make sure signature does NOT verify when the original data + // has changed + sig.initVerify(pub); + sig.update(data); + sig.update(data); + if (sig.verify(signedData)) { + throw new RuntimeException("Failed to detect bad signature"); + } + System.out.println(" => Passed"); + } +} diff --git a/test/jdk/sun/security/pkcs11/ec/TestECDH.java b/test/jdk/sun/security/pkcs11/ec/TestECDH.java index b6821b88372..2900656f626 100644 --- a/test/jdk/sun/security/pkcs11/ec/TestECDH.java +++ b/test/jdk/sun/security/pkcs11/ec/TestECDH.java @@ -111,6 +111,7 @@ protected boolean skipTest(Provider p) { * PKCS11Test.main will remove this provider if needed */ Providers.setAt(p, 1); + System.out.println("Testing provider " + p.getName()); if (false) { KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", p); diff --git a/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeChecksClient.java b/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeChecksClient.java index e2885e38779..851aa5af59c 100644 --- a/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeChecksClient.java +++ b/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeChecksClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8206929 8212885 + * @bug 8206929 8212885 8333857 * @summary ensure that client only resumes a session if certain properties * of the session are compatible with the new connection * @library /javax/net/ssl/templates @@ -47,6 +47,9 @@ import java.security.*; import java.net.*; import java.util.*; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; public class ResumeChecksClient extends SSLContextTemplate { enum TestMode { @@ -56,49 +59,60 @@ enum TestMode { CIPHER_SUITE, SIGNATURE_SCHEME } + static TestMode testMode; public static void main(String[] args) throws Exception { - new ResumeChecksClient(TestMode.valueOf(args[0])).run(); + testMode = TestMode.valueOf(args[0]); + new ResumeChecksClient().test(); } - private final TestMode testMode; - public ResumeChecksClient(TestMode mode) { - this.testMode = mode; - } - - private void run() throws Exception { - Server server = startServer(); - server.signal(); + private void test() throws Exception { + Server server = new Server(); SSLContext sslContext = createClientSSLContext(); - while (!server.started) { - Thread.yield(); - } - SSLSession firstSession = connect(sslContext, server.port, testMode, false); + HexFormat hex = HexFormat.of(); + long firstStartTime = System.currentTimeMillis(); + SSLSession firstSession = connect(sslContext, server.port, true); + System.err.println("firstStartTime = " + firstStartTime); + System.err.println("firstId = " + hex.formatHex(firstSession.getId())); + System.err.println("firstSession.getCreationTime() = " + + firstSession.getCreationTime()); - server.signal(); long secondStartTime = System.currentTimeMillis(); - Thread.sleep(10); - SSLSession secondSession = connect(sslContext, server.port, testMode, true); - - server.go = false; - server.signal(); + SSLSession secondSession = connect(sslContext, server.port, false); + System.err.println("secondStartTime = " + secondStartTime); + // Note: Ids will never match with TLS 1.3 due to spec + System.err.println("secondId = " + hex.formatHex(secondSession.getId())); + System.err.println("secondSession.getCreationTime() = " + + secondSession.getCreationTime()); switch (testMode) { case BASIC: // fail if session is not resumed - checkResumedSession(firstSession, secondSession); + try { + checkResumedSession(firstSession, secondSession); + } catch (Exception e) { + throw new AssertionError("secondSession did not resume: FAIL", + e); + } + System.out.println("secondSession used resumption: PASS"); break; case VERSION_2_TO_3: case VERSION_3_TO_2: case CIPHER_SUITE: case SIGNATURE_SCHEME: // fail if a new session is not created - if (secondSession.getCreationTime() <= secondStartTime) { - throw new RuntimeException("Existing session was used"); + try { + checkResumedSession(firstSession, secondSession); + System.err.println("firstSession = " + firstSession); + System.err.println("secondSession = " + secondSession); + throw new AssertionError("Second connection should not " + + "have resumed first session: FAIL"); + } catch (Exception e) { + System.out.println("secondSession didn't use resumption: PASS"); } break; default: - throw new RuntimeException("unknown mode: " + testMode); + throw new AssertionError("unknown mode: " + testMode); } } @@ -134,51 +148,29 @@ public boolean permits(Set primitives, } private static SSLSession connect(SSLContext sslContext, int port, - TestMode mode, boolean second) { + boolean first) { try { SSLSocket sock = (SSLSocket) sslContext.getSocketFactory().createSocket(); SSLParameters params = sock.getSSLParameters(); - switch (mode) { - case BASIC: - // do nothing to ensure resumption works - break; - case VERSION_2_TO_3: - if (second) { - params.setProtocols(new String[] {"TLSv1.3"}); - } else { - params.setProtocols(new String[] {"TLSv1.2"}); - } - break; - case VERSION_3_TO_2: - if (second) { - params.setProtocols(new String[] {"TLSv1.2"}); - } else { - params.setProtocols(new String[] {"TLSv1.3"}); - } - break; - case CIPHER_SUITE: - if (second) { - params.setCipherSuites( - new String[] {"TLS_AES_256_GCM_SHA384"}); - } else { - params.setCipherSuites( - new String[] {"TLS_AES_128_GCM_SHA256"}); - } - break; - case SIGNATURE_SCHEME: - AlgorithmConstraints constraints = - params.getAlgorithmConstraints(); - if (second) { - params.setAlgorithmConstraints(new NoSig("ecdsa")); - } else { - params.setAlgorithmConstraints(new NoSig("rsa")); - } - break; - default: - throw new RuntimeException("unknown mode: " + mode); + switch (testMode) { + case BASIC -> {} // do nothing + case VERSION_2_TO_3 -> params.setProtocols(new String[]{ + first ? "TLSv1.2" : "TLSv1.3"}); + case VERSION_3_TO_2 -> params.setProtocols(new String[]{ + first ? "TLSv1.3" : "TLSv1.2"}); + case CIPHER_SUITE -> params.setCipherSuites( + new String[]{ + first ? "TLS_AES_128_GCM_SHA256" : + "TLS_AES_256_GCM_SHA384"}); + case SIGNATURE_SCHEME -> + params.setAlgorithmConstraints(new NoSig( + first ? "rsa" : "ecdsa")); + default -> + throw new AssertionError("unknown mode: " + + testMode); } sock.setSSLParameters(params); sock.connect(new InetSocketAddress("localhost", port)); @@ -195,7 +187,7 @@ private static SSLSession connect(SSLContext sslContext, int port, return result; } catch (Exception ex) { // unexpected exception - throw new RuntimeException(ex); + throw new AssertionError(ex); } } @@ -274,65 +266,63 @@ private static void checkResumedSession(SSLSession initSession, } } - private static Server startServer() { - Server server = new Server(); - new Thread(server).start(); - return server; - } - - private static class Server extends SSLContextTemplate implements Runnable { - - public volatile boolean go = true; - private boolean signal = false; - public volatile int port = 0; - public volatile boolean started = false; + private static class Server extends SSLContextTemplate { + public int port; + private final SSLServerSocket ssock; + ExecutorService threadPool = Executors.newFixedThreadPool(1); + CountDownLatch serverLatch = new CountDownLatch(1); - private synchronized void waitForSignal() { - while (!signal) { - try { - wait(); - } catch (InterruptedException ex) { - // do nothing - } - } - signal = false; - } - public synchronized void signal() { - signal = true; - notify(); - } - - @Override - public void run() { + Server() { try { - SSLContext sc = createServerSSLContext(); ServerSocketFactory fac = sc.getServerSocketFactory(); - SSLServerSocket ssock = (SSLServerSocket) - fac.createServerSocket(0); - this.port = ssock.getLocalPort(); + ssock = (SSLServerSocket) fac.createServerSocket(0); + port = ssock.getLocalPort(); - waitForSignal(); - started = true; - while (go) { + // Thread to allow multiple clients to connect + new Thread(() -> { try { - System.out.println("Waiting for connection"); - Socket sock = ssock.accept(); - BufferedReader reader = new BufferedReader( - new InputStreamReader(sock.getInputStream())); - String line = reader.readLine(); - System.out.println("server read: " + line); - PrintWriter out = new PrintWriter( - new OutputStreamWriter(sock.getOutputStream())); - out.println(line); - out.flush(); - waitForSignal(); + System.err.println("Server starting to accept"); + serverLatch.countDown(); + do { + threadPool.submit( + new ServerThread((SSLSocket) ssock.accept())); + } while (true); } catch (Exception ex) { - ex.printStackTrace(); + throw new AssertionError("Server Down", ex); + } finally { + threadPool.close(); } + }).start(); + + } catch (Exception e) { + throw new AssertionError(e); + } + } + + static class ServerThread extends Thread { + SSLSocket sock; + + ServerThread(SSLSocket s) { + this.sock = s; + System.err.println("(Server) client connection on port " + + sock.getPort()); + } + + public void run() { + try { + BufferedReader reader = new BufferedReader( + new InputStreamReader(sock.getInputStream())); + String line = reader.readLine(); + System.out.println("server read: " + line); + PrintWriter out = new PrintWriter( + new OutputStreamWriter(sock.getOutputStream())); + out.println(line); + out.flush(); + out.close(); + } catch (Exception e) { + throw new AssertionError("Server thread error", e); } - } catch (Exception ex) { - throw new RuntimeException(ex); } } } diff --git a/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeChecksServer.java b/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeChecksServer.java index 341dfb11d77..d1918aab7f1 100644 --- a/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeChecksServer.java +++ b/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeChecksServer.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8206929 + * @bug 8206929 8333857 * @summary ensure that server only resumes a session if certain properties * of the session are compatible with the new connection * @modules java.base/sun.security.x509 @@ -49,6 +49,10 @@ import java.security.*; import java.net.*; import java.util.*; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + import sun.security.x509.X509CertImpl; public class ResumeChecksServer extends SSLContextTemplate { @@ -63,60 +67,56 @@ enum TestMode { LOCAL_CERTS } - public static void main(String[] args) throws Exception { - - new ResumeChecksServer(TestMode.valueOf(args[0])).run(); - } - private final TestMode testMode; + static CountDownLatch latch = new CountDownLatch(1); + static TestMode testMode; + static int serverPort; - public ResumeChecksServer(TestMode testMode) { - this.testMode = testMode; + public static void main(String[] args) throws Exception { + testMode = TestMode.valueOf(args[0]); + new ResumeChecksServer().test(); } - private void run() throws Exception { - SSLSession firstSession; - SSLSession secondSession = null; + private void test() throws Exception { + SSLSession firstSession, secondSession; + HexFormat hex = HexFormat.of(); - SSLContext sslContext = createServerSSLContext(); - ServerSocketFactory fac = sslContext.getServerSocketFactory(); - SSLServerSocket ssock = (SSLServerSocket) - fac.createServerSocket(0); + serverPort = new Server().port; + latch.await(); + Client c = new Client(serverPort); - Client client = startClient(ssock.getLocalPort()); + System.out.println("Waiting for connection"); + long firstStartTime = System.currentTimeMillis(); + firstSession = c.test(); - try { - firstSession = connect(client, ssock, testMode, null); - } catch (Exception ex) { - throw new RuntimeException(ex); - } + System.err.println("firstStartTime = " + firstStartTime); + System.err.println("firstId = " + hex.formatHex(firstSession.getId())); + System.err.println("firstSession.getCreationTime() = " + + firstSession.getCreationTime()); long secondStartTime = System.currentTimeMillis(); - Thread.sleep(10); - try { - secondSession = connect(client, ssock, testMode, firstSession); - } catch (SSLHandshakeException ex) { - // this is expected - } catch (Exception ex) { - throw new RuntimeException(ex); - } + secondSession = c.test(); - client.go = false; - client.signal(); + System.err.println("secondStartTime = " + secondStartTime); + // Note: Ids will never match with TLS 1.3 due to spec + System.err.println("secondId = " + hex.formatHex(secondSession.getId())); + System.err.println("secondSession.getCreationTime() = " + + secondSession.getCreationTime()); switch (testMode) { case BASIC: // fail if session is not resumed - if (secondSession.getCreationTime() > secondStartTime) { - throw new RuntimeException("Session was not reused"); + if (firstSession.getCreationTime() != + secondSession.getCreationTime()) { + throw new AssertionError("Session was not reused: FAIL"); } // Fail if session's certificates are not restored correctly. - if (!java.util.Arrays.equals( + if (!Arrays.equals( firstSession.getLocalCertificates(), secondSession.getLocalCertificates())) { - throw new RuntimeException("Certificates do not match"); + throw new AssertionError("Certificates do not match: FAIL"); } - + System.out.println("secondSession used resumption: PASS"); break; case CLIENT_AUTH: // throws an exception if the client is not authenticated @@ -128,24 +128,23 @@ private void run() throws Exception { case SIGNATURE_SCHEME: case LOCAL_CERTS: // fail if a new session is not created - if (secondSession.getCreationTime() <= secondStartTime) { - throw new RuntimeException("Existing session was used"); + if (secondSession.getCreationTime() < secondStartTime) { + throw new AssertionError("Existing session was used: FAIL"); } + System.out.println("secondSession not resumed: PASS"); break; default: - throw new RuntimeException("unknown mode: " + testMode); + throw new AssertionError("unknown mode: " + testMode); } } private static class NoSig implements AlgorithmConstraints { - private final String alg; NoSig(String alg) { this.alg = alg; } - private boolean test(String a) { return !a.toLowerCase().contains(alg.toLowerCase()); } @@ -153,176 +152,151 @@ private boolean test(String a) { public boolean permits(Set primitives, Key key) { return true; } + public boolean permits(Set primitives, String algorithm, AlgorithmParameters parameters) { - return test(algorithm); } + public boolean permits(Set primitives, String algorithm, Key key, AlgorithmParameters parameters) { - return test(algorithm); } } - private static SSLSession connect(Client client, SSLServerSocket ssock, - TestMode mode, SSLSession firstSession) throws Exception { - - boolean second = firstSession != null; + private static class Client extends SSLContextTemplate { + private final int port; + private final SSLContext sc; + public SSLSession session; - try { - client.signal(); - System.out.println("Waiting for connection"); - SSLSocket sock = (SSLSocket) ssock.accept(); - SSLParameters params = sock.getSSLParameters(); + Client(int port) throws Exception { + sc = createClientSSLContext(); + this.port = port; + } - switch (mode) { - case BASIC: - // do nothing to ensure resumption works - break; - case CLIENT_AUTH: - if (second) { - params.setNeedClientAuth(true); - } else { - params.setNeedClientAuth(false); - } - break; - case VERSION_2_TO_3: - if (second) { - params.setProtocols(new String[] {"TLSv1.3"}); - } else { - params.setProtocols(new String[] {"TLSv1.2"}); - } - break; - case VERSION_3_TO_2: - if (second) { - params.setProtocols(new String[] {"TLSv1.2"}); - } else { - params.setProtocols(new String[] {"TLSv1.3"}); - } - break; - case CIPHER_SUITE: - if (second) { - params.setCipherSuites( - new String[] {"TLS_AES_128_GCM_SHA256"}); - } else { - params.setCipherSuites( - new String[] {"TLS_AES_256_GCM_SHA384"}); - } - break; - case SIGNATURE_SCHEME: - params.setNeedClientAuth(true); - AlgorithmConstraints constraints = - params.getAlgorithmConstraints(); - if (second) { - params.setAlgorithmConstraints( - new NoSig("ecdsa_secp384r1_sha384")); - } else { - params.setAlgorithmConstraints( - new NoSig("ecdsa_secp521r1_sha512")); - } - break; - case LOCAL_CERTS: - if (second) { - // Add first session's certificate signature - // algorithm to constraints so local certificates - // can't be restored from the session ticket. - params.setAlgorithmConstraints( - new NoSig(X509CertImpl.toImpl((X509CertImpl) - firstSession.getLocalCertificates()[0]) - .getSigAlgName())); + public SSLSession test() throws Exception { + SSLSocket sock = null; + latch.await(); + do { + try { + sock = (SSLSocket) sc.getSocketFactory().createSocket(); + } catch (IOException e) { + // If the server never starts, test will time out. + System.err.println("client trying again to connect"); + Thread.sleep(500); } - break; - default: - throw new RuntimeException("unknown mode: " + mode); - } - sock.setSSLParameters(params); - BufferedReader reader = new BufferedReader( - new InputStreamReader(sock.getInputStream())); - String line = reader.readLine(); - System.out.println("server read: " + line); + } while (sock == null); + sock.connect(new InetSocketAddress("localhost", port)); PrintWriter out = new PrintWriter( new OutputStreamWriter(sock.getOutputStream())); - out.println(line); + out.println("message"); out.flush(); + BufferedReader reader = new BufferedReader( + new InputStreamReader(sock.getInputStream())); + String inMsg = reader.readLine(); + System.out.println("Client received: " + inMsg); out.close(); - SSLSession result = sock.getSession(); + session = sock.getSession(); sock.close(); - return result; - } catch (SSLHandshakeException ex) { - if (!second) { - throw ex; - } + return session; } - return null; - } - - private static Client startClient(int port) { - Client client = new Client(port); - new Thread(client).start(); - return client; } - private static class Client extends SSLContextTemplate implements Runnable { - - public volatile boolean go = true; - private boolean signal = false; - private final int port; - - Client(int port) { - this.port = port; - } - - private synchronized void waitForSignal() { - while (!signal) { + // The server will only have two connections each tests + private static class Server extends SSLContextTemplate { + public int port; + ExecutorService threadPool = Executors.newFixedThreadPool(1); + // Stores the certs from the first connection in mode LOCAL_CERTS + static X509CertImpl localCerts; + // first connection to the server + static boolean first = true; + + Server() throws Exception { + SSLContext sc = createServerSSLContext(); + ServerSocketFactory fac = sc.getServerSocketFactory(); + SSLServerSocket ssock = (SSLServerSocket) fac.createServerSocket(0); + port = ssock.getLocalPort(); + + // Thread to allow multiple clients to connect + new Thread(() -> { try { - wait(); - } catch (InterruptedException ex) { - // do nothing + System.err.println("Server starting to accept"); + latch.countDown(); + do { + threadPool.submit(new ServerThread(ssock.accept())); + } while (true); + } catch (Exception ex) { + throw new AssertionError("Server Down", ex); + } finally { + threadPool.close(); } - } - signal = false; - - try { - Thread.sleep(1000); - } catch (InterruptedException ex) { - // do nothing - } - } - public synchronized void signal() { - signal = true; - notify(); + }).start(); } - public void run() { - try { + static class ServerThread implements Runnable { + final SSLSocket sock; - SSLContext sc = createClientSSLContext(); + ServerThread(Socket s) { + this.sock = (SSLSocket) s; + System.err.println("(Server) client connection on port " + + sock.getPort()); + } - waitForSignal(); - while (go) { - try { - SSLSocket sock = (SSLSocket) - sc.getSocketFactory().createSocket(); - sock.connect(new InetSocketAddress("localhost", port)); - PrintWriter out = new PrintWriter( - new OutputStreamWriter(sock.getOutputStream())); - out.println("message"); - out.flush(); - BufferedReader reader = new BufferedReader( - new InputStreamReader(sock.getInputStream())); - String inMsg = reader.readLine(); - System.out.println("Client received: " + inMsg); - out.close(); - sock.close(); - waitForSignal(); - } catch (Exception ex) { - ex.printStackTrace(); + public void run() { + try { + SSLParameters params = sock.getSSLParameters(); + switch (testMode) { + case BASIC -> {} // do nothing + case CLIENT_AUTH -> params.setNeedClientAuth(!first); + case VERSION_2_TO_3 -> params.setProtocols(new String[]{ + first ? "TLSv1.2" : "TLSv1.3"}); + case VERSION_3_TO_2 -> params.setProtocols(new String[]{ + first ? "TLSv1.3" : "TLSv1.2"}); + case CIPHER_SUITE -> params.setCipherSuites( + new String[]{ + first ? "TLS_AES_256_GCM_SHA384" : + "TLS_AES_128_GCM_SHA256"}); + case SIGNATURE_SCHEME -> { + params.setNeedClientAuth(true); + params.setAlgorithmConstraints(new NoSig( + first ? "ecdsa_secp521r1_sha512" : + "ecdsa_secp384r1_sha384")); + } + case LOCAL_CERTS -> { + if (!first) { + // Add first session's certificate signature + // algorithm to constraints so local certificates + // can't be restored from the session ticket. + params.setAlgorithmConstraints( + new NoSig(X509CertImpl.toImpl(localCerts) + .getSigAlgName())); + } + } + default -> + throw new AssertionError("Server: " + + "unknown mode: " + testMode); + } + sock.setSSLParameters(params); + BufferedReader reader = new BufferedReader( + new InputStreamReader(sock.getInputStream())); + String line = reader.readLine(); + System.err.println("server read: " + line); + PrintWriter out = new PrintWriter( + new OutputStreamWriter(sock.getOutputStream())); + out.println(line); + out.flush(); + out.close(); + SSLSession session = sock.getSession(); + if (testMode == TestMode.LOCAL_CERTS && first) { + localCerts = (X509CertImpl) session. + getLocalCertificates()[0]; } + first = false; + System.err.println("server socket closed: " + session); + } catch (Exception e) { + throw new AssertionError("Server error", e); } - } catch (Exception ex) { - throw new RuntimeException(ex); } } } -} +} \ No newline at end of file diff --git a/test/jdk/sun/security/ssl/SSLSocketImpl/ReuseAddr.java b/test/jdk/sun/security/ssl/SSLSocketImpl/ReuseAddr.java index f7e677bbbd0..68761f10c59 100644 --- a/test/jdk/sun/security/ssl/SSLSocketImpl/ReuseAddr.java +++ b/test/jdk/sun/security/ssl/SSLSocketImpl/ReuseAddr.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, 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 @@ -38,7 +38,7 @@ public class ReuseAddr extends SSLSocketTemplate { - private static final int MAX_ATTEMPTS = 3; + private static final int MAX_ATTEMPTS = 15; @Override protected void doServerSide() throws Exception { @@ -65,6 +65,7 @@ public static void main(String[] args) throws Exception { System.err.println(msg); throw new AssertionError("Failed to reuse address: " + msg, x); } else { + Thread.sleep(100*i); System.out.println("Retrying..."); } } diff --git a/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java b/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java index 598c0fe62af..43bc40fabf2 100644 --- a/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java +++ b/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. - * Copyright (C) 2021, 2024 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, 2024, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java b/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java index 2ad48f59e83..034af3ac7c5 100644 --- a/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java +++ b/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Entrust.java b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Entrust.java index 809674e8f20..0e7617d1b9c 100644 --- a/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Entrust.java +++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Entrust.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -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 @@ public static void main(String[] args) throws Exception { }; Date notBefore = distrust.getNotBefore(DISTRUST_DATE); - distrust.testCertificateChain(certPath, notBefore, tms, rootsToTest); + distrust.testCertificateChain(CERT_PATH, notBefore, tms, ROOTS_TO_TEST); } } diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustcommercialca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustcommercialca-chain.pem deleted file mode 100644 index 76aa6d14338..00000000000 --- a/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustcommercialca-chain.pem +++ /dev/null @@ -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 --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustnetworkingca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustnetworkingca-chain.pem deleted file mode 100644 index 7384d31152e..00000000000 --- a/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustnetworkingca-chain.pem +++ /dev/null @@ -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 --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustpremiumca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustpremiumca-chain.pem deleted file mode 100644 index 6f108bc1229..00000000000 --- a/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustpremiumca-chain.pem +++ /dev/null @@ -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 --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustpremiumeccca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustpremiumeccca-chain.pem deleted file mode 100644 index 37b1b787084..00000000000 --- a/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustpremiumeccca-chain.pem +++ /dev/null @@ -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 --git a/test/jdk/sun/security/tools/jarsigner/DefaultOptions.java b/test/jdk/sun/security/tools/jarsigner/DefaultOptions.java index 72756de6f8b..fe8adfb8962 100644 --- a/test/jdk/sun/security/tools/jarsigner/DefaultOptions.java +++ b/test/jdk/sun/security/tools/jarsigner/DefaultOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,10 @@ public static void main(String[] args) throws Throwable { keytool("-genkeypair -dname CN=CA -alias ca -keyalg rsa -ext bc:c") .shouldHaveExitValue(0); keytool("-alias a -certreq -file a.req"); - keytool("-alias ca -gencert -infile a.req -outfile a.cert"); + + // The start date is set to -1M to prevent the certificate not yet + // valid during fast enough execution. + keytool("-alias ca -gencert -infile a.req -outfile a.cert -startdate -1M"); keytool("-alias a -import -file a.cert").shouldHaveExitValue(0); Files.write(Path.of("js.conf"), List.of( diff --git a/test/jdk/sun/security/tools/jarsigner/EC.java b/test/jdk/sun/security/tools/jarsigner/EC.java index 848dc8bf843..1b41c48e234 100644 --- a/test/jdk/sun/security/tools/jarsigner/EC.java +++ b/test/jdk/sun/security/tools/jarsigner/EC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ * @bug 6870812 * @summary enhance security tools to use ECC algorithm * @library /test/lib + * @run main/timeout=300 EC */ import jdk.test.lib.SecurityTools; diff --git a/test/jdk/sun/security/tools/jarsigner/VerifyJarEntryName.java b/test/jdk/sun/security/tools/jarsigner/VerifyJarEntryName.java index f5589484f3d..e2554ee0f91 100644 --- a/test/jdk/sun/security/tools/jarsigner/VerifyJarEntryName.java +++ b/test/jdk/sun/security/tools/jarsigner/VerifyJarEntryName.java @@ -38,12 +38,13 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Arrays; import java.util.jar.JarFile; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import jdk.test.lib.SecurityTools; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; public class VerifyJarEntryName { @@ -85,7 +86,7 @@ void cleanup() throws Exception { */ @Test void verifyManifestEntryName() throws Exception { - modifyJarEntryName(ORIGINAL_JAR, MODIFIED_JAR, "MANIFEST.MF"); + modifyJarEntryName(ORIGINAL_JAR, MODIFIED_JAR, "META-INF/MANIFEST.MF"); SecurityTools.jarsigner("-verify -verbose " + MODIFIED_JAR) .shouldContain("This JAR file contains internal " + "inconsistencies that may result in different " + @@ -95,6 +96,22 @@ void verifyManifestEntryName() throws Exception { .shouldHaveExitValue(0); } + /* + * Modify a single byte in signature filename in LOC, and + * validate that jarsigner -verify emits a warning message. + */ + @Test + void verifySignatureEntryName() throws Exception { + modifyJarEntryName(ORIGINAL_JAR, MODIFIED_JAR, "META-INF/MYKEY.SF"); + SecurityTools.jarsigner("-verify -verbose " + MODIFIED_JAR) + .shouldContain("This JAR file contains internal " + + "inconsistencies that may result in different " + + "contents when reading via JarFile and JarInputStream:") + .shouldContain("- Entry XETA-INF/MYKEY.SF is present when reading " + + "via JarInputStream but missing when reading via JarFile") + .shouldHaveExitValue(0); + } + /* * Validate that jarsigner -verify on a valid JAR works without * emitting warnings about internal inconsistencies. @@ -111,9 +128,14 @@ void verifyOriginalJar() throws Exception { private void modifyJarEntryName(Path origJar, Path modifiedJar, String entryName) throws Exception { byte[] jarBytes = Files.readAllBytes(origJar); - var jarString = new String(jarBytes, StandardCharsets.UTF_8); - var pos = jarString.indexOf(entryName); - assertTrue(pos != -1, entryName + " is not present in the JAR"); + byte[] entryNameBytes = entryName.getBytes(StandardCharsets.UTF_8); + int pos = 0; + try { + while (!Arrays.equals(jarBytes, pos, pos + entryNameBytes.length, + entryNameBytes, 0, entryNameBytes.length)) pos++; + } catch (ArrayIndexOutOfBoundsException ignore) { + fail(entryName + " is not present in the JAR"); + } jarBytes[pos] = 'X'; Files.write(modifiedJar, jarBytes); } diff --git a/test/jdk/sun/security/tools/keytool/EchoPassword.java b/test/jdk/sun/security/tools/keytool/EchoPassword.java new file mode 100644 index 00000000000..db1a878ce36 --- /dev/null +++ b/test/jdk/sun/security/tools/keytool/EchoPassword.java @@ -0,0 +1,182 @@ +/* + * 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 8354469 + * @summary keytool password does not echo in multiple cases + * @library /java/awt/regtesthelpers + * @modules java.base/jdk.internal.util + * @build PassFailJFrame + * @run main/manual/othervm EchoPassword + */ + +import jdk.internal.util.OperatingSystem; + +import javax.swing.JEditorPane; +import javax.swing.JLabel; +import javax.swing.event.HyperlinkEvent; + +import java.awt.Toolkit; +import java.awt.datatransfer.StringSelection; +import java.io.File; +import java.nio.file.Path; + +public class EchoPassword { + + static JLabel label; + + public static void main(String[] args) throws Exception { + + var ks1 = "\"" + Path.of("8354469.ks1").toAbsolutePath() + "\""; + var ks2 = "\"" + Path.of("8354469.ks2").toAbsolutePath() + "\""; + var ks3 = "\"" + Path.of("8354469.ks3").toAbsolutePath() + "\""; + + final String keytool = "\"" + System.getProperty("java.home") + + File.separator + "bin" + File.separator + "keytool\""; + final String nonASCII = "äöäöäöäö"; + + final String[][] commands = { + // Input password from real Console + {"First command", keytool + " -keystore " + ks1 + + " -genkeypair -keyalg ec -dname cn=a -alias first"}, + // Input password from limited Console (when stdout is redirected) + {"Second command", keytool + " -keystore " + ks2 + + " -genkeypair -keyalg ec -dname cn=b -alias second | sort"}, + // Input password from System.in stream + {"Third command", "echo changeit| " + keytool + " -keystore " + ks1 + + " -genkeypair -keyalg ec -dname cn=c -alias third"}, + // Ensure limited Console does not write a newline to System.out + {"Fourth command", keytool + " -keystore " + ks1 + + " -exportcert -alias first | " + + keytool + " -printcert -rfc"}, + // Non-ASCII password from System.in + {"Fifth command", "(" + // Solution 2 of https://stackoverflow.com/a/29747723 + + (OperatingSystem.isWindows() + ? ("echo " + nonASCII + "^&echo " + nonASCII + "^&rem.") + : ("echo " + nonASCII + "; echo " + nonASCII)) + + ") | " + keytool + " -keystore " + ks3 + + " -genkeypair -alias a -keyalg ec -dname cn=a"}, + // Non-ASCII password from Console + {"Sixth command", keytool + " -keystore " + ks3 + + " -exportcert -alias a -rfc"}, + {"The password", nonASCII} + }; + + final String message = String.format(""" + Open a terminal or Windows Command Prompt window, perform + the following steps, and record the final result. Each time you + click a link to copy something, make sure the status line at the + bottom shows the link has been successfully clicked. +

    Part I: Password Echoing Tests

    +
      +
    1. Click Copy First Command to copy the + following command into the system clipboard. Paste it into the + terminal window and execute the command. +

      + %s +

      + When prompted, enter "changeit" and press Enter. When prompted + again, enter "changeit" again and press Enter. Verify that the + two password prompts show up on different lines, both + passwords are hidden, and a key pair is generated successfully. + +

    2. Click Copy Second Command to copy the + following command into the system clipboard. Paste it into the + terminal window and execute the command. +

      + %s +

      + When prompted, enter "changeit" and press Enter. When prompted + again, enter "changeit" again and press Enter. Verify that the + two password prompts show up on different lines, both + passwords are hidden, and a key pair is generated successfully. + +

    3. Click Copy Third Command to copy the + following command into the system clipboard. Paste it into the + terminal window and execute the command. +

      + %s +

      + You will see a prompt but you don't need to enter anything. + Verify that the password "changeit" is not shown in the command + output and a key pair is generated successfully. + +

    4. Click Copy Fourth Command to copy the + following command into the system clipboard. Paste it into the + terminal window and execute the command. +

      + %s +

      + When prompted, enter "changeit" and press Enter. Verify that the + password is hidden and a PEM certificate is correctly shown. +

    +

    Part II: Interoperability on Non-ASCII Passwords

    +
      +
    1. Click Copy Fifth Command to copy the + following command into the system clipboard. Paste it into the + terminal window and execute the command. +

      + %s +

      + Verify that a key pair is generated successfully. + +

    2. Click Copy Sixth Command to copy the + following command into the system clipboard. Paste it into the + terminal window and execute the command. +

      + %s +

      + When prompted, click Copy Password to copy the + password. Paste it into the terminal window and press Enter. + Verify that the password is hidden and a PEM certificate is + correctly shown. +

    + Press "pass" if the behavior matches expectations; + otherwise, press "fail". + """, commands[0][1], commands[1][1], commands[2][1], commands[3][1], + commands[4][1], commands[5][1], commands[6][1]); + + PassFailJFrame.builder() + .instructions(message) + .rows(40).columns(100) + .hyperlinkListener(e -> { + if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + int pos = Integer.parseInt(e.getDescription().substring(1)); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents( + new StringSelection(commands[pos][1]), null); + label.setText(commands[pos][0] + " copied"); + if (e.getSource() instanceof JEditorPane ep) { + ep.getCaret().setVisible(false); + } + } + }) + .splitUIBottom(() -> { + label = new JLabel("Status"); + return label; + }) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/sun/security/tools/keytool/SetInPassword.java b/test/jdk/sun/security/tools/keytool/SetInPassword.java new file mode 100644 index 00000000000..ba6f06f898f --- /dev/null +++ b/test/jdk/sun/security/tools/keytool/SetInPassword.java @@ -0,0 +1,44 @@ +/* + * 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 8354469 + * @summary ensure password can be read from user's System.in + * @library /test/lib + * @modules java.base/sun.security.tools.keytool + */ + +import jdk.test.lib.SecurityTools; + +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; + +public class SetInPassword { + public static void main(String[] args) throws Exception { + SecurityTools.keytool("-keystore ks -storepass changeit -genkeypair -alias a -dname CN=A -keyalg EC") + .shouldHaveExitValue(0); + System.setIn(new ByteArrayInputStream("changeit".getBytes(StandardCharsets.UTF_8))); + sun.security.tools.keytool.Main.main("-keystore ks -alias a -certreq".split(" ")); + } +} diff --git a/test/jdk/sun/security/tools/keytool/i18n.java b/test/jdk/sun/security/tools/keytool/i18n.java index 6eac0239eee..030735e966c 100644 --- a/test/jdk/sun/security/tools/keytool/i18n.java +++ b/test/jdk/sun/security/tools/keytool/i18n.java @@ -28,7 +28,7 @@ * @author charlie lai * @modules java.base/sun.security.tools.keytool * @library /test/lib - * @run main/manual/othervm -Duser.language=en i18n + * @run main/manual/othervm -Duser.language=en -Duser.country=USA i18n */ /* @@ -38,7 +38,7 @@ * @author charlie lai * @modules java.base/sun.security.tools.keytool * @library /test/lib - * @run main/manual/othervm -Duser.language=de i18n + * @run main/manual/othervm -Duser.language=de -Duser.country=DE i18n */ /* @@ -48,7 +48,7 @@ * @author charlie lai * @modules java.base/sun.security.tools.keytool * @library /test/lib - * @run main/manual/othervm -Duser.language=ja i18n + * @run main/manual/othervm -Duser.language=ja -Duser.country=JP i18n */ /* @@ -63,11 +63,21 @@ import jdk.test.lib.UIBuilder; -import javax.swing.*; +import javax.swing.JDialog; +import javax.swing.SwingUtilities; +import javax.swing.JTextArea; +import javax.swing.JButton; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JFrame; +import java.awt.FlowLayout; +import java.awt.BorderLayout; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.util.Locale; +import static javax.swing.BorderFactory.createEmptyBorder; + public class i18n { private static final String[][] TABLE = new String[][]{ {"-help", "All the output in this test should be in ${LANG}. " @@ -234,11 +244,12 @@ public class i18n { "Output in ${LANG}. Check keytool error: java.lang" + ".IllegalArgumentException: if -protected is " + "specified, then -storepass, -keypass, and -new " - + "must not be specified."}, + + "must not be specified."} }; private static String TEST_SRC = System.getProperty("test.src"); private static int TIMEOUT_MS = 120000; private volatile boolean failed = false; + private volatile String failureReason = ""; private volatile boolean aborted = false; private Thread currentThread = null; @@ -330,6 +341,7 @@ public boolean validate(String command, String instruction, String message) { if (failed) { System.out.println(command + ": TEST FAILED"); + System.out.println("REASON: " + failureReason); System.out.println(message); } else { System.out.println(command + ": TEST PASSED"); @@ -348,6 +360,7 @@ public void pass() { public void fail() { failed = true; + failureReason = requestFailDescription(); currentThread.interrupt(); } @@ -355,4 +368,33 @@ public void abort() { aborted = true; currentThread.interrupt(); } + + /** + * Opens a prompt to enter a failure reason to be filled by the tester + */ + public static String requestFailDescription() { + + final JDialog dialogWindow = new JDialog(new JFrame(), "Failure Description", true); + final JTextArea reasonTextArea = new JTextArea(5, 20); + + final JButton okButton = new JButton("OK"); + okButton.addActionListener(_ -> dialogWindow.setVisible(false)); + + final JPanel okayBtnPanel = new JPanel( + new FlowLayout(FlowLayout.CENTER, 4, 0)); + okayBtnPanel.setBorder(createEmptyBorder(4, 0, 0, 0)); + okayBtnPanel.add(okButton); + + final JPanel mainPanel = new JPanel(new BorderLayout()); + mainPanel.add(new JScrollPane(reasonTextArea), BorderLayout.CENTER); + mainPanel.add(okayBtnPanel, BorderLayout.SOUTH); + + dialogWindow.add(mainPanel); + dialogWindow.pack(); + dialogWindow.setVisible(true); + + dialogWindow.dispose(); + + return reasonTextArea.getText(); + } } diff --git a/test/jdk/sun/security/util/AlgorithmConstraints/InvalidCryptoDisabledAlgos.java b/test/jdk/sun/security/util/AlgorithmConstraints/InvalidCryptoDisabledAlgos.java new file mode 100644 index 00000000000..bc59c85bec1 --- /dev/null +++ b/test/jdk/sun/security/util/AlgorithmConstraints/InvalidCryptoDisabledAlgos.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8244336 + * @modules java.base/sun.security.util + * @summary Check that invalid property values for + * "jdk.crypto.disabledAlgorithms" are rejected + * @run main/othervm InvalidCryptoDisabledAlgos "*" + * @run main/othervm InvalidCryptoDisabledAlgos "." + * @run main/othervm InvalidCryptoDisabledAlgos ".AES" + * @run main/othervm InvalidCryptoDisabledAlgos "Cipher." + * @run main/othervm InvalidCryptoDisabledAlgos "A.B" + * @run main/othervm InvalidCryptoDisabledAlgos "KeyStore.MY,." + * @run main/othervm InvalidCryptoDisabledAlgos "KeyStore.MY,.AES" + * @run main/othervm InvalidCryptoDisabledAlgos "KeyStore.MY,Cipher." + * @run main/othervm InvalidCryptoDisabledAlgos "KeyStore.MY,A.B" + */ +import java.security.Security; +import sun.security.util.CryptoAlgorithmConstraints; + +public class InvalidCryptoDisabledAlgos { + + public static void main(String[] args) throws Exception { + System.out.println("Invalid Property Value = " + args[0]); + Security.setProperty("jdk.crypto.disabledAlgorithms", args[0]); + try { + // Trigger the check to parse and validate property value + CryptoAlgorithmConstraints.permits("x", "y"); + throw new AssertionError( + "CryptoAlgorithmConstraints.permits() did not generate expected exception"); + } catch (Throwable t) { + if (!(t instanceof ExceptionInInitializerError) + || !(t.getCause() instanceof IllegalArgumentException)) { + // unexpected exception, propagate it + throw t; + } + // got expected + System.out.println("Received expected exception: " + t); + } + } +} diff --git a/test/jdk/sun/security/util/Debug/DebugOptions.java b/test/jdk/sun/security/util/Debug/DebugOptions.java index 5fa02af5112..72d8b3606bc 100644 --- a/test/jdk/sun/security/util/Debug/DebugOptions.java +++ b/test/jdk/sun/security/util/Debug/DebugOptions.java @@ -29,16 +29,20 @@ * @run junit DebugOptions */ -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - import java.security.KeyStore; import java.security.Security; -import java.util.stream.Stream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class DebugOptions { @@ -47,54 +51,133 @@ public class DebugOptions { "properties\\[.*\\|main|" + DATE_REGEX + ".*\\]:"; static final String EXPECTED_PROP_KEYSTORE_REGEX = "properties\\[.*\\|main|" + DATE_REGEX + - ".*\\Rkeystore\\[.*\\|main|" + DATE_REGEX + ".*\\]:"; + ".*\\Rkeystore\\[.*\\|main|" + DATE_REGEX + ".*\\]:"; static final String EXPECTED_ALL_REGEX = "properties\\[.*\\|main.*\\|" + DATE_REGEX + - ".*\\]((.*\\R)*)keystore\\[.*\\|main.*\\|" - + DATE_REGEX + ".*\\]:"; - - private static Stream patternMatches() { - return Stream.of( - // test for thread and timestamp info - Arguments.of("properties", - EXPECTED_PROP_REGEX, - "properties:"), - // test for thread and timestamp info - Arguments.of("properties+thread", - EXPECTED_PROP_REGEX, - "properties:"), - // flip the arguments of previous test - Arguments.of("properties+thread+timestamp", - EXPECTED_PROP_REGEX, - "properties:"), - // regular keystore,properties component string - Arguments.of("keystore,properties", - EXPECTED_PROP_KEYSTORE_REGEX, - "properties:"), - // turn on all - Arguments.of("all", - EXPECTED_ALL_REGEX, - "properties:"), - // expect thread and timestamp info - Arguments.of("all+thread", - EXPECTED_ALL_REGEX, - "properties:") - ); - } + ".*\\]((.*\\R)*)keystore\\[.*\\|main.*\\|" + + DATE_REGEX + ".*\\]:"; + + private static final List patternMatches = List.of( + // test for thread and timestamp info + new String[]{"properties", + EXPECTED_PROP_REGEX, + "properties:"}, + // test for thread and timestamp info + new String[]{"properties+thread", + EXPECTED_PROP_REGEX, + "properties:"}, + // flip the arguments of previous test + new String[]{"properties+thread+timestamp", + EXPECTED_PROP_REGEX, + "properties:"}, + // regular keystore,properties component string + new String[]{"keystore,properties", + EXPECTED_PROP_KEYSTORE_REGEX, + "properties:"}, + // turn on all + new String[]{"all", + EXPECTED_ALL_REGEX, + "properties:"}, + // expect thread and timestamp info + new String[]{"all+thread", + EXPECTED_ALL_REGEX, + "properties:"} + ); + + /** + * This will execute the test logic, but first change the param + * to be mixed case + * + * @param paramName name of the parameter e.g. -Djava.security.debug= + * @param paramVal value of the parameter + * @param expected expected output + * @param notExpected not expected output + */ + public void testMixedCaseParameter(String paramName, + String paramVal, + String expected, + String notExpected) throws Exception { - @ParameterizedTest - @MethodSource("patternMatches") - public void shouldContain(String params, String expected, String notExpected) throws Exception { - OutputAnalyzer outputAnalyzer = ProcessTools.executeTestJava( - "-Djava.security.debug=" + params, - "DebugOptions" - ); + final String formattedParam = makeFirstAndLastLetterUppercase(paramVal); + System.out.printf("Executing: {%s%s DebugOptions}%n", + paramName, + formattedParam); + + final OutputAnalyzer outputAnalyzer = ProcessTools.executeTestJava( + paramName + formattedParam, + "DebugOptions"); outputAnalyzer.shouldHaveExitValue(0) .shouldMatch(expected) .shouldNotMatch(notExpected); } + /** + * This method will change the input string to have + * first and last letters uppercase + *

    + * e.g.: + * hello -> HellO + * + * @param paramString string to change. Must not be null or empty + * @return resulting string + */ + private String makeFirstAndLastLetterUppercase(final String paramString) { + Assertions.assertTrue(paramString != null && !paramString.isEmpty()); + + final int length = paramString.length(); + final String firstLetter = paramString.substring(0, 1); + final String lastLetter = paramString.substring((length - 1), + length); + + return firstLetter.toUpperCase() + + paramString.substring(1, length - 1) + + lastLetter.toUpperCase(); + } + + /** + * This test will run all options in parallel with all param names + * in mixed case + */ + @Test + public void debugOptionsMixedCaseTest() throws Exception { + + try (final ExecutorService executorService = Executors.newVirtualThreadPerTaskExecutor()) { + final List> testsCallables = new ArrayList<>(); + + patternMatches.forEach(params -> { + testsCallables.add(() -> { + testMixedCaseParameter( + "-Djava.security.debug=", + params[0], + params[1], + params[2]); + return null; + }); + testsCallables.add(() -> { + testMixedCaseParameter( + "-Djava.security.auth.debug=", + params[0], + params[1], + params[2]); + return null; + }); + + System.out.println("Option added to all mixed case tests " + Arrays.toString(params)); + }); + + System.out.println("Starting all the threads"); + final List> res = executorService.invokeAll(testsCallables); + for (final Future future : res) { + future.get(); + } + } + } + + /** + * This is used for the test logic itself + */ public static void main(String[] args) throws Exception { + // something to trigger "properties" debug output Security.getProperty("test"); // trigger "keystore" debug output diff --git a/test/jdk/sun/security/util/Password/EmptyIn.java b/test/jdk/sun/security/util/Password/EmptyIn.java new file mode 100644 index 00000000000..b5692b9e7f9 --- /dev/null +++ b/test/jdk/sun/security/util/Password/EmptyIn.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import jdk.test.lib.Asserts; +import sun.security.util.Password; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +/* + * @test + * @bug 8374555 + * @summary only print warning when reading from System.in + * @modules java.base/sun.security.util + * @library /test/lib + */ +public class EmptyIn { + public static void main(String[] args) throws Exception { + testSystemIn(); + testNotSystemIn(); + } + + static void testSystemIn() throws Exception { + var in = new ByteArrayInputStream(new byte[0]); + var err = new ByteArrayOutputStream(); + var oldErr = System.err; + var oldIn = System.in; + try { + System.setIn(in); + System.setErr(new PrintStream(err)); + Password.readPassword(System.in); + } finally { + System.setIn(oldIn); + System.setErr(oldErr); + } + // Read from System.in. Should warn. + Asserts.assertNotEquals(0, err.size()); + } + + static void testNotSystemIn() throws Exception { + var in = new ByteArrayInputStream(new byte[0]); + var err = new ByteArrayOutputStream(); + var oldErr = System.err; + try { + System.setErr(new PrintStream(err)); + Password.readPassword(in); + } finally { + System.setErr(oldErr); + } + // Not read from System.in. Should not warn. + Asserts.assertEQ(0, err.size()); + } +} diff --git a/test/jdk/sun/security/util/Resources/Usages.java b/test/jdk/sun/security/util/Resources/Usages.java index 1e0a7d7ef70..447a4cb4913 100644 --- a/test/jdk/sun/security/util/Resources/Usages.java +++ b/test/jdk/sun/security/util/Resources/Usages.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8215937 8345940 + * @bug 8215937 8345940 8354469 * @modules java.base/sun.security.util * java.base/sun.security.util.resources * java.base/sun.security.tools.keytool.resources @@ -139,6 +139,8 @@ public class Usages { List.of(MGR_GETSTRING)), new Pair("java.base/share/classes/sun/security/provider/PolicyParser.java", List.of(LOC_GETNONLOC, NEW_LOC)), + new Pair("java.base/share/classes/sun/security/util/Password.java", + List.of(MGR_GETSTRING)), new Pair("java.base/share/classes/javax/security/auth/", List.of(MGR_GETSTRING))) ); diff --git a/test/jdk/sun/security/x509/URICertStore/AIACertTimeout.java b/test/jdk/sun/security/x509/URICertStore/AIACertTimeout.java index cabb225bf1c..5491d7b0d7a 100644 --- a/test/jdk/sun/security/x509/URICertStore/AIACertTimeout.java +++ b/test/jdk/sun/security/x509/URICertStore/AIACertTimeout.java @@ -47,6 +47,7 @@ import java.io.*; import java.math.BigInteger; import java.net.InetSocketAddress; +import java.security.Security; import java.security.cert.*; import java.security.KeyPair; import java.security.KeyPairGenerator; @@ -69,6 +70,7 @@ public class AIACertTimeout { private static X509Certificate eeCert; public static void main(String[] args) throws Exception { + Security.setProperty("com.sun.security.allowedAIALocations", "any"); int servTimeoutMsec = (args != null && args.length >= 1) ? Integer.parseInt(args[0]) : -1; boolean expectedPass = args != null && args.length >= 2 && diff --git a/test/jdk/sun/security/x509/URICertStore/CRLReadTimeout.java b/test/jdk/sun/security/x509/URICertStore/CRLReadTimeout.java index 1076aafb6b0..84b8dead425 100644 --- a/test/jdk/sun/security/x509/URICertStore/CRLReadTimeout.java +++ b/test/jdk/sun/security/x509/URICertStore/CRLReadTimeout.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,45 +22,101 @@ */ /* - * @test + * @test id=0 * @bug 8191808 8179502 * @summary check that CRL download is interrupted if it takes too long * @modules java.base/sun.security.x509 * java.base/sun.security.util * @library /test/lib - * @run main/othervm -Dcom.sun.security.crl.readtimeout=1 + * @run main/othervm -Djava.security.debug=certpath -Dcom.sun.security.crl.readtimeout=1 * CRLReadTimeout 5000 false - * @run main/othervm -Dcom.sun.security.crl.readtimeout=1s + */ + +/* + * @test id=1 + * @bug 8191808 8179502 + * @summary check that CRL download is interrupted if it takes too long + * @modules java.base/sun.security.x509 + * java.base/sun.security.util + * @library /test/lib + * @run main/othervm -Djava.security.debug=certpath -Dcom.sun.security.crl.readtimeout=1s * CRLReadTimeout 5000 false - * @run main/othervm -Dcom.sun.security.crl.readtimeout=4 + */ + +/* + * @test id=2 + * @bug 8191808 8179502 + * @summary check that CRL download is interrupted if it takes too long + * @modules java.base/sun.security.x509 + * java.base/sun.security.util + * @library /test/lib + * @run main/othervm -Djava.security.debug=certpath -Dcom.sun.security.crl.readtimeout=200 * CRLReadTimeout 1000 true - * @run main/othervm -Dcom.sun.security.crl.readtimeout=1500ms + */ + +/* + * @test id=3 + * @bug 8191808 8179502 + * @summary check that CRL download is interrupted if it takes too long + * @modules java.base/sun.security.x509 + * java.base/sun.security.util + * @library /test/lib + * @run main/othervm -Djava.security.debug=certpath -Dcom.sun.security.crl.readtimeout=1500ms * CRLReadTimeout 5000 false - * @run main/othervm -Dcom.sun.security.crl.readtimeout=4500ms - * CRLReadTimeout 1000 true */ -import java.io.*; +/* + * @test id=4 + * @bug 8191808 8179502 + * @summary check that CRL download is interrupted if it takes too long + * @modules java.base/sun.security.x509 + * java.base/sun.security.util + * @library /test/lib + * @run main/othervm -Djava.security.debug=certpath -Dcom.sun.security.crl.readtimeout=4500ms + * CRLReadTimeout 100 true + */ + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.math.BigInteger; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketTimeoutException; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.PrivateKey; -import java.security.cert.*; +import java.security.cert.CRLException; +import java.security.cert.CertPath; +import java.security.cert.CertPathValidator; +import java.security.cert.CertPathValidatorException; +import java.security.cert.CertificateFactory; +import java.security.cert.PKIXParameters; +import java.security.cert.PKIXRevocationChecker; +import java.security.cert.TrustAnchor; +import java.security.cert.X509CRL; +import java.security.cert.X509Certificate; import java.util.Date; import java.util.EnumSet; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; -import static java.security.cert.PKIXRevocationChecker.Option.*; +import static java.security.cert.PKIXRevocationChecker.Option.NO_FALLBACK; +import static java.security.cert.PKIXRevocationChecker.Option.PREFER_CRLS; +import static java.security.cert.PKIXRevocationChecker.Option.SOFT_FAIL; import com.sun.net.httpserver.HttpServer; import jdk.test.lib.SecurityTools; import jdk.test.lib.process.OutputAnalyzer; import sun.security.util.SignatureUtil; -import sun.security.x509.*; +import sun.security.x509.AuthorityKeyIdentifierExtension; +import sun.security.x509.CRLExtensions; +import sun.security.x509.CRLNumberExtension; +import sun.security.x509.KeyIdentifier; +import sun.security.x509.X500Name; +import sun.security.x509.X509CRLImpl; public class CRLReadTimeout { @@ -117,9 +173,10 @@ private static void testTimeout(int port, boolean expectedPass) // unwrap soft fail exceptions and check for SocketTimeoutException List softExc = prc.getSoftFailExceptions(); if (expectedPass) { - if (softExc.size() > 0) { + if (!softExc.isEmpty()) { throw new RuntimeException("Expected to pass, found " + - softExc.size() + " soft fail exceptions"); + softExc.size() + + " soft fail exceptions"); } } else { boolean foundSockTOExc = false; @@ -182,7 +239,7 @@ public CrlHttpServer(int timeout) throws IOException { } public void start() throws IOException { - server.bind(new InetSocketAddress(0), 0); + server.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); server.createContext("/crl", t -> { try (InputStream is = t.getRequestBody()) { is.readAllBytes(); diff --git a/test/jdk/sun/security/x509/URICertStore/ExtensionsWithLDAP.java b/test/jdk/sun/security/x509/URICertStore/ExtensionsWithLDAP.java index 3b598d78d9f..2214e9256c3 100644 --- a/test/jdk/sun/security/x509/URICertStore/ExtensionsWithLDAP.java +++ b/test/jdk/sun/security/x509/URICertStore/ExtensionsWithLDAP.java @@ -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,6 +38,7 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; +import java.security.Security; import java.security.cert.CertPath; import java.security.cert.CertPathValidator; import java.security.cert.CertPathValidatorException; @@ -47,7 +48,6 @@ import java.security.cert.TrustAnchor; import java.security.cert.X509Certificate; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -67,25 +67,27 @@ public class ExtensionsWithLDAP { * Not After : Jan 17 18:03:59 2043 GMT * Subject: CN=Root */ - private static final String CA_CERT = "" - + "-----BEGIN CERTIFICATE-----\n" - + "MIIC8TCCAdmgAwIBAgIJAJsSNtj5wdqqMA0GCSqGSIb3DQEBDQUAMA8xDTALBgNV\n" - + "BAMMBFJvb3QwHhcNMTUwOTAxMTgwMzU5WhcNNDMwMTE3MTgwMzU5WjAPMQ0wCwYD\n" - + "VQQDDARSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvj892vPm\n" - + "bB++x9QqqyBveP+ZqQ2B1stV7vh5JmDnOTevkZUOcemp3SXu/esNLSbpL+fARYXH\n" - + "V5ubnrfip6RbvcxPfVIIDJrRTLIIsU6W7M6/LJLbLkEVGy4ZV4IHkOw9W2O92rcv\n" - + "BkoqhzZnOTGR6uT3rRcKx4RevEKBKhZO+OPPf//lnckOybmYL7t7yQrajzHro76b\n" - + "QTXYjAUq/DKhglXfC7vF/JzlAvG2IunGmIfjGcnuDo/9X3Bxef/q5TxCS35fvb7t\n" - + "svC+g2QhTcBkQh4uNW2jSjlTIVp1uErCfP5aCjLaez5mqmb1hxPIlcvsNR23HwU6\n" - + "bQO7z7NBo9Do6QIDAQABo1AwTjAdBgNVHQ4EFgQUmLZNOBBkqdYoElyxklPYHmAb\n" - + "QXIwHwYDVR0jBBgwFoAUmLZNOBBkqdYoElyxklPYHmAbQXIwDAYDVR0TBAUwAwEB\n" - + "/zANBgkqhkiG9w0BAQ0FAAOCAQEAYV4fOhDi5q7+XNXCxO8Eil2frR9jqdP4LaQp\n" - + "3L0evW0gvPX68s2WmkPWzIu4TJcpdGFQqxyQFSXuKBXjthyiln77QItGTHWeafES\n" - + "q5ESrKdSaJZq1bTIrrReCIP74f+fY/F4Tnb3dCqzaljXfzpdbeRsIW6gF71xcOUQ\n" - + "nnPEjGVPLUegN+Wn/jQpeLxxIB7FmNXncdRUfMfZ43xVSKuMCy1UUYqJqTa/pXZj\n" - + "jCMeRPThRjRqHlJ69jStfWUQATbLyj9KN09rUaJxzmUSt61UqJi7sjcGySaCjAJc\n" - + "IcCdVmX/DmRLsdv8W36O3MgrvpT1zR3kaAlv2d8HppnBqcL3xg==\n" - + "-----END CERTIFICATE-----"; + private static final String CA_CERT = + """ + -----BEGIN CERTIFICATE----- + MIIC8TCCAdmgAwIBAgIJAJsSNtj5wdqqMA0GCSqGSIb3DQEBDQUAMA8xDTALBgNV + BAMMBFJvb3QwHhcNMTUwOTAxMTgwMzU5WhcNNDMwMTE3MTgwMzU5WjAPMQ0wCwYD + VQQDDARSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvj892vPm + bB++x9QqqyBveP+ZqQ2B1stV7vh5JmDnOTevkZUOcemp3SXu/esNLSbpL+fARYXH + V5ubnrfip6RbvcxPfVIIDJrRTLIIsU6W7M6/LJLbLkEVGy4ZV4IHkOw9W2O92rcv + BkoqhzZnOTGR6uT3rRcKx4RevEKBKhZO+OPPf//lnckOybmYL7t7yQrajzHro76b + QTXYjAUq/DKhglXfC7vF/JzlAvG2IunGmIfjGcnuDo/9X3Bxef/q5TxCS35fvb7t + svC+g2QhTcBkQh4uNW2jSjlTIVp1uErCfP5aCjLaez5mqmb1hxPIlcvsNR23HwU6 + bQO7z7NBo9Do6QIDAQABo1AwTjAdBgNVHQ4EFgQUmLZNOBBkqdYoElyxklPYHmAb + QXIwHwYDVR0jBBgwFoAUmLZNOBBkqdYoElyxklPYHmAbQXIwDAYDVR0TBAUwAwEB + /zANBgkqhkiG9w0BAQ0FAAOCAQEAYV4fOhDi5q7+XNXCxO8Eil2frR9jqdP4LaQp + 3L0evW0gvPX68s2WmkPWzIu4TJcpdGFQqxyQFSXuKBXjthyiln77QItGTHWeafES + q5ESrKdSaJZq1bTIrrReCIP74f+fY/F4Tnb3dCqzaljXfzpdbeRsIW6gF71xcOUQ + nnPEjGVPLUegN+Wn/jQpeLxxIB7FmNXncdRUfMfZ43xVSKuMCy1UUYqJqTa/pXZj + jCMeRPThRjRqHlJ69jStfWUQATbLyj9KN09rUaJxzmUSt61UqJi7sjcGySaCjAJc + IcCdVmX/DmRLsdv8W36O3MgrvpT1zR3kaAlv2d8HppnBqcL3xg== + -----END CERTIFICATE----- + """; /* * Certificate: @@ -106,39 +108,41 @@ public class ExtensionsWithLDAP { * Authority Information Access: * CA Issuers - URI:ldap://ldap.host.for.aia/dc=Root?cACertificate */ - private static final String EE_CERT = "" - + "-----BEGIN CERTIFICATE-----\n" - + "MIIDHTCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQ0FADAPMQ0wCwYDVQQDDARSb290\n" - + "MB4XDTE1MDkwMTE4MDM1OVoXDTQzMDExNzE4MDM1OVowDTELMAkGA1UEAwwCRUUw\n" - + "ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpyz97liuWPDYcLH9TX8Bi\n" - + "T78olCmAfmevvch6ncXUVuCzbdaKuKXwn4EVbDszsVJLoK5zdtP+X3iDhutj+IgK\n" - + "mLhuczF3M9VIcWr+JJUyTH4+3h/RT8cjCDZOmk9iXkb5ifruVsLqzb9g+Vp140Oz\n" - + "7leikne7KmclHvTfvFd0WDI7Gb9vo4f5rT717BXJ/n+M6pNk8DLpLiEu6eziYvXR\n" - + "v5x+t5Go3x0eCXdaxEQUf2j876Wfr2qHRJK7lDfFe1DDsMg/KpKGiILYZ+g2qtVM\n" - + "ZSxtp5BZEtfB5qV/IE5kWO+mCIAGpXSZIdbERR6pZUq8GLEe1T9e+sO6H24w2F19\n" - + "AgMBAAGjgYUwgYIwNAYDVR0fBC0wKzApoCegJYYjbGRhcDovL2xkYXAuaG9zdC5m\n" - + "b3IuY3JsZHAvbWFpbi5jcmwwSgYIKwYBBQUHAQEEPjA8MDoGCCsGAQUFBzAChi5s\n" - + "ZGFwOi8vbGRhcC5ob3N0LmZvci5haWEvZGM9Um9vdD9jQUNlcnRpZmljYXRlMA0G\n" - + "CSqGSIb3DQEBDQUAA4IBAQBWDfZHpuUx0yn5d3+BuztFqoks1MkGdk+USlH0TB1/\n" - + "gWWBd+4S4PCKlpSur0gj2rMW4fP5HQfNlHci8JV8/bG4KuKRAXW56dg1818Hl3pc\n" - + "iIrUSRn8uUjH3p9qb+Rb/u3mmVQRyJjN2t/zceNsO8/+Dd808OB9aEwGs8lMT0nn\n" - + "ZYaaAqYz1GIY/Ecyx1vfEZEQ1ljo6i/r70C3igbypBUShxSiGsleiVTLOGNA+MN1\n" - + "/a/Qh0bkaQyTGqK3bwvzzMeQVqWu2EWTBD/PmND5ExkpRICdv8LBVXfLnpoBr4lL\n" - + "hnxn9+e0Ah+t8dS5EKfn44w5bI5PCu2bqxs6RCTxNjcY\n" - + "-----END CERTIFICATE-----"; + private static final String EE_CERT = + """ + -----BEGIN CERTIFICATE----- + MIIDHTCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQ0FADAPMQ0wCwYDVQQDDARSb290 + MB4XDTE1MDkwMTE4MDM1OVoXDTQzMDExNzE4MDM1OVowDTELMAkGA1UEAwwCRUUw + ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpyz97liuWPDYcLH9TX8Bi + T78olCmAfmevvch6ncXUVuCzbdaKuKXwn4EVbDszsVJLoK5zdtP+X3iDhutj+IgK + mLhuczF3M9VIcWr+JJUyTH4+3h/RT8cjCDZOmk9iXkb5ifruVsLqzb9g+Vp140Oz + 7leikne7KmclHvTfvFd0WDI7Gb9vo4f5rT717BXJ/n+M6pNk8DLpLiEu6eziYvXR + v5x+t5Go3x0eCXdaxEQUf2j876Wfr2qHRJK7lDfFe1DDsMg/KpKGiILYZ+g2qtVM + ZSxtp5BZEtfB5qV/IE5kWO+mCIAGpXSZIdbERR6pZUq8GLEe1T9e+sO6H24w2F19 + AgMBAAGjgYUwgYIwNAYDVR0fBC0wKzApoCegJYYjbGRhcDovL2xkYXAuaG9zdC5m + b3IuY3JsZHAvbWFpbi5jcmwwSgYIKwYBBQUHAQEEPjA8MDoGCCsGAQUFBzAChi5s + ZGFwOi8vbGRhcC5ob3N0LmZvci5haWEvZGM9Um9vdD9jQUNlcnRpZmljYXRlMA0G + CSqGSIb3DQEBDQUAA4IBAQBWDfZHpuUx0yn5d3+BuztFqoks1MkGdk+USlH0TB1/ + gWWBd+4S4PCKlpSur0gj2rMW4fP5HQfNlHci8JV8/bG4KuKRAXW56dg1818Hl3pc + iIrUSRn8uUjH3p9qb+Rb/u3mmVQRyJjN2t/zceNsO8/+Dd808OB9aEwGs8lMT0nn + ZYaaAqYz1GIY/Ecyx1vfEZEQ1ljo6i/r70C3igbypBUShxSiGsleiVTLOGNA+MN1 + /a/Qh0bkaQyTGqK3bwvzzMeQVqWu2EWTBD/PmND5ExkpRICdv8LBVXfLnpoBr4lL + hnxn9+e0Ah+t8dS5EKfn44w5bI5PCu2bqxs6RCTxNjcY + -----END CERTIFICATE-----"""; public static void main(String[] args) throws Exception { String extension = args[0]; String targetHost = args[1]; - + Security.setProperty("com.sun.security.allowedAIALocations", + "ldap://" + targetHost + "/dc=Root"); X509Certificate trustedCert = loadCertificate(CA_CERT); X509Certificate eeCert = loadCertificate(EE_CERT); Set trustedCertsSet = new HashSet<>(); trustedCertsSet.add(new TrustAnchor(trustedCert, null)); - CertPath cp = (CertPath) CertificateFactory.getInstance("X509") - .generateCertPath(Arrays.asList(eeCert)); + CertPath cp = CertificateFactory.getInstance("X509") + .generateCertPath(List.of(eeCert)); // CertPath validator should try to parse CRLDP and AIA extensions, // and load CRLs/certs which they point to. @@ -151,7 +155,7 @@ public static void main(String[] args) throws Exception { = (InetSocketAddress) socket.getRemoteSocketAddress(); hosts.add(remoteAddress.getHostName()); }; - try (SocksProxy proxy = SocksProxy.startProxy(socketConsumer)) { + try (SocksProxy _ = SocksProxy.startProxy(socketConsumer)) { CertPathValidator.getInstance("PKIX").validate(cp, new PKIXParameters(trustedCertsSet)); throw new RuntimeException("CertPathValidatorException not thrown"); diff --git a/test/jdk/sun/text/resources/LocaleDataTest.java b/test/jdk/sun/text/resources/LocaleDataTest.java index 009ba718de5..40182034854 100644 --- a/test/jdk/sun/text/resources/LocaleDataTest.java +++ b/test/jdk/sun/text/resources/LocaleDataTest.java @@ -41,7 +41,7 @@ * 8187946 8195478 8181157 8179071 8193552 8202026 8204269 8202537 8208746 * 8209775 8221432 8227127 8230284 8231273 8233579 8234288 8250665 8255086 * 8251317 8274658 8283277 8283805 8265315 8287868 8295564 8284840 8296715 - * 8301206 8303472 8317979 8306116 8174269 8333582 8357075 8357882 + * 8301206 8303472 8317979 8306116 8174269 8333582 8357075 8357882 8367021 * @summary Verify locale data * @modules java.base/sun.util.resources * @modules jdk.localedata @@ -204,7 +204,7 @@ else if (!args[i].startsWith("-") && in == null) in = new BufferedReader(new InputStreamReader(new FileInputStream(localeData), StandardCharsets.UTF_8)); } - out = new PrintWriter(new OutputStreamWriter(System.out, StandardCharsets.UTF_8)); + out = new PrintWriter(new OutputStreamWriter(System.out, StandardCharsets.UTF_8), true); // perform the actual test int errorCount = doTest(in, out, writeNewFile); diff --git a/test/jdk/sun/tools/jstat/jstatGcCapacityOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcCapacityOutput1.sh index ccc95be281f..c1908855ea7 100644 --- a/test/jdk/sun/tools/jstat/jstatGcCapacityOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcCapacityOutput1.sh @@ -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 @@ verify_os 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 --git a/test/jdk/sun/tools/jstat/jstatGcCauseOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcCauseOutput1.sh index c34a1881673..8652a25fdb7 100644 --- a/test/jdk/sun/tools/jstat/jstatGcCauseOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcCauseOutput1.sh @@ -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 @@ JSTAT="${TESTJAVA}/bin/jstat" # 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 --git a/test/jdk/sun/tools/jstat/jstatGcMetaCapacityOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcMetaCapacityOutput1.sh index 66446517c50..b16d0e38d02 100644 --- a/test/jdk/sun/tools/jstat/jstatGcMetaCapacityOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcMetaCapacityOutput1.sh @@ -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 @@ verify_os 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 --git a/test/jdk/sun/tools/jstat/jstatGcNewCapacityOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcNewCapacityOutput1.sh index 44aa864b475..64ce2efd455 100644 --- a/test/jdk/sun/tools/jstat/jstatGcNewCapacityOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcNewCapacityOutput1.sh @@ -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 @@ verify_os 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 --git a/test/jdk/sun/tools/jstat/jstatGcNewOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcNewOutput1.sh index 0f909f18a9e..b15ec02d2b0 100644 --- a/test/jdk/sun/tools/jstat/jstatGcNewOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcNewOutput1.sh @@ -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 @@ verify_os 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 --git a/test/jdk/sun/tools/jstat/jstatGcOldCapacityOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcOldCapacityOutput1.sh index 433072fddfa..1c13d6f916d 100644 --- a/test/jdk/sun/tools/jstat/jstatGcOldCapacityOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcOldCapacityOutput1.sh @@ -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 @@ verify_os 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 --git a/test/jdk/sun/tools/jstat/jstatGcOldOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcOldOutput1.sh index ee9e30296e0..7f505228b12 100644 --- a/test/jdk/sun/tools/jstat/jstatGcOldOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcOldOutput1.sh @@ -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 @@ verify_os 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 --git a/test/jdk/sun/tools/jstat/jstatGcOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcOutput1.sh index 167c53606ad..dfffa2d1a55 100644 --- a/test/jdk/sun/tools/jstat/jstatGcOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcOutput1.sh @@ -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 @@ verify_os 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 --git a/test/jdk/sun/tools/jstat/jstatLineCounts1.sh b/test/jdk/sun/tools/jstat/jstatLineCounts1.sh index 75cb051cccf..97338b8e793 100644 --- a/test/jdk/sun/tools/jstat/jstatLineCounts1.sh +++ b/test/jdk/sun/tools/jstat/jstatLineCounts1.sh @@ -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 @@ verify_os 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 --git a/test/jdk/sun/tools/jstat/jstatLineCounts2.sh b/test/jdk/sun/tools/jstat/jstatLineCounts2.sh index 5e0cbafe08d..eab19f3931e 100644 --- a/test/jdk/sun/tools/jstat/jstatLineCounts2.sh +++ b/test/jdk/sun/tools/jstat/jstatLineCounts2.sh @@ -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 @@ verify_os 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 --git a/test/jdk/sun/tools/jstat/jstatLineCounts3.sh b/test/jdk/sun/tools/jstat/jstatLineCounts3.sh index ef8bbc8ad75..9a769a92464 100644 --- a/test/jdk/sun/tools/jstat/jstatLineCounts3.sh +++ b/test/jdk/sun/tools/jstat/jstatLineCounts3.sh @@ -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 @@ verify_os 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 --git a/test/jdk/sun/tools/jstat/jstatLineCounts4.sh b/test/jdk/sun/tools/jstat/jstatLineCounts4.sh index 537172c75e3..817c3b14f62 100644 --- a/test/jdk/sun/tools/jstat/jstatLineCounts4.sh +++ b/test/jdk/sun/tools/jstat/jstatLineCounts4.sh @@ -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 @@ verify_os 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 --git a/test/jdk/sun/tools/jstat/lineCounts1.awk b/test/jdk/sun/tools/jstat/lineCounts1.awk index d7a7c1d9fb7..1e05506100b 100644 --- a/test/jdk/sun/tools/jstat/lineCounts1.awk +++ b/test/jdk/sun/tools/jstat/lineCounts1.awk @@ -29,7 +29,7 @@ BEGIN { 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 --git a/test/jdk/sun/tools/jstat/lineCounts2.awk b/test/jdk/sun/tools/jstat/lineCounts2.awk index 201457a3833..4d838c2103e 100644 --- a/test/jdk/sun/tools/jstat/lineCounts2.awk +++ b/test/jdk/sun/tools/jstat/lineCounts2.awk @@ -21,7 +21,7 @@ BEGIN { 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 --git a/test/jdk/sun/tools/jstat/lineCounts3.awk b/test/jdk/sun/tools/jstat/lineCounts3.awk index 1f155a99ed5..79ae969a47d 100644 --- a/test/jdk/sun/tools/jstat/lineCounts3.awk +++ b/test/jdk/sun/tools/jstat/lineCounts3.awk @@ -39,7 +39,7 @@ BEGIN { 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 --git a/test/jdk/sun/tools/jstat/lineCounts4.awk b/test/jdk/sun/tools/jstat/lineCounts4.awk index 62aea881e71..7ceb56b9f27 100644 --- a/test/jdk/sun/tools/jstat/lineCounts4.awk +++ b/test/jdk/sun/tools/jstat/lineCounts4.awk @@ -44,7 +44,7 @@ BEGIN { 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 --git a/test/jdk/tools/jar/ReproducibleJar.java b/test/jdk/tools/jar/ReproducibleJar.java index ed5e2ed2ae3..5f59d1cbe41 100644 --- a/test/jdk/tools/jar/ReproducibleJar.java +++ b/test/jdk/tools/jar/ReproducibleJar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,7 +66,9 @@ public class ReproducibleJar { private static final TimeZone TZ = TimeZone.getDefault(); private static final boolean DST = TZ.inDaylightTime(new Date()); private static final String UNIX_2038_ROLLOVER_TIME = "2038-01-19T03:14:07Z"; + private static final String UNIX_EPOCH_TIME = "1970-01-01T00:00:00Z"; private static final Instant UNIX_2038_ROLLOVER = Instant.parse(UNIX_2038_ROLLOVER_TIME); + private static final Instant UNIX_EPOCH = Instant.parse(UNIX_EPOCH_TIME); private static final File DIR_OUTER = new File("outer"); private static final File DIR_INNER = new File(DIR_OUTER, "inner"); private static final File FILE_INNER = new File(DIR_INNER, "foo.txt"); @@ -231,12 +233,15 @@ static void checkFileTime(long now, long original) { if (Math.abs(now - original) > PRECISION) { // If original time is after UNIX 2038 32bit rollover - // and the now time is exactly the rollover time, then assume + // and the now time is exactly the rollover time or UNIX epoch time, then assume // running on a file system that only supports to 2038 (e.g.XFS) and pass test - if (FileTime.fromMillis(original).toInstant().isAfter(UNIX_2038_ROLLOVER) && - FileTime.fromMillis(now).toInstant().equals(UNIX_2038_ROLLOVER)) { - System.out.println("Checking file time after Unix 2038 rollover," + - " and extracted file time is " + UNIX_2038_ROLLOVER_TIME + ", " + + Instant originalInstant = FileTime.fromMillis(original).toInstant(); + Instant nowInstant = FileTime.fromMillis(now).toInstant(); + if (originalInstant.isAfter(UNIX_2038_ROLLOVER) && + (nowInstant.equals(UNIX_2038_ROLLOVER) || + nowInstant.equals(UNIX_EPOCH))) { + System.out.println("Checking file time after Unix 2038 rollover," + + " and extracted file time is " + nowInstant + ", " + " Assuming restricted file system, pass file time check."); } else { throw new AssertionError("checkFileTime failed," + diff --git a/test/jdk/tools/jpackage/TEST.properties b/test/jdk/tools/jpackage/TEST.properties index 58a82a9444b..f6a0dc7dfc7 100644 --- a/test/jdk/tools/jpackage/TEST.properties +++ b/test/jdk/tools/jpackage/TEST.properties @@ -22,5 +22,6 @@ modules = \ jdk.jpackage/jdk.jpackage.internal:+open \ jdk.jpackage/jdk.jpackage.internal.util \ jdk.jpackage/jdk.jpackage.internal.util.function \ + jdk.jpackage/jdk.jpackage.internal.resources:+open \ java.base/jdk.internal.util \ jdk.jlink/jdk.tools.jlink.internal diff --git a/test/jdk/tools/jpackage/apps/PrintEnv.java b/test/jdk/tools/jpackage/apps/PrintEnv.java index bb1cef800f4..64a243a0abc 100644 --- a/test/jdk/tools/jpackage/apps/PrintEnv.java +++ b/test/jdk/tools/jpackage/apps/PrintEnv.java @@ -21,18 +21,38 @@ * questions. */ +import java.io.IOException; +import java.io.UncheckedIOException; import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleFinder; import java.lang.module.ModuleReference; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; public class PrintEnv { public static void main(String[] args) { List lines = printArgs(args); - lines.forEach(System.out::println); + Optional.ofNullable(System.getProperty("jpackage.test.appOutput")).map(Path::of).ifPresentOrElse(outputFilePath -> { + Optional.ofNullable(outputFilePath.getParent()).ifPresent(dir -> { + try { + Files.createDirectories(dir); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + }); + try { + Files.write(outputFilePath, lines); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + }, () -> { + lines.forEach(System.out::println); + }); } private static List printArgs(String[] args) { @@ -45,11 +65,13 @@ private static List printArgs(String[] args) { } else if (arg.startsWith(PRINT_SYS_PROP)) { String name = arg.substring(PRINT_SYS_PROP.length()); lines.add(name + "=" + System.getProperty(name)); - } else if (arg.startsWith(PRINT_MODULES)) { + } else if (arg.equals(PRINT_MODULES)) { lines.add(ModuleFinder.ofSystem().findAll().stream() .map(ModuleReference::descriptor) .map(ModuleDescriptor::name) .collect(Collectors.joining(","))); + } else if (arg.equals(PRINT_WORK_DIR)) { + lines.add("$CD=" + Path.of("").toAbsolutePath()); } else { throw new IllegalArgumentException(); } @@ -58,7 +80,8 @@ private static List printArgs(String[] args) { return lines; } - private final static String PRINT_ENV_VAR = "--print-env-var="; - private final static String PRINT_SYS_PROP = "--print-sys-prop="; - private final static String PRINT_MODULES = "--print-modules"; + private static final String PRINT_ENV_VAR = "--print-env-var="; + private static final String PRINT_SYS_PROP = "--print-sys-prop="; + private static final String PRINT_MODULES = "--print-modules"; + private static final String PRINT_WORK_DIR = "--print-workdir"; } diff --git a/test/jdk/tools/jpackage/apps/UseShutdownHook.java b/test/jdk/tools/jpackage/apps/UseShutdownHook.java new file mode 100644 index 00000000000..c558ee85701 --- /dev/null +++ b/test/jdk/tools/jpackage/apps/UseShutdownHook.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +public class UseShutdownHook { + + public static void main(String[] args) throws InterruptedException { + trace("Started"); + + var outputFile = Path.of(args[0]); + trace(String.format("Write output in [%s] file", outputFile)); + + var shutdownTimeoutSeconds = Integer.parseInt(args[1]); + trace(String.format("Automatically shutdown the app in %ss", shutdownTimeoutSeconds)); + + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + output(outputFile, "shutdown hook executed"); + } + }); + + var startTime = System.currentTimeMillis(); + var lock = new Object(); + do { + synchronized (lock) { + lock.wait(shutdownTimeoutSeconds * 1000); + } + } while ((System.currentTimeMillis() - startTime) < (shutdownTimeoutSeconds * 1000)); + + output(outputFile, "exit"); + } + + private static void output(Path outputFilePath, String msg) { + + trace(String.format("Writing [%s] into [%s]", msg, outputFilePath)); + + try { + Files.createDirectories(outputFilePath.getParent()); + Files.writeString(outputFilePath, msg, StandardOpenOption.APPEND, StandardOpenOption.CREATE); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + } + + private static void trace(String msg) { + Date time = new Date(System.currentTimeMillis()); + msg = String.format("UseShutdownHook [%s]: %s", SDF.format(time), msg); + System.out.println(msg); + try { + Files.write(traceFile, List.of(msg), StandardOpenOption.APPEND, StandardOpenOption.CREATE); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + } + + private static final SimpleDateFormat SDF = new SimpleDateFormat("HH:mm:ss.SSS"); + + private static final Path traceFile = Path.of(System.getProperty("jpackage.test.trace-file")); +} diff --git a/test/jdk/tools/jpackage/clean_test_output.sh b/test/jdk/tools/jpackage/clean_test_output.sh new file mode 100644 index 00000000000..e472d780ded --- /dev/null +++ b/test/jdk/tools/jpackage/clean_test_output.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +# 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. + +# +# Filters output produced by running jpackage test(s). +# + +set -eu +set -o pipefail + + +sed_inplace_option=-i +sed_version_string=$(sed --version 2>&1 | head -1 || true) +if [ "${sed_version_string#sed (GNU sed)}" != "$sed_version_string" ]; then + # GNU sed, the default + : +elif [ "${sed_version_string#sed: illegal option}" != "$sed_version_string" ]; then + # Macos sed + sed_inplace_option="-i ''" +else + echo 'WARNING: Unknown sed variant, assume it is GNU compatible' +fi + + +filterFile () { + local expressions=( + # Strip leading log message timestamp `[19:33:44.713] ` + -e 's/^\[[0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}\.[0-9]\{3\}\] //' + + # Strip log message timestamps `[19:33:44.713]` + -e 's/\[[0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}\.[0-9]\{3\}\]//g' + + # Convert variable part of R/O directory path timestamp `#2025-07-24T16:38:13.3589878Z` + -e 's/#[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}T[0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}\.[0-9]\{1,\}Z/#Z/' + + # Strip variable part of temporary directory name `jdk.jpackage5060841750457404688` + -e 's|\([\/]\)jdk\.jpackage[0-9]\{1,\}\b|\1jdk.jpackage|g' + + # Convert PID value `[PID: 131561]` + -e 's/\[PID: [0-9]\{1,\}\]/[PID: ]/' + + # Strip a warning message `Windows Defender may prevent jpackage from functioning` + -e '/Windows Defender may prevent jpackage from functioning/d' + + # Convert variable part of test output directory `out-6268` + -e 's|\bout-[0-9]\{1,\}\b|out-N|g' + + # Convert variable part of test summary `[ OK ] IconTest(AppImage, ResourceDirIcon, DefaultIcon).test; checks=39` + -e 's/^\(.*\bchecks=\)[0-9]\{1,\}\(\r\{0,1\}\)$/\1N\2/' + + # Convert variable part of ldd output `libdl.so.2 => /lib64/libdl.so.2 (0x00007fbf63c81000)` + -e 's/(0x[[:xdigit:]]\{1,\})$/(0xHEX)/' + + # Convert variable part of rpmbuild output `Executing(%build): /bin/sh -e /var/tmp/rpm-tmp.CMO6a9` + -e 's|/rpm-tmp\...*$|/rpm-tmp.V|' + + # Convert variable part of stack trace entry `at jdk.jpackage.test.JPackageCommand.execute(JPackageCommand.java:863)` + -e 's/^\(.*\b\.java:\)[0-9]\{1,\}\()\r\{0,1\}\)$/\1N\2/' + ) + + sed $sed_inplace_option "$1" "${expressions[@]}" +} + + +for f in "$@"; do + filterFile "$f" +done diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java index 801df8624c4..07c8e06856f 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java @@ -22,39 +22,54 @@ */ package jdk.jpackage.test; -import static java.util.stream.Collectors.toMap; -import static jdk.jpackage.internal.util.function.ThrowingFunction.toFunction; +import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; +import static jdk.jpackage.test.LauncherShortcut.LINUX_SHORTCUT; +import static jdk.jpackage.test.LauncherShortcut.WIN_DESKTOP_SHORTCUT; +import static jdk.jpackage.test.LauncherShortcut.WIN_START_MENU_SHORTCUT; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.Properties; +import java.util.Set; import java.util.function.BiConsumer; -import java.util.function.Supplier; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Stream; import jdk.jpackage.internal.util.function.ThrowingBiConsumer; +import jdk.jpackage.internal.util.function.ThrowingConsumer; +import jdk.jpackage.test.LauncherShortcut.StartupDirectory; +import jdk.jpackage.test.LauncherVerifier.Action; -public class AdditionalLauncher { +public final class AdditionalLauncher { public AdditionalLauncher(String name) { - this.name = name; - this.rawProperties = new ArrayList<>(); + this.name = Objects.requireNonNull(name); setPersistenceHandler(null); } - public final AdditionalLauncher setDefaultArguments(String... v) { + public AdditionalLauncher withVerifyActions(Action... actions) { + verifyActions.addAll(List.of(actions)); + return this; + } + + public AdditionalLauncher withoutVerifyActions(Action... actions) { + verifyActions.removeAll(List.of(actions)); + return this; + } + + public AdditionalLauncher setDefaultArguments(String... v) { defaultArguments = new ArrayList<>(List.of(v)); return this; } - public final AdditionalLauncher addDefaultArguments(String... v) { + public AdditionalLauncher addDefaultArguments(String... v) { if (defaultArguments == null) { return setDefaultArguments(v); } @@ -63,12 +78,12 @@ public final AdditionalLauncher addDefaultArguments(String... v) { return this; } - public final AdditionalLauncher setJavaOptions(String... v) { + public AdditionalLauncher setJavaOptions(String... v) { javaOptions = new ArrayList<>(List.of(v)); return this; } - public final AdditionalLauncher addJavaOptions(String... v) { + public AdditionalLauncher addJavaOptions(String... v) { if (javaOptions == null) { return setJavaOptions(v); } @@ -77,51 +92,46 @@ public final AdditionalLauncher addJavaOptions(String... v) { return this; } - public final AdditionalLauncher setVerifyUninstalled(boolean value) { - verifyUninstalled = value; + public AdditionalLauncher setProperty(String name, Object value) { + rawProperties.put(Objects.requireNonNull(name), Objects.requireNonNull(value.toString())); return this; } - public final AdditionalLauncher setLauncherAsService() { - return addRawProperties(LAUNCHER_AS_SERVICE); - } - - public final AdditionalLauncher addRawProperties( - Map.Entry v) { - return addRawProperties(List.of(v)); - } - - public final AdditionalLauncher addRawProperties( - Map.Entry v, Map.Entry v2) { - return addRawProperties(List.of(v, v2)); - } - - public final AdditionalLauncher addRawProperties( - Collection> v) { - rawProperties.addAll(v); + public AdditionalLauncher setShortcuts(boolean menu, boolean desktop) { + if (TKit.isLinux()) { + setShortcut(LINUX_SHORTCUT, desktop); + } else if (TKit.isWindows()) { + setShortcut(WIN_DESKTOP_SHORTCUT, desktop); + setShortcut(WIN_START_MENU_SHORTCUT, menu); + } return this; } - public final String getRawPropertyValue( - String key, Supplier getDefault) { - return rawProperties.stream() - .filter(item -> item.getKey().equals(key)) - .map(e -> e.getValue()).findAny().orElseGet(getDefault); + public AdditionalLauncher setShortcut(LauncherShortcut shortcut, StartupDirectory value) { + if (value != null) { + setProperty(shortcut.propertyName(), value.asStringValue()); + } else { + setProperty(shortcut.propertyName(), false); + } + return this; } - private String getDesciption(JPackageCommand cmd) { - return getRawPropertyValue("description", () -> cmd.getArgumentValue( - "--description", unused -> cmd.name())); + public AdditionalLauncher setShortcut(LauncherShortcut shortcut, boolean value) { + if (value) { + setShortcut(shortcut, StartupDirectory.DEFAULT); + } else { + setShortcut(shortcut, null); + } + return this; } - public final AdditionalLauncher setShortcuts(boolean menu, boolean shortcut) { - withMenuShortcut = menu; - withShortcut = shortcut; + public AdditionalLauncher removeShortcut(LauncherShortcut shortcut) { + rawProperties.remove(shortcut.propertyName()); return this; } - public final AdditionalLauncher setIcon(Path iconPath) { - if (iconPath == NO_ICON) { + public AdditionalLauncher setIcon(Path iconPath) { + if (iconPath.equals(NO_ICON)) { throw new IllegalArgumentException(); } @@ -129,13 +139,13 @@ public final AdditionalLauncher setIcon(Path iconPath) { return this; } - public final AdditionalLauncher setNoIcon() { + public AdditionalLauncher setNoIcon() { icon = NO_ICON; return this; } - public final AdditionalLauncher setPersistenceHandler( - ThrowingBiConsumer>> handler) { + public AdditionalLauncher setPersistenceHandler( + ThrowingBiConsumer>> handler) { if (handler != null) { createFileHandler = ThrowingBiConsumer.toBiConsumer(handler); } else { @@ -144,21 +154,31 @@ public final AdditionalLauncher setPersistenceHandler( return this; } - public final void applyTo(JPackageCommand cmd) { + public void applyTo(JPackageCommand cmd) { cmd.addPrerequisiteAction(this::initialize); - cmd.addVerifyAction(this::verify); + cmd.addVerifyAction(createVerifierAsConsumer()); } - public final void applyTo(PackageTest test) { + public void applyTo(PackageTest test) { test.addInitializer(this::initialize); - test.addInstallVerifier(this::verify); - if (verifyUninstalled) { - test.addUninstallVerifier(this::verifyUninstalled); - } + test.addInstallVerifier(createVerifierAsConsumer()); } public final void verifyRemovedInUpgrade(PackageTest test) { - test.addInstallVerifier(this::verifyUninstalled); + test.addInstallVerifier(cmd -> { + createVerifier().verify(cmd, LauncherVerifier.Action.VERIFY_UNINSTALLED); + }); + } + + private LauncherVerifier createVerifier() { + return new LauncherVerifier(name, Optional.ofNullable(javaOptions), + Optional.ofNullable(defaultArguments), Optional.ofNullable(icon), rawProperties); + } + + private ThrowingConsumer createVerifierAsConsumer() { + return cmd -> { + createVerifier().verify(cmd, verifyActions.stream().sorted(Comparator.comparing(Action::ordinal)).toArray(Action[]::new)); + }; } static void forEachAdditionalLauncher(JPackageCommand cmd, @@ -179,11 +199,12 @@ static PropertyFile getAdditionalLauncherProperties( PropertyFile shell[] = new PropertyFile[1]; forEachAdditionalLauncher(cmd, (name, propertiesFilePath) -> { if (name.equals(launcherName)) { - shell[0] = toFunction(PropertyFile::new).apply( - propertiesFilePath); + shell[0] = toSupplier(() -> { + return new PropertyFile(propertiesFilePath); + }).get(); } }); - return Optional.of(shell[0]).get(); + return Objects.requireNonNull(shell[0]); } private void initialize(JPackageCommand cmd) throws IOException { @@ -191,259 +212,63 @@ private void initialize(JPackageCommand cmd) throws IOException { cmd.addArguments("--add-launcher", String.format("%s=%s", name, propsFile)); - List> properties = new ArrayList<>(); + Map properties = new HashMap<>(); if (defaultArguments != null) { - properties.add(Map.entry("arguments", - JPackageCommand.escapeAndJoin(defaultArguments))); + properties.put("arguments", JPackageCommand.escapeAndJoin(defaultArguments)); } if (javaOptions != null) { - properties.add(Map.entry("java-options", - JPackageCommand.escapeAndJoin(javaOptions))); + properties.put("java-options", JPackageCommand.escapeAndJoin(javaOptions)); } if (icon != null) { final String iconPath; - if (icon == NO_ICON) { + if (icon.equals(NO_ICON)) { iconPath = ""; } else { iconPath = icon.toAbsolutePath().toString().replace('\\', '/'); } - properties.add(Map.entry("icon", iconPath)); - } - - if (withShortcut != null) { - if (TKit.isLinux()) { - properties.add(Map.entry("linux-shortcut", withShortcut.toString())); - } else if (TKit.isWindows()) { - properties.add(Map.entry("win-shortcut", withShortcut.toString())); - } - } - - if (TKit.isWindows() && withMenuShortcut != null) { - properties.add(Map.entry("win-menu", withMenuShortcut.toString())); - } - - properties.addAll(rawProperties); - - createFileHandler.accept(propsFile, properties); - } - - private static Path iconInResourceDir(JPackageCommand cmd, - String launcherName) { - Path resourceDir = cmd.getArgumentValue("--resource-dir", () -> null, - Path::of); - if (resourceDir != null) { - Path icon = resourceDir.resolve( - Optional.ofNullable(launcherName).orElseGet(() -> cmd.name()) - + TKit.ICON_SUFFIX); - if (Files.exists(icon)) { - return icon; - } - } - return null; - } - - private void verifyIcon(JPackageCommand cmd) throws IOException { - var verifier = new LauncherIconVerifier().setLauncherName(name); - - if (TKit.isOSX()) { - // On Mac should be no icon files for additional launchers. - verifier.applyTo(cmd); - return; - } - - boolean withLinuxDesktopFile = false; - - final Path effectiveIcon = Optional.ofNullable(icon).orElseGet( - () -> iconInResourceDir(cmd, name)); - while (effectiveIcon != NO_ICON) { - if (effectiveIcon != null) { - withLinuxDesktopFile = Boolean.FALSE != withShortcut; - verifier.setExpectedIcon(effectiveIcon); - break; - } - - Path customMainLauncherIcon = cmd.getArgumentValue("--icon", - () -> iconInResourceDir(cmd, null), Path::of); - if (customMainLauncherIcon != null) { - withLinuxDesktopFile = Boolean.FALSE != withShortcut; - verifier.setExpectedIcon(customMainLauncherIcon); - break; - } - - verifier.setExpectedDefaultIcon(); - break; - } - - if (TKit.isLinux() && !cmd.isImagePackageType()) { - if (effectiveIcon != NO_ICON && !withLinuxDesktopFile) { - withLinuxDesktopFile = (Boolean.FALSE != withShortcut) && - Stream.of("--linux-shortcut").anyMatch(cmd::hasArgument); - verifier.setExpectedDefaultIcon(); - } - Path desktopFile = LinuxHelper.getDesktopFile(cmd, name); - if (withLinuxDesktopFile) { - TKit.assertFileExists(desktopFile); - } else { - TKit.assertPathExists(desktopFile, false); - } - } - - verifier.applyTo(cmd); - } - - private void verifyShortcuts(JPackageCommand cmd) throws IOException { - if (TKit.isLinux() && !cmd.isImagePackageType() - && withShortcut != null) { - Path desktopFile = LinuxHelper.getDesktopFile(cmd, name); - if (withShortcut) { - TKit.assertFileExists(desktopFile); - } else { - TKit.assertPathExists(desktopFile, false); - } - } - } - - private void verifyDescription(JPackageCommand cmd) throws IOException { - if (TKit.isWindows()) { - String expectedDescription = getDesciption(cmd); - Path launcherPath = cmd.appLauncherPath(name); - String actualDescription = - WindowsHelper.getExecutableDesciption(launcherPath); - TKit.assertEquals(expectedDescription, actualDescription, - String.format("Check file description of [%s]", launcherPath)); - } else if (TKit.isLinux() && !cmd.isImagePackageType()) { - String expectedDescription = getDesciption(cmd); - Path desktopFile = LinuxHelper.getDesktopFile(cmd, name); - if (Files.exists(desktopFile)) { - TKit.assertTextStream("Comment=" + expectedDescription) - .label(String.format("[%s] file", desktopFile)) - .predicate(String::equals) - .apply(Files.readAllLines(desktopFile)); - } - } - } - - private void verifyInstalled(JPackageCommand cmd, boolean installed) throws IOException { - if (TKit.isLinux() && !cmd.isImagePackageType() && !cmd. - isPackageUnpacked(String.format( - "Not verifying package and system .desktop files for [%s] launcher", - cmd.appLauncherPath(name)))) { - Path packageDesktopFile = LinuxHelper.getDesktopFile(cmd, name); - Path systemDesktopFile = LinuxHelper.getSystemDesktopFilesFolder(). - resolve(packageDesktopFile.getFileName()); - if (Files.exists(packageDesktopFile) && installed) { - TKit.assertFileExists(systemDesktopFile); - TKit.assertStringListEquals(Files.readAllLines( - packageDesktopFile), - Files.readAllLines(systemDesktopFile), String.format( - "Check [%s] and [%s] files are equal", - packageDesktopFile, - systemDesktopFile)); - } else { - TKit.assertPathExists(packageDesktopFile, false); - TKit.assertPathExists(systemDesktopFile, false); - } + properties.put("icon", iconPath); } - } - protected void verifyUninstalled(JPackageCommand cmd) throws IOException { - verifyInstalled(cmd, false); - Path launcherPath = cmd.appLauncherPath(name); - TKit.assertPathExists(launcherPath, false); - } - - protected void verify(JPackageCommand cmd) throws IOException { - verifyIcon(cmd); - verifyShortcuts(cmd); - verifyDescription(cmd); - verifyInstalled(cmd, true); - - Path launcherPath = cmd.appLauncherPath(name); - - TKit.assertExecutableFileExists(launcherPath); - - if (!cmd.canRunLauncher(String.format( - "Not running %s launcher", launcherPath))) { - return; - } + properties.putAll(rawProperties); - var appVerifier = HelloApp.assertApp(launcherPath) - .addDefaultArguments(Optional - .ofNullable(defaultArguments) - .orElseGet(() -> List.of(cmd.getAllArgumentValues("--arguments")))) - .addJavaOptions(Optional - .ofNullable(javaOptions) - .orElseGet(() -> List.of(cmd.getAllArgumentValues( - "--java-options"))).stream().map( - str -> resolveVariables(cmd, str)).toList()); - - if (!rawProperties.contains(LAUNCHER_AS_SERVICE)) { - appVerifier.executeAndVerifyOutput(); - } else if (!cmd.isPackageUnpacked(String.format( - "Not verifying contents of test output file for [%s] launcher", - launcherPath))) { - appVerifier.verifyOutput(); - } + createFileHandler.accept(propsFile, properties.entrySet()); } public static final class PropertyFile { - PropertyFile(Path path) throws IOException { - data = Files.readAllLines(path).stream().map(str -> { - return str.split("=", 2); - }).collect(toMap(tokens -> tokens[0], tokens -> { - if (tokens.length == 1) { - return ""; - } else { - return tokens[1]; - } - }, (oldValue, newValue) -> { - return newValue; - })); + PropertyFile(Map data) { + this.data = new Properties(); + this.data.putAll(data); } - public boolean isPropertySet(String name) { - Objects.requireNonNull(name); - return data.containsKey(name); + PropertyFile(Path path) throws IOException { + data = new Properties(); + try (var reader = Files.newBufferedReader(path)) { + data.load(reader); + } } - public Optional getPropertyValue(String name) { + public Optional findProperty(String name) { Objects.requireNonNull(name); - return Optional.of(data.get(name)); + return Optional.ofNullable(data.getProperty(name)); } - public Optional getPropertyBooleanValue(String name) { - Objects.requireNonNull(name); - return Optional.ofNullable(data.get(name)).map(Boolean::parseBoolean); + public Optional findBooleanProperty(String name) { + return findProperty(name).map(Boolean::parseBoolean); } - private final Map data; + private final Properties data; } - private static String resolveVariables(JPackageCommand cmd, String str) { - var map = Stream.of(JPackageCommand.Macro.values()).collect(toMap(x -> { - return String.format("$%s", x.name()); - }, cmd::macroValue)); - for (var e : map.entrySet()) { - str = str.replaceAll(Pattern.quote(e.getKey()), - Matcher.quoteReplacement(e.getValue().toString())); - } - return str; - } - - private boolean verifyUninstalled; private List javaOptions; private List defaultArguments; private Path icon; private final String name; - private final List> rawProperties; - private BiConsumer>> createFileHandler; - private Boolean withMenuShortcut; - private Boolean withShortcut; - - private static final Path NO_ICON = Path.of(""); - private static final Map.Entry LAUNCHER_AS_SERVICE = Map.entry( - "launcher-as-service", "true"); + private final Map rawProperties = new HashMap<>(); + private BiConsumer>> createFileHandler; + private final Set verifyActions = new HashSet<>(Action.VERIFY_DEFAULTS); + + static final Path NO_ICON = Path.of(""); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AppImageFile.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AppImageFile.java index 2381aecec2e..e676e0d1e87 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AppImageFile.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AppImageFile.java @@ -22,20 +22,28 @@ */ package jdk.jpackage.test; +import static java.util.stream.Collectors.toMap; +import static jdk.jpackage.internal.util.function.ThrowingFunction.toFunction; +import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; + import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.Optional; +import java.util.stream.Stream; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathFactory; import jdk.internal.util.OperatingSystem; import jdk.jpackage.internal.util.XmlUtils; -import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; public record AppImageFile(String mainLauncherName, String mainLauncherClassName, - String version, boolean macSigned, boolean macAppStore) { + String version, boolean macSigned, boolean macAppStore, Map> launchers) { public static Path getPathInAppImage(Path appImageDir) { return ApplicationLayout.platformAppImage() @@ -44,8 +52,23 @@ public static Path getPathInAppImage(Path appImageDir) { .resolve(FILENAME); } + public AppImageFile { + Objects.requireNonNull(mainLauncherName); + Objects.requireNonNull(mainLauncherClassName); + Objects.requireNonNull(version); + if (!launchers.containsKey(mainLauncherName)) { + throw new IllegalArgumentException(); + } + } + public AppImageFile(String mainLauncherName, String mainLauncherClassName) { - this(mainLauncherName, mainLauncherClassName, "1.0", false, false); + this(mainLauncherName, mainLauncherClassName, "1.0", false, false, Map.of(mainLauncherName, Map.of())); + } + + public Map> addLaunchers() { + return launchers.entrySet().stream().filter(e -> { + return !e.getKey().equals(mainLauncherName); + }).collect(toMap(Map.Entry::getKey, Map.Entry::getValue)); } public void save(Path appImageDir) throws IOException { @@ -73,6 +96,18 @@ public void save(Path appImageDir) throws IOException { xml.writeStartElement("app-store"); xml.writeCharacters(Boolean.toString(macAppStore)); xml.writeEndElement(); + + for (var al : addLaunchers().keySet().stream().sorted().toList()) { + xml.writeStartElement("add-launcher"); + xml.writeAttribute("name", al); + var props = launchers.get(al); + for (var prop : props.keySet().stream().sorted().toList()) { + xml.writeStartElement(prop); + xml.writeCharacters(props.get(prop)); + xml.writeEndElement(); + } + xml.writeEndElement(); + } }); } @@ -99,8 +134,34 @@ public static AppImageFile load(Path appImageDir) { "/jpackage-state/app-store/text()", doc)).map( Boolean::parseBoolean).orElse(false); + var addLaunchers = XmlUtils.queryNodes(doc, xPath, "/jpackage-state/add-launcher").map(Element.class::cast).map(toFunction(addLauncher -> { + Map launcherProps = new HashMap<>(); + + // @name and @service attributes. + XmlUtils.toStream(addLauncher.getAttributes()).forEach(attr -> { + launcherProps.put(attr.getNodeName(), attr.getNodeValue()); + }); + + // Extra properties. + XmlUtils.queryNodes(addLauncher, xPath, "*[count(*) = 0]").map(Element.class::cast).forEach(e -> { + launcherProps.put(e.getNodeName(), e.getTextContent()); + }); + + return launcherProps; + })); + + var mainLauncherProperties = Map.of("name", mainLauncherName); + + var launchers = Stream.concat(Stream.of(mainLauncherProperties), addLaunchers).collect(toMap(attrs -> { + return Objects.requireNonNull(attrs.get("name")); + }, attrs -> { + Map copy = new HashMap<>(attrs); + copy.remove("name"); + return Map.copyOf(copy); + })); + return new AppImageFile(mainLauncherName, mainLauncherClassName, - version, macSigned, macAppStore); + version, macSigned, macAppStore, launchers); }).get(); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CfgFile.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CfgFile.java index 9df28b3915e..52e8ecf819b 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CfgFile.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CfgFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,13 +59,18 @@ public String getValueUnchecked(String sectionName, String key) { } } - public void addValue(String sectionName, String key, String value) { + public CfgFile addValue(String sectionName, String key, String value) { var section = getSection(sectionName); if (section == null) { section = new Section(sectionName, new ArrayList<>()); data.add(section); } section.data.add(Map.entry(key, value)); + return this; + } + + public CfgFile add(CfgFile other) { + return combine(this, other); } public CfgFile() { @@ -89,7 +94,7 @@ private CfgFile(List

    data, String id) { this.id = id; } - public void save(Path path) { + public CfgFile save(Path path) { var lines = data.stream().flatMap(section -> { return Stream.concat( Stream.of(String.format("[%s]", section.name)), @@ -98,6 +103,7 @@ public void save(Path path) { })); }); TKit.createTextFile(path, lines); + return this; } private Section getSection(String name) { diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CommandArguments.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CommandArguments.java index cb7f0574afd..4a78ad40cd1 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CommandArguments.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CommandArguments.java @@ -35,16 +35,17 @@ public class CommandArguments { } public final T clearArguments() { + verifyMutable(); args.clear(); return thiz(); } public final T addArgument(String v) { - args.add(v); - return thiz(); + return addArguments(v); } public final T addArguments(List v) { + verifyMutable(); args.addAll(v); return thiz(); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ConfigFilesStasher.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ConfigFilesStasher.java index 98c79131045..e630659bdb1 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ConfigFilesStasher.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ConfigFilesStasher.java @@ -220,7 +220,7 @@ private static boolean isWithServices(JPackageCommand cmd) { AdditionalLauncher.forEachAdditionalLauncher(cmd, (launcherName, propertyFilePath) -> { try { final var launcherAsService = new AdditionalLauncher.PropertyFile(propertyFilePath) - .getPropertyBooleanValue("launcher-as-service").orElse(false); + .findBooleanProperty("launcher-as-service").orElse(false); if (launcherAsService) { withServices[0] = true; } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java index 7f9feb986b4..9439221260b 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java @@ -72,7 +72,7 @@ public JPackageCommand() { verifyActions = new Actions(); } - public JPackageCommand(JPackageCommand cmd) { + private JPackageCommand(JPackageCommand cmd, boolean immutable) { args.addAll(cmd.args); withToolProvider = cmd.withToolProvider; saveConsoleOutput = cmd.saveConsoleOutput; @@ -81,7 +81,7 @@ public JPackageCommand(JPackageCommand cmd) { suppressOutput = cmd.suppressOutput; ignoreDefaultRuntime = cmd.ignoreDefaultRuntime; ignoreDefaultVerbose = cmd.ignoreDefaultVerbose; - immutable = cmd.immutable; + this.immutable = immutable; dmgInstallDir = cmd.dmgInstallDir; prerequisiteActions = new Actions(cmd.prerequisiteActions); verifyActions = new Actions(cmd.verifyActions); @@ -90,12 +90,15 @@ public JPackageCommand(JPackageCommand cmd) { outputValidators = cmd.outputValidators; executeInDirectory = cmd.executeInDirectory; winMsiLogFile = cmd.winMsiLogFile; + unpackedPackageDirectory = cmd.unpackedPackageDirectory; } JPackageCommand createImmutableCopy() { - JPackageCommand reply = new JPackageCommand(this); - reply.immutable = true; - return reply; + return new JPackageCommand(this, true); + } + + JPackageCommand createMutableCopy() { + return new JPackageCommand(this, false); } public JPackageCommand setArgumentValue(String argName, String newValue) { @@ -316,13 +319,11 @@ public JPackageCommand setFakeRuntime() { } JPackageCommand addPrerequisiteAction(ThrowingConsumer action) { - verifyMutable(); prerequisiteActions.add(action); return this; } JPackageCommand addVerifyAction(ThrowingConsumer action) { - verifyMutable(); verifyActions.add(action); return this; } @@ -484,7 +485,7 @@ public Path pathToPackageFile(Path path) { Path unpackedPackageDirectory() { verifyIsOfType(PackageType.NATIVE); - return getArgumentValue(UNPACKED_PATH_ARGNAME, () -> null, Path::of); + return unpackedPackageDirectory; } /** @@ -662,7 +663,7 @@ public boolean isPackageUnpacked(String msg) { } public boolean isPackageUnpacked() { - return hasArgument(UNPACKED_PATH_ARGNAME); + return unpackedPackageDirectory != null; } public static void useToolProviderByDefault(ToolProvider jpackageToolProvider) { @@ -791,11 +792,6 @@ public JPackageCommand executePrerequisiteActions() { return this; } - public JPackageCommand executeVerifyActions() { - verifyActions.run(); - return this; - } - private Executor createExecutor() { Executor exec = new Executor() .saveOutput(saveConsoleOutput).dumpOutput(!suppressOutput) @@ -820,6 +816,7 @@ public Executor.Result execute() { } public Executor.Result execute(int expectedExitCode) { + verifyMutable(); executePrerequisiteActions(); if (hasArgument("--dest")) { @@ -859,7 +856,7 @@ public Executor.Result execute(int expectedExitCode) { ConfigFilesStasher.INSTANCE.accept(this); } - final var copy = new JPackageCommand(this).adjustArgumentsBeforeExecution(); + final var copy = createMutableCopy().adjustArgumentsBeforeExecution(); final var directoriesAssert = new ReadOnlyPathsAssert(copy); @@ -876,7 +873,7 @@ public Executor.Result execute(int expectedExitCode) { } if (result.exitCode() == 0) { - executeVerifyActions(); + verifyActions.run(); } return result; @@ -884,7 +881,7 @@ public Executor.Result execute(int expectedExitCode) { public Executor.Result executeAndAssertHelloAppImageCreated() { Executor.Result result = executeAndAssertImageCreated(); - HelloApp.executeLauncherAndVerifyOutput(this); + LauncherVerifier.executeMainLauncherAndVerifyOutput(this); return result; } @@ -1046,6 +1043,7 @@ private static Stream tokenizeValue(String str) { } public JPackageCommand setReadOnlyPathAsserts(ReadOnlyPathAssert... asserts) { + verifyMutable(); readOnlyPathAsserts = Set.of(asserts); return this; } @@ -1059,18 +1057,21 @@ public JPackageCommand excludeReadOnlyPathAssert(ReadOnlyPathAssert... asserts) public static enum AppLayoutAssert { APP_IMAGE_FILE(JPackageCommand::assertAppImageFile), PACKAGE_FILE(JPackageCommand::assertPackageFile), - MAIN_LAUNCHER(cmd -> { + NO_MAIN_LAUNCHER_IN_RUNTIME(cmd -> { if (cmd.isRuntime()) { TKit.assertPathExists(convertFromRuntime(cmd).appLauncherPath(), false); - } else { - TKit.assertExecutableFileExists(cmd.appLauncherPath()); } }), - MAIN_LAUNCHER_CFG_FILE(cmd -> { + NO_MAIN_LAUNCHER_CFG_FILE_IN_RUNTIME(cmd -> { if (cmd.isRuntime()) { TKit.assertPathExists(convertFromRuntime(cmd).appLauncherCfgPath(null), false); - } else { - TKit.assertFileExists(cmd.appLauncherCfgPath(null)); + } + }), + MAIN_LAUNCHER_FILES(cmd -> { + if (!cmd.isRuntime()) { + new LauncherVerifier(cmd).verify(cmd, + LauncherVerifier.Action.VERIFY_INSTALLED, + LauncherVerifier.Action.VERIFY_MAC_ENTITLEMENTS); } }), MAIN_JAR_FILE(cmd -> { @@ -1101,7 +1102,7 @@ public static enum AppLayoutAssert { } private static JPackageCommand convertFromRuntime(JPackageCommand cmd) { - var copy = new JPackageCommand(cmd); + var copy = cmd.createMutableCopy(); copy.immutable = false; copy.removeArgumentWithValue("--runtime-image"); copy.dmgInstallDir = cmd.appInstallationDirectory(); @@ -1115,6 +1116,7 @@ private static JPackageCommand convertFromRuntime(JPackageCommand cmd) { } public JPackageCommand setAppLayoutAsserts(AppLayoutAssert ... asserts) { + verifyMutable(); appLayoutAsserts = Set.of(asserts); return this; } @@ -1161,12 +1163,12 @@ private void assertAppImageFile() { } else { assertFileInAppImage(lookupPath); - if (TKit.isOSX()) { - final Path rootDir = isImagePackageType() ? outputBundle() : - pathToUnpackedPackageFile(appInstallationDirectory()); + final Path rootDir = isImagePackageType() ? outputBundle() : + pathToUnpackedPackageFile(appInstallationDirectory()); - AppImageFile aif = AppImageFile.load(rootDir); + final AppImageFile aif = AppImageFile.load(rootDir); + if (TKit.isOSX()) { boolean expectedValue = MacHelper.appImageSigned(this); boolean actualValue = aif.macSigned(); TKit.assertEquals(expectedValue, actualValue, @@ -1177,6 +1179,11 @@ private void assertAppImageFile() { TKit.assertEquals(expectedValue, actualValue, "Check for unexpected value of property in app image file"); } + + TKit.assertStringListEquals( + addLauncherNames().stream().sorted().toList(), + aif.addLaunchers().keySet().stream().sorted().toList(), + "Check additional launcher names"); } } @@ -1258,16 +1265,14 @@ private void assertFileInAppImage(Path filename, Path expectedPath) { } JPackageCommand setUnpackedPackageLocation(Path path) { + verifyMutable(); verifyIsOfType(PackageType.NATIVE); - if (path != null) { - setArgumentValue(UNPACKED_PATH_ARGNAME, path); - } else { - removeArgumentWithValue(UNPACKED_PATH_ARGNAME); - } + unpackedPackageDirectory = path; return this; } JPackageCommand winMsiLogFile(Path v) { + verifyMutable(); if (!TKit.isWindows()) { throw new UnsupportedOperationException(); } @@ -1290,6 +1295,7 @@ public Optional> winMsiLogFileContents() { } private JPackageCommand adjustArgumentsBeforeExecution() { + verifyMutable(); if (!isWithToolProvider()) { // if jpackage is launched as a process then set the jlink.debug system property // to allow the jlink process to print exception stacktraces on any failure @@ -1473,6 +1479,7 @@ public void run() { private final Actions verifyActions; private Path executeInDirectory; private Path winMsiLogFile; + private Path unpackedPackageDirectory; private Set readOnlyPathAsserts = Set.of(ReadOnlyPathAssert.values()); private Set appLayoutAsserts = Set.of(AppLayoutAssert.values()); private List>> outputValidators = new ArrayList<>(); @@ -1500,8 +1507,6 @@ public void run() { return null; }).get(); - private static final String UNPACKED_PATH_ARGNAME = "jpt-unpacked-folder"; - // [HH:mm:ss.SSS] private static final Pattern TIMESTAMP_REGEXP = Pattern.compile( "^\\[\\d\\d:\\d\\d:\\d\\d.\\d\\d\\d\\] "); diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherAsServiceVerifier.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherAsServiceVerifier.java index fd8b4011341..e1cd37fe8b4 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherAsServiceVerifier.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherAsServiceVerifier.java @@ -22,11 +22,19 @@ */ package jdk.jpackage.test; +import static jdk.jpackage.internal.util.function.ThrowingBiConsumer.toBiConsumer; +import static jdk.jpackage.internal.util.function.ThrowingConsumer.toConsumer; +import static jdk.jpackage.test.AdditionalLauncher.forEachAdditionalLauncher; +import static jdk.jpackage.test.PackageType.LINUX; +import static jdk.jpackage.test.PackageType.MAC_PKG; +import static jdk.jpackage.test.PackageType.WINDOWS; + import java.io.IOException; import java.nio.file.FileSystemException; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -36,12 +44,9 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.jpackage.internal.util.PathUtils; -import jdk.jpackage.internal.util.function.ThrowingBiConsumer; -import static jdk.jpackage.internal.util.function.ThrowingConsumer.toConsumer; import jdk.jpackage.internal.util.function.ThrowingRunnable; -import static jdk.jpackage.test.PackageType.LINUX; -import static jdk.jpackage.test.PackageType.MAC_PKG; -import static jdk.jpackage.test.PackageType.WINDOWS; +import jdk.jpackage.test.AdditionalLauncher.PropertyFile; +import jdk.jpackage.test.LauncherVerifier.Action; public final class LauncherAsServiceVerifier { @@ -111,6 +116,7 @@ public void applyTo(PackageTest pkg) { } else { applyToAdditionalLauncher(pkg); } + pkg.addInstallVerifier(this::verifyLauncherExecuted); } static void verify(JPackageCommand cmd) { @@ -127,7 +133,6 @@ static void verify(JPackageCommand cmd) { "service-installer.exe"); if (launcherNames.isEmpty()) { TKit.assertPathExists(serviceInstallerPath, false); - } else { TKit.assertFileExists(serviceInstallerPath); } @@ -188,23 +193,11 @@ static List getLaunchersAsServices(JPackageCommand cmd) { launcherNames.add(null); } - AdditionalLauncher.forEachAdditionalLauncher(cmd, - ThrowingBiConsumer.toBiConsumer( - (launcherName, propFilePath) -> { - if (Files.readAllLines(propFilePath).stream().anyMatch( - line -> { - if (line.startsWith( - "launcher-as-service=")) { - return Boolean.parseBoolean( - line.substring( - "launcher-as-service=".length())); - } else { - return false; - } - })) { - launcherNames.add(launcherName); - } - })); + forEachAdditionalLauncher(cmd, toBiConsumer((launcherName, propFilePath) -> { + if (new PropertyFile(propFilePath).findBooleanProperty("launcher-as-service").orElse(false)) { + launcherNames.add(launcherName); + } + })); return launcherNames; } @@ -237,45 +230,33 @@ private void applyToMainLauncher(PackageTest pkg) { + appOutputFilePathInitialize().toString()); cmd.addArguments("--java-options", "-Djpackage.test.noexit=true"); }); - pkg.addInstallVerifier(cmd -> { - if (canVerifyInstall(cmd)) { - delayInstallVerify(); - Path outputFilePath = appOutputFilePathVerify(cmd); - HelloApp.assertApp(cmd.appLauncherPath()) - .addParam("jpackage.test.appOutput", - outputFilePath.toString()) - .addDefaultArguments(expectedValue) - .verifyOutput(); - deleteOutputFile(outputFilePath); - } - }); - pkg.addInstallVerifier(cmd -> { - verify(cmd, launcherName); - }); } private void applyToAdditionalLauncher(PackageTest pkg) { - AdditionalLauncher al = new AdditionalLauncher(launcherName) { - @Override - protected void verify(JPackageCommand cmd) throws IOException { - if (canVerifyInstall(cmd)) { - delayInstallVerify(); - super.verify(cmd); - deleteOutputFile(appOutputFilePathVerify(cmd)); - } - LauncherAsServiceVerifier.verify(cmd, launcherName); - } - }.setLauncherAsService() - .addJavaOptions("-Djpackage.test.appOutput=" - + appOutputFilePathInitialize().toString()) + var al = new AdditionalLauncher(launcherName) + .setProperty("launcher-as-service", true) + .addJavaOptions("-Djpackage.test.appOutput=" + appOutputFilePathInitialize().toString()) .addJavaOptions("-Djpackage.test.noexit=true") - .addDefaultArguments(expectedValue); + .addDefaultArguments(expectedValue) + .withoutVerifyActions(Action.EXECUTE_LAUNCHER); Optional.ofNullable(additionalLauncherCallback).ifPresent(v -> v.accept(al)); al.applyTo(pkg); } + private void verifyLauncherExecuted(JPackageCommand cmd) throws IOException { + if (canVerifyInstall(cmd)) { + delayInstallVerify(); + Path outputFilePath = appOutputFilePathVerify(cmd); + HelloApp.assertApp(cmd.appLauncherPath()) + .addParam("jpackage.test.appOutput", outputFilePath.toString()) + .addDefaultArguments(expectedValue) + .verifyOutput(); + deleteOutputFile(outputFilePath); + } + } + private static void deleteOutputFile(Path file) throws IOException { try { TKit.deleteIfExists(file); @@ -291,8 +272,7 @@ private static void deleteOutputFile(Path file) throws IOException { } } - private static void verify(JPackageCommand cmd, String launcherName) throws - IOException { + private static void verify(JPackageCommand cmd, String launcherName) throws IOException { if (LINUX.contains(cmd.packageType())) { verifyLinuxUnitFile(cmd, launcherName); } else if (MAC_PKG.equals(cmd.packageType())) { @@ -331,7 +311,7 @@ private static void verifyMacDaemonPlistFile(JPackageCommand cmd, var servicePlist = MacHelper.readPList(servicePlistFile); - var args = servicePlist.queryArrayValue("ProgramArguments"); + var args = servicePlist.queryStringArrayValue("ProgramArguments"); TKit.assertEquals(1, args.size(), "Check number of array elements in 'ProgramArguments' property in the property file"); TKit.assertEquals(installedLauncherPath.toString(), args.get(0), @@ -370,6 +350,9 @@ private Path appOutputFilePathVerify(JPackageCommand cmd) { private final Path appOutputFileName; private final Consumer additionalLauncherCallback; - static final Set SUPPORTED_PACKAGES = Stream.of(LINUX, WINDOWS, - Set.of(MAC_PKG)).flatMap(x -> x.stream()).collect(Collectors.toSet()); + static final Set SUPPORTED_PACKAGES = Stream.of( + LINUX, + WINDOWS, + Set.of(MAC_PKG) + ).flatMap(Collection::stream).collect(Collectors.toSet()); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java index a1971ee0835..6285d9d93a0 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java @@ -46,6 +46,11 @@ public LauncherIconVerifier setExpectedDefaultIcon() { return this; } + public LauncherIconVerifier verifyFileInAppImageOnly(boolean v) { + verifyFileInAppImageOnly = true; + return this; + } + public void applyTo(JPackageCommand cmd) throws IOException { final String curLauncherName; final String label; @@ -62,22 +67,26 @@ public void applyTo(JPackageCommand cmd) throws IOException { if (TKit.isWindows()) { TKit.assertPathExists(iconPath, false); - WinExecutableIconVerifier.verifyLauncherIcon(cmd, launcherName, - expectedIcon, expectedDefault); + if (!verifyFileInAppImageOnly) { + WinExecutableIconVerifier.verifyLauncherIcon(cmd, launcherName, expectedIcon, expectedDefault); + } } else if (expectedDefault) { TKit.assertPathExists(iconPath, true); } else if (expectedIcon == null) { TKit.assertPathExists(iconPath, false); } else { TKit.assertFileExists(iconPath); - TKit.assertTrue(-1 == Files.mismatch(expectedIcon, iconPath), - String.format( - "Check icon file [%s] of %s launcher is a copy of source icon file [%s]", - iconPath, label, expectedIcon)); + if (!verifyFileInAppImageOnly) { + TKit.assertTrue(-1 == Files.mismatch(expectedIcon, iconPath), + String.format( + "Check icon file [%s] of %s launcher is a copy of source icon file [%s]", + iconPath, label, expectedIcon)); + } } } private String launcherName; private Path expectedIcon; private boolean expectedDefault; + private boolean verifyFileInAppImageOnly; } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherShortcut.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherShortcut.java new file mode 100644 index 00000000000..5e86f975870 --- /dev/null +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherShortcut.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jpackage.test; + +import static java.util.stream.Collectors.toMap; +import static jdk.jpackage.test.AdditionalLauncher.getAdditionalLauncherProperties; + +import java.nio.file.Path; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Stream; +import jdk.jpackage.test.AdditionalLauncher.PropertyFile; + +public enum LauncherShortcut { + + LINUX_SHORTCUT("linux-shortcut"), + + WIN_DESKTOP_SHORTCUT("win-shortcut"), + + WIN_START_MENU_SHORTCUT("win-menu"); + + public enum StartupDirectory { + DEFAULT("true"), + ; + + StartupDirectory(String stringValue) { + this.stringValue = Objects.requireNonNull(stringValue); + } + + public String asStringValue() { + return stringValue; + } + + /** + * Returns shortcut startup directory or an empty {@link Optional} instance if + * the value of the {@code str} parameter evaluates to {@code false}. + * + * @param str the value of a shortcut startup directory + * @return shortcut startup directory or an empty {@link Optional} instance + * @throws IllegalArgumentException if the value of the {@code str} parameter is + * unrecognized + */ + static Optional parse(String str) { + Objects.requireNonNull(str); + return Optional.ofNullable(VALUE_MAP.get(str)).or(() -> { + if (Boolean.TRUE.toString().equals(str)) { + return Optional.of(StartupDirectory.DEFAULT); + } else if (Boolean.FALSE.toString().equals(str)) { + return Optional.empty(); + } else { + throw new IllegalArgumentException(String.format( + "Unrecognized launcher shortcut startup directory: [%s]", str)); + } + }); + } + + private final String stringValue; + + private final static Map VALUE_MAP = + Stream.of(values()).collect(toMap(StartupDirectory::asStringValue, x -> x)); + } + + LauncherShortcut(String propertyName) { + this.propertyName = Objects.requireNonNull(propertyName); + } + + public String propertyName() { + return propertyName; + } + + public String appImageFilePropertyName() { + return propertyName.substring(propertyName.indexOf('-') + 1); + } + + public String optionName() { + return "--" + propertyName; + } + + Optional expectShortcut(JPackageCommand cmd, Optional predefinedAppImage, String launcherName) { + Objects.requireNonNull(predefinedAppImage); + + final var name = Optional.ofNullable(launcherName).orElseGet(cmd::name); + + if (name.equals(cmd.name())) { + return findMainLauncherShortcut(cmd); + } else { + String[] propertyName = new String[1]; + return findAddLauncherShortcut(cmd, predefinedAppImage.map(appImage -> { + propertyName[0] = appImageFilePropertyName(); + return new PropertyFile(appImage.addLaunchers().get(launcherName)); + }).orElseGet(() -> { + propertyName[0] = this.propertyName; + return getAdditionalLauncherProperties(cmd, launcherName); + })::findProperty, propertyName[0]); + } + } + + + public interface InvokeShortcutSpec { + String launcherName(); + LauncherShortcut shortcut(); + Optional expectedWorkDirectory(); + List commandLine(); + + default Executor.Result execute() { + return HelloApp.configureAndExecute(0, Executor.of(commandLine()).dumpOutput()); + } + + record Stub( + String launcherName, + LauncherShortcut shortcut, + Optional expectedWorkDirectory, + List commandLine) implements InvokeShortcutSpec { + + public Stub { + Objects.requireNonNull(launcherName); + Objects.requireNonNull(shortcut); + Objects.requireNonNull(expectedWorkDirectory); + Objects.requireNonNull(commandLine); + } + } + } + + + private Optional findMainLauncherShortcut(JPackageCommand cmd) { + if (cmd.hasArgument(optionName())) { + return Optional.of(StartupDirectory.DEFAULT); + } else { + return Optional.empty(); + } + } + + private Optional findAddLauncherShortcut(JPackageCommand cmd, + Function> addlauncherProperties, String propertyName) { + var explicit = addlauncherProperties.apply(propertyName); + if (explicit.isPresent()) { + return explicit.flatMap(StartupDirectory::parse); + } else { + return findMainLauncherShortcut(cmd); + } + } + + private final String propertyName; +} diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherVerifier.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherVerifier.java new file mode 100644 index 00000000000..1ae64288a29 --- /dev/null +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherVerifier.java @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jpackage.test; + +import static java.util.stream.Collectors.toMap; +import static jdk.jpackage.test.AdditionalLauncher.NO_ICON; +import static jdk.jpackage.test.LauncherShortcut.LINUX_SHORTCUT; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.function.BiConsumer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Stream; +import javax.xml.parsers.ParserConfigurationException; +import jdk.jpackage.internal.resources.ResourceLocator; +import jdk.jpackage.internal.util.PListReader; +import jdk.jpackage.internal.util.function.ThrowingBiConsumer; +import jdk.jpackage.internal.util.function.ThrowingSupplier; +import jdk.jpackage.test.AdditionalLauncher.PropertyFile; +import jdk.jpackage.test.LauncherShortcut.StartupDirectory; +import org.xml.sax.SAXException; + +public final class LauncherVerifier { + + LauncherVerifier(JPackageCommand cmd) { + name = cmd.name(); + javaOptions = Optional.empty(); + arguments = Optional.empty(); + icon = Optional.empty(); + properties = Optional.empty(); + } + + LauncherVerifier(String name, + Optional> javaOptions, + Optional> arguments, + Optional icon, + Map properties) { + this.name = Objects.requireNonNull(name); + this.javaOptions = javaOptions.map(List::copyOf); + this.arguments = arguments.map(List::copyOf); + this.icon = icon; + this.properties = Optional.of(new PropertyFile(properties)); + } + + static void executeMainLauncherAndVerifyOutput(JPackageCommand cmd) { + new LauncherVerifier(cmd).verify(cmd, Action.EXECUTE_LAUNCHER); + } + + + public enum Action { + VERIFY_ICON(LauncherVerifier::verifyIcon), + VERIFY_DESCRIPTION(LauncherVerifier::verifyDescription), + VERIFY_INSTALLED((verifier, cmd) -> { + verifier.verifyInstalled(cmd, true); + }), + VERIFY_UNINSTALLED((verifier, cmd) -> { + verifier.verifyInstalled(cmd, false); + }), + VERIFY_MAC_ENTITLEMENTS((verifier, cmd) -> { + if (TKit.isOSX() && MacHelper.appImageSigned(cmd)) { + verifier.verifyMacEntitlements(cmd); + } + }), + EXECUTE_LAUNCHER(LauncherVerifier::executeLauncher), + ; + + Action(ThrowingBiConsumer action) { + this.action = ThrowingBiConsumer.toBiConsumer(action); + } + + private void apply(LauncherVerifier verifier, JPackageCommand cmd) { + action.accept(verifier, cmd); + } + + private final BiConsumer action; + + static final List VERIFY_APP_IMAGE = List.of( + VERIFY_ICON, VERIFY_DESCRIPTION, VERIFY_INSTALLED, VERIFY_MAC_ENTITLEMENTS + ); + + static final List VERIFY_DEFAULTS = Stream.concat( + VERIFY_APP_IMAGE.stream(), Stream.of(EXECUTE_LAUNCHER) + ).toList(); + } + + + void verify(JPackageCommand cmd, Action... actions) { + verify(cmd, List.of(actions)); + } + + void verify(JPackageCommand cmd, Iterable actions) { + Objects.requireNonNull(cmd); + for (var a : actions) { + a.apply(this, cmd); + } + } + + private boolean isMainLauncher() { + return properties.isEmpty(); + } + + private Optional findProperty(String key) { + return properties.flatMap(v -> { + return v.findProperty(key); + }); + } + + private String getDescription(JPackageCommand cmd) { + return findProperty("description").orElseGet(() -> { + return cmd.getArgumentValue("--description", cmd::name); + }); + } + + private List getArguments(JPackageCommand cmd) { + return getStringArrayProperty(cmd, "--arguments", arguments); + } + + private List getJavaOptions(JPackageCommand cmd) { + return getStringArrayProperty(cmd, "--java-options", javaOptions); + } + + private List getStringArrayProperty(JPackageCommand cmd, String optionName, Optional> items) { + Objects.requireNonNull(cmd); + Objects.requireNonNull(optionName); + Objects.requireNonNull(items); + if (isMainLauncher()) { + return List.of(cmd.getAllArgumentValues(optionName)); + } else { + return items.orElseGet(() -> { + return List.of(cmd.getAllArgumentValues(optionName)); + }); + } + } + + private boolean explicitlyNoShortcut(LauncherShortcut shortcut) { + var explicit = findProperty(shortcut.propertyName()); + if (explicit.isPresent()) { + return explicit.flatMap(StartupDirectory::parse).isEmpty(); + } else { + return false; + } + } + + private static boolean explicitShortcutForMainLauncher(JPackageCommand cmd, LauncherShortcut shortcut) { + return cmd.hasArgument(shortcut.optionName()); + } + + private void verifyIcon(JPackageCommand cmd) throws IOException { + initIconVerifier(cmd).applyTo(cmd); + } + + private LauncherIconVerifier initIconVerifier(JPackageCommand cmd) { + var verifier = new LauncherIconVerifier().setLauncherName(name); + + var mainLauncherIcon = Optional.ofNullable(cmd.getArgumentValue("--icon")).map(Path::of).or(() -> { + return iconInResourceDir(cmd, cmd.name()); + }); + + if (TKit.isOSX()) { + // There should be no icon files on Mac for additional launchers, + // and always an icon file for the main launcher. + if (isMainLauncher()) { + mainLauncherIcon.ifPresentOrElse(verifier::setExpectedIcon, verifier::setExpectedDefaultIcon); + } + return verifier; + } + + if (isMainLauncher()) { + mainLauncherIcon.ifPresentOrElse(verifier::setExpectedIcon, verifier::setExpectedDefaultIcon); + } else { + icon.ifPresentOrElse(icon -> { + if (!NO_ICON.equals(icon)) { + verifier.setExpectedIcon(icon); + } + }, () -> { + // No "icon" property in the property file + iconInResourceDir(cmd, name).ifPresentOrElse(verifier::setExpectedIcon, () -> { + // No icon for this additional launcher in the resource directory. + mainLauncherIcon.ifPresentOrElse(verifier::setExpectedIcon, verifier::setExpectedDefaultIcon); + }); + }); + } + + return verifier; + } + + private static boolean withLinuxMainLauncherDesktopFile(JPackageCommand cmd) { + if (!TKit.isLinux() || cmd.isImagePackageType()) { + return false; + } + + return explicitShortcutForMainLauncher(cmd, LINUX_SHORTCUT) + || cmd.hasArgument("--icon") + || cmd.hasArgument("--file-associations") + || iconInResourceDir(cmd, cmd.name()).isPresent(); + } + + private boolean withLinuxDesktopFile(JPackageCommand cmd) { + if (!TKit.isLinux() || cmd.isImagePackageType()) { + return false; + } + + if (isMainLauncher()) { + return withLinuxMainLauncherDesktopFile(cmd); + } else if (explicitlyNoShortcut(LINUX_SHORTCUT) || icon.map(icon -> { + return icon.equals(NO_ICON); + }).orElse(false)) { + return false; + } else if (iconInResourceDir(cmd, name).isPresent() || icon.map(icon -> { + return !icon.equals(NO_ICON); + }).orElse(false)) { + return true; + } else if (findProperty(LINUX_SHORTCUT.propertyName()).flatMap(StartupDirectory::parse).isPresent()) { + return true; + } else { + return withLinuxMainLauncherDesktopFile(cmd.createMutableCopy().removeArgument("--file-associations")); + } + } + + private void verifyDescription(JPackageCommand cmd) throws IOException { + if (TKit.isWindows()) { + String expectedDescription = getDescription(cmd); + Path launcherPath = cmd.appLauncherPath(name); + String actualDescription = + WindowsHelper.getExecutableDescription(launcherPath); + TKit.assertEquals(expectedDescription, actualDescription, + String.format("Check file description of [%s]", launcherPath)); + } else if (TKit.isLinux() && !cmd.isImagePackageType()) { + String expectedDescription = getDescription(cmd); + Path desktopFile = LinuxHelper.getDesktopFile(cmd, name); + if (Files.exists(desktopFile)) { + TKit.assertTextStream("Comment=" + expectedDescription) + .label(String.format("[%s] file", desktopFile)) + .predicate(String::equals) + .apply(Files.readAllLines(desktopFile)); + } + } + } + + private void verifyInstalled(JPackageCommand cmd, boolean installed) throws IOException { + var launcherPath = cmd.appLauncherPath(name); + var launcherCfgFilePath = cmd.appLauncherCfgPath(name); + if (installed) { + TKit.assertExecutableFileExists(launcherPath); + TKit.assertFileExists(launcherCfgFilePath); + } else { + TKit.assertPathExists(launcherPath, false); + TKit.assertPathExists(launcherCfgFilePath, false); + } + + if (TKit.isLinux() && !cmd.isImagePackageType()) { + final var packageDesktopFile = LinuxHelper.getDesktopFile(cmd, name); + final var withLinuxDesktopFile = withLinuxDesktopFile(cmd) && installed; + if (withLinuxDesktopFile) { + TKit.assertFileExists(packageDesktopFile); + } else { + TKit.assertPathExists(packageDesktopFile, false); + } + } + + if (installed) { + initIconVerifier(cmd).verifyFileInAppImageOnly(true).applyTo(cmd); + } + } + + private void verifyMacEntitlements(JPackageCommand cmd) throws ParserConfigurationException, SAXException, IOException { + Path launcherPath = cmd.appLauncherPath(name); + var entitlements = MacSignVerify.findEntitlements(launcherPath); + + TKit.assertTrue(entitlements.isPresent(), String.format("Check [%s] launcher is signed with entitlements", name)); + + Map expected; + if (cmd.hasArgument("--mac-entitlements")) { + expected = new PListReader(Files.readAllBytes(Path.of(cmd.getArgumentValue("--mac-entitlements")))).toMap(true); + } else if (cmd.hasArgument("--mac-app-store")) { + expected = DefaultEntitlements.APP_STORE; + } else { + expected = DefaultEntitlements.STANDARD; + } + + TKit.assertEquals(expected, entitlements.orElseThrow().toMap(true), String.format("Check [%s] launcher is signed with expected entitlements", name)); + } + + private void executeLauncher(JPackageCommand cmd) throws IOException { + Path launcherPath = cmd.appLauncherPath(name); + + if (!cmd.canRunLauncher(String.format("Not running [%s] launcher", launcherPath))) { + return; + } + + var appVerifier = HelloApp.assertApp(launcherPath) + .addDefaultArguments(getArguments(cmd)) + .addJavaOptions(getJavaOptions(cmd).stream().map(str -> { + return resolveVariables(cmd, str); + }).toList()); + + appVerifier.executeAndVerifyOutput(); + } + + private static String resolveVariables(JPackageCommand cmd, String str) { + var map = Stream.of(JPackageCommand.Macro.values()).collect(toMap(x -> { + return String.format("$%s", x.name()); + }, cmd::macroValue)); + for (var e : map.entrySet()) { + str = str.replaceAll(Pattern.quote(e.getKey()), + Matcher.quoteReplacement(e.getValue().toString())); + } + return str; + } + + private static Optional iconInResourceDir(JPackageCommand cmd, String launcherName) { + Objects.requireNonNull(launcherName); + return Optional.ofNullable(cmd.getArgumentValue("--resource-dir")).map(Path::of).map(resourceDir -> { + Path icon = resourceDir.resolve(launcherName + TKit.ICON_SUFFIX); + if (Files.exists(icon)) { + return icon; + } else { + return null; + } + }); + } + + + private static final class DefaultEntitlements { + private static Map loadFromResources(String resourceName) { + return ThrowingSupplier.toSupplier(() -> { + var bytes = ResourceLocator.class.getResourceAsStream(resourceName).readAllBytes(); + return new PListReader(bytes).toMap(true); + }).get(); + } + + static final Map STANDARD = loadFromResources("entitlements.plist"); + static final Map APP_STORE = loadFromResources("sandbox.plist"); + } + + + private final String name; + private final Optional> javaOptions; + private final Optional> arguments; + private final Optional icon; + private final Optional properties; +} diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java index 1669d1f8233..e8f6273b18b 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java @@ -23,25 +23,30 @@ package jdk.jpackage.test; import java.io.IOException; +import java.io.UncheckedIOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.function.Function; +import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.jpackage.internal.util.PathUtils; import jdk.jpackage.internal.util.function.ThrowingConsumer; +import jdk.jpackage.test.LauncherShortcut.InvokeShortcutSpec; import jdk.jpackage.test.PackageTest.PackageHandlers; @@ -308,8 +313,8 @@ static String getRpmBundleProperty(Path bundle, String fieldName) { } static void verifyPackageBundleEssential(JPackageCommand cmd) { - String packageName = LinuxHelper.getPackageName(cmd); - long packageSize = LinuxHelper.getInstalledPackageSizeKB(cmd); + String packageName = getPackageName(cmd); + long packageSize = getInstalledPackageSizeKB(cmd); TKit.trace("InstalledPackageSize: " + packageSize); TKit.assertNotEquals(0, packageSize, String.format( "Check installed size of [%s] package in not zero", packageName)); @@ -330,7 +335,7 @@ static void verifyPackageBundleEssential(JPackageCommand cmd) { checkPrerequisites = packageSize > 5; } - List prerequisites = LinuxHelper.getPrerequisitePackages(cmd); + List prerequisites = getPrerequisitePackages(cmd); if (checkPrerequisites) { final String vitalPackage = "libc"; TKit.assertTrue(prerequisites.stream().filter( @@ -340,13 +345,28 @@ static void verifyPackageBundleEssential(JPackageCommand cmd) { vitalPackage, prerequisites, packageName)); } else { TKit.trace(String.format( - "Not cheking %s required packages of [%s] package", + "Not checking %s required packages of [%s] package", prerequisites, packageName)); } } - static void addBundleDesktopIntegrationVerifier(PackageTest test, - boolean integrated) { + public static Collection getInvokeShortcutSpecs(JPackageCommand cmd) { + cmd.verifyIsOfType(PackageType.LINUX); + + final var desktopFiles = getDesktopFiles(cmd); + final var predefinedAppImage = Optional.ofNullable(cmd.getArgumentValue("--app-image")).map(Path::of).map(AppImageFile::load); + + return desktopFiles.stream().map(desktopFile -> { + var systemDesktopFile = getSystemDesktopFilesFolder().resolve(desktopFile.getFileName()); + return new InvokeShortcutSpec.Stub( + launcherNameFromDesktopFile(cmd, predefinedAppImage, desktopFile), + LauncherShortcut.LINUX_SHORTCUT, + new DesktopFile(systemDesktopFile, false).findQuotedValue("Path").map(Path::of), + List.of("gtk-launch", PathUtils.replaceSuffix(systemDesktopFile.getFileName(), "").toString())); + }).toList(); + } + + static void addBundleDesktopIntegrationVerifier(PackageTest test, boolean integrated) { final String xdgUtils = "xdg-utils"; Function, String> verifier = (lines) -> { @@ -392,52 +412,81 @@ static void addBundleDesktopIntegrationVerifier(PackageTest test, }); test.addInstallVerifier(cmd -> { - // Verify .desktop files. - try (var files = Files.list(cmd.appLayout().desktopIntegrationDirectory())) { - List desktopFiles = files - .filter(path -> path.getFileName().toString().endsWith(".desktop")) - .toList(); - if (!integrated) { - TKit.assertStringListEquals(List.of(), - desktopFiles.stream().map(Path::toString).collect( - Collectors.toList()), - "Check there are no .desktop files in the package"); - } - for (var desktopFile : desktopFiles) { - verifyDesktopFile(cmd, desktopFile); - } + if (!integrated) { + TKit.assertStringListEquals( + List.of(), + getDesktopFiles(cmd).stream().map(Path::toString).toList(), + "Check there are no .desktop files in the package"); } }); } - private static void verifyDesktopFile(JPackageCommand cmd, Path desktopFile) - throws IOException { - TKit.trace(String.format("Check [%s] file BEGIN", desktopFile)); + static void verifyDesktopFiles(JPackageCommand cmd, boolean installed) { + final var desktopFiles = getDesktopFiles(cmd); + try { + if (installed) { + var predefinedAppImage = Optional.ofNullable(cmd.getArgumentValue("--app-image")).map(Path::of).map(AppImageFile::load); + for (var desktopFile : desktopFiles) { + verifyDesktopFile(cmd, predefinedAppImage, desktopFile); + } - var launcherName = Stream.of(List.of(cmd.name()), cmd.addLauncherNames()).flatMap(List::stream).filter(name -> { - return getDesktopFile(cmd, name).equals(desktopFile); - }).findAny(); - if (!cmd.hasArgument("--app-image")) { - TKit.assertTrue(launcherName.isPresent(), - "Check the desktop file corresponds to one of app launchers"); + if (!cmd.isPackageUnpacked("Not verifying system .desktop files")) { + for (var desktopFile : desktopFiles) { + Path systemDesktopFile = getSystemDesktopFilesFolder().resolve(desktopFile.getFileName()); + TKit.assertFileExists(systemDesktopFile); + TKit.assertStringListEquals( + Files.readAllLines(desktopFile), + Files.readAllLines(systemDesktopFile), + String.format("Check [%s] and [%s] files are equal", desktopFile, systemDesktopFile)); + } + } + } else { + for (var desktopFile : getDesktopFiles(cmd)) { + Path systemDesktopFile = getSystemDesktopFilesFolder().resolve(desktopFile.getFileName()); + TKit.assertPathExists(systemDesktopFile, false); + } + } + } catch (IOException ex) { + throw new UncheckedIOException(ex); } + } - List lines = Files.readAllLines(desktopFile); - TKit.assertEquals("[Desktop Entry]", lines.get(0), "Check file header"); + private static Collection getDesktopFiles(JPackageCommand cmd) { + var unpackedDir = cmd.appLayout().desktopIntegrationDirectory(); + var packageDir = cmd.pathToPackageFile(unpackedDir); + return getPackageFiles(cmd).filter(path -> { + return packageDir.equals(path.getParent()) && path.getFileName().toString().endsWith(".desktop"); + }).map(Path::getFileName).map(unpackedDir::resolve).toList(); + } - Map data = lines.stream() - .skip(1) - .peek(str -> TKit.assertTextStream("=").predicate(String::contains).apply(List.of(str))) - .map(str -> { - String components[] = str.split("=(?=.+)"); - if (components.length == 1) { - return Map.entry(str.substring(0, str.length() - 1), ""); - } - return Map.entry(components[0], components[1]); - }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> { - TKit.assertUnexpected("Multiple values of the same key"); + private static String launcherNameFromDesktopFile(JPackageCommand cmd, Optional predefinedAppImage, Path desktopFile) { + Objects.requireNonNull(cmd); + Objects.requireNonNull(predefinedAppImage); + Objects.requireNonNull(desktopFile); + + return predefinedAppImage.map(v -> { + return v.launchers().keySet().stream(); + }).orElseGet(() -> { + return Stream.concat(Stream.of(cmd.name()), cmd.addLauncherNames().stream()); + }).filter(name-> { + return getDesktopFile(cmd, name).equals(desktopFile); + }).findAny().orElseThrow(() -> { + TKit.assertUnexpected(String.format("Failed to find launcher corresponding to [%s] file", desktopFile)); + // Unreachable return null; - })); + }); + } + + private static void verifyDesktopFile(JPackageCommand cmd, Optional predefinedAppImage, Path desktopFile) throws IOException { + Objects.requireNonNull(cmd); + Objects.requireNonNull(predefinedAppImage); + Objects.requireNonNull(desktopFile); + + TKit.trace(String.format("Check [%s] file BEGIN", desktopFile)); + + var launcherName = launcherNameFromDesktopFile(cmd, predefinedAppImage, desktopFile); + + var data = new DesktopFile(desktopFile, true); final Set mandatoryKeys = new HashSet<>(Set.of("Name", "Comment", "Exec", "Icon", "Terminal", "Type", "Categories")); @@ -447,34 +496,44 @@ private static void verifyDesktopFile(JPackageCommand cmd, Path desktopFile) for (var e : Map.of("Type", "Application", "Terminal", "false").entrySet()) { String key = e.getKey(); - TKit.assertEquals(e.getValue(), data.get(key), String.format( + TKit.assertEquals(e.getValue(), data.find(key).orElseThrow(), String.format( "Check value of [%s] key", key)); } - // Verify the value of `Exec` key is escaped if required - String launcherPath = data.get("Exec"); - if (Pattern.compile("\\s").matcher(launcherPath).find()) { - TKit.assertTrue(launcherPath.startsWith("\"") - && launcherPath.endsWith("\""), - "Check path to the launcher is enclosed in double quotes"); - launcherPath = launcherPath.substring(1, launcherPath.length() - 1); - } + String launcherPath = data.findQuotedValue("Exec").orElseThrow(); - if (launcherName.isPresent()) { - TKit.assertEquals(launcherPath, cmd.pathToPackageFile( - cmd.appLauncherPath(launcherName.get())).toString(), - String.format( - "Check the value of [Exec] key references [%s] app launcher", - launcherName.get())); - } + TKit.assertEquals( + launcherPath, + cmd.pathToPackageFile(cmd.appLauncherPath(launcherName)).toString(), + String.format("Check the value of [Exec] key references [%s] app launcher", launcherName)); + + var appLayout = cmd.appLayout(); + + LauncherShortcut.LINUX_SHORTCUT.expectShortcut(cmd, predefinedAppImage, launcherName).map(shortcutWorkDirType -> { + switch (shortcutWorkDirType) { + case DEFAULT -> { + return (Path)null; + } + default -> { + throw new AssertionError(); + } + } + }).map(Path::toString).ifPresentOrElse(shortcutWorkDir -> { + var actualShortcutWorkDir = data.find("Path"); + TKit.assertTrue(actualShortcutWorkDir.isPresent(), "Check [Path] key exists"); + TKit.assertEquals(actualShortcutWorkDir.get(), shortcutWorkDir, "Check the value of [Path] key"); + }, () -> { + TKit.assertTrue(data.find("Path").isEmpty(), "Check there is no [Path] key"); + }); for (var e : List.>, Function>>of( Map.entry(Map.entry("Exec", Optional.of(launcherPath)), ApplicationLayout::launchersDirectory), Map.entry(Map.entry("Icon", Optional.empty()), ApplicationLayout::desktopIntegrationDirectory))) { - var path = e.getKey().getValue().or(() -> Optional.of(data.get( - e.getKey().getKey()))).map(Path::of).get(); + var path = e.getKey().getValue().or(() -> { + return data.findQuotedValue(e.getKey().getKey()); + }).map(Path::of).get(); TKit.assertFileExists(cmd.pathToUnpackedPackageFile(path)); - Path expectedDir = cmd.pathToPackageFile(e.getValue().apply(cmd.appLayout())); + Path expectedDir = cmd.pathToPackageFile(e.getValue().apply(appLayout)); TKit.assertTrue(path.getParent().equals(expectedDir), String.format( "Check the value of [%s] key references a file in [%s] folder", e.getKey().getKey(), expectedDir)); @@ -761,6 +820,62 @@ private static Method initGetServiceUnitFileName() { } } + + private static final class DesktopFile { + DesktopFile(Path path, boolean verify) { + try { + List lines = Files.readAllLines(path); + if (verify) { + TKit.assertEquals("[Desktop Entry]", lines.getFirst(), "Check file header"); + } + + var stream = lines.stream().skip(1).filter(Predicate.not(String::isEmpty)); + if (verify) { + stream = stream.peek(str -> { + TKit.assertTextStream("=").predicate(String::contains).apply(List.of(str)); + }); + } + + data = stream.map(str -> { + String components[] = str.split("=(?=.+)"); + if (components.length == 1) { + return Map.entry(str.substring(0, str.length() - 1), ""); + } else { + return Map.entry(components[0], components[1]); + } + }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + } + + Set keySet() { + return data.keySet(); + } + + Optional find(String property) { + return Optional.ofNullable(data.get(Objects.requireNonNull(property))); + } + + Optional findQuotedValue(String property) { + return find(property).map(value -> { + if (Pattern.compile("\\s").matcher(value).find()) { + boolean quotesMatched = value.startsWith("\"") && value.endsWith("\""); + if (!quotesMatched) { + TKit.assertTrue(quotesMatched, + String.format("Check the value of key [%s] is enclosed in double quotes", property)); + } + return value.substring(1, value.length() - 1); + } else { + return value; + } + }); + } + + private final Map data; + } + + static final Set CRITICAL_RUNTIME_FILES = Set.of(Path.of( "lib/server/libjvm.so")); diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java index 7b676737ed3..07a553dd8ba 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java @@ -32,6 +32,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.List; +import java.util.NoSuchElementException; import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -74,9 +75,23 @@ public static void withExplodedDmg(JPackageCommand cmd, Path mountPoint = null; try { - var plist = readPList(attachExecutor.getOutput()); - mountPoint = Path.of(plist.queryValue("mount-point")); + // One of "dict" items of "system-entities" array property should contain "mount-point" string property. + mountPoint = readPList(attachExecutor.getOutput()).queryArrayValue("system-entities", false).map(PListReader.class::cast).map(dict -> { + try { + return dict.queryValue("mount-point"); + } catch (NoSuchElementException ex) { + return (String)null; + } + }).filter(Objects::nonNull).map(Path::of).findFirst().orElseThrow(); + } finally { + if (mountPoint == null) { + TKit.trace("Unexpected plist file missing `system-entities` array:"); + attachExecutor.getOutput().forEach(TKit::trace); + TKit.trace("Done"); + } + } + try { // code here used to copy just or .app // We now have option to include arbitrary content, so we copy // everything in the mounted image. diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSignVerify.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSignVerify.java index 432433b4fd0..ae27e292bf6 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSignVerify.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSignVerify.java @@ -56,6 +56,17 @@ public static void assertAdhocSigned(Path path) { String.format("Check [%s] signed with adhoc signature", path)); } + public static Optional findEntitlements(Path path) { + final var exec = Executor.of("/usr/bin/codesign", "-d", "--entitlements", "-", "--xml", path.toString()).saveOutput().dumpOutput(); + final var result = exec.execute(); + var xml = result.stdout().getOutput(); + if (xml.isEmpty()) { + return Optional.empty(); + } else { + return Optional.of(MacHelper.readPList(xml)); + } + } + public static void assertUnsigned(Path path) { TKit.assertTrue(findSpctlSignOrigin(SpctlType.EXEC, path).isEmpty(), String.format("Check [%s] unsigned", path)); diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MsiDatabase.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MsiDatabase.java new file mode 100644 index 00000000000..87236575e2e --- /dev/null +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MsiDatabase.java @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jpackage.test; + + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + + +final class MsiDatabase { + + static MsiDatabase load(Path msiFile, Path idtFileOutputDir, Set tableNames) { + try { + Files.createDirectories(idtFileOutputDir); + + var orderedTableNames = tableNames.stream().sorted().toList(); + + Executor.of("cscript.exe", "//Nologo") + .addArgument(TKit.TEST_SRC_ROOT.resolve("resources/msi-export.js")) + .addArgument(msiFile) + .addArgument(idtFileOutputDir) + .addArguments(orderedTableNames.stream().map(Table::tableName).toList()) + .dumpOutput() + .execute(0); + + var tables = orderedTableNames.stream().map(tableName -> { + return Map.entry(tableName, idtFileOutputDir.resolve(tableName + ".idt")); + }).filter(e -> { + return Files.exists(e.getValue()); + }).collect(Collectors.toMap(Map.Entry::getKey, e -> { + return MsiTable.loadFromTextArchiveFile(e.getValue()); + })); + + return new MsiDatabase(tables); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + } + + + enum Table { + COMPONENT("Component"), + DIRECTORY("Directory"), + FILE("File"), + PROPERTY("Property"), + SHORTCUT("Shortcut"), + ; + + Table(String name) { + this.tableName = Objects.requireNonNull(name); + } + + String tableName() { + return tableName; + } + + private final String tableName; + + static final Set
    FIND_PROPERTY_REQUIRED_TABLES = Set.of(PROPERTY); + static final Set
    LIST_SHORTCUTS_REQUIRED_TABLES = Set.of(COMPONENT, DIRECTORY, FILE, SHORTCUT); + } + + + private MsiDatabase(Map tables) { + this.tables = Map.copyOf(tables); + } + + Set
    tableNames() { + return tables.keySet(); + } + + MsiDatabase append(MsiDatabase other) { + Map newTables = new HashMap<>(tables); + newTables.putAll(other.tables); + return new MsiDatabase(newTables); + } + + Optional findProperty(String propertyName) { + Objects.requireNonNull(propertyName); + return tables.get(Table.PROPERTY).findRow("Property", propertyName).map(row -> { + return row.apply("Value"); + }); + } + + Collection listShortcuts() { + var shortcuts = tables.get(Table.SHORTCUT); + if (shortcuts == null) { + return List.of(); + } + return IntStream.range(0, shortcuts.rowCount()).mapToObj(i -> { + var row = shortcuts.row(i); + var shortcutPath = directoryPath(row.apply("Directory_")).resolve(fileNameFromFieldValue(row.apply("Name"))); + var workDir = directoryPath(row.apply("WkDir")); + var shortcutTarget = Path.of(expandFormattedString(row.apply("Target"))); + return new Shortcut(shortcutPath, shortcutTarget, workDir); + }).toList(); + } + + record Shortcut(Path path, Path target, Path workDir) { + + Shortcut { + Objects.requireNonNull(path); + Objects.requireNonNull(target); + Objects.requireNonNull(workDir); + } + + void assertEquals(Shortcut expected) { + TKit.assertEquals(expected.path, path, "Check the shortcut path"); + TKit.assertEquals(expected.target, target, "Check the shortcut target"); + TKit.assertEquals(expected.workDir, workDir, "Check the shortcut work directory"); + } + } + + private Path directoryPath(String directoryId) { + var table = tables.get(Table.DIRECTORY); + Path result = null; + for (var row = table.findRow("Directory", directoryId); + row.isPresent(); + directoryId = row.get().apply("Directory_Parent"), row = table.findRow("Directory", directoryId)) { + + Path pathComponent; + if (DIRECTORY_PROPERTIES.contains(directoryId)) { + pathComponent = Path.of(directoryId); + directoryId = null; + } else { + pathComponent = fileNameFromFieldValue(row.get().apply("DefaultDir")); + } + + if (result != null) { + result = pathComponent.resolve(result); + } else { + result = pathComponent; + } + + if (directoryId == null) { + break; + } + } + + return Objects.requireNonNull(result); + } + + private String expandFormattedString(String str) { + return expandFormattedString(str, token -> { + if (token.charAt(0) == '#') { + var filekey = token.substring(1); + var fileRow = tables.get(Table.FILE).findRow("File", filekey).orElseThrow(); + + var component = fileRow.apply("Component_"); + var componentRow = tables.get(Table.COMPONENT).findRow("Component", component).orElseThrow(); + + var fileName = fileNameFromFieldValue(fileRow.apply("FileName")); + var filePath = directoryPath(componentRow.apply("Directory_")); + + return filePath.resolve(fileName).toString(); + } else { + throw new UnsupportedOperationException(String.format( + "Unrecognized token [%s] in formatted string [%s]", token, str)); + } + }); + } + + private static Path fileNameFromFieldValue(String fieldValue) { + var pipeIdx = fieldValue.indexOf('|'); + if (pipeIdx < 0) { + return Path.of(fieldValue); + } else { + return Path.of(fieldValue.substring(pipeIdx + 1)); + } + } + + private static String expandFormattedString(String str, Function callback) { + // Naive implementation of https://learn.microsoft.com/en-us/windows/win32/msi/formatted + // - No recursive property expansion. + // - No curly brakes ({}) handling. + + Objects.requireNonNull(str); + Objects.requireNonNull(callback); + var sb = new StringBuffer(); + var m = FORMATTED_STRING_TOKEN.matcher(str); + while (m.find()) { + var token = m.group(); + token = token.substring(1, token.length() - 1); + if (token.equals("~")) { + m.appendReplacement(sb, "\0"); + } else { + var replacement = Matcher.quoteReplacement(callback.apply(token)); + m.appendReplacement(sb, replacement); + } + } + m.appendTail(sb); + return sb.toString(); + } + + + private record MsiTable(Map> columns) { + + MsiTable { + Objects.requireNonNull(columns); + if (columns.isEmpty()) { + throw new IllegalArgumentException("Table should have columns"); + } + } + + Optional> findRow(String columnName, String fieldValue) { + Objects.requireNonNull(columnName); + Objects.requireNonNull(fieldValue); + var column = columns.get(columnName); + for (int i = 0; i != column.size(); i++) { + if (fieldValue.equals(column.get(i))) { + return Optional.of(row(i)); + } + } + return Optional.empty(); + } + + /** + * Loads a table from a text archive file. + * @param idtFile path to the input text archive file + * @return the table + */ + static MsiTable loadFromTextArchiveFile(Path idtFile) { + + var header = IdtFileHeader.loadFromTextArchiveFile(idtFile); + + Map> columns = new HashMap<>(); + header.columns.forEach(column -> { + columns.put(column, new ArrayList<>()); + }); + + try { + var lines = Files.readAllLines(idtFile, header.charset()).toArray(String[]::new); + for (int i = 3; i != lines.length; i++) { + var line = lines[i]; + var row = line.split("\t", -1); + if (row.length != header.columns().size()) { + throw new IllegalArgumentException(String.format( + "Expected %d columns. Actual is %d in line %d in [%s] file", + header.columns().size(), row.length, i, idtFile)); + } + for (int j = 0; j != row.length; j++) { + var field = row[j]; + // https://learn.microsoft.com/en-us/windows/win32/msi/archive-file-format + field = field.replace((char)21, (char)0); + field = field.replace((char)27, '\b'); + field = field.replace((char)16, '\t'); + field = field.replace((char)25, '\n'); + field = field.replace((char)24, '\f'); + field = field.replace((char)17, '\r'); + columns.get(header.columns.get(j)).add(field); + } + } + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + + return new MsiTable(columns); + } + + int columnCount() { + return columns.size(); + } + + int rowCount() { + return columns.values().stream().findAny().orElseThrow().size(); + } + + Function row(int rowIndex) { + return columnName -> { + var column = Objects.requireNonNull(columns.get(Objects.requireNonNull(columnName))); + return column.get(rowIndex); + }; + } + } + + + private record IdtFileHeader(Charset charset, List columns) { + + IdtFileHeader { + Objects.requireNonNull(charset); + columns.forEach(Objects::requireNonNull); + if (columns.isEmpty()) { + throw new IllegalArgumentException("Table should have columns"); + } + } + + /** + * Loads a table header from a text archive (.idt) file. + * @see https://learn.microsoft.com/en-us/windows/win32/msi/archive-file-format + * @see https://learn.microsoft.com/en-us/windows/win32/msi/ascii-data-in-text-archive-files + * @param path path to the input text archive file + * @return the table header + */ + static IdtFileHeader loadFromTextArchiveFile(Path idtFile) { + var charset = StandardCharsets.US_ASCII; + try (var stream = Files.lines(idtFile, charset)) { + var headerLines = stream.limit(3).toList(); + if (headerLines.size() != 3) { + throw new IllegalArgumentException(String.format( + "[%s] file should have at least three text lines", idtFile)); + } + + var columns = headerLines.get(0).split("\t"); + + var header = headerLines.get(2).split("\t", 4); + if (header.length == 3) { + if (Pattern.matches("^[1-9]\\d+$", header[0])) { + charset = Charset.forName(header[0]); + } else { + throw new IllegalArgumentException(String.format( + "Unexpected charset name [%s] in [%s] file", header[0], idtFile)); + } + } else if (header.length != 2) { + throw new IllegalArgumentException(String.format( + "Unexpected number of fields (%d) in the 3rd line of [%s] file", + header.length, idtFile)); + } + + return new IdtFileHeader(charset, List.of(columns)); + + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + } + } + + + private final Map tables; + + // https://learn.microsoft.com/en-us/windows/win32/msi/formatted + private static final Pattern FORMATTED_STRING_TOKEN = Pattern.compile("\\[[^\\]]+\\]"); + + // https://learn.microsoft.com/en-us/windows/win32/msi/property-reference#system-folder-properties + private final Set DIRECTORY_PROPERTIES = Set.of( + "DesktopFolder", + "LocalAppDataFolder", + "ProgramFiles64Folder", + "ProgramMenuFolder" + ); +} diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java index 61e4ccdb4a2..56e09288997 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java @@ -30,11 +30,13 @@ import static jdk.jpackage.test.PackageType.MAC_PKG; import static jdk.jpackage.test.PackageType.NATIVE; import static jdk.jpackage.test.PackageType.WINDOWS; +import static jdk.jpackage.test.PackageType.WIN_MSI; import java.awt.GraphicsEnvironment; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.time.Duration; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -270,10 +272,6 @@ static void withFileAssociationsTestRuns(FileAssociations fa, PackageTest addHelloAppFileAssociationsVerifier(FileAssociations fa) { Objects.requireNonNull(fa); - // Setup test app to have valid jpackage command line before - // running check of type of environment. - addHelloAppInitializer(null); - forTypes(LINUX, () -> { LinuxHelper.addFileAssociationsVerifier(this, fa); }); @@ -296,13 +294,9 @@ PackageTest addHelloAppFileAssociationsVerifier(FileAssociations fa) { Files.deleteIfExists(appOutput); List expectedArgs = testRun.openFiles(testFiles); - TKit.waitForFileCreated(appOutput, 7); + TKit.waitForFileCreated(appOutput, Duration.ofSeconds(7), Duration.ofSeconds(3)); - // Wait a little bit after file has been created to - // make sure there are no pending writes into it. - Thread.sleep(3000); - HelloApp.verifyOutputFile(appOutput, expectedArgs, - Collections.emptyMap()); + HelloApp.verifyOutputFile(appOutput, expectedArgs, Map.of()); }); if (isOfType(cmd, WINDOWS)) { @@ -352,15 +346,14 @@ public PackageTest configureHelloApp() { public PackageTest configureHelloApp(String javaAppDesc) { addHelloAppInitializer(javaAppDesc); - addInstallVerifier(HelloApp::executeLauncherAndVerifyOutput); + addInstallVerifier(LauncherVerifier::executeMainLauncherAndVerifyOutput); return this; } public PackageTest addHelloAppInitializer(String javaAppDesc) { - addInitializer( - cmd -> new HelloApp(JavaAppDesc.parse(javaAppDesc)).addTo(cmd), - "HelloApp"); - return this; + return addInitializer(cmd -> { + new HelloApp(JavaAppDesc.parse(javaAppDesc)).addTo(cmd); + }, "HelloApp"); } public static class Group extends RunnablePackageTest { @@ -603,11 +596,7 @@ private ActionAction analizeAction(Action action) { } } case VERIFY_INSTALL -> { - if (unpackNotSupported()) { - return ActionAction.SKIP; - } - - if (installFailed()) { + if (unpackNotSupported() || installFailed()) { return ActionAction.SKIP; } } @@ -745,6 +734,8 @@ private void verifyPackageBundle(JPackageCommand cmd, if (expectedJPackageExitCode == 0) { if (isOfType(cmd, LINUX)) { LinuxHelper.verifyPackageBundleEssential(cmd); + } else if (isOfType(cmd, WIN_MSI)) { + WinShortcutVerifier.verifyBundleShortcuts(cmd); } } bundleVerifiers.forEach(v -> v.accept(cmd, result)); @@ -766,12 +757,11 @@ private void verifyPackageInstalled(JPackageCommand cmd) { if (!cmd.isRuntime()) { if (isOfType(cmd, WINDOWS) && !cmd.isPackageUnpacked("Not verifying desktop integration")) { - // Check main launcher - WindowsHelper.verifyDesktopIntegration(cmd, null); - // Check additional launchers - cmd.addLauncherNames().forEach(name -> { - WindowsHelper.verifyDesktopIntegration(cmd, name); - }); + WindowsHelper.verifyDeployedDesktopIntegration(cmd, true); + } + + if (isOfType(cmd, LINUX)) { + LinuxHelper.verifyDesktopFiles(cmd, true); } } @@ -848,12 +838,11 @@ private void verifyPackageUninstalled(JPackageCommand cmd) { TKit.assertPathExists(cmd.appLauncherPath(), false); if (isOfType(cmd, WINDOWS)) { - // Check main launcher - WindowsHelper.verifyDesktopIntegration(cmd, null); - // Check additional launchers - cmd.addLauncherNames().forEach(name -> { - WindowsHelper.verifyDesktopIntegration(cmd, name); - }); + WindowsHelper.verifyDeployedDesktopIntegration(cmd, false); + } + + if (isOfType(cmd, LINUX)) { + LinuxHelper.verifyDesktopFiles(cmd, false); } } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java index 2508db00295..b3f188bb371 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java @@ -41,8 +41,9 @@ import java.nio.file.StandardWatchEventKinds; import java.nio.file.WatchEvent; import java.nio.file.WatchKey; -import java.nio.file.WatchService; import java.text.SimpleDateFormat; +import java.time.Duration; +import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; @@ -597,49 +598,56 @@ public static Path createRelativePathCopy(final Path file) { return file; } - static void waitForFileCreated(Path fileToWaitFor, - long timeoutSeconds) throws IOException { + public static void waitForFileCreated(Path fileToWaitFor, + Duration timeout, Duration afterCreatedTimeout) throws IOException { + waitForFileCreated(fileToWaitFor, timeout); + // Wait after the file has been created to ensure it is fully written. + ThrowingConsumer.toConsumer(Thread::sleep).accept(afterCreatedTimeout); + } + + private static void waitForFileCreated(Path fileToWaitFor, Duration timeout) throws IOException { trace(String.format("Wait for file [%s] to be available", fileToWaitFor.toAbsolutePath())); - WatchService ws = FileSystems.getDefault().newWatchService(); - - Path watchDirectory = fileToWaitFor.toAbsolutePath().getParent(); - watchDirectory.register(ws, ENTRY_CREATE, ENTRY_MODIFY); - - long waitUntil = System.currentTimeMillis() + timeoutSeconds * 1000; - for (;;) { - long timeout = waitUntil - System.currentTimeMillis(); - assertTrue(timeout > 0, String.format( - "Check timeout value %d is positive", timeout)); - - WatchKey key = ThrowingSupplier.toSupplier(() -> ws.poll(timeout, - TimeUnit.MILLISECONDS)).get(); - if (key == null) { - if (fileToWaitFor.toFile().exists()) { - trace(String.format( - "File [%s] is available after poll timeout expired", - fileToWaitFor)); - return; + try (var ws = FileSystems.getDefault().newWatchService()) { + + Path watchDirectory = fileToWaitFor.toAbsolutePath().getParent(); + watchDirectory.register(ws, ENTRY_CREATE, ENTRY_MODIFY); + + var waitUntil = Instant.now().plus(timeout); + for (;;) { + var remainderTimeout = Instant.now().until(waitUntil); + assertTrue(remainderTimeout.isPositive(), String.format( + "Check timeout value %dms is positive", remainderTimeout.toMillis())); + + WatchKey key = ThrowingSupplier.toSupplier(() -> { + return ws.poll(remainderTimeout.toMillis(), TimeUnit.MILLISECONDS); + }).get(); + if (key == null) { + if (Files.exists(fileToWaitFor)) { + trace(String.format( + "File [%s] is available after poll timeout expired", + fileToWaitFor)); + return; + } + assertUnexpected(String.format("Timeout %dms expired", remainderTimeout.toMillis())); } - assertUnexpected(String.format("Timeout expired", timeout)); - } - for (WatchEvent event : key.pollEvents()) { - if (event.kind() == StandardWatchEventKinds.OVERFLOW) { - continue; - } - Path contextPath = (Path) event.context(); - if (Files.isSameFile(watchDirectory.resolve(contextPath), - fileToWaitFor)) { - trace(String.format("File [%s] is available", fileToWaitFor)); - return; + for (WatchEvent event : key.pollEvents()) { + if (event.kind() == StandardWatchEventKinds.OVERFLOW) { + continue; + } + Path contextPath = (Path) event.context(); + if (Files.exists(fileToWaitFor) && Files.isSameFile(watchDirectory.resolve(contextPath), fileToWaitFor)) { + trace(String.format("File [%s] is available", fileToWaitFor)); + return; + } } - } - if (!key.reset()) { - assertUnexpected("Watch key invalidated"); + if (!key.reset()) { + assertUnexpected("Watch key invalidated"); + } } } } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WinShortcutVerifier.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WinShortcutVerifier.java new file mode 100644 index 00000000000..cca904e017e --- /dev/null +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WinShortcutVerifier.java @@ -0,0 +1,283 @@ +/* + * 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 + * 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.jpackage.test; + +import static java.util.stream.Collectors.groupingBy; +import static jdk.jpackage.test.LauncherShortcut.WIN_DESKTOP_SHORTCUT; +import static jdk.jpackage.test.LauncherShortcut.WIN_START_MENU_SHORTCUT; +import static jdk.jpackage.test.WindowsHelper.getInstallationSubDirectory; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Stream; +import jdk.jpackage.internal.util.PathUtils; +import jdk.jpackage.test.LauncherShortcut.InvokeShortcutSpec; +import jdk.jpackage.test.LauncherShortcut.StartupDirectory; +import jdk.jpackage.test.MsiDatabase.Shortcut; +import jdk.jpackage.test.WindowsHelper.SpecialFolder; + + +public final class WinShortcutVerifier { + + static void verifyBundleShortcuts(JPackageCommand cmd) { + cmd.verifyIsOfType(PackageType.WIN_MSI); + + if (Stream.of("--win-menu", "--win-shortcut").noneMatch(cmd::hasArgument) && cmd.addLauncherNames().isEmpty()) { + return; + } + + var actualShortcuts = WindowsHelper.getMsiShortcuts(cmd).stream().collect(groupingBy(shortcut -> { + return PathUtils.replaceSuffix(shortcut.target().getFileName(), "").toString(); + })); + + var expectedShortcuts = expectShortcuts(cmd); + + var launcherNames = expectedShortcuts.keySet().stream().sorted().toList(); + + TKit.assertStringListEquals( + launcherNames, + actualShortcuts.keySet().stream().sorted().toList(), + "Check the list of launchers with shortcuts"); + + Function, List> sorter = shortcuts -> { + return shortcuts.stream().sorted(SHORTCUT_COMPARATOR).toList(); + }; + + for (var name : launcherNames) { + var actualLauncherShortcuts = sorter.apply(actualShortcuts.get(name)); + var expectedLauncherShortcuts = sorter.apply(expectedShortcuts.get(name)); + + TKit.assertEquals(expectedLauncherShortcuts.size(), actualLauncherShortcuts.size(), + String.format("Check the number of shortcuts of launcher [%s]", name)); + + for (int i = 0; i != expectedLauncherShortcuts.size(); i++) { + TKit.trace(String.format("Verify shortcut #%d of launcher [%s]", i + 1, name)); + actualLauncherShortcuts.get(i).assertEquals(expectedLauncherShortcuts.get(i)); + TKit.trace("Done"); + } + } + } + + static void verifyDeployedShortcuts(JPackageCommand cmd, boolean installed) { + cmd.verifyIsOfType(PackageType.WINDOWS); + + verifyDeployedShortcutsInternal(cmd, installed); + var copyCmd = cmd.createMutableCopy(); + if (copyCmd.hasArgument("--win-per-user-install")) { + copyCmd.removeArgument("--win-per-user-install"); + } else { + copyCmd.addArgument("--win-per-user-install"); + } + verifyDeployedShortcutsInternal(copyCmd, false); + } + + public static Collection getInvokeShortcutSpecs(JPackageCommand cmd) { + return expectShortcuts(cmd).entrySet().stream().map(e -> { + return e.getValue().stream().map(shortcut -> { + return convert(cmd, e.getKey(), shortcut); + }); + }).flatMap(x -> x).toList(); + } + + private static void verifyDeployedShortcutsInternal(JPackageCommand cmd, boolean installed) { + + var expectedShortcuts = expectShortcuts(cmd).values().stream().flatMap(Collection::stream).toList(); + + var isUserLocalInstall = WindowsHelper.isUserLocalInstall(cmd); + + expectedShortcuts.stream().map(Shortcut::path).sorted().map(path -> { + return resolvePath(path, !isUserLocalInstall); + }).map(path -> { + return PathUtils.addSuffix(path, ".lnk"); + }).forEach(path -> { + if (installed) { + TKit.assertFileExists(path); + } else { + TKit.assertPathExists(path, false); + } + }); + + if (!installed) { + expectedShortcuts.stream().map(Shortcut::path).filter(path -> { + return Stream.of(ShortcutType.COMMON_START_MENU, ShortcutType.USER_START_MENU).anyMatch(type -> { + return path.startsWith(Path.of(type.rootFolder().getMsiPropertyName())); + }); + }).map(Path::getParent).distinct().map(unresolvedShortcutDir -> { + return resolvePath(unresolvedShortcutDir, !isUserLocalInstall); + }).forEach(shortcutDir -> { + if (Files.isDirectory(shortcutDir)) { + TKit.assertDirectoryNotEmpty(shortcutDir); + } else { + TKit.assertPathExists(shortcutDir, false); + } + }); + } + } + + private enum ShortcutType { + COMMON_START_MENU(SpecialFolder.COMMON_START_MENU_PROGRAMS), + USER_START_MENU(SpecialFolder.USER_START_MENU_PROGRAMS), + COMMON_DESKTOP(SpecialFolder.COMMON_DESKTOP), + USER_DESKTOP(SpecialFolder.USER_DESKTOP), + ; + + ShortcutType(SpecialFolder rootFolder) { + this.rootFolder = Objects.requireNonNull(rootFolder); + } + + SpecialFolder rootFolder() { + return rootFolder; + } + + private final SpecialFolder rootFolder; + } + + private static Path resolvePath(Path path, boolean allUsers) { + var root = path.getName(0); + var resolvedRoot = SpecialFolder.findMsiProperty(root.toString(), allUsers).orElseThrow().getPath(); + return resolvedRoot.resolve(root.relativize(path)); + } + + private static Shortcut createLauncherShortcutSpec(JPackageCommand cmd, String launcherName, + SpecialFolder installRoot, Path workDir, ShortcutType type) { + + var name = Optional.ofNullable(launcherName).orElseGet(cmd::name); + + var appLayout = ApplicationLayout.windowsAppImage().resolveAt( + Path.of(installRoot.getMsiPropertyName()).resolve(getInstallationSubDirectory(cmd))); + + Path path; + switch (type) { + case COMMON_START_MENU, USER_START_MENU -> { + path = Path.of(cmd.getArgumentValue("--win-menu-group", () -> "Unknown"), name); + } + default -> { + path = Path.of(name); + } + } + + return new Shortcut( + Path.of(type.rootFolder().getMsiPropertyName()).resolve(path), + appLayout.launchersDirectory().resolve(name + ".exe"), + workDir); + } + + private static Collection expectLauncherShortcuts(JPackageCommand cmd, + Optional predefinedAppImage, String launcherName) { + Objects.requireNonNull(cmd); + Objects.requireNonNull(predefinedAppImage); + + final List shortcuts = new ArrayList<>(); + + final var winMenu = WIN_START_MENU_SHORTCUT.expectShortcut(cmd, predefinedAppImage, launcherName); + final var desktop = WIN_DESKTOP_SHORTCUT.expectShortcut(cmd, predefinedAppImage, launcherName); + + final var isUserLocalInstall = WindowsHelper.isUserLocalInstall(cmd); + + final SpecialFolder installRoot; + if (isUserLocalInstall) { + installRoot = SpecialFolder.LOCAL_APPLICATION_DATA; + } else { + installRoot = SpecialFolder.PROGRAM_FILES; + } + + final var installDir = Path.of(installRoot.getMsiPropertyName()).resolve(getInstallationSubDirectory(cmd)); + + final Function workDir = startupDirectory -> { + return installDir; + }; + + if (winMenu.isPresent()) { + ShortcutType type; + if (isUserLocalInstall) { + type = ShortcutType.USER_START_MENU; + } else { + type = ShortcutType.COMMON_START_MENU; + } + shortcuts.add(createLauncherShortcutSpec(cmd, launcherName, installRoot, winMenu.map(workDir).orElseThrow(), type)); + } + + if (desktop.isPresent()) { + ShortcutType type; + if (isUserLocalInstall) { + type = ShortcutType.USER_DESKTOP; + } else { + type = ShortcutType.COMMON_DESKTOP; + } + shortcuts.add(createLauncherShortcutSpec(cmd, launcherName, installRoot, desktop.map(workDir).orElseThrow(), type)); + } + + return shortcuts; + } + + private static Map> expectShortcuts(JPackageCommand cmd) { + Map> expectedShortcuts = new HashMap<>(); + + var predefinedAppImage = Optional.ofNullable(cmd.getArgumentValue("--app-image")).map(Path::of).map(AppImageFile::load); + + predefinedAppImage.map(v -> { + return v.launchers().keySet().stream(); + }).orElseGet(() -> { + return Stream.concat(Stream.of(cmd.name()), cmd.addLauncherNames().stream()); + }).forEach(launcherName -> { + var shortcuts = expectLauncherShortcuts(cmd, predefinedAppImage, launcherName); + if (!shortcuts.isEmpty()) { + expectedShortcuts.put(launcherName, shortcuts); + } + }); + + return expectedShortcuts; + } + + private static InvokeShortcutSpec convert(JPackageCommand cmd, String launcherName, Shortcut shortcut) { + LauncherShortcut launcherShortcut; + if (Stream.of(ShortcutType.COMMON_START_MENU, ShortcutType.USER_START_MENU).anyMatch(type -> { + return shortcut.path().startsWith(Path.of(type.rootFolder().getMsiPropertyName())); + })) { + launcherShortcut = WIN_START_MENU_SHORTCUT; + } else { + launcherShortcut = WIN_DESKTOP_SHORTCUT; + } + + var isUserLocalInstall = WindowsHelper.isUserLocalInstall(cmd); + return new InvokeShortcutSpec.Stub( + launcherName, + launcherShortcut, + Optional.of(resolvePath(shortcut.workDir(), !isUserLocalInstall)), + List.of("cmd", "/c", "start", "/wait", PathUtils.addSuffix(resolvePath(shortcut.path(), !isUserLocalInstall), ".lnk").toString())); + } + + + private static final Comparator SHORTCUT_COMPARATOR = Comparator.comparing(Shortcut::target) + .thenComparing(Comparator.comparing(Shortcut::path)) + .thenComparing(Comparator.comparing(Shortcut::workDir)); +} diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java index 3ac302ce0fe..5e97b0d2dde 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java @@ -26,19 +26,24 @@ import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; import java.io.IOException; +import java.io.UncheckedIOException; +import java.lang.ref.SoftReference; import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Path; +import java.time.Instant; +import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Optional; +import java.util.Properties; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.jpackage.internal.util.function.ThrowingRunnable; import jdk.jpackage.test.PackageTest.PackageHandlers; @@ -63,7 +68,7 @@ private static Path getInstallationRootDirectory(JPackageCommand cmd) { return PROGRAM_FILES; } - private static Path getInstallationSubDirectory(JPackageCommand cmd) { + static Path getInstallationSubDirectory(JPackageCommand cmd) { cmd.verifyIsOfType(PackageType.WINDOWS); return Path.of(cmd.getArgumentValue("--install-dir", cmd::name)); } @@ -263,22 +268,22 @@ static Optional toShortPath(Path path) { } } - static void verifyDesktopIntegration(JPackageCommand cmd, - String launcherName) { - new DesktopIntegrationVerifier(cmd, launcherName); + static void verifyDeployedDesktopIntegration(JPackageCommand cmd, boolean installed) { + WinShortcutVerifier.verifyDeployedShortcuts(cmd, installed); + DesktopIntegrationVerifier.verify(cmd, installed); } public static String getMsiProperty(JPackageCommand cmd, String propertyName) { cmd.verifyIsOfType(PackageType.WIN_MSI); - return Executor.of("cscript.exe", "//Nologo") - .addArgument(TKit.TEST_SRC_ROOT.resolve("resources/query-msi-property.js")) - .addArgument(cmd.outputBundle()) - .addArgument(propertyName) - .dumpOutput() - .executeAndGetOutput().stream().collect(Collectors.joining("\n")); + return MsiDatabaseCache.INSTANCE.findProperty(cmd.outputBundle(), propertyName).orElseThrow(); } - public static String getExecutableDesciption(Path pathToExeFile) { + static Collection getMsiShortcuts(JPackageCommand cmd) { + cmd.verifyIsOfType(PackageType.WIN_MSI); + return MsiDatabaseCache.INSTANCE.listShortcuts(cmd.outputBundle()); + } + + public static String getExecutableDescription(Path pathToExeFile) { Executor exec = Executor.of("powershell", "-NoLogo", "-NoProfile", @@ -386,7 +391,7 @@ private static long[] findAppLauncherPIDs(JPackageCommand cmd, String launcherNa } } - private static boolean isUserLocalInstall(JPackageCommand cmd) { + static boolean isUserLocalInstall(JPackageCommand cmd) { return cmd.hasArgument("--win-per-user-install"); } @@ -394,141 +399,42 @@ private static boolean isPathTooLong(Path path) { return path.toString().length() > WIN_MAX_PATH; } + private static class DesktopIntegrationVerifier { - DesktopIntegrationVerifier(JPackageCommand cmd, String launcherName) { + static void verify(JPackageCommand cmd, boolean installed) { cmd.verifyIsOfType(PackageType.WINDOWS); - - name = Optional.ofNullable(launcherName).orElseGet(cmd::name); - - isUserLocalInstall = isUserLocalInstall(cmd); - - appInstalled = cmd.appLauncherPath(launcherName).toFile().exists(); - - desktopShortcutPath = Path.of(name + ".lnk"); - - startMenuShortcutPath = Path.of(cmd.getArgumentValue( - "--win-menu-group", () -> "Unknown"), name + ".lnk"); - - if (name.equals(cmd.name())) { - isWinMenu = cmd.hasArgument("--win-menu"); - isDesktop = cmd.hasArgument("--win-shortcut"); - } else { - var props = AdditionalLauncher.getAdditionalLauncherProperties(cmd, - launcherName); - isWinMenu = props.getPropertyBooleanValue("win-menu").orElseGet( - () -> cmd.hasArgument("--win-menu")); - isDesktop = props.getPropertyBooleanValue("win-shortcut").orElseGet( - () -> cmd.hasArgument("--win-shortcut")); - } - - verifyStartMenuShortcut(); - - verifyDesktopShortcut(); - - Stream.of(cmd.getAllArgumentValues("--file-associations")).map( - Path::of).forEach(this::verifyFileAssociationsRegistry); - } - - private void verifyDesktopShortcut() { - if (isDesktop) { - if (isUserLocalInstall) { - verifyUserLocalDesktopShortcut(appInstalled); - verifySystemDesktopShortcut(false); - } else { - verifySystemDesktopShortcut(appInstalled); - verifyUserLocalDesktopShortcut(false); - } - } else { - verifySystemDesktopShortcut(false); - verifyUserLocalDesktopShortcut(false); - } - } - - private void verifyShortcut(Path path, boolean exists) { - if (exists) { - TKit.assertFileExists(path); - } else { - TKit.assertPathExists(path, false); - } - } - - private void verifySystemDesktopShortcut(boolean exists) { - Path dir = SpecialFolder.COMMON_DESKTOP.getPath(); - verifyShortcut(dir.resolve(desktopShortcutPath), exists); - } - - private void verifyUserLocalDesktopShortcut(boolean exists) { - Path dir = SpecialFolder.USER_DESKTOP.getPath(); - verifyShortcut(dir.resolve(desktopShortcutPath), exists); - } - - private void verifyStartMenuShortcut() { - if (isWinMenu) { - if (isUserLocalInstall) { - verifyUserLocalStartMenuShortcut(appInstalled); - verifySystemStartMenuShortcut(false); - } else { - verifySystemStartMenuShortcut(appInstalled); - verifyUserLocalStartMenuShortcut(false); - } - } else { - verifySystemStartMenuShortcut(false); - verifyUserLocalStartMenuShortcut(false); - } - } - - private void verifyStartMenuShortcut(Path shortcutsRoot, boolean exists) { - Path shortcutPath = shortcutsRoot.resolve(startMenuShortcutPath); - verifyShortcut(shortcutPath, exists); - if (!exists) { - final var parentDir = shortcutPath.getParent(); - if (Files.isDirectory(parentDir)) { - TKit.assertDirectoryNotEmpty(parentDir); - } else { - TKit.assertPathExists(parentDir, false); - } + for (var faFile : cmd.getAllArgumentValues("--file-associations")) { + verifyFileAssociationsRegistry(Path.of(faFile), installed); } } - private void verifySystemStartMenuShortcut(boolean exists) { - verifyStartMenuShortcut(SpecialFolder.COMMON_START_MENU_PROGRAMS.getPath(), exists); + private static void verifyFileAssociationsRegistry(Path faFile, boolean installed) { - } + TKit.trace(String.format( + "Get file association properties from [%s] file", + faFile)); - private void verifyUserLocalStartMenuShortcut(boolean exists) { - verifyStartMenuShortcut(SpecialFolder.USER_START_MENU_PROGRAMS.getPath(), exists); - } + var faProps = new Properties(); - private void verifyFileAssociationsRegistry(Path faFile) { - try { - TKit.trace(String.format( - "Get file association properties from [%s] file", - faFile)); - Map faProps = Files.readAllLines(faFile).stream().filter( - line -> line.trim().startsWith("extension=") || line.trim().startsWith( - "mime-type=")).map( - line -> { - String[] keyValue = line.trim().split("=", 2); - return Map.entry(keyValue[0], keyValue[1]); - }).collect(Collectors.toMap( - entry -> entry.getKey(), - entry -> entry.getValue())); - String suffix = faProps.get("extension"); - String contentType = faProps.get("mime-type"); + try (var reader = Files.newBufferedReader(faFile)) { + faProps.load(reader); + String suffix = faProps.getProperty("extension"); + String contentType = faProps.getProperty("mime-type"); TKit.assertNotNull(suffix, String.format( "Check file association suffix [%s] is found in [%s] property file", suffix, faFile)); TKit.assertNotNull(contentType, String.format( "Check file association content type [%s] is found in [%s] property file", contentType, faFile)); - verifyFileAssociations(appInstalled, "." + suffix, contentType); + verifyFileAssociations(installed, "." + suffix, contentType); + } catch (IOException ex) { - throw new RuntimeException(ex); + throw new UncheckedIOException(ex); } } - private void verifyFileAssociations(boolean exists, String suffix, + private static void verifyFileAssociations(boolean exists, String suffix, String contentType) { String contentTypeFromRegistry = queryRegistryValue(Path.of( "HKLM\\Software\\Classes", suffix).toString(), @@ -549,16 +455,9 @@ private void verifyFileAssociations(boolean exists, String suffix, "Check content type in registry not found"); } } - - private final Path desktopShortcutPath; - private final Path startMenuShortcutPath; - private final boolean isUserLocalInstall; - private final boolean appInstalled; - private final boolean isWinMenu; - private final boolean isDesktop; - private final String name; } + static String queryRegistryValue(String keyPath, String valueName) { var status = Executor.of("reg", "query", keyPath, "/v", valueName) .saveOutput() @@ -611,7 +510,12 @@ private enum SpecialFolderDotNet { CommonDesktop, Programs, - CommonPrograms; + CommonPrograms, + + ProgramFiles, + + LocalApplicationData, + ; Path getPath() { final var str = Executor.of("powershell", "-NoLogo", "-NoProfile", @@ -636,33 +540,84 @@ Optional findValue() { } } - private enum SpecialFolder { - COMMON_START_MENU_PROGRAMS(SYSTEM_SHELL_FOLDERS_REGKEY, "Common Programs", SpecialFolderDotNet.CommonPrograms), - USER_START_MENU_PROGRAMS(USER_SHELL_FOLDERS_REGKEY, "Programs", SpecialFolderDotNet.Programs), - - COMMON_DESKTOP(SYSTEM_SHELL_FOLDERS_REGKEY, "Common Desktop", SpecialFolderDotNet.CommonDesktop), - USER_DESKTOP(USER_SHELL_FOLDERS_REGKEY, "Desktop", SpecialFolderDotNet.Desktop); - - SpecialFolder(String keyPath, String valueName) { - reg = new RegValuePath(keyPath, valueName); + enum SpecialFolder { + COMMON_START_MENU_PROGRAMS( + SYSTEM_SHELL_FOLDERS_REGKEY, + "Common Programs", + "ProgramMenuFolder", + SpecialFolderDotNet.CommonPrograms), + USER_START_MENU_PROGRAMS( + USER_SHELL_FOLDERS_REGKEY, + "Programs", + "ProgramMenuFolder", + SpecialFolderDotNet.Programs), + + COMMON_DESKTOP( + SYSTEM_SHELL_FOLDERS_REGKEY, + "Common Desktop", + "DesktopFolder", + SpecialFolderDotNet.CommonDesktop), + USER_DESKTOP( + USER_SHELL_FOLDERS_REGKEY, + "Desktop", + "DesktopFolder", + SpecialFolderDotNet.Desktop), + + PROGRAM_FILES("ProgramFiles64Folder", SpecialFolderDotNet.ProgramFiles), + + LOCAL_APPLICATION_DATA("LocalAppDataFolder", SpecialFolderDotNet.LocalApplicationData), + ; + + SpecialFolder(String keyPath, String valueName, String msiPropertyName) { + reg = Optional.of(new RegValuePath(keyPath, valueName)); alt = Optional.empty(); + this.msiPropertyName = Objects.requireNonNull(msiPropertyName); } - SpecialFolder(String keyPath, String valueName, SpecialFolderDotNet alt) { - reg = new RegValuePath(keyPath, valueName); + SpecialFolder(String keyPath, String valueName, String msiPropertyName, SpecialFolderDotNet alt) { + reg = Optional.of(new RegValuePath(keyPath, valueName)); this.alt = Optional.of(alt); + this.msiPropertyName = Objects.requireNonNull(msiPropertyName); + } + + SpecialFolder(String msiPropertyName, SpecialFolderDotNet alt) { + reg = Optional.empty(); + this.alt = Optional.of(alt); + this.msiPropertyName = Objects.requireNonNull(msiPropertyName); + } + + static Optional findMsiProperty(String pathComponent, boolean allUsers) { + Objects.requireNonNull(pathComponent); + String regPath; + if (allUsers) { + regPath = SYSTEM_SHELL_FOLDERS_REGKEY; + } else { + regPath = USER_SHELL_FOLDERS_REGKEY; + } + return Stream.of(values()) + .filter(v -> v.msiPropertyName.equals(pathComponent)) + .filter(v -> { + return v.reg.map(r -> r.keyPath().equals(regPath)).orElse(true); + }) + .findFirst(); + } + + String getMsiPropertyName() { + return msiPropertyName; } Path getPath() { - return CACHE.computeIfAbsent(this, k -> reg.findValue().map(Path::of).orElseGet(() -> { + return CACHE.computeIfAbsent(this, k -> reg.flatMap(RegValuePath::findValue).map(Path::of).orElseGet(() -> { return alt.map(SpecialFolderDotNet::getPath).orElseThrow(() -> { return new NoSuchElementException(String.format("Failed to find path to %s folder", name())); }); })); } - private final RegValuePath reg; + private final Optional reg; private final Optional alt; + // One of "System Folder Properties" from https://learn.microsoft.com/en-us/windows/win32/msi/property-reference + private final String msiPropertyName; private static final Map CACHE = new ConcurrentHashMap<>(); } @@ -693,6 +648,63 @@ static Path toShortPath(Path path) { private static final ShortPathUtils INSTANCE = new ShortPathUtils(); } + + private static final class MsiDatabaseCache { + + Optional findProperty(Path msiPath, String propertyName) { + return ensureTables(msiPath, MsiDatabase.Table.FIND_PROPERTY_REQUIRED_TABLES).findProperty(propertyName); + } + + Collection listShortcuts(Path msiPath) { + return ensureTables(msiPath, MsiDatabase.Table.LIST_SHORTCUTS_REQUIRED_TABLES).listShortcuts(); + } + + MsiDatabase ensureTables(Path msiPath, Set tableNames) { + Objects.requireNonNull(msiPath); + try { + synchronized (items) { + var value = Optional.ofNullable(items.get(msiPath)).map(SoftReference::get).orElse(null); + if (value != null) { + var lastModifiedTime = Files.getLastModifiedTime(msiPath).toInstant(); + if (lastModifiedTime.isAfter(value.timestamp())) { + value = null; + } else { + tableNames = Comm.compare(value.db().tableNames(), tableNames).unique2(); + } + } + + if (!tableNames.isEmpty()) { + var idtOutputDir = TKit.createTempDirectory("msi-db"); + var db = MsiDatabase.load(msiPath, idtOutputDir, tableNames); + if (value != null) { + value = new MsiDatabaseWithTimestamp(db.append(value.db()), value.timestamp()); + } else { + value = new MsiDatabaseWithTimestamp(db, Files.getLastModifiedTime(msiPath).toInstant()); + } + items.put(msiPath, new SoftReference<>(value)); + } + + return value.db(); + } + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + } + + private record MsiDatabaseWithTimestamp(MsiDatabase db, Instant timestamp) { + + MsiDatabaseWithTimestamp { + Objects.requireNonNull(db); + Objects.requireNonNull(timestamp); + } + } + + private final Map> items = new HashMap<>(); + + static final MsiDatabaseCache INSTANCE = new MsiDatabaseCache(); + } + + static final Set CRITICAL_RUNTIME_FILES = Set.of(Path.of( "bin\\server\\jvm.dll")); diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/PListReaderTest.java b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/PListReaderTest.java index d766505cf14..fe7d0c63870 100644 --- a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/PListReaderTest.java +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/PListReaderTest.java @@ -32,14 +32,18 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Optional; import java.util.function.BiFunction; +import java.util.stream.Stream; import javax.xml.parsers.ParserConfigurationException; +import jdk.jpackage.internal.util.PListReader.Raw; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; +import org.junit.jupiter.params.provider.EnumSource.Mode; import org.junit.jupiter.params.provider.MethodSource; import org.w3c.dom.Node; import org.xml.sax.InputSource; @@ -51,7 +55,23 @@ public class PListReaderTest { enum QueryType { STRING(PListReader::queryValue), BOOLEAN(PListReader::queryBoolValue), - STRING_ARRAY(PListReader::queryArrayValue); + DICT((plistReader, keyName) -> { + return plistReader.queryDictValue(keyName).toMap(true); + }), + STRING_ARRAY(PListReader::queryStringArrayValue), + RAW_ARRAY((plistReader, keyName) -> { + return plistReader.queryArrayValue(keyName, false).toList(); + }), + RAW_ARRAY_RECURSIVE((plistReader, keyName) -> { + return plistReader.queryArrayValue(keyName, true).toList(); + }), + TO_MAP((plistReader, _) -> { + return plistReader.toMap(false); + }), + TO_MAP_RECURSIVE((plistReader, _) -> { + return plistReader.toMap(true); + }), + ; QueryType(BiFunction queryMethod) { this.queryMethod = Objects.requireNonNull(queryMethod); @@ -65,10 +85,10 @@ T queryValue(PListReader pListReader, String keyName) { private final BiFunction queryMethod; } - public record QueryValueTestSpec(QueryType queryType, String keyName, Optional expectedValue, + public record TestSpec(QueryType queryType, Optional keyName, Optional expectedValue, Optional> expectedException, String... xml) { - public QueryValueTestSpec { + public TestSpec { Objects.requireNonNull(queryType); Objects.requireNonNull(keyName); Objects.requireNonNull(expectedValue); @@ -77,6 +97,14 @@ public record QueryValueTestSpec(QueryType queryType, String keyName, Optional {} + default -> { + throw new IllegalArgumentException(); + } + } + } } static final class Builder { @@ -91,7 +119,7 @@ Builder keyName(String v) { return this; } - Builder expectedValue(Object v) { + Builder expect(Object v) { expectedValue = v; if (v instanceof String) { queryType(QueryType.STRING); @@ -99,11 +127,13 @@ Builder expectedValue(Object v) { queryType(QueryType.BOOLEAN); } else if (v instanceof List) { queryType(QueryType.STRING_ARRAY); + } else if (v instanceof Map) { + queryType(QueryType.DICT); } return this; } - Builder expectedException(Class v) { + Builder expectException(Class v) { expectedException = v; return this; } @@ -113,8 +143,11 @@ Builder xml(String... v) { return this; } - QueryValueTestSpec create() { - return new QueryValueTestSpec(queryType, keyName, Optional.ofNullable(expectedValue), + TestSpec create() { + return new TestSpec( + queryType, + Optional.ofNullable(keyName), + Optional.ofNullable(expectedValue), validatedExpectedException(), xml); } @@ -137,12 +170,12 @@ void test() { final var plistReader = new PListReader(createXml(xml)); expectedValue.ifPresent(v -> { - final var actualValue = queryType.queryValue(plistReader, keyName); + final var actualValue = queryType.queryValue(plistReader, keyName.orElse(null)); assertEquals(v, actualValue); }); expectedException.ifPresent(v -> { - assertThrows(v, () -> queryType.queryValue(plistReader, keyName)); + assertThrows(v, () -> queryType.queryValue(plistReader, keyName.orElse(null))); }); } @@ -150,7 +183,9 @@ void test() { public String toString() { final var sb = new StringBuilder(); sb.append(queryType); - sb.append("; key=").append(keyName); + if (keyName != null) { + sb.append("; key=").append(keyName); + } expectedValue.ifPresent(v -> { sb.append("; expected="); sb.append(v); @@ -166,13 +201,13 @@ public String toString() { } @ParameterizedTest - @EnumSource(QueryType.class) + @EnumSource(mode = Mode.MATCH_NONE, names = {"TO_MAP.*"}) public void testNoSuchElement(QueryType queryType) { testSpec(queryType).create().test(); } @ParameterizedTest - @EnumSource(QueryType.class) + @EnumSource(mode = Mode.MATCH_NONE, names = {"TO_MAP.*"}) public void testWrongValueType(QueryType queryType) { final var builder = testSpec(queryType).xml( "string-key", @@ -182,33 +217,56 @@ public void testWrongValueType(QueryType queryType) { "boolean-false-key", "", "array-key", - "b"); + "b", + "dict-key", + "nested-dict-key345"); - List testSpecs = new ArrayList<>(); + List testSpecs = new ArrayList<>(); switch (queryType) { case STRING -> { testSpecs.add(builder.keyName("boolean-true-key").create()); testSpecs.add(builder.keyName("boolean-false-key").create()); testSpecs.add(builder.keyName("array-key").create()); + testSpecs.add(builder.keyName("dict-key").create()); } case BOOLEAN -> { testSpecs.add(builder.keyName("string-key").create()); testSpecs.add(builder.keyName("array-key").create()); + testSpecs.add(builder.keyName("dict-key").create()); } - case STRING_ARRAY -> { + case STRING_ARRAY, RAW_ARRAY, RAW_ARRAY_RECURSIVE -> { testSpecs.add(builder.keyName("string-key").create()); testSpecs.add(builder.keyName("boolean-true-key").create()); testSpecs.add(builder.keyName("boolean-false-key").create()); + testSpecs.add(builder.keyName("dict-key").create()); + } + case DICT -> { + testSpecs.add(builder.keyName("string-key").create()); + testSpecs.add(builder.keyName("boolean-true-key").create()); + testSpecs.add(builder.keyName("boolean-false-key").create()); + testSpecs.add(builder.keyName("array-key").create()); + } + case TO_MAP, TO_MAP_RECURSIVE -> { + throw new UnsupportedOperationException(); } } - testSpecs.forEach(QueryValueTestSpec::test); + testSpecs.forEach(TestSpec::test); + + builder.keyName(null).expect(Map.of( + "string-key", new Raw("a", Raw.Type.STRING), + "boolean-true-key", new Raw(Boolean.TRUE.toString(), Raw.Type.BOOLEAN), + "boolean-false-key", new Raw(Boolean.FALSE.toString(), Raw.Type.BOOLEAN), + "array-key", List.of(new Raw("b", Raw.Type.STRING)), + "dict-key", Map.of("nested-dict-key", new Raw("345", Raw.Type.INTEGER)) + )).queryType(QueryType.TO_MAP_RECURSIVE).create().test(); + } @ParameterizedTest @MethodSource - public void testQueryValue(QueryValueTestSpec testSpec) { + public void test(TestSpec testSpec) { testSpec.test(); } @@ -219,28 +277,190 @@ public void testByteArrayCtor() throws ParserConfigurationException, SAXExceptio assertEquals("A", actualValue); } - private static List testQueryValue() { - return List.of( - testSpec().expectedValue("A").xml("fooA").create(), - testSpec().expectedValue("").xml("foo").create(), - testSpec().xml("foo").create(), - testSpec().expectedValue(Boolean.TRUE).xml("foo").create(), - testSpec().expectedValue(Boolean.FALSE).xml("foo").create(), - testSpec(QueryType.BOOLEAN).xml("foo").create(), - testSpec(QueryType.BOOLEAN).xml("foo").create(), - testSpec().expectedValue(List.of("foo", "bar")).xml("foofoobar").create(), - testSpec().expectedValue(List.of()).xml("foo").create(), - testSpec(QueryType.STRING_ARRAY).xml("foo").create(), - testSpec().expectedValue("A").xml("fooAB").create(), - testSpec().expectedValue("A").xml("fooAfooB").create() + @Test + public void test_toMap() { + + var builder = testSpec(); + + builder.xml( + "AppName", + "Hello", + "", + "AppVersion", + "1.0", + "Release", + "", + "Debug", + "", + "ReleaseDate", + "2025-09-24T09:23:00Z", + "UserData", + "", + "", + " Foo", + " ", + " Str", + " ", + " Another Str", + " ", + " ", + " ", + " ", + "", + "Checksum", + "7841ff0076cdde93bdca02cfd332748c40620ce4", + "Plugins", + "", + " ", + " PluginName", + " Foo", + " Priority", + " 13", + " History", + " ", + " New File", + " Another New File", + " ", + " ", + " ", + " PluginName", + " Bar", + " Priority", + " 23", + " History", + " ", + " ", + "" ); + + var expected = Map.of( + "AppName", new Raw("Hello", Raw.Type.STRING), + "AppVersion", new Raw("1.0", Raw.Type.REAL), + "Release", new Raw(Boolean.TRUE.toString(), Raw.Type.BOOLEAN), + "Debug", new Raw(Boolean.FALSE.toString(), Raw.Type.BOOLEAN), + "ReleaseDate", new Raw("2025-09-24T09:23:00Z", Raw.Type.DATE), + "Checksum", new Raw("7841ff0076cdde93bdca02cfd332748c40620ce4", Raw.Type.DATA), + "UserData", Map.of( + "Foo", List.of( + new Raw("Str", Raw.Type.STRING), + List.of( + new Raw("Another Str", Raw.Type.STRING), + new Raw(Boolean.TRUE.toString(), Raw.Type.BOOLEAN), + new Raw(Boolean.FALSE.toString(), Raw.Type.BOOLEAN) + ) + ) + ), + "Plugins", List.of( + Map.of( + "PluginName", new Raw("Foo", Raw.Type.STRING), + "Priority", new Raw("13", Raw.Type.INTEGER), + "History", List.of( + new Raw("New File", Raw.Type.STRING), + new Raw("Another New File", Raw.Type.STRING) + ) + ), + Map.of( + "PluginName", new Raw("Bar", Raw.Type.STRING), + "Priority", new Raw("23", Raw.Type.REAL), + "History", List.of() + ) + ) + ); + + builder.expect(expected).queryType(QueryType.TO_MAP_RECURSIVE).create().test(); + } + + private static List test() { + + List data = new ArrayList<>(); + + Stream.of( + testSpec().expect("A").xml("fooA"), + testSpec().expect("A").xml("BfooA"), + testSpec().expect("").xml("foo some text "), + testSpec().xml("foo"), + testSpec().xml("foo"), + testSpec().xml("fooA"), + testSpec().expect(Boolean.TRUE).xml("foo"), + testSpec().expect(Boolean.FALSE).xml("foo"), + testSpec(QueryType.BOOLEAN).xml("foo"), + testSpec(QueryType.BOOLEAN).xml("foo"), + testSpec().expect(List.of("foo", "bar")).xml("foofoobar"), + testSpec().expect(List.of()).xml("foo"), + testSpec(QueryType.STRING_ARRAY).xml("foo"), + testSpec().expect("A").xml("fooAB"), + testSpec().expect("A").xml("fooAfooB"), + + testSpec().expect(Map.of()).xml("foo"), + + // + // Test that if there are multiple keys with the same name, all but the first are ignored. + // + testSpec().expect("A").xml("fooAfooBfooC"), + testSpec().expect("A").xml("fooAfooB"), + testSpec(QueryType.STRING).xml("fooBfooA"), + testSpec().expect(Boolean.TRUE).xml("foofoo"), + testSpec().expect(Boolean.TRUE).xml("foofoo"), + testSpec(QueryType.BOOLEAN).xml("foofoo"), + + // + // Test that it doesn't look up keys in nested "dict" or "array" elements. + // + testSpec().xml("foofooA"), + testSpec().expect("B").xml("barfooAfooB"), + testSpec().xml("foofooA"), + testSpec().expect("B").xml("barfooAfooB"), + + // + // Test empty arrays. + // + testSpec().expect(List.of()).queryType(QueryType.RAW_ARRAY_RECURSIVE).xml("foo"), + testSpec().expect(List.of()).queryType(QueryType.RAW_ARRAY).xml("foo") + + ).map(TestSpec.Builder::create).forEach(data::add); + + // + // Test toMap() method. + // + Stream.of( + testSpec().expect(Map.of()).xml(), + testSpec().expect(Map.of()).xml("foobar"), + testSpec().expect(Map.of()).xml("Abar"), + testSpec().expect(Map.of()).xml("A"), + testSpec().expect(Map.of()).xml("fooA"), + testSpec().expect(Map.of("foo", new Raw("A", Raw.Type.STRING))).xml("fooAB"), + testSpec().expect(Map.of("foo", new Raw("A", Raw.Type.STRING))).xml("fooA hello foo bye B"), + testSpec().expect(Map.of("foo", new Raw("A", Raw.Type.STRING), "Foo", new Raw("B", Raw.Type.STRING))).xml("fooAFooB") + ).map(builder -> { + return builder.queryType(QueryType.TO_MAP_RECURSIVE); + }).map(TestSpec.Builder::create).forEach(data::add); + + var arrayTestSpec = testSpec().expect(List.of( + new Raw("Hello", Raw.Type.STRING), + Map.of("foo", new Raw("Bye", Raw.Type.STRING)), + new Raw("integer", Raw.Type.INTEGER), + Map.of(), + new Raw(Boolean.TRUE.toString(), Raw.Type.BOOLEAN) + )).queryType(QueryType.RAW_ARRAY_RECURSIVE); + + Stream.of( + "HellofooByeinteger", + "HelloBingofooByeinteger", + "BHellofooByeByeeeinteger", + "HellobarfooByeinteger", + "HellofooByefooByeByeinteger" + ).map(xml -> { + return "foo" + xml + ""; + }).map(arrayTestSpec::xml).map(TestSpec.Builder::create).forEach(data::add); + + return data; } - private static QueryValueTestSpec.Builder testSpec() { - return new QueryValueTestSpec.Builder(); + private static TestSpec.Builder testSpec() { + return new TestSpec.Builder(); } - private static QueryValueTestSpec.Builder testSpec(QueryType queryType) { + private static TestSpec.Builder testSpec(QueryType queryType) { return testSpec().queryType(queryType); } @@ -248,7 +468,9 @@ private static String xmlToString(String ...xml) { final List content = new ArrayList<>(); content.add(""); content.add(""); + content.add(""); content.addAll(List.of(xml)); + content.add(""); content.add(""); return String.join("", content.toArray(String[]::new)); } diff --git a/test/jdk/tools/jpackage/linux/UpgradeTest.java b/test/jdk/tools/jpackage/linux/UpgradeTest.java index fb399cec12b..bfbdcf3aa0c 100644 --- a/test/jdk/tools/jpackage/linux/UpgradeTest.java +++ b/test/jdk/tools/jpackage/linux/UpgradeTest.java @@ -60,16 +60,16 @@ public void testDesktopFiles() { var alA = createAdditionalLauncher("launcherA"); alA.applyTo(pkg); - createAdditionalLauncher("launcherB").addRawProperties(Map.entry( - "description", "Foo")).applyTo(pkg); + createAdditionalLauncher("launcherB").setProperty( + "description", "Foo").applyTo(pkg); var pkg2 = createPackageTest().addInitializer(cmd -> { cmd.addArguments("--app-version", "2.0"); }); alA.verifyRemovedInUpgrade(pkg2); - createAdditionalLauncher("launcherB").addRawProperties(Map.entry( - "description", "Bar")).applyTo(pkg2); + createAdditionalLauncher("launcherB").setProperty( + "description", "Bar").applyTo(pkg2); createAdditionalLauncher("launcherC").applyTo(pkg2); new PackageTest.Group(pkg, pkg2).run(); @@ -88,6 +88,6 @@ private static AdditionalLauncher createAdditionalLauncher(String name) { return new AdditionalLauncher(name).setIcon(GOLDEN_ICON); } - private final static Path GOLDEN_ICON = TKit.TEST_SRC_ROOT.resolve(Path.of( + private static final Path GOLDEN_ICON = TKit.TEST_SRC_ROOT.resolve(Path.of( "resources", "icon" + TKit.ICON_SUFFIX)); } diff --git a/test/jdk/tools/jpackage/macosx/MacFileAssociationsTest.java b/test/jdk/tools/jpackage/macosx/MacFileAssociationsTest.java index 889a5bb374e..e99bb65ea3d 100644 --- a/test/jdk/tools/jpackage/macosx/MacFileAssociationsTest.java +++ b/test/jdk/tools/jpackage/macosx/MacFileAssociationsTest.java @@ -21,15 +21,16 @@ * questions. */ +import static java.util.Map.entry; + import java.nio.file.Path; import java.util.List; import java.util.Map; -import static java.util.Map.entry; -import jdk.jpackage.test.JPackageCommand; -import jdk.jpackage.test.TKit; -import jdk.jpackage.test.MacHelper; import jdk.jpackage.internal.util.PListReader; import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.JPackageCommand; +import jdk.jpackage.test.MacHelper; +import jdk.jpackage.test.TKit; /** * Tests generation of app image with --file-associations and mac additional file @@ -80,21 +81,26 @@ private static void checkStringValue(PListReader plist, String key, String value "Check value of %s plist key", key)); } - private static void checkBoolValue(PListReader plist, String key, Boolean value) { - Boolean result = plist.queryBoolValue(key); - TKit.assertEquals(value.toString(), result.toString(), String.format( + private static void checkBoolValue(PListReader plist, String key, boolean value) { + boolean result = plist.queryBoolValue(key); + TKit.assertEquals(value, result, String.format( "Check value of %s plist key", key)); } private static void checkArrayValue(PListReader plist, String key, List values) { - List result = plist.queryArrayValue(key); + List result = plist.queryStringArrayValue(key); TKit.assertStringListEquals(values, result, String.format( "Check value of %s plist key", key)); } private static void verifyPList(Path appImage) throws Exception { - var plist = MacHelper.readPListFromAppImage(appImage); + final var rootPlist = MacHelper.readPListFromAppImage(appImage); + + TKit.traceFileContents(appImage.resolve("Contents/Info.plist"), "Info.plist"); + + var plist = rootPlist.queryArrayValue("CFBundleDocumentTypes", false).findFirst().map(PListReader.class::cast).orElseThrow(); + checkStringValue(plist, "CFBundleTypeRole", "Viewer"); checkStringValue(plist, "LSHandlerRank", "Default"); checkStringValue(plist, "NSDocumentClass", "SomeClass"); @@ -103,10 +109,13 @@ private static void verifyPList(Path appImage) throws Exception { checkBoolValue(plist, "LSSupportsOpeningDocumentsInPlace", false); checkBoolValue(plist, "UISupportsDocumentBrowser", false); - checkArrayValue(plist, "NSExportableTypes", List.of("public.png", - "public.jpg")); + plist = rootPlist.queryArrayValue("UTExportedTypeDeclarations", false).findFirst().map(PListReader.class::cast).orElseThrow(); + + checkArrayValue(plist, "UTTypeConformsTo", List.of("public.image", "public.data")); + + plist = plist.queryDictValue("UTTypeTagSpecification"); + + checkArrayValue(plist, "NSExportableTypes", List.of("public.png", "public.jpg")); - checkArrayValue(plist, "UTTypeConformsTo", List.of("public.image", - "public.data")); } } diff --git a/test/jdk/tools/jpackage/macosx/MacSignTest.java b/test/jdk/tools/jpackage/macosx/MacSignTest.java index 7b2e06dc7ca..ee163a8f7b5 100644 --- a/test/jdk/tools/jpackage/macosx/MacSignTest.java +++ b/test/jdk/tools/jpackage/macosx/MacSignTest.java @@ -160,6 +160,7 @@ public static void testMultipleCertificates(PackageType type, SignOption... opti @Test @ParameterSupplier + @ParameterSupplier("testSelectSigningIdentity_JDK_8371094") public static void testSelectSigningIdentity(String signingKeyUserName, CertificateRequest certRequest) { final var keychain = SigningBase.StandardKeychain.MAIN.spec().keychain(); @@ -187,6 +188,12 @@ public static Collection testSelectSigningIdentity() { }).toList(); } + public static Collection testSelectSigningIdentity_JDK_8371094() { + return List.of(new Object[] { + "ACME Technologies Limited", SigningBase.StandardCertificateRequest.CODESIGN_ACME_TECH_LTD.spec() + }); + } + enum SignOption { EXPIRED_SIGNING_KEY_USER_NAME("--mac-signing-key-user-name", SigningBase.StandardCertificateRequest.CODESIGN_EXPIRED.spec(), true, false), EXPIRED_SIGNING_KEY_USER_NAME_PKG("--mac-signing-key-user-name", SigningBase.StandardCertificateRequest.PKG_EXPIRED.spec(), true, false), diff --git a/test/jdk/tools/jpackage/macosx/base/SigningBase.java b/test/jdk/tools/jpackage/macosx/base/SigningBase.java index 5484245f111..dcbccc02ab5 100644 --- a/test/jdk/tools/jpackage/macosx/base/SigningBase.java +++ b/test/jdk/tools/jpackage/macosx/base/SigningBase.java @@ -68,6 +68,7 @@ public class SigningBase { public enum StandardCertificateRequest { CODESIGN(cert().userName(DEV_NAMES[CertIndex.ASCII_INDEX.value()])), CODESIGN_COPY(cert().days(100).userName(DEV_NAMES[CertIndex.ASCII_INDEX.value()])), + CODESIGN_ACME_TECH_LTD(cert().days(100).userName("ACME Technologies Limited (ABC12345)")), PKG(cert().type(CertificateType.INSTALLER).userName(DEV_NAMES[CertIndex.ASCII_INDEX.value()])), PKG_COPY(cert().type(CertificateType.INSTALLER).days(100).userName(DEV_NAMES[CertIndex.ASCII_INDEX.value()])), CODESIGN_UNICODE(cert().userName(DEV_NAMES[CertIndex.UNICODE_INDEX.value()])), @@ -95,7 +96,8 @@ public enum StandardKeychain { StandardCertificateRequest.CODESIGN, StandardCertificateRequest.PKG, StandardCertificateRequest.CODESIGN_UNICODE, - StandardCertificateRequest.PKG_UNICODE), + StandardCertificateRequest.PKG_UNICODE, + StandardCertificateRequest.CODESIGN_ACME_TECH_LTD), EXPIRED("jpackagerTest-expired.keychain", StandardCertificateRequest.CODESIGN, StandardCertificateRequest.PKG, diff --git a/test/jdk/tools/jpackage/resources/Win8365790Test.ps1 b/test/jdk/tools/jpackage/resources/Win8365790Test.ps1 new file mode 100644 index 00000000000..3a7d8c9a90b --- /dev/null +++ b/test/jdk/tools/jpackage/resources/Win8365790Test.ps1 @@ -0,0 +1,83 @@ +# +# Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +param ( + # Path to executable to start. + [Parameter(Mandatory=$true)] + [string]$Executable, + + # Timeout to wait after the executable has been started. + [Parameter(Mandatory=$true)] + [double]$TimeoutSeconds +) + +$type = @{ + TypeDefinition = @' +using System; +using System.Runtime.InteropServices; + +namespace Stuff { + + internal struct Details { + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool GenerateConsoleCtrlEvent(uint dwCtrlEvent, uint dwProcessGroupId); + } + + public struct Facade { + public static void GenerateConsoleCtrlEvent() { + if (!Details.GenerateConsoleCtrlEvent(0, 0)) { + reportLastErrorAndExit("GenerateConsoleCtrlEvent"); + } + } + + internal static void reportLastErrorAndExit(String func) { + int errorCode = Marshal.GetLastWin32Error(); + Console.Error.WriteLine(func + " function failed with error code: " + errorCode); + Environment.Exit(100); + } + } +} +'@ +} +Add-Type @type + +Set-PSDebug -Trace 2 + +# Launch the target executable. +# `-NoNewWindow` parameter will attach the started process to the existing console. +$childProc = Start-Process -PassThru -NoNewWindow $Executable + +# Wait a bit to let the started process complete initialization. +Start-Sleep -Seconds $TimeoutSeconds + +# Call GenerateConsoleCtrlEvent to send a CTRL+C event to the launched executable. +# CTRL+C event will be sent to all processes attached to the console of the current process, +# i.e., it will be sent to this PowerShell process and to the started $Executable process because +# it was configured to attach to the existing console (the console of this PowerShell process). +[Stuff.Facade]::GenerateConsoleCtrlEvent() + +# Wait for child process termination +Wait-Process -InputObject $childProc + +Exit 0 diff --git a/test/jdk/tools/jpackage/resources/msi-export.js b/test/jdk/tools/jpackage/resources/msi-export.js new file mode 100644 index 00000000000..d639f19ca44 --- /dev/null +++ b/test/jdk/tools/jpackage/resources/msi-export.js @@ -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. + */ + + +function readMsi(msiPath, callback) { + var installer = new ActiveXObject('WindowsInstaller.Installer') + var database = installer.OpenDatabase(msiPath, 0 /* msiOpenDatabaseModeReadOnly */) + + return callback(database) +} + + +function exportTables(db, outputDir, requestedTableNames) { + var tables = {} + + var view = db.OpenView("SELECT `Name` FROM _Tables") + view.Execute() + + try { + while (true) { + var record = view.Fetch() + if (!record) { + break + } + + var name = record.StringData(1) + + if (requestedTableNames.hasOwnProperty(name)) { + tables[name] = name + } + } + } finally { + view.Close() + } + + var fso = new ActiveXObject("Scripting.FileSystemObject") + for (var table in tables) { + var idtFileName = table + ".idt" + var idtFile = outputDir + "/" + idtFileName + if (fso.FileExists(idtFile)) { + WScript.Echo("Delete [" + idtFile + "]") + fso.DeleteFile(idtFile) + } + WScript.Echo("Export table [" + table + "] in [" + idtFile + "] file") + db.Export(table, fso.GetFolder(outputDir).Path, idtFileName) + } +} + + +(function () { + var msi = WScript.arguments(0) + var outputDir = WScript.arguments(1) + var tables = {} + for (var i = 0; i !== WScript.arguments.Count(); i++) { + tables[WScript.arguments(i)] = true + } + + readMsi(msi, function (db) { + exportTables(db, outputDir, tables) + }) +})() diff --git a/test/jdk/tools/jpackage/share/AddLShortcutTest.java b/test/jdk/tools/jpackage/share/AddLShortcutTest.java index 6430a55d784..7d7d8b50c1d 100644 --- a/test/jdk/tools/jpackage/share/AddLShortcutTest.java +++ b/test/jdk/tools/jpackage/share/AddLShortcutTest.java @@ -21,13 +21,32 @@ * questions. */ -import java.nio.file.Path; +import java.io.IOException; import java.lang.invoke.MethodHandles; -import jdk.jpackage.test.PackageTest; -import jdk.jpackage.test.FileAssociations; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import jdk.internal.util.OperatingSystem; import jdk.jpackage.test.AdditionalLauncher; -import jdk.jpackage.test.TKit; +import jdk.jpackage.test.Annotations.Parameter; +import jdk.jpackage.test.Annotations.ParameterSupplier; import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.FileAssociations; +import jdk.jpackage.test.JPackageCommand; +import jdk.jpackage.test.LauncherShortcut; +import jdk.jpackage.test.LauncherShortcut.InvokeShortcutSpec; +import jdk.jpackage.test.LauncherShortcut.StartupDirectory; +import jdk.jpackage.test.LauncherVerifier.Action; +import jdk.jpackage.test.LinuxHelper; +import jdk.jpackage.test.PackageTest; +import jdk.jpackage.test.RunnablePackageTest; +import jdk.jpackage.test.TKit; +import jdk.jpackage.test.WinShortcutVerifier; /** * Test --add-launcher parameter with shortcuts (platform permitting). @@ -44,9 +63,23 @@ * @key jpackagePlatformPackage * @library /test/jdk/tools/jpackage/helpers * @build jdk.jpackage.test.* + * @requires (jpackage.test.SQETest != null) * @compile -Xlint:all -Werror AddLShortcutTest.java * @run main/othervm/timeout=540 -Xmx512m * jdk.jpackage.test.Main + * --jpt-run=AddLShortcutTest.test + */ + +/* + * @test + * @summary jpackage with --add-launcher + * @key jpackagePlatformPackage + * @library /test/jdk/tools/jpackage/helpers + * @build jdk.jpackage.test.* + * @requires (jpackage.test.SQETest == null) + * @compile -Xlint:all -Werror AddLShortcutTest.java + * @run main/othervm/timeout=1080 -Xmx512m + * jdk.jpackage.test.Main * --jpt-run=AddLShortcutTest */ @@ -107,6 +140,287 @@ public void test() { packageTest.run(); } + @Test(ifNotOS = OperatingSystem.MACOS) + @ParameterSupplier(ifOS = OperatingSystem.LINUX, value = "testShortcutStartupDirectoryLinux") + @ParameterSupplier(ifOS = OperatingSystem.WINDOWS, value = "testShortcutStartupDirectoryWindows") + public void testStartupDirectory(LauncherShortcutStartupDirectoryConfig... cfgs) { + + var test = new PackageTest().addInitializer(cmd -> { + cmd.setArgumentValue("--name", "AddLShortcutDirTest"); + }).addInitializer(JPackageCommand::setFakeRuntime).addHelloAppInitializer(null); + + test.addInitializer(cfgs[0]::applyToMainLauncher); + for (var i = 1; i != cfgs.length; ++i) { + var al = new AdditionalLauncher("launcher-" + i); + cfgs[i].applyToAdditionalLauncher(al); + al.withoutVerifyActions(Action.EXECUTE_LAUNCHER).applyTo(test); + } + + test.run(RunnablePackageTest.Action.CREATE_AND_UNPACK); + } + + @Test(ifNotOS = OperatingSystem.MACOS) + @ParameterSupplier(ifOS = OperatingSystem.LINUX, value = "testShortcutStartupDirectoryLinux") + @ParameterSupplier(ifOS = OperatingSystem.WINDOWS, value = "testShortcutStartupDirectoryWindows") + public void testStartupDirectory2(LauncherShortcutStartupDirectoryConfig... cfgs) { + + // + // Launcher shortcuts in the predefined app image. + // + // Shortcut configuration for the main launcher is not supported when building an app image. + // However, shortcut configuration for additional launchers is supported. + // The test configures shortcuts for additional launchers in the app image building jpackage command + // and applies shortcut configuration to the main launcher in the native packaging jpackage command. + // + + Path[] predefinedAppImage = new Path[1]; + + new PackageTest().addRunOnceInitializer(() -> { + var cmd = JPackageCommand.helloAppImage() + .setArgumentValue("--name", "foo") + .setFakeRuntime(); + + for (var i = 1; i != cfgs.length; ++i) { + var al = new AdditionalLauncher("launcher-" + i); + cfgs[i].applyToAdditionalLauncher(al); + al.withoutVerifyActions(Action.EXECUTE_LAUNCHER).applyTo(cmd); + } + + cmd.execute(); + + predefinedAppImage[0] = cmd.outputBundle(); + }).addInitializer(cmd -> { + cmd.removeArgumentWithValue("--input"); + cmd.setArgumentValue("--name", "AddLShortcutDir2Test"); + cmd.addArguments("--app-image", predefinedAppImage[0]); + cfgs[0].applyToMainLauncher(cmd); + }).run(RunnablePackageTest.Action.CREATE_AND_UNPACK); + } + + public static Collection testShortcutStartupDirectoryLinux() { + return testShortcutStartupDirectory(LauncherShortcut.LINUX_SHORTCUT); + } + + public static Collection testShortcutStartupDirectoryWindows() { + return testShortcutStartupDirectory(LauncherShortcut.WIN_DESKTOP_SHORTCUT, LauncherShortcut.WIN_START_MENU_SHORTCUT); + } + + @Test(ifNotOS = OperatingSystem.MACOS) + @Parameter(value = "DEFAULT") + public void testInvokeShortcuts(StartupDirectory startupDirectory) { + + var testApp = TKit.TEST_SRC_ROOT.resolve("apps/PrintEnv.java"); + + var name = "AddLShortcutRunTest"; + + var test = new PackageTest().addInitializer(cmd -> { + cmd.setArgumentValue("--name", name); + }).addInitializer(cmd -> { + cmd.addArguments("--arguments", "--print-workdir"); + }).addInitializer(JPackageCommand::ignoreFakeRuntime).addHelloAppInitializer(testApp + "*Hello"); + + var shortcutStartupDirectoryVerifier = new ShortcutStartupDirectoryVerifier(name, "a"); + + shortcutStartupDirectoryVerifier.applyTo(test, startupDirectory); + + test.addInstallVerifier(cmd -> { + if (!cmd.isPackageUnpacked("Not invoking launcher shortcuts")) { + Collection invokeShortcutSpecs; + if (TKit.isLinux()) { + invokeShortcutSpecs = LinuxHelper.getInvokeShortcutSpecs(cmd); + } else if (TKit.isWindows()) { + invokeShortcutSpecs = WinShortcutVerifier.getInvokeShortcutSpecs(cmd); + } else { + throw new UnsupportedOperationException(); + } + shortcutStartupDirectoryVerifier.verify(invokeShortcutSpecs); + } + }); + + test.run(); + } + + + private record ShortcutStartupDirectoryVerifier(String packageName, String launcherName) { + ShortcutStartupDirectoryVerifier { + Objects.requireNonNull(packageName); + Objects.requireNonNull(launcherName); + } + + void applyTo(PackageTest test, StartupDirectory startupDirectory) { + var al = new AdditionalLauncher(launcherName); + al.setShortcut(shortcut(), Objects.requireNonNull(startupDirectory)); + al.addJavaOptions(String.format("-Djpackage.test.appOutput=${%s}/%s", + outputDirVarName(), expectedOutputFilename())); + al.withoutVerifyActions(Action.EXECUTE_LAUNCHER).applyTo(test); + } + + void verify(Collection invokeShortcutSpecs) throws IOException { + + TKit.trace(String.format("Verify shortcut [%s]", launcherName)); + + var expectedOutputFile = Path.of(System.getenv(outputDirVarName())).resolve(expectedOutputFilename()); + + TKit.deleteIfExists(expectedOutputFile); + + var invokeShortcutSpec = invokeShortcutSpecs.stream().filter(v -> { + return launcherName.equals(v.launcherName()); + }).findAny().orElseThrow(); + + invokeShortcutSpec.execute(); + + // On Linux, "gtk-launch" is used to launch a .desktop file. It is async and there is no + // way to make it wait for exit of a process it triggers. + TKit.waitForFileCreated(expectedOutputFile, Duration.ofSeconds(10), Duration.ofSeconds(3)); + + TKit.assertFileExists(expectedOutputFile); + var actualStr = Files.readAllLines(expectedOutputFile).getFirst(); + + var outputPrefix = "$CD="; + + TKit.assertTrue(actualStr.startsWith(outputPrefix), "Check output starts with '" + outputPrefix+ "' string"); + + invokeShortcutSpec.expectedWorkDirectory().ifPresent(expectedWorkDirectory -> { + TKit.assertEquals( + expectedWorkDirectory, + Path.of(actualStr.substring(outputPrefix.length())), + String.format("Check work directory of %s of launcher [%s]", + invokeShortcutSpec.shortcut().propertyName(), + invokeShortcutSpec.launcherName())); + }); + } + + private String expectedOutputFilename() { + return String.format("%s-%s.out", packageName, launcherName); + } + + private String outputDirVarName() { + if (TKit.isLinux()) { + return "HOME"; + } else if (TKit.isWindows()) { + return "LOCALAPPDATA"; + } else { + throw new UnsupportedOperationException(); + } + } + + private LauncherShortcut shortcut() { + if (TKit.isLinux()) { + return LauncherShortcut.LINUX_SHORTCUT; + } else if (TKit.isWindows()) { + return LauncherShortcut.WIN_DESKTOP_SHORTCUT; + } else { + throw new UnsupportedOperationException(); + } + } + } + + + private static Collection testShortcutStartupDirectory(LauncherShortcut... shortcuts) { + List> items = new ArrayList<>(); + + for (var shortcut : shortcuts) { + List mainLauncherVariants = new ArrayList<>(); + for (var valueSetter : StartupDirectoryValueSetter.MAIN_LAUNCHER_VALUES) { + mainLauncherVariants.add(new LauncherShortcutStartupDirectoryConfig(shortcut, valueSetter)); + } + mainLauncherVariants.stream().map(List::of).forEach(items::add); + mainLauncherVariants.add(new LauncherShortcutStartupDirectoryConfig(shortcut)); + + List addLauncherVariants = new ArrayList<>(); + addLauncherVariants.add(new LauncherShortcutStartupDirectoryConfig(shortcut)); + for (var valueSetter : StartupDirectoryValueSetter.ADD_LAUNCHER_VALUES) { + addLauncherVariants.add(new LauncherShortcutStartupDirectoryConfig(shortcut, valueSetter)); + } + + for (var mainLauncherVariant : mainLauncherVariants) { + for (var addLauncherVariant : addLauncherVariants) { + if (mainLauncherVariant.valueSetter().isPresent() || addLauncherVariant.valueSetter().isPresent()) { + items.add(List.of(mainLauncherVariant, addLauncherVariant)); + } + } + } + } + + return items.stream().map(List::toArray).toList(); + } + + + private enum StartupDirectoryValueSetter { + DEFAULT(""), + TRUE("true"), + FALSE("false"), + ; + + StartupDirectoryValueSetter(String value) { + this.value = Objects.requireNonNull(value); + } + + void applyToMainLauncher(LauncherShortcut shortcut, JPackageCommand cmd) { + switch (this) { + case TRUE, FALSE -> { + throw new UnsupportedOperationException(); + } + case DEFAULT -> { + cmd.addArgument(shortcut.optionName()); + } + default -> { + cmd.addArguments(shortcut.optionName(), value); + } + } + } + + void applyToAdditionalLauncher(LauncherShortcut shortcut, AdditionalLauncher addLauncher) { + addLauncher.setProperty(shortcut.propertyName(), value); + } + + private final String value; + + static final List MAIN_LAUNCHER_VALUES = List.of( + StartupDirectoryValueSetter.DEFAULT + ); + + static final List ADD_LAUNCHER_VALUES = List.of( + StartupDirectoryValueSetter.TRUE, + StartupDirectoryValueSetter.FALSE + ); + } + + + record LauncherShortcutStartupDirectoryConfig(LauncherShortcut shortcut, Optional valueSetter) { + + LauncherShortcutStartupDirectoryConfig { + Objects.requireNonNull(shortcut); + Objects.requireNonNull(valueSetter); + } + + LauncherShortcutStartupDirectoryConfig(LauncherShortcut shortcut, StartupDirectoryValueSetter valueSetter) { + this(shortcut, Optional.of(valueSetter)); + } + + LauncherShortcutStartupDirectoryConfig(LauncherShortcut shortcut) { + this(shortcut, Optional.empty()); + } + + void applyToMainLauncher(JPackageCommand target) { + valueSetter.ifPresent(valueSetter -> { + valueSetter.applyToMainLauncher(shortcut, target); + }); + } + + void applyToAdditionalLauncher(AdditionalLauncher target) { + valueSetter.ifPresent(valueSetter -> { + valueSetter.applyToAdditionalLauncher(shortcut, target); + }); + } + + @Override + public String toString() { + return shortcut + "=" + valueSetter.map(Object::toString).orElse(""); + } + } + + private static final Path GOLDEN_ICON = TKit.TEST_SRC_ROOT.resolve(Path.of( "resources", "icon" + TKit.ICON_SUFFIX)); } diff --git a/test/jdk/tools/jpackage/share/AddLauncherTest.java b/test/jdk/tools/jpackage/share/AddLauncherTest.java index 5c21be71258..8d5f0de28f2 100644 --- a/test/jdk/tools/jpackage/share/AddLauncherTest.java +++ b/test/jdk/tools/jpackage/share/AddLauncherTest.java @@ -89,17 +89,17 @@ public void test() { new AdditionalLauncher("Baz2") .setDefaultArguments() - .addRawProperties(Map.entry("description", "Baz2 Description")) + .setProperty("description", "Baz2 Description") .applyTo(packageTest); new AdditionalLauncher("foo") .setDefaultArguments("yep!") - .addRawProperties(Map.entry("description", "foo Description")) + .setProperty("description", "foo Description") .applyTo(packageTest); new AdditionalLauncher("Bar") .setDefaultArguments("one", "two", "three") - .addRawProperties(Map.entry("description", "Bar Description")) + .setProperty("description", "Bar Description") .setIcon(GOLDEN_ICON) .applyTo(packageTest); @@ -194,8 +194,8 @@ public void testMainLauncherIsModular(boolean mainLauncherIsModular) { .toString(); new AdditionalLauncher("ModularAppLauncher") - .addRawProperties(Map.entry("module", expectedMod)) - .addRawProperties(Map.entry("main-jar", "")) + .setProperty("module", expectedMod) + .setProperty("main-jar", "") .applyTo(cmd); new AdditionalLauncher("NonModularAppLauncher") @@ -204,8 +204,8 @@ public void testMainLauncherIsModular(boolean mainLauncherIsModular) { .setPersistenceHandler((path, properties) -> TKit.createTextFile(path, properties.stream().map(entry -> String.join(" ", entry.getKey(), entry.getValue())))) - .addRawProperties(Map.entry("main-class", nonModularAppDesc.className())) - .addRawProperties(Map.entry("main-jar", nonModularAppDesc.jarFileName())) + .setProperty("main-class", nonModularAppDesc.className()) + .setProperty("main-jar", nonModularAppDesc.jarFileName()) .applyTo(cmd); cmd.executeAndAssertHelloAppImageCreated(); diff --git a/test/jdk/tools/jpackage/share/FileAssociationsTest.java b/test/jdk/tools/jpackage/share/FileAssociationsTest.java index 2257c5dbc65..7d84470fc9a 100644 --- a/test/jdk/tools/jpackage/share/FileAssociationsTest.java +++ b/test/jdk/tools/jpackage/share/FileAssociationsTest.java @@ -25,12 +25,14 @@ import java.nio.file.Path; import java.util.Map; +import jdk.jpackage.test.AdditionalLauncher; import jdk.jpackage.test.Annotations.Parameter; import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.test.FileAssociations; import jdk.jpackage.test.JPackageCommand; import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.PackageType; +import jdk.jpackage.test.RunnablePackageTest; import jdk.jpackage.test.TKit; /** @@ -64,7 +66,7 @@ * @requires jpackage.test.SQETest == null * @build jdk.jpackage.test.* * @compile -Xlint:all -Werror FileAssociationsTest.java - * @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main + * @run main/othervm/timeout=1080 -Xmx512m jdk.jpackage.test.Main * --jpt-run=FileAssociationsTest */ @@ -85,7 +87,7 @@ public class FileAssociationsTest { @Parameter("true") @Parameter("false") public static void test(boolean includeDescription) { - PackageTest packageTest = new PackageTest(); + PackageTest packageTest = new PackageTest().configureHelloApp(); // Not supported packageTest.excludeTypes(PackageType.MAC_DMG); @@ -144,6 +146,34 @@ public static void testTooManyMimes() { }).run(); } + @Test + @Parameter("true") + @Parameter("false") + public static void testFromAppImage(boolean withAdditionalLauncher) { + + var appImageCmd = JPackageCommand.helloAppImage(); + + if (RunnablePackageTest.hasAction(RunnablePackageTest.Action.INSTALL)) { + // Ensure launchers are executable. + appImageCmd.ignoreFakeRuntime(); + } + + if (withAdditionalLauncher) { + new AdditionalLauncher("foo").applyTo(appImageCmd); + } + + var test = new PackageTest().excludeTypes(PackageType.MAC_DMG) + .addRunOnceInitializer(appImageCmd::execute) + .addInitializer(cmd -> { + cmd.removeArgumentWithValue("--input"); + cmd.setArgumentValue("--app-image", appImageCmd.outputBundle()); + }); + + new FileAssociations("jptest3").applyTo(test); + + test.run(); + } + private static PackageTest initPackageTest() { return new PackageTest() .excludeTypes(PackageType.MAC) diff --git a/test/jdk/tools/jpackage/share/PerUserCfgTest.java b/test/jdk/tools/jpackage/share/PerUserCfgTest.java index 080df1f959d..d2f368cd824 100644 --- a/test/jdk/tools/jpackage/share/PerUserCfgTest.java +++ b/test/jdk/tools/jpackage/share/PerUserCfgTest.java @@ -27,13 +27,14 @@ import java.util.List; import java.util.Objects; import java.util.Optional; +import jdk.jpackage.internal.util.function.ThrowingConsumer; import jdk.jpackage.test.AdditionalLauncher; -import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.Annotations.Test; -import jdk.jpackage.internal.util.function.ThrowingConsumer; import jdk.jpackage.test.HelloApp; import jdk.jpackage.test.JPackageCommand; +import jdk.jpackage.test.LauncherVerifier.Action; import jdk.jpackage.test.LinuxHelper; +import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.PackageType; import jdk.jpackage.test.TKit; @@ -65,7 +66,7 @@ public static void test() throws IOException { cfgCmd.execute(); - new PackageTest().configureHelloApp().addInstallVerifier(cmd -> { + new PackageTest().addHelloAppInitializer(null).addInstallVerifier(cmd -> { if (cmd.isPackageUnpacked("Not running per-user configuration tests")) { return; } @@ -144,10 +145,7 @@ public static void test() throws IOException { } private static void addLauncher(JPackageCommand cmd, String name) { - new AdditionalLauncher(name) { - @Override - protected void verify(JPackageCommand cmd) {} - }.setDefaultArguments(name).applyTo(cmd); + new AdditionalLauncher(name).setDefaultArguments(name).withoutVerifyActions(Action.EXECUTE_LAUNCHER).applyTo(cmd); } private static Path getUserHomeDir() { diff --git a/test/jdk/tools/jpackage/windows/Win8365790Test.java b/test/jdk/tools/jpackage/windows/Win8365790Test.java new file mode 100644 index 00000000000..6376a16cecc --- /dev/null +++ b/test/jdk/tools/jpackage/windows/Win8365790Test.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static jdk.jpackage.test.HelloApp.configureAndExecute; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Duration; +import jdk.jpackage.test.AdditionalLauncher; +import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.CfgFile; +import jdk.jpackage.test.Executor; +import jdk.jpackage.test.JPackageCommand; +import jdk.jpackage.test.LauncherVerifier; +import jdk.jpackage.test.TKit; + +/** + * Test the child process has a chance to handle Ctrl+C signal. + */ + +/* + * @test + * @summary Test case for JDK-8365790 + * @library /test/jdk/tools/jpackage/helpers + * @build jdk.jpackage.test.* + * @build Win8365790Test + * @requires (os.family == "windows") + * @run main/othervm/timeout=100 -Xmx512m jdk.jpackage.test.Main + * --jpt-run=Win8365790Test + */ +public class Win8365790Test { + + @Test + public void test() throws InterruptedException, IOException { + + var outputDir = TKit.createTempDirectory("response-dir"); + + var mainOutputFile = outputDir.resolve("output.txt"); + var mainTraceFile = outputDir.resolve("trace.txt"); + + var probeOutputFile = outputDir.resolve("probe-output.txt"); + var probeTraceFile = outputDir.resolve("probe-trace.txt"); + + var cmd = JPackageCommand + .helloAppImage(TEST_APP_JAVA + "*UseShutdownHook") + .ignoreFakeRuntime() + .addArguments("--java-options", "-Djpackage.test.trace-file=" + mainTraceFile.toString()) + .addArguments("--arguments", mainOutputFile.toString()) + .addArguments("--arguments", Long.toString(Duration.ofSeconds(TETS_APP_AUTOCLOSE_TIMEOUT_SECONDS).getSeconds())); + + new AdditionalLauncher("probe") + .withoutVerifyActions(LauncherVerifier.Action.values()) + .addJavaOptions("-Djpackage.test.trace-file=" + probeTraceFile.toString()) + .addDefaultArguments(probeOutputFile.toString(), Long.toString(Duration.ofSeconds(TETS_APP_AUTOCLOSE_TIMEOUT_SECONDS).getSeconds())) + .applyTo(cmd); + + cmd.executeAndAssertImageCreated(); + + cmd.readLauncherCfgFile("probe") + .add(new CfgFile().addValue("Application", "win.norestart", Boolean.TRUE.toString())) + .save(cmd.appLauncherCfgPath("probe")); + + // Try Ctrl+C signal on a launcher with disabled restart functionality. + // It will create a single launcher process instead of the parent and the child processes. + // Ctrl+C always worked for launcher with disabled restart functionality. + var probeOutput = runLauncher(cmd, "probe", probeTraceFile, probeOutputFile); + + if (!probeOutput.equals("shutdown hook executed")) { + // Ctrl+C signal didn't make it. Test environment doesn't support Ctrl+C signal + // delivery from the prowershell process to a child process, don't run the main + // test. + TKit.throwSkippedException( + "The environment does NOT support Ctrl+C signal delivery from the prowershell process to a child process"); + } + + var mainOutput = runLauncher(cmd, null, mainTraceFile, mainOutputFile); + + TKit.assertEquals("shutdown hook executed", mainOutput, "Check shutdown hook executed"); + } + + private static String runLauncher(JPackageCommand cmd, String launcherName, Path traceFile, Path outputFile) throws IOException { + // Launch the specified launcher and send Ctrl+C signal to it. + Thread.ofVirtual().start(() -> { + configureAndExecute(0, Executor.of("powershell", "-NonInteractive", "-NoLogo", "-NoProfile", "-ExecutionPolicy", "Unrestricted") + .addArgument("-File").addArgument(TEST_PS1) + .addArguments("-TimeoutSeconds", Long.toString(Duration.ofSeconds(5).getSeconds())) + .addArgument("-Executable").addArgument(cmd.appLauncherPath(launcherName)) + .dumpOutput()); + }); + + TKit.waitForFileCreated(traceFile, Duration.ofSeconds(20), Duration.ofSeconds(2)); + + try { + TKit.waitForFileCreated(outputFile, Duration.ofSeconds(TETS_APP_AUTOCLOSE_TIMEOUT_SECONDS * 2), Duration.ofSeconds(2)); + } finally { + TKit.traceFileContents(traceFile, "Test app trace"); + } + + TKit.assertFileExists(outputFile); + return Files.readString(outputFile); + } + + private static final long TETS_APP_AUTOCLOSE_TIMEOUT_SECONDS = 30; + + private static final Path TEST_APP_JAVA = TKit.TEST_SRC_ROOT.resolve("apps/UseShutdownHook.java"); + private static final Path TEST_PS1 = TKit.TEST_SRC_ROOT.resolve(Path.of("resources/Win8365790Test.ps1")).normalize(); +} diff --git a/test/jdk/tools/launcher/TooSmallStackSize.java b/test/jdk/tools/launcher/TooSmallStackSize.java index 8485f115d6e..8133dbf4550 100644 --- a/test/jdk/tools/launcher/TooSmallStackSize.java +++ b/test/jdk/tools/launcher/TooSmallStackSize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,8 @@ * @bug 6762191 8222334 * @summary Setting stack size to 16K causes segmentation fault * @compile TooSmallStackSize.java + * @comment VM fails to launch with minimum allowed stack size of 136k when asan is enabled + * @requires !vm.asan * @run main TooSmallStackSize */ diff --git a/test/hotspot/jtreg/runtime/signal/TestSigusr2.java b/test/jdk/tools/sincechecker/modules/jdk.editpad/JdkEditpadCheckSince.java similarity index 74% rename from test/hotspot/jtreg/runtime/signal/TestSigusr2.java rename to test/jdk/tools/sincechecker/modules/jdk.editpad/JdkEditpadCheckSince.java index fc5bff9d67d..364bc8bd3f2 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigusr2.java +++ b/test/jdk/tools/sincechecker/modules/jdk.editpad/JdkEditpadCheckSince.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,15 +21,10 @@ * questions. */ - /* * @test - * @requires os.family != "windows" & os.family != "aix" - * - * @summary converted from VM testbase runtime/signal/sigusr201. - * VM testbase keywords: [signal, runtime, linux, macosx] - * - * @library /test/lib - * @run main/native SigTestDriver SIGUSR2 + * @bug 8346884 + * @summary Test for `@since` in jdk.editpad module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker jdk.editpad */ - diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java index 360c96c74ef..b12e62f6987 100644 --- a/test/jtreg-ext/requires/VMProps.java +++ b/test/jtreg-ext/requires/VMProps.java @@ -122,6 +122,8 @@ public Map call() { map.put("vm.rtm.compiler", this::vmRTMCompiler); // vm.cds is true if the VM is compiled with cds support. map.put("vm.cds", this::vmCDS); + map.put("vm.cds.default.archive.available", this::vmCDSDefaultArchiveAvailable); + map.put("vm.cds.nocoops.archive.available", this::vmCDSNocoopsArchiveAvailable); map.put("vm.cds.custom.loaders", this::vmCDSForCustomLoaders); map.put("vm.cds.supports.aot.class.linking", this::vmCDSSupportsAOTClassLinking); map.put("vm.cds.supports.aot.code.caching", this::vmCDSSupportsAOTCodeCaching); @@ -138,6 +140,8 @@ public Map call() { map.put("container.support", this::containerSupport); 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); @@ -446,6 +450,26 @@ protected String vmCDS() { return "" + WB.isCDSIncluded(); } + /** + * Check for CDS default archive existence. + * + * @return true if CDS default archive classes.jsa exists in the JDK to be tested. + */ + protected String vmCDSDefaultArchiveAvailable() { + Path archive = Paths.get(System.getProperty("java.home"), "lib", "server", "classes.jsa"); + return "" + ("true".equals(vmCDS()) && Files.exists(archive)); + } + + /** + * Check for CDS no compressed oops archive existence. + * + * @return true if CDS archive classes_nocoops.jsa exists in the JDK to be tested. + */ + protected String vmCDSNocoopsArchiveAvailable() { + Path archive = Paths.get(System.getProperty("java.home"), "lib", "server", "classes_nocoops.jsa"); + return "" + ("true".equals(vmCDS()) && Files.exists(archive)); + } + /** * Check for CDS support for custom loaders. * @@ -728,6 +752,15 @@ protected String isMusl() { 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 --git a/test/langtools/TEST.ROOT b/test/langtools/TEST.ROOT index 9b1c5368e66..1aaaa7dffe1 100644 --- a/test/langtools/TEST.ROOT +++ b/test/langtools/TEST.ROOT @@ -15,7 +15,7 @@ keys=intermittent randomness needs-src needs-src-jdk_javadoc groups=TEST.groups # Minimum jtreg version -requiredVersion=7.5.1+1 +requiredVersion=8+2 # Use new module options useNewOptions=true diff --git a/test/langtools/jdk/javadoc/doclet/testHtmlLandmarkRegions/TestHtmlLandmarkRegions.java b/test/langtools/jdk/javadoc/doclet/testHtmlLandmarkRegions/TestHtmlLandmarkRegions.java index a65e474a251..784efa9767d 100644 --- a/test/langtools/jdk/javadoc/doclet/testHtmlLandmarkRegions/TestHtmlLandmarkRegions.java +++ b/test/langtools/jdk/javadoc/doclet/testHtmlLandmarkRegions/TestHtmlLandmarkRegions.java @@ -83,7 +83,7 @@ public void testModules(Path base) throws Exception {

    Document Title

    """, """ -
    """, +
    """, """ bottom text""" ); @@ -113,7 +113,7 @@ public void testPackages(Path base) throws Exception {

    Document Title

    """, """ -
    """, +
    """, """ bottom text"""); } @@ -150,7 +150,7 @@ public void testDocFiles(Path base) throws Exception { """
    A sample doc file""", """ -
    """, +
    """, """ bottom text""" ); diff --git a/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java b/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java index 15c85765d68..e9d7f7a795d 100644 --- a/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java +++ b/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java @@ -85,7 +85,7 @@ void html5Output() {