diff --git a/.github/workflows/submit.yml b/.github/workflows/submit.yml index 35fc2d53431..d2c297ae2ae 100644 --- a/.github/workflows/submit.yml +++ b/.github/workflows/submit.yml @@ -12,6 +12,10 @@ on: required: true default: "Linux additional (hotspot only), Linux x64, Linux x86, Windows aarch64, Windows x64, macOS x64" +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: prerequisites: name: Prerequisites @@ -19,6 +23,7 @@ jobs: outputs: should_run: ${{ steps.check_submit.outputs.should_run }} bundle_id: ${{ steps.check_bundle_id.outputs.bundle_id }} + jdk_version: ${{ steps.check_jdk_versions.outputs.jdk_version }} platform_linux_additional: ${{ steps.check_platforms.outputs.platform_linux_additional }} platform_linux_x64: ${{ steps.check_platforms.outputs.platform_linux_x64 }} platform_linux_x86: ${{ steps.check_platforms.outputs.platform_linux_x86 }} @@ -51,7 +56,7 @@ jobs: if: steps.check_submit.outputs.should_run != 'false' - name: Checkout the source - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: jdk if: steps.check_submit.outputs.should_run != 'false' @@ -66,20 +71,37 @@ jobs: run: "echo '${{ steps.check_deps.outputs.dependencies }}'" if: steps.check_submit.outputs.should_run != 'false' + - name: Determine full JDK versions + id: check_jdk_versions + shell: bash + run: | + FEATURE=${{ fromJson(steps.check_deps.outputs.dependencies).DEFAULT_VERSION_FEATURE }} + INTERIM=${{ fromJson(steps.check_deps.outputs.dependencies).DEFAULT_VERSION_INTERIM }} + UPDATE=${{ fromJson(steps.check_deps.outputs.dependencies).DEFAULT_VERSION_UPDATE }} + if [ "x${UPDATE}" != "x0" ]; then + V=${FEATURE}.${INTERIM}.${UPDATE} + elif [ "x${INTERIM}" != "x0" ]; then + V={FEATURE}.${INTERIM} + else + V=${FEATURE} + fi + echo "::set-output name=jdk_version::${V}" + if: steps.check_submit.outputs.should_run != 'false' + - name: Determine the jtreg ref to checkout run: "echo JTREG_REF=jtreg-${{ fromJson(steps.check_deps.outputs.dependencies).JTREG_VERSION }}+${{ fromJson(steps.check_deps.outputs.dependencies).JTREG_BUILD }} >> $GITHUB_ENV" if: steps.check_submit.outputs.should_run != 'false' - name: Check if a jtreg image is present in the cache id: jtreg - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/jtreg/ key: jtreg-${{ env.JTREG_REF }}-v1 if: steps.check_submit.outputs.should_run != 'false' - name: Checkout the jtreg source - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: "openjdk/jtreg" ref: ${{ env.JTREG_REF }} @@ -97,7 +119,7 @@ jobs: if: steps.check_submit.outputs.should_run != 'false' && steps.jtreg.outputs.cache-hit != 'true' - name: Store jtreg for use by later steps - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: transient_jtreg_${{ steps.check_bundle_id.outputs.bundle_id }} path: ~/jtreg/ @@ -121,7 +143,7 @@ jobs: artifact: -debug env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}.${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_INTERIM }}.${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_UPDATE }}" + JDK_VERSION: "${{ needs.prerequisites.outputs.jdk_version }}" BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_FILENAME }}" BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_URL }}" @@ -129,13 +151,13 @@ jobs: steps: - name: Checkout the source - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: jdk - name: Restore boot JDK from cache id: bootjdk - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/bootjdk/${{ env.BOOT_JDK_VERSION }} key: bootjdk-${{ runner.os }}-${{ env.BOOT_JDK_VERSION }}-${{ env.BOOT_JDK_SHA256 }}-v1 @@ -151,21 +173,21 @@ jobs: - name: Restore jtreg artifact id: jtreg_restore - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jtreg/ continue-on-error: true - name: Restore jtreg artifact (retry) - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jtreg/ if: steps.jtreg_restore.outcome == 'failure' - name: Checkout gtest sources - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: "google/googletest" ref: "release-${{ fromJson(needs.prerequisites.outputs.dependencies).GTEST_VERSION }}" @@ -197,7 +219,7 @@ jobs: working-directory: jdk - name: Persist test bundles - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: transient_jdk-linux-x64${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} path: | @@ -250,7 +272,7 @@ jobs: artifact: -debug env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}.${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_INTERIM }}.${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_UPDATE }}" + JDK_VERSION: "${{ needs.prerequisites.outputs.jdk_version }}" BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_FILENAME }}" BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_URL }}" @@ -258,11 +280,11 @@ jobs: steps: - name: Checkout the source - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Restore boot JDK from cache id: bootjdk - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/bootjdk/${{ env.BOOT_JDK_VERSION }} key: bootjdk-${{ runner.os }}-${{ env.BOOT_JDK_VERSION }}-${{ env.BOOT_JDK_SHA256 }}-v1 @@ -278,14 +300,14 @@ jobs: - name: Restore jtreg artifact id: jtreg_restore - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jtreg/ continue-on-error: true - name: Restore jtreg artifact (retry) - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jtreg/ @@ -293,14 +315,14 @@ jobs: - name: Restore build artifacts id: build_restore - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jdk-linux-x64${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jdk-linux-x64${{ matrix.artifact }} continue-on-error: true - name: Restore build artifacts (retry) - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jdk-linux-x64${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jdk-linux-x64${{ matrix.artifact }} @@ -322,6 +344,7 @@ jobs: echo "imageroot=`dirname ${imageroot}`" >> $GITHUB_ENV - name: Run tests + id: run_tests run: > JDK_IMAGE_DIR=${{ env.imageroot }} TEST_IMAGE_DIR=${HOME}/jdk-linux-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x64_bin-tests${{ matrix.artifact }} @@ -337,7 +360,7 @@ jobs: JTREG="JAVA_OPTIONS=-XX:-CreateCoredumpOnCrash" - name: Check that all tests executed successfully - if: always() + if: steps.run_tests.outcome != 'skipped' run: > if ! grep --include=test-summary.txt -lqr build/*/test-results -e "TEST SUCCESS" ; then cat build/*/test-results/*/text/newfailures.txt ; @@ -372,14 +395,14 @@ jobs: - name: Persist test results if: always() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: path: ~/linux-x64${{ matrix.artifact }}_testresults_${{ env.logsuffix }}.zip continue-on-error: true - name: Persist test outputs if: always() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: path: ~/linux-x64${{ matrix.artifact }}_testsupport_${{ env.logsuffix }}.zip continue-on-error: true @@ -432,7 +455,7 @@ jobs: gnu-arch: powerpc64le env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}.${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_INTERIM }}.${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_UPDATE }}" + JDK_VERSION: "${{ needs.prerequisites.outputs.jdk_version }}" BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_FILENAME }}" BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_URL }}" @@ -440,13 +463,13 @@ jobs: steps: - name: Checkout the source - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: jdk - name: Restore boot JDK from cache id: bootjdk - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/bootjdk/${{ env.BOOT_JDK_VERSION }} key: bootjdk-${{ runner.os }}-${{ env.BOOT_JDK_VERSION }}-${{ env.BOOT_JDK_SHA256 }}-v1 @@ -462,14 +485,14 @@ jobs: - name: Restore build JDK id: build_restore - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jdk-linux-x64_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jdk-linux-x64 continue-on-error: true - name: Restore build JDK (retry) - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jdk-linux-x64_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jdk-linux-x64 @@ -500,7 +523,7 @@ jobs: - name: Cache sysroot id: cache-sysroot - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/sysroot-${{ matrix.debian-arch }}/ key: sysroot-${{ matrix.debian-arch }}-${{ hashFiles('jdk/.github/workflows/submit.yml') }} @@ -580,7 +603,7 @@ jobs: # Reduced 32-bit build uses the same boot JDK as 64-bit build env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}.${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_INTERIM }}.${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_UPDATE }}" + JDK_VERSION: "${{ needs.prerequisites.outputs.jdk_version }}" BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_FILENAME }}" BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_URL }}" @@ -588,13 +611,13 @@ jobs: steps: - name: Checkout the source - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: jdk - name: Restore boot JDK from cache id: bootjdk - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/bootjdk/${{ env.BOOT_JDK_VERSION }} key: bootjdk-${{ runner.os }}-${{ env.BOOT_JDK_VERSION }}-${{ env.BOOT_JDK_SHA256 }}-v1 @@ -610,21 +633,21 @@ jobs: - name: Restore jtreg artifact id: jtreg_restore - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jtreg/ continue-on-error: true - name: Restore jtreg artifact (retry) - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jtreg/ if: steps.jtreg_restore.outcome == 'failure' - name: Checkout gtest sources - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: "google/googletest" ref: "release-${{ fromJson(needs.prerequisites.outputs.dependencies).GTEST_VERSION }}" @@ -663,7 +686,7 @@ jobs: working-directory: jdk - name: Persist test bundles - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: transient_jdk-linux-x86${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} path: | @@ -717,7 +740,7 @@ jobs: # Reduced 32-bit build uses the same boot JDK as 64-bit build env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}.${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_INTERIM }}.${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_UPDATE }}" + JDK_VERSION: "${{ needs.prerequisites.outputs.jdk_version }}" BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_FILENAME }}" BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_URL }}" @@ -725,11 +748,11 @@ jobs: steps: - name: Checkout the source - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Restore boot JDK from cache id: bootjdk - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/bootjdk/${{ env.BOOT_JDK_VERSION }} key: bootjdk-${{ runner.os }}-${{ env.BOOT_JDK_VERSION }}-${{ env.BOOT_JDK_SHA256 }}-v1 @@ -745,14 +768,14 @@ jobs: - name: Restore jtreg artifact id: jtreg_restore - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jtreg/ continue-on-error: true - name: Restore jtreg artifact (retry) - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jtreg/ @@ -760,14 +783,14 @@ jobs: - name: Restore build artifacts id: build_restore - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jdk-linux-x86${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jdk-linux-x86${{ matrix.artifact }} continue-on-error: true - name: Restore build artifacts (retry) - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jdk-linux-x86${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jdk-linux-x86${{ matrix.artifact }} @@ -789,6 +812,7 @@ jobs: echo "imageroot=`dirname ${imageroot}`" >> $GITHUB_ENV - name: Run tests + id: run_tests run: > JDK_IMAGE_DIR=${{ env.imageroot }} TEST_IMAGE_DIR=${HOME}/jdk-linux-x86${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_linux-x86_bin-tests${{ matrix.artifact }} @@ -804,7 +828,7 @@ jobs: JTREG="JAVA_OPTIONS=-XX:-CreateCoredumpOnCrash" - name: Check that all tests executed successfully - if: always() + if: steps.run_tests.outcome != 'skipped' run: > if ! grep --include=test-summary.txt -lqr build/*/test-results -e "TEST SUCCESS" ; then cat build/*/test-results/*/text/newfailures.txt ; @@ -839,14 +863,14 @@ jobs: - name: Persist test results if: always() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: path: ~/linux-x86${{ matrix.artifact }}_testresults_${{ env.logsuffix }}.zip continue-on-error: true - name: Persist test outputs if: always() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: path: ~/linux-x86${{ matrix.artifact }}_testsupport_${{ env.logsuffix }}.zip continue-on-error: true @@ -868,34 +892,45 @@ jobs: artifact: -debug env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}" + JDK_VERSION: "${{ needs.prerequisites.outputs.jdk_version }}" BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).WINDOWS_X64_BOOT_JDK_FILENAME }}" BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).WINDOWS_X64_BOOT_JDK_URL }}" BOOT_JDK_SHA256: "${{ fromJson(needs.prerequisites.outputs.dependencies).WINDOWS_X64_BOOT_JDK_SHA256 }}" steps: + - name: Restore cygwin installer from cache + id: cygwin-installer + uses: actions/cache@v3 + with: + path: ~/cygwin/setup-x86_64.exe + key: cygwin-installer + + - name: Download cygwin installer + run: | + New-Item -Force -ItemType directory -Path "$HOME\cygwin" + & curl -L "https://www.cygwin.com/setup-x86_64.exe" -o "$HOME/cygwin/setup-x86_64.exe" + if: steps.cygwin-installer.outputs.cache-hit != 'true' + - name: Restore cygwin packages from cache id: cygwin - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/cygwin/packages key: cygwin-packages-${{ runner.os }}-v1 - name: Install cygwin run: | - New-Item -Force -ItemType directory -Path "$HOME\cygwin" - & curl -L "https://www.cygwin.com/setup-x86_64.exe" -o "$HOME/cygwin/setup-x86_64.exe" Start-Process -FilePath "$HOME\cygwin\setup-x86_64.exe" -ArgumentList "--quiet-mode --packages cygwin=3.2.0-1,autoconf,make,zip,unzip --root $HOME\cygwin\cygwin64 --local-package-dir $HOME\cygwin\packages --site http://mirrors.kernel.org/sourceware/cygwin --no-desktop --no-shortcuts --no-startmenu --no-admin" -Wait -NoNewWindow - name: Checkout the source - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: jdk - name: Restore boot JDK from cache id: bootjdk - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/bootjdk/${{ env.BOOT_JDK_VERSION }} key: bootjdk-${{ runner.os }}-${{ env.BOOT_JDK_VERSION }}-${{ env.BOOT_JDK_SHA256 }}-v1 @@ -957,34 +992,45 @@ jobs: artifact: -debug env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}.${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_INTERIM }}.${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_UPDATE }}" + JDK_VERSION: "${{ needs.prerequisites.outputs.jdk_version }}" BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).WINDOWS_X64_BOOT_JDK_FILENAME }}" BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).WINDOWS_X64_BOOT_JDK_URL }}" BOOT_JDK_SHA256: "${{ fromJson(needs.prerequisites.outputs.dependencies).WINDOWS_X64_BOOT_JDK_SHA256 }}" steps: + - name: Restore cygwin installer from cache + id: cygwin-installer + uses: actions/cache@v3 + with: + path: ~/cygwin/setup-x86_64.exe + key: cygwin-installer + + - name: Download cygwin installer + run: | + New-Item -Force -ItemType directory -Path "$HOME\cygwin" + & curl -L "https://www.cygwin.com/setup-x86_64.exe" -o "$HOME/cygwin/setup-x86_64.exe" + if: steps.cygwin-installer.outputs.cache-hit != 'true' + - name: Restore cygwin packages from cache id: cygwin - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/cygwin/packages key: cygwin-packages-${{ runner.os }}-v1 - name: Install cygwin run: | - New-Item -Force -ItemType directory -Path "$HOME\cygwin" - & curl -L "https://www.cygwin.com/setup-x86_64.exe" -o "$HOME/cygwin/setup-x86_64.exe" Start-Process -FilePath "$HOME\cygwin\setup-x86_64.exe" -ArgumentList "--quiet-mode --packages cygwin=3.2.0-1,autoconf,make,zip,unzip --root $HOME\cygwin\cygwin64 --local-package-dir $HOME\cygwin\packages --site http://mirrors.kernel.org/sourceware/cygwin --no-desktop --no-shortcuts --no-startmenu --no-admin" -Wait -NoNewWindow - name: Checkout the source - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: jdk - name: Restore boot JDK from cache id: bootjdk - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/bootjdk/${{ env.BOOT_JDK_VERSION }} key: bootjdk-${{ runner.os }}-${{ env.BOOT_JDK_VERSION }}-${{ env.BOOT_JDK_SHA256 }}-v1 @@ -1000,7 +1046,7 @@ jobs: if: steps.bootjdk.outputs.cache-hit != 'true' - name: Checkout gtest sources - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: "google/googletest" ref: "release-${{ fromJson(needs.prerequisites.outputs.dependencies).GTEST_VERSION }}" @@ -1008,14 +1054,14 @@ jobs: - name: Restore jtreg artifact id: jtreg_restore - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jtreg/ continue-on-error: true - name: Restore jtreg artifact (retry) - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jtreg/ @@ -1055,7 +1101,7 @@ jobs: working-directory: jdk - name: Persist test bundles - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: transient_jdk-windows-x64${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} path: | @@ -1109,7 +1155,7 @@ jobs: artifact: -debug env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}.${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_INTERIM }}.${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_UPDATE }}" + JDK_VERSION: "${{ needs.prerequisites.outputs.jdk_version }}" BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).WINDOWS_X64_BOOT_JDK_FILENAME }}" BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).WINDOWS_X64_BOOT_JDK_URL }}" @@ -1117,11 +1163,11 @@ jobs: steps: - name: Checkout the source - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Restore boot JDK from cache id: bootjdk - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/bootjdk/${{ env.BOOT_JDK_VERSION }} key: bootjdk-${{ runner.os }}-${{ env.BOOT_JDK_VERSION }}-${{ env.BOOT_JDK_SHA256 }}-v1 @@ -1136,29 +1182,40 @@ jobs: Get-ChildItem "$HOME\bootjdk\$env:BOOT_JDK_VERSION\*\*" | Move-Item -Destination "$HOME\bootjdk\$env:BOOT_JDK_VERSION" if: steps.bootjdk.outputs.cache-hit != 'true' + - name: Restore cygwin installer from cache + id: cygwin-installer + uses: actions/cache@v3 + with: + path: ~/cygwin/setup-x86_64.exe + key: cygwin-installer + + - name: Download cygwin installer + run: | + New-Item -Force -ItemType directory -Path "$HOME\cygwin" + & curl -L "https://www.cygwin.com/setup-x86_64.exe" -o "$HOME/cygwin/setup-x86_64.exe" + if: steps.cygwin-installer.outputs.cache-hit != 'true' + - name: Restore cygwin packages from cache id: cygwin - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/cygwin/packages key: cygwin-packages-${{ runner.os }}-v1 - name: Install cygwin run: | - New-Item -Force -ItemType directory -Path "$HOME\cygwin" - & curl -L "https://www.cygwin.com/setup-x86_64.exe" -o "$HOME/cygwin/setup-x86_64.exe" Start-Process -FilePath "$HOME\cygwin\setup-x86_64.exe" -ArgumentList "--quiet-mode --packages cygwin=3.2.0-1,autoconf,make,zip,unzip --root $HOME\cygwin\cygwin64 --local-package-dir $HOME\cygwin\packages --site http://mirrors.kernel.org/sourceware/cygwin --no-desktop --no-shortcuts --no-startmenu --no-admin" -Wait -NoNewWindow - name: Restore jtreg artifact id: jtreg_restore - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jtreg/ continue-on-error: true - name: Restore jtreg artifact (retry) - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jtreg/ @@ -1166,14 +1223,14 @@ jobs: - name: Restore build artifacts id: build_restore - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jdk-windows-x64${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jdk-windows-x64${{ matrix.artifact }} continue-on-error: true - name: Restore build artifacts (retry) - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jdk-windows-x64${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jdk-windows-x64${{ matrix.artifact }} @@ -1198,6 +1255,7 @@ jobs: run: echo ("imageroot=" + (Get-ChildItem -Path $HOME/jdk-windows-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_windows-x64_bin${{ matrix.artifact }} -Filter release -Recurse -ErrorAction SilentlyContinue -Force).DirectoryName) | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 - name: Run tests + id: run_tests run: > $env:Path = "$HOME\cygwin\cygwin64\bin;$HOME\cygwin\cygwin64\bin;$env:Path" ; $env:Path = $env:Path -split ";" -match "C:\\Windows|PowerShell|cygwin" -join ";" ; @@ -1216,7 +1274,7 @@ jobs: JTREG="JAVA_OPTIONS=-XX:-CreateCoredumpOnCrash" - name: Check that all tests executed successfully - if: always() + if: steps.run_tests.outcome != 'skipped' run: > if ((Get-ChildItem -Path build\*\test-results\test-summary.txt -Recurse | Select-String -Pattern "TEST SUCCESS" ).Count -eq 0) { Get-Content -Path build\*\test-results\*\*\newfailures.txt ; @@ -1253,14 +1311,14 @@ jobs: - name: Persist test results if: always() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: path: ~/windows-x64${{ matrix.artifact }}_testresults_${{ env.logsuffix }}.zip continue-on-error: true - name: Persist test outputs if: always() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: path: ~/windows-x64${{ matrix.artifact }}_testsupport_${{ env.logsuffix }}.zip continue-on-error: true @@ -1284,7 +1342,7 @@ jobs: artifact: -debug env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}.${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_INTERIM }}.${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_UPDATE }}" + JDK_VERSION: "${{ needs.prerequisites.outputs.jdk_version }}" BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).MACOS_X64_BOOT_JDK_FILENAME }}" BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).MACOS_X64_BOOT_JDK_URL }}" @@ -1292,13 +1350,13 @@ jobs: steps: - name: Checkout the source - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: jdk - name: Restore boot JDK from cache id: bootjdk - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/bootjdk/${{ env.BOOT_JDK_VERSION }} key: bootjdk-${{ runner.os }}-${{ env.BOOT_JDK_VERSION }}-${{ env.BOOT_JDK_SHA256 }}-v1 @@ -1314,21 +1372,21 @@ jobs: - name: Restore jtreg artifact id: jtreg_restore - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jtreg/ continue-on-error: true - name: Restore jtreg artifact (retry) - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jtreg/ if: steps.jtreg_restore.outcome == 'failure' - name: Checkout gtest sources - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: "google/googletest" ref: "release-${{ fromJson(needs.prerequisites.outputs.dependencies).GTEST_VERSION }}" @@ -1360,7 +1418,7 @@ jobs: working-directory: jdk - name: Persist test bundles - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: transient_jdk-macos-x64${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} path: | @@ -1386,7 +1444,7 @@ jobs: artifact: -debug env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}.${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_INTERIM }}.${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_UPDATE }}" + JDK_VERSION: "${{ needs.prerequisites.outputs.jdk_version }}" BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).MACOS_X64_BOOT_JDK_FILENAME }}" BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).MACOS_X64_BOOT_JDK_URL }}" @@ -1394,13 +1452,13 @@ jobs: steps: - name: Checkout the source - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: jdk - name: Restore boot JDK from cache id: bootjdk - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/bootjdk/${{ env.BOOT_JDK_VERSION }} key: bootjdk-${{ runner.os }}-${{ env.BOOT_JDK_VERSION }}-${{ env.BOOT_JDK_SHA256 }}-v1 @@ -1416,21 +1474,21 @@ jobs: - name: Restore jtreg artifact id: jtreg_restore - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jtreg/ continue-on-error: true - name: Restore jtreg artifact (retry) - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jtreg/ if: steps.jtreg_restore.outcome == 'failure' - name: Checkout gtest sources - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: "google/googletest" ref: "release-${{ fromJson(needs.prerequisites.outputs.dependencies).GTEST_VERSION }}" @@ -1463,7 +1521,7 @@ jobs: working-directory: jdk - name: Persist test bundles - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: transient_jdk-macos-aarch64${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} path: | @@ -1517,7 +1575,7 @@ jobs: artifact: -debug env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}.${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_INTERIM }}.${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_UPDATE }}" + JDK_VERSION: "${{ needs.prerequisites.outputs.jdk_version }}" BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).MACOS_X64_BOOT_JDK_FILENAME }}" BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).MACOS_X64_BOOT_JDK_URL }}" @@ -1525,11 +1583,11 @@ jobs: steps: - name: Checkout the source - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Restore boot JDK from cache id: bootjdk - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/bootjdk/${{ env.BOOT_JDK_VERSION }} key: bootjdk-${{ runner.os }}-${{ env.BOOT_JDK_VERSION }}-${{ env.BOOT_JDK_SHA256 }}-v1 @@ -1545,14 +1603,14 @@ jobs: - name: Restore jtreg artifact id: jtreg_restore - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jtreg/ continue-on-error: true - name: Restore jtreg artifact (retry) - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jtreg_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jtreg/ @@ -1560,14 +1618,14 @@ jobs: - name: Restore build artifacts id: build_restore - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jdk-macos-x64${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jdk-macos-x64${{ matrix.artifact }} continue-on-error: true - name: Restore build artifacts (retry) - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: transient_jdk-macos-x64${{ matrix.artifact }}_${{ needs.prerequisites.outputs.bundle_id }} path: ~/jdk-macos-x64${{ matrix.artifact }} @@ -1595,6 +1653,7 @@ jobs: echo "imageroot=`dirname ${imageroot}`" >> $GITHUB_ENV - name: Run tests + id: run_tests run: > JDK_IMAGE_DIR=${{ env.imageroot }} TEST_IMAGE_DIR=${HOME}/jdk-macos-x64${{ matrix.artifact }}/jdk-${{ env.JDK_VERSION }}-internal+0_macos-x64_bin-tests${{ matrix.artifact }} @@ -1610,7 +1669,7 @@ jobs: JTREG="JAVA_OPTIONS=-XX:-CreateCoredumpOnCrash" - name: Check that all tests executed successfully - if: always() + if: steps.run_tests.outcome != 'skipped' run: > if ! grep --include=test-summary.txt -lqr build/*/test-results -e "TEST SUCCESS" ; then cat build/*/test-results/*/text/newfailures.txt ; @@ -1645,14 +1704,14 @@ jobs: - name: Persist test results if: always() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: path: ~/macos-x64${{ matrix.artifact }}_testresults_${{ env.logsuffix }}.zip continue-on-error: true - name: Persist test outputs if: always() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: path: ~/macos-x64${{ matrix.artifact }}_testsupport_${{ env.logsuffix }}.zip continue-on-error: true @@ -1675,7 +1734,7 @@ jobs: steps: - name: Determine current artifacts endpoint id: actions_runtime - uses: actions/github-script@v3 + uses: actions/github-script@v6 with: script: "return { url: process.env['ACTIONS_RUNTIME_URL'], token: process.env['ACTIONS_RUNTIME_TOKEN'] }" @@ -1698,7 +1757,7 @@ jobs: done - name: Fetch remaining artifacts (test results) - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: path: test-results @@ -1715,7 +1774,7 @@ jobs: done - name: Upload a combined test results artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: test-results_${{ needs.prerequisites.outputs.bundle_id }} path: test-results diff --git a/.jcheck/conf b/.jcheck/conf index 9f3becb0f4e..685b2712329 100644 --- a/.jcheck/conf +++ b/.jcheck/conf @@ -1,7 +1,7 @@ [general] project=jdk-updates jbs=JDK -version=17.0.3 +version=17.0.4 [checks] error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists diff --git a/ci.jsonnet b/ci.jsonnet index 6221ce82e6c..91ff0e9b3c3 100644 --- a/ci.jsonnet +++ b/ci.jsonnet @@ -7,9 +7,18 @@ local labsjdk_builder_version = "e9c60b5174490f2012c7c5d60a20aace93209a56"; { overlay: "de70fec80b4947d9ef25c39e059b01ef38dfc387", - specVersion: "2", + specVersion: "3", - OSBase:: { + mxDependencies:: { + "python_version": "3", + packages+: { + "mx": "HEAD", + "python3": "==3.8.10", + 'pip:pylint': '==2.4.4', + }, + }, + + OSBase:: self.mxDependencies + { path(unixpath):: unixpath, exe(unixpath):: unixpath, jdk_home(java_home):: self.path(java_home), @@ -19,7 +28,7 @@ local labsjdk_builder_version = "e9c60b5174490f2012c7c5d60a20aace93209a56"; JIB_PATH: "${PATH}", MAKE : "make", ZLIB_BUNDLING: "system", - MX_PYTHON: "python3" + MX_PYTHON: "python3.8" }, }, @@ -32,7 +41,7 @@ local labsjdk_builder_version = "e9c60b5174490f2012c7c5d60a20aace93209a56"; downloads+: { CYGWIN: {name: "cygwin", version: "3.0.7", platformspecific: true}, }, - packages : { + packages+: { # devkit_platform_revisions in make/conf/jib-profiles.js "devkit:VS2019-16.9.3+1" : "==0" }, @@ -53,14 +62,15 @@ local labsjdk_builder_version = "e9c60b5174490f2012c7c5d60a20aace93209a56"; docker: { image: defs.linux_docker_image_amd64_musl }, + packages: {}, }, LinuxAMD64(for_jdk_build):: self.Linux + self.AMD64 { docker: { image: defs.linux_docker_image_amd64, - mount_modules: !for_jdk_build # needed for installing the devtoolset package below + mount_modules: true # needed for installing the devtoolset package below }, - packages : if for_jdk_build then { + packages+: if for_jdk_build then { # devkit_platform_revisions in make/conf/jib-profiles.js "devkit:gcc10.3.0-OL6.4+1" : "==0" } else { @@ -70,7 +80,7 @@ local labsjdk_builder_version = "e9c60b5174490f2012c7c5d60a20aace93209a56"; }, }, LinuxAArch64(for_jdk_build):: self.Linux + self.AArch64 { - packages : if for_jdk_build then { + packages+: if for_jdk_build then { # devkit_platform_revisions in make/conf/jib-profiles.js "devkit:gcc10.3.0-OL7.6+1" : "==0" } else { @@ -96,10 +106,7 @@ local labsjdk_builder_version = "e9c60b5174490f2012c7c5d60a20aace93209a56"; DarwinAArch64:: self.Darwin + self.AArch64 + { capabilities+: ["darwin"], packages+: { - "python3": "==3.9.9", - '00:pip:logilab-common': '==1.8.3', - '01:pip:astroid': '==2.11.0', - 'pip:pylint': '==2.12.2', + }, }, @@ -187,12 +194,6 @@ local labsjdk_builder_version = "e9c60b5174490f2012c7c5d60a20aace93209a56"; }, Build(conf, is_musl_build):: conf + setupJDKSources(conf) + (if is_musl_build then self.MuslBootJDK else self.BootJDK) + { - packages+: if !is_musl_build && !std.endsWith(conf.name, 'darwin-aarch64') then { - # GR-19828 - "00:pip:logilab-common ": "==1.4.4", - "01:pip:astroid" : "==1.1.0", - "pip:pylint" : "==1.1.0", - } else {}, name: "build-jdk" + conf.name, timelimit: "1:50:00", diskspace_required: "10G", @@ -385,7 +386,7 @@ local labsjdk_builder_version = "e9c60b5174490f2012c7c5d60a20aace93209a56"; self.LinuxAArch64(true), self.DarwinAMD64, self.DarwinAArch64, - self.Windows + self.AMD64 + self.Windows + self.AMD64 ], local graal_confs = [ diff --git a/make/CreateJmods.gmk b/make/CreateJmods.gmk index 6edc69397a5..e1f18459071 100644 --- a/make/CreateJmods.gmk +++ b/make/CreateJmods.gmk @@ -221,6 +221,13 @@ else JMOD_FLAGS += --exclude '**{_the.*,_*.marker*,*.diz,*.debuginfo,*.dSYM/**,*.dSYM}' endif +# For reproducible builds specify the jmod --date using SOURCE_DATE in ISO-8601 +ifeq ($(ENABLE_REPRODUCIBLE_BUILD), true) + JMOD_SOURCE_DATE := --date $(SOURCE_DATE_ISO_8601) +else + JMOD_SOURCE_DATE := +endif + # Create jmods in the support dir and then move them into place to keep the # module path in $(IMAGES_OUTPUTDIR)/jmods valid at all times. $(eval $(call SetupExecute, create_$(JMOD_FILE), \ @@ -232,6 +239,7 @@ $(eval $(call SetupExecute, create_$(JMOD_FILE), \ COMMAND := $(JMOD) create --module-version $(VERSION_SHORT) \ --target-platform '$(OPENJDK_MODULE_TARGET_PLATFORM)' \ --module-path $(JMODS_DIR) $(JMOD_FLAGS) \ + $(JMOD_SOURCE_DATE) \ $(JMODS_SUPPORT_DIR)/$(JMOD_FILE), \ POST_COMMAND := $(MV) $(JMODS_SUPPORT_DIR)/$(JMOD_FILE) $(JMODS_DIR)/$(JMOD_FILE), \ )) diff --git a/make/InitSupport.gmk b/make/InitSupport.gmk index 8ee2e9098ba..d2291c50f21 100644 --- a/make/InitSupport.gmk +++ b/make/InitSupport.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 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 @@ -313,6 +313,15 @@ else # $(HAS_SPEC)=true SOURCE_DATE := $$(shell $$(DATE) +"%s") endif export SOURCE_DATE_EPOCH := $$(SOURCE_DATE) + ifeq ($$(IS_GNU_DATE), yes) + export SOURCE_DATE_ISO_8601 := $$(shell $$(DATE) --utc \ + --date="@$$(SOURCE_DATE_EPOCH)" \ + +"%Y-%m-%dT%H:%M:%SZ" 2> /dev/null) + else + export SOURCE_DATE_ISO_8601 := $$(shell $$(DATE) -u \ + -j -f "%s" "$$(SOURCE_DATE_EPOCH)" \ + +"%Y-%m-%dT%H:%M:%SZ" 2> /dev/null) + endif endef # Parse COMPARE_BUILD into COMPARE_BUILD_* diff --git a/make/TestImage.gmk b/make/TestImage.gmk index 26d10f95d3b..b719d6824da 100644 --- a/make/TestImage.gmk +++ b/make/TestImage.gmk @@ -35,8 +35,8 @@ BUILD_INFO_PROPERTIES := $(TEST_IMAGE_DIR)/build-info.properties $(BUILD_INFO_PROPERTIES): $(call MakeTargetDir) $(ECHO) "# Build info properties for JDK tests" > $@ - $(ECHO) "build.workspace.root=$(call FixPath, $(WORKSPACE_ROOT))" >> $@ - $(ECHO) "build.output.root=$(call FixPath, $(OUTPUTDIR))" >> $@ + $(ECHO) 'build.workspace.root=$(call FixPath, $(WORKSPACE_ROOT))' >> $@ + $(ECHO) 'build.output.root=$(call FixPath, $(OUTPUTDIR))' >> $@ README := $(TEST_IMAGE_DIR)/Readme.txt diff --git a/make/autoconf/basic_tools.m4 b/make/autoconf/basic_tools.m4 index 820d2f4924d..9ce90303d45 100644 --- a/make/autoconf/basic_tools.m4 +++ b/make/autoconf/basic_tools.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 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 @@ -356,6 +356,18 @@ AC_DEFUN_ONCE([BASIC_SETUP_COMPLEX_TOOLS], fi AC_SUBST(IS_GNU_TIME) + # 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"` + if test "x$check_date" != x; then + AC_MSG_RESULT([yes]) + IS_GNU_DATE=yes + else + AC_MSG_RESULT([no]) + IS_GNU_DATE=no + fi + AC_SUBST(IS_GNU_DATE) + if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then UTIL_REQUIRE_PROGS(DSYMUTIL, dsymutil) UTIL_REQUIRE_PROGS(MIG, mig) diff --git a/make/autoconf/boot-jdk.m4 b/make/autoconf/boot-jdk.m4 index 1d82f7c79b9..0a04d1f82b2 100644 --- a/make/autoconf/boot-jdk.m4 +++ b/make/autoconf/boot-jdk.m4 @@ -357,6 +357,16 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK], # Finally, set some other options... + # Determine if the boot jdk jar supports the --date option + if $JAR --help 2>&1 | $GREP -q "\-\-date=TIMESTAMP"; then + BOOT_JDK_JAR_SUPPORTS_DATE=true + else + BOOT_JDK_JAR_SUPPORTS_DATE=false + fi + AC_MSG_CHECKING([if Boot JDK jar supports --date=TIMESTAMP]) + AC_MSG_RESULT([$BOOT_JDK_JAR_SUPPORTS_DATE]) + AC_SUBST(BOOT_JDK_JAR_SUPPORTS_DATE) + # When compiling code to be executed by the Boot JDK, force compatibility with the # oldest supported bootjdk. OLDEST_BOOT_JDK=`$ECHO $DEFAULT_ACCEPTABLE_BOOT_VERSIONS \ diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4 index 5eed1138f1f..762f5dc3872 100644 --- a/make/autoconf/flags-cflags.m4 +++ b/make/autoconf/flags-cflags.m4 @@ -782,10 +782,8 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_CPU_DEP], test "x$ENABLE_REPRODUCIBLE_BUILD" = xtrue; then # There is a known issue with the pathmap if the mapping is made to the # empty string. Add a minimal string "s" as prefix to work around this. - workspace_root_win=`$FIXPATH_BASE print "${WORKSPACE_ROOT%/}"` # PATHMAP_FLAGS is also added to LDFLAGS in flags-ldflags.m4. - PATHMAP_FLAGS="-pathmap:${workspace_root_win//\//\\\\}=s \ - -pathmap:${workspace_root_win}=s" + PATHMAP_FLAGS="-pathmap:${WORKSPACE_ROOT}=s" FILE_MACRO_CFLAGS="$PATHMAP_FLAGS" FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [${FILE_MACRO_CFLAGS}], PREFIX: $3, diff --git a/make/autoconf/help.m4 b/make/autoconf/help.m4 index b28218d66aa..139d18a8628 100644 --- a/make/autoconf/help.m4 +++ b/make/autoconf/help.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 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 @@ -25,7 +25,7 @@ AC_DEFUN_ONCE([HELP_SETUP_DEPENDENCY_HELP], [ - UTIL_LOOKUP_PROGS(PKGHANDLER, zypper apt-get yum brew port pkgutil pkgadd pacman) + UTIL_LOOKUP_PROGS(PKGHANDLER, zypper apt-get yum brew port pkgutil pkgadd pacman apk) ]) AC_DEFUN([HELP_MSG_MISSING_DEPENDENCY], @@ -58,6 +58,8 @@ AC_DEFUN([HELP_MSG_MISSING_DEPENDENCY], zypper_help $MISSING_DEPENDENCY ;; *pacman) pacman_help $MISSING_DEPENDENCY ;; + *apk) + apk_help $MISSING_DEPENDENCY ;; esac if test "x$PKGHANDLER_COMMAND" != x; then @@ -184,6 +186,27 @@ pkgadd_help() { PKGHANDLER_COMMAND="" } +apk_help() { + case $1 in + devkit) + PKGHANDLER_COMMAND="sudo apk add alpine-sdk linux-headers" ;; + alsa) + PKGHANDLER_COMMAND="sudo apk add alsa-lib-dev" ;; + cups) + PKGHANDLER_COMMAND="sudo apk add cups-dev" ;; + fontconfig) + PKGHANDLER_COMMAND="sudo apk add fontconfig-dev" ;; + freetype) + PKGHANDLER_COMMAND="sudo apk add freetype-dev" ;; + harfbuzz) + PKGHANDLER_COMMAND="sudo apk add harfbuzz-dev" ;; + x11) + PKGHANDLER_COMMAND="sudo apk add libxtst-dev libxt-dev libxrender-dev libxrandr-dev" ;; + ccache) + PKGHANDLER_COMMAND="sudo apk add ccache" ;; + esac +} + # This function will check if we're called from the "configure" wrapper while # printing --help. If so, we will print out additional information that can # only be extracted within the autoconf script, and then exit. This must be diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4 index 4bd35d609c0..d6c389ad61e 100644 --- a/make/autoconf/jdk-options.m4 +++ b/make/autoconf/jdk-options.m4 @@ -216,6 +216,12 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_OPTIONS], AC_MSG_ERROR([Copyright year must have a value]) elif test "x$with_copyright_year" != x; then COPYRIGHT_YEAR="$with_copyright_year" + elif test "x$SOURCE_DATE_EPOCH" != x; then + if test "x$IS_GNU_DATE" = xyes; then + COPYRIGHT_YEAR=`date --date=@$SOURCE_DATE_EPOCH +%Y` + else + COPYRIGHT_YEAR=`date -j -f %s $SOURCE_DATE_EPOCH +%Y` + fi else COPYRIGHT_YEAR=`$DATE +'%Y'` fi diff --git a/make/autoconf/spec.gmk.in b/make/autoconf/spec.gmk.in index c2c9c4adf3a..d557549adb3 100644 --- a/make/autoconf/spec.gmk.in +++ b/make/autoconf/spec.gmk.in @@ -364,6 +364,9 @@ BUILD_JDK:=@BUILD_JDK@ CREATE_BUILDJDK:=@CREATE_BUILDJDK@ EXTERNAL_BUILDJDK:=@EXTERNAL_BUILDJDK@ +# Whether the boot jdk jar supports --date=TIMESTAMP +BOOT_JDK_JAR_SUPPORTS_DATE:=@BOOT_JDK_JAR_SUPPORTS_DATE@ + # When compiling Java source to be run by the boot jdk # use these extra flags, eg -source 6 -target 6 BOOT_JDK_SOURCETARGET:=@BOOT_JDK_SOURCETARGET@ @@ -700,6 +703,7 @@ CODESIGN:=@CODESIGN@ CP:=@CP@ CUT:=@CUT@ DATE:=@DATE@ +IS_GNU_DATE:=@IS_GNU_DATE@ DIFF:=@DIFF@ DIRNAME:=@DIRNAME@ DSYMUTIL:=@DSYMUTIL@ diff --git a/make/autoconf/util.m4 b/make/autoconf/util.m4 index 9ececc55e5e..877165ab3a3 100644 --- a/make/autoconf/util.m4 +++ b/make/autoconf/util.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 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 @@ -236,13 +236,15 @@ AC_DEFUN([UTIL_GET_MATCHING_VALUES], # $2: input date/time string AC_DEFUN([UTIL_GET_EPOCH_TIMESTAMP], [ - timestamp=$($DATE --utc --date=$2 +"%s" 2> /dev/null) - if test "x$timestamp" = x; then - # GNU date format did not work, try BSD date options - timestamp=$($DATE -j -f "%F %T" "$2" "+%s" 2> /dev/null) + if test "x$IS_GNU_DATE" = xyes; then + # GNU date + timestamp=$($DATE --utc --date=$2 +"%s" 2> /dev/null) + else + # BSD date + timestamp=$($DATE -u -j -f "%F %T" "$2" "+%s" 2> /dev/null) if test "x$timestamp" = x; then # Perhaps the time was missing - timestamp=$($DATE -j -f "%F %T" "$2 00:00:00" "+%s" 2> /dev/null) + timestamp=$($DATE -u -j -f "%F %T" "$2 00:00:00" "+%s" 2> /dev/null) # If this did not work, we give up and return the empty string fi fi diff --git a/make/common/JarArchive.gmk b/make/common/JarArchive.gmk index d2a4ec103c4..5a87e471428 100644 --- a/make/common/JarArchive.gmk +++ b/make/common/JarArchive.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 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 @@ -193,7 +193,7 @@ define SetupJarArchiveBody $1_UPDATE_CONTENTS=\ if [ "`$(WC) -l $$($1_BIN)/_the.$$($1_JARNAME)_contents | $(AWK) '{ print $$$$1 }'`" -gt "0" ]; then \ $(ECHO) " updating" `$(WC) -l $$($1_BIN)/_the.$$($1_JARNAME)_contents | $(AWK) '{ print $$$$1 }'` files && \ - $$($1_JAR_CMD) $$($1_JAR_UPDATE_OPTIONS) $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents; \ + $$($1_JAR_CMD) --update $$($1_JAR_OPTIONS) --file $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents; \ fi $$(NEWLINE) # The s-variants of the above macros are used when the jar is created from scratch. # NOTICE: please leave the parentheses space separated otherwise the AIX build will break! @@ -212,25 +212,27 @@ define SetupJarArchiveBody | $(SED) 's|$$(src)/|-C $$(src) |g' >> \ $$($1_BIN)/_the.$$($1_JARNAME)_contents) $$(NEWLINE) ) endif - $1_SUPDATE_CONTENTS=$$($1_JAR_CMD) $$($1_JAR_UPDATE_OPTIONS) $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE) + $1_SUPDATE_CONTENTS=$$($1_JAR_CMD) --update $$($1_JAR_OPTIONS) --file $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE) # Use a slightly shorter name for logging, but with enough path to identify this jar. $1_NAME:=$$(subst $$(OUTPUTDIR)/,,$$($1_JAR)) + # If reproducible build and the boot jdk jar supports --date option + # then specify the --date using SOURCE_DATE in ISO-8601 + $1_JAR_OPTIONS := + ifeq ($$(ENABLE_REPRODUCIBLE_BUILD), true) + ifeq ($$(BOOT_JDK_JAR_SUPPORTS_DATE), true) + $1_JAR_OPTIONS += --date $(SOURCE_DATE_ISO_8601) + endif + endif ifneq (,$$($1_CHECK_COMPRESS_JAR)) - $1_JAR_CREATE_OPTIONS := c0fm - $1_JAR_UPDATE_OPTIONS := u0f - ifeq ($(COMPRESS_JARS), true) - $1_JAR_CREATE_OPTIONS := cfm - $1_JAR_UPDATE_OPTIONS := uf + ifneq ($(COMPRESS_JARS), true) + $1_JAR_OPTIONS += --no-compress endif - else - $1_JAR_CREATE_OPTIONS := cfm - $1_JAR_UPDATE_OPTIONS := uf endif # Include all variables of significance in the vardeps file - $1_VARDEPS := $$($1_JAR_CMD) $$($1_JAR_CREATE_OPTIONS) $$($1_MANIFEST) \ + $1_VARDEPS := $$($1_JAR_CMD) $$($1_JAR_OPTIONS) $$($1_MANIFEST) \ $$($1_JARMAIN) $$($1_EXTRA_MANIFEST_ATTR) $$($1_ORIG_DEPS) $$($1_SRCS) \ $$($1_INCLUDES) $$($1_EXCLUDES) $$($1_EXCLUDE_FILES) $$($1_EXTRA_FILES) $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$($1_BIN)/_the.$$($1_JARNAME).vardeps) @@ -255,7 +257,7 @@ define SetupJarArchiveBody $$(if $$($1_EXTRA_MANIFEST_ATTR), \ $(PRINTF) "$$($1_EXTRA_MANIFEST_ATTR)\n" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \ $(ECHO) Creating $$($1_NAME) $$(NEWLINE) \ - $$($1_JAR_CMD) $$($1_JAR_CREATE_OPTIONS) $$@ $$($1_MANIFEST_FILE) $$(NEWLINE) \ + $$($1_JAR_CMD) --create $$($1_JAR_OPTIONS) --file $$@ --manifest $$($1_MANIFEST_FILE) $$(NEWLINE) \ $$($1_SCAPTURE_CONTENTS) \ $$($1_SCAPTURE_METAINF) \ $$($1_SUPDATE_CONTENTS) \ diff --git a/make/conf/test-dependencies b/make/conf/test-dependencies index a95357a56da..6f4624dcc41 100644 --- a/make/conf/test-dependencies +++ b/make/conf/test-dependencies @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 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 @@ -25,19 +25,19 @@ # Versions and download locations for dependencies used by pre-submit testing. -BOOT_JDK_VERSION=16 +BOOT_JDK_VERSION=17 JTREG_VERSION=6 JTREG_BUILD=1 GTEST_VERSION=1.8.1 -LINUX_X64_BOOT_JDK_FILENAME=openjdk-17.0.1_linux-x64_bin.tar.gz -LINUX_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk17.0.1/2a2082e5a09d4267845be086888add4f/12/GPL/openjdk-17.0.1_linux-x64_bin.tar.gz -LINUX_X64_BOOT_JDK_SHA256=1c0a73cbb863aad579b967316bf17673b8f98a9bb938602a140ba2e5c38f880a +LINUX_X64_BOOT_JDK_FILENAME=openjdk-17.0.2_linux-x64_bin.tar.gz +LINUX_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.2%2B8/OpenJDK17U-jdk_x64_linux_hotspot_17.0.2_8.tar.gz +LINUX_X64_BOOT_JDK_SHA256=288f34e3ba8a4838605636485d0365ce23e57d5f2f68997ac4c2e4c01967cd48 -WINDOWS_X64_BOOT_JDK_FILENAME=openjdk-17.0.1_windows-x64_bin.zip -WINDOWS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk17.0.1/2a2082e5a09d4267845be086888add4f/12/GPL/openjdk-17.0.1_windows-x64_bin.zip -WINDOWS_X64_BOOT_JDK_SHA256=329900a6673b237b502bdcf77bc334da34bc91355c5fd2d457fc00f53fd71ef1 +WINDOWS_X64_BOOT_JDK_FILENAME=openjdk-17.0.2_windows-x64_bin.zip +WINDOWS_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.2%2B8/OpenJDK17U-jdk_x64_windows_hotspot_17.0.2_8.zip +WINDOWS_X64_BOOT_JDK_SHA256=d083479ca927dce2f586f779373d895e8bf668c632505740279390384edf03fa -MACOS_X64_BOOT_JDK_FILENAME=openjdk-17.0.1_macos-x64_bin.tar.gz -MACOS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk17.0.1/2a2082e5a09d4267845be086888add4f/12/GPL/openjdk-17.0.1_macos-x64_bin.tar.gz -MACOS_X64_BOOT_JDK_SHA256=6ccb35800e723cabe15af60e67099d1a07c111d2d3208aa75523614dde68bee1 +MACOS_X64_BOOT_JDK_FILENAME=openjdk-17.0.2_macos-x64_bin.tar.gz +MACOS_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.2%2B8/OpenJDK17U-jdk_x64_mac_hotspot_17.0.2_8.tar.gz +MACOS_X64_BOOT_JDK_SHA256=3630e21a571b7180876bf08f85d0aac0bdbb3267b2ae9bd242f4933b21f9be32 diff --git a/make/conf/version-numbers.conf b/make/conf/version-numbers.conf index 9b8a7b64155..71b19762f2e 100644 --- a/make/conf/version-numbers.conf +++ b/make/conf/version-numbers.conf @@ -28,12 +28,12 @@ DEFAULT_VERSION_FEATURE=17 DEFAULT_VERSION_INTERIM=0 -DEFAULT_VERSION_UPDATE=3 +DEFAULT_VERSION_UPDATE=4 DEFAULT_VERSION_PATCH=0 DEFAULT_VERSION_EXTRA1=0 DEFAULT_VERSION_EXTRA2=0 DEFAULT_VERSION_EXTRA3=0 -DEFAULT_VERSION_DATE=2022-04-19 +DEFAULT_VERSION_DATE=2022-07-19 DEFAULT_VERSION_CLASSFILE_MAJOR=61 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" DEFAULT_VERSION_CLASSFILE_MINOR=0 DEFAULT_VERSION_DOCS_API_SINCE=11 diff --git a/make/data/publicsuffixlist/VERSION b/make/data/publicsuffixlist/VERSION index 3367b24a0be..be9290a33fc 100644 --- a/make/data/publicsuffixlist/VERSION +++ b/make/data/publicsuffixlist/VERSION @@ -1,2 +1,2 @@ -Github: https://raw.githubusercontent.com/publicsuffix/list/cbbba1d234670453df9c930dfbf510c0474d4301/public_suffix_list.dat -Date: 2020-04-24 +Github: https://raw.githubusercontent.com/publicsuffix/list/3c213aab32b3c014f171b1673d4ce9b5cd72bf1c/public_suffix_list.dat +Date: 2021-11-27 diff --git a/make/data/publicsuffixlist/public_suffix_list.dat b/make/data/publicsuffixlist/public_suffix_list.dat index 27fe1ee51b4..5529554d82d 100644 --- a/make/data/publicsuffixlist/public_suffix_list.dat +++ b/make/data/publicsuffixlist/public_suffix_list.dat @@ -175,17 +175,21 @@ it.ao // aq : https://en.wikipedia.org/wiki/.aq aq -// ar : https://nic.ar/nic-argentina/normativa-vigente +// ar : https://nic.ar/es/nic-argentina/normativa ar +bet.ar com.ar +coop.ar edu.ar gob.ar gov.ar int.ar mil.ar musica.ar +mutual.ar net.ar org.ar +senasa.ar tur.ar // arpa : https://en.wikipedia.org/wiki/.arpa @@ -258,7 +262,7 @@ tas.gov.au vic.gov.au wa.gov.au // 4LDs -education.tas.edu.au +// education.tas.edu.au - Removed at the request of the Department of Education Tasmania schools.nsw.edu.au // aw : https://en.wikipedia.org/wiki/.aw @@ -456,6 +460,7 @@ aju.br am.br anani.br aparecida.br +app.br arq.br art.br ato.br @@ -463,6 +468,7 @@ b.br barueri.br belem.br bhz.br +bib.br bio.br blog.br bmd.br @@ -477,14 +483,19 @@ cnt.br com.br contagem.br coop.br +coz.br cri.br cuiaba.br curitiba.br def.br +des.br +det.br +dev.br ecn.br eco.br edu.br emp.br +enf.br eng.br esp.br etc.br @@ -500,6 +511,7 @@ fot.br foz.br fst.br g12.br +geo.br ggf.br goiania.br gov.br @@ -543,6 +555,7 @@ jor.br jus.br leg.br lel.br +log.br londrina.br macapa.br maceio.br @@ -575,6 +588,7 @@ qsl.br radio.br rec.br recife.br +rep.br ribeirao.br rio.br riobranco.br @@ -585,6 +599,7 @@ santamaria.br santoandre.br saobernardo.br saogonca.br +seg.br sjc.br slg.br slz.br @@ -592,6 +607,7 @@ sorocaba.br srv.br taxi.br tc.br +tec.br teo.br the.br tmp.br @@ -722,7 +738,6 @@ gouv.ci // cl : https://www.nic.cl // Confirmed by .CL registry cl -aprendemas.cl co.cl gob.cl gov.cl @@ -827,7 +842,13 @@ gov.cu inf.cu // cv : https://en.wikipedia.org/wiki/.cv +// cv : http://www.dns.cv/tldcv_portal/do?com=DS;5446457100;111;+PAGE(4000018)+K-CAT-CODIGO(RDOM)+RCNT(100); <- registration rules cv +com.cv +edu.cv +int.cv +nome.cv +org.cv // cw : http://www.una.cw/cw_registry/ // Confirmed by registry 2013-03-26 @@ -895,16 +916,18 @@ org.do sld.do web.do -// dz : https://en.wikipedia.org/wiki/.dz +// dz : http://www.nic.dz/images/pdf_nic/charte.pdf dz +art.dz +asso.dz com.dz +edu.dz +gov.dz org.dz net.dz -gov.dz -edu.dz -asso.dz pol.dz -art.dz +soc.dz +tm.dz // ec : http://www.nic.ec/reg/paso1.asp // Submitted by registry @@ -1002,6 +1025,10 @@ pro.fj *.fk // fm : https://en.wikipedia.org/wiki/.fm +com.fm +edu.fm +net.fm +org.fm fm // fo : https://en.wikipedia.org/wiki/.fo @@ -1041,6 +1068,8 @@ ga gb // gd : https://en.wikipedia.org/wiki/.gd +edu.gd +gov.gd gd // ge : http://www.nic.net.ge/policy_en.pdf @@ -1132,7 +1161,7 @@ gov.gr // gs : https://en.wikipedia.org/wiki/.gs gs -// gt : http://www.gt/politicas_de_registro.html +// gt : https://www.gt/sitio/registration_policy.php?lang=en gt com.gt edu.gt @@ -1156,6 +1185,7 @@ org.gu web.gu // gw : https://en.wikipedia.org/wiki/.gw +// gw : https://nic.gw/regras/ gw // gy : https://en.wikipedia.org/wiki/.gy @@ -3785,7 +3815,7 @@ gov.lc // li : https://en.wikipedia.org/wiki/.li li -// lk : http://www.nic.lk/seclevpr.html +// lk : https://www.nic.lk/index.php/domain-registration/lk-domain-naming-structure lk gov.lk sch.lk @@ -4574,15 +4604,17 @@ gob.mx edu.mx net.mx -// my : http://www.mynic.net.my/ +// my : http://www.mynic.my/ +// Available strings: https://mynic.my/resources/domains/buying-a-domain/ my +biz.my com.my -net.my -org.my -gov.my edu.my +gov.my mil.my name.my +net.my +org.my // mz : http://www.uem.mz/ // Submitted by registry @@ -4679,13 +4711,13 @@ web.ni // ccTLD for the Netherlands nl -// no : http://www.norid.no/regelverk/index.en.html -// The Norwegian registry has declined to notify us of updates. The web pages -// referenced below are the official source of the data. There is also an -// announce mailing list: -// https://postlister.uninett.no/sympa/info/norid-diskusjon +// no : https://www.norid.no/en/om-domenenavn/regelverk-for-no/ +// Norid geographical second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-b/ +// Norid category second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-c/ +// Norid category second-level domains managed by parties other than Norid : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-d/ +// RSS feed: https://teknisk.norid.no/en/feed/ no -// Norid generic domains : http://www.norid.no/regelverk/vedlegg-c.en.html +// Norid category second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-c/ fhs.no vgs.no fylkesbibl.no @@ -4693,13 +4725,13 @@ folkebibl.no museum.no idrett.no priv.no -// Non-Norid generic domains : http://www.norid.no/regelverk/vedlegg-d.en.html +// Norid category second-level domains managed by parties other than Norid : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-d/ mil.no stat.no dep.no kommune.no herad.no -// no geographical names : http://www.norid.no/regelverk/vedlegg-b.en.html +// Norid geographical second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-b/ // counties aa.no ah.no @@ -5828,7 +5860,7 @@ com.ps org.ps net.ps -// pt : http://online.dns.pt/dns/start_dns +// pt : https://www.dns.pt/en/domain/pt-terms-and-conditions-registration-rules/ pt net.pt gov.pt @@ -6065,8 +6097,10 @@ biz.ss com.ss edu.ss gov.ss +me.ss net.ss org.ss +sch.ss // st : http://www.nic.st/html/policyrules/ st @@ -6075,7 +6109,6 @@ com.st consulado.st edu.st embaixada.st -gov.st mil.st net.st org.st @@ -6180,29 +6213,22 @@ gov.tm mil.tm edu.tm -// tn : https://en.wikipedia.org/wiki/.tn -// http://whois.ati.tn/ +// tn : http://www.registre.tn/fr/ +// https://whois.ati.tn/ tn com.tn ens.tn fin.tn gov.tn ind.tn +info.tn intl.tn +mincom.tn nat.tn net.tn org.tn -info.tn perso.tn tourism.tn -edunet.tn -rnrt.tn -rns.tn -rnu.tn -mincom.tn -agrinet.tn -defense.tn -turen.tn // to : https://en.wikipedia.org/wiki/.to // Submitted by registry @@ -6327,7 +6353,6 @@ cv.ua dn.ua dnepropetrovsk.ua dnipropetrovsk.ua -dominic.ua donetsk.ua dp.ua if.ua @@ -6693,9 +6718,10 @@ mil.vc edu.vc // ve : https://registro.nic.ve/ -// Submitted by registry +// Submitted by registry nic@nic.ve and nicve@conatel.gob.ve ve arts.ve +bib.ve co.ve com.ve e12.ve @@ -6707,7 +6733,9 @@ info.ve int.ve mil.ve net.ve +nom.ve org.ve +rar.ve rec.ve store.ve tec.ve @@ -6786,6 +6814,9 @@ yt // xn--90ae ("bg", Bulgarian) : BG бг +// xn--mgbcpq6gpa1a ("albahrain", Arabic) : BH +البحرين + // xn--90ais ("bel", Belarusian/Russian Cyrillic) : BY // Operated by .by registry бел @@ -6918,12 +6949,15 @@ yt // xn--80ao21a ("Kaz", Kazakh) : KZ қаз +// xn--q7ce6a ("Lao", Lao) : LA +ລາວ + // xn--fzc2c9e2c ("Lanka", Sinhalese-Sinhala) : LK -// http://nic.lk +// https://nic.lk ලංකා // xn--xkc2al3hye2a ("Ilangai", Tamil) : LK -// http://nic.lk +// https://nic.lk இலங்கை // xn--mgbc0a9azcg ("Morocco/al-Maghrib", Arabic) : MA @@ -7043,7 +7077,13 @@ yt xxx // ye : http://www.y.net.ye/services/domain_name.htm -*.ye +ye +com.ye +edu.ye +gov.ye +net.ye +mil.ye +org.ye // za : https://www.zadna.org.za/content/page/domain-information/ ac.za @@ -7092,7 +7132,7 @@ org.zw // newGTLDs -// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2020-04-02T18:20:31Z +// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2021-11-13T15:12:42Z // This list is auto-generated, don't edit it manually. // aaa : 2015-02-26 American Automobile Association, Inc. aaa @@ -7118,7 +7158,7 @@ abc // able : 2015-06-25 Able Inc. able -// abogado : 2014-04-24 Minds + Machines Group Limited +// abogado : 2014-04-24 Registry Services, LLC abogado // abudhabi : 2015-07-30 Abu Dhabi Systems and Information Centre @@ -7175,9 +7215,6 @@ agency // aig : 2014-12-18 American International Group, Inc. aig -// aigo : 2015-08-06 aigo Digital Technology Co,Ltd. -aigo - // airbus : 2015-07-30 Airbus S.A.S. airbus @@ -7241,7 +7278,7 @@ analytics // android : 2014-08-07 Charleston Road Registry Inc. android -// anquan : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +// anquan : 2015-01-08 Beijing Qihu Keji Co., Ltd. anquan // anz : 2015-07-31 Australia and New Zealand Banking Group Limited @@ -7301,7 +7338,7 @@ audi // audible : 2015-06-25 Amazon Registry Services, Inc. audible -// audio : 2014-03-20 Uniregistry, Corp. +// audio : 2014-03-20 UNR Corp. audio // auspost : 2015-08-13 Australian Postal Corporation @@ -7310,19 +7347,19 @@ auspost // author : 2014-12-18 Amazon Registry Services, Inc. author -// auto : 2014-11-13 Cars Registry Limited +// auto : 2014-11-13 XYZ.COM LLC auto -// autos : 2014-01-09 DERAutos, LLC +// autos : 2014-01-09 XYZ.COM LLC autos // avianca : 2015-01-08 Avianca Holdings S.A. avianca -// aws : 2015-06-25 Amazon Registry Services, Inc. +// aws : 2015-06-25 AWS Registry LLC aws -// axa : 2013-12-19 AXA SA +// axa : 2013-12-19 AXA Group Operations SAS axa // azure : 2014-12-18 Microsoft Corporation @@ -7397,7 +7434,7 @@ beats // beauty : 2015-12-03 XYZ.COM LLC beauty -// beer : 2014-01-09 Minds + Machines Group Limited +// beer : 2014-01-09 Registry Services, LLC beer // bentley : 2014-12-18 Bentley Motors Limited @@ -7439,7 +7476,7 @@ bio // black : 2014-01-16 Afilias Limited black -// blackfriday : 2014-01-16 Uniregistry, Corp. +// blackfriday : 2014-01-16 UNR Corp. blackfriday // blockbuster : 2015-07-30 Dish DBS Corporation @@ -7463,7 +7500,7 @@ bmw // bnpparibas : 2014-05-29 BNP Paribas bnpparibas -// boats : 2014-12-04 DERBoats, LLC +// boats : 2014-12-04 XYZ.COM LLC boats // boehringer : 2015-07-09 Boehringer Ingelheim International GmbH @@ -7502,7 +7539,7 @@ bot // boutique : 2013-11-14 Binky Moon, LLC boutique -// box : 2015-11-12 .BOX INC. +// box : 2015-11-12 Intercap Registry Inc. box // bradesco : 2014-12-18 Banco Bradesco S.A. @@ -7514,7 +7551,7 @@ bridgestone // broadway : 2014-12-22 Celebrate Broadway, Inc. broadway -// broker : 2014-12-11 Dotbroker Registry Limited +// broker : 2014-12-11 Dog Beach, LLC broker // brother : 2015-01-29 Brother Industries, Ltd. @@ -7586,7 +7623,7 @@ capital // capitalone : 2015-08-06 Capital One Financial Corporation capitalone -// car : 2015-01-22 Cars Registry Limited +// car : 2015-01-22 XYZ.COM LLC car // caravan : 2013-12-12 Caravan International, Inc. @@ -7604,18 +7641,15 @@ career // careers : 2013-10-02 Binky Moon, LLC careers -// cars : 2014-11-13 Cars Registry Limited +// cars : 2014-11-13 XYZ.COM LLC cars -// casa : 2013-11-21 Minds + Machines Group Limited +// casa : 2013-11-21 Registry Services, LLC casa -// case : 2015-09-03 CNH Industrial N.V. +// case : 2015-09-03 Helium TLDs Ltd case -// caseih : 2015-09-03 CNH Industrial N.V. -caseih - // cash : 2014-03-06 Binky Moon, LLC cash @@ -7640,9 +7674,6 @@ cbre // cbs : 2015-08-06 CBS Domains Inc. cbs -// ceb : 2015-04-09 The Corporate Executive Board Company -ceb - // center : 2013-11-07 Binky Moon, LLC center @@ -7655,7 +7686,7 @@ cern // cfa : 2014-08-28 CFA Institute cfa -// cfd : 2014-12-11 DotCFD Registry Limited +// cfd : 2014-12-11 ShortDot SA cfd // chanel : 2015-04-09 Chanel International B.V. @@ -7679,7 +7710,7 @@ cheap // chintai : 2015-06-11 CHINTAI Corporation chintai -// christmas : 2013-11-21 Uniregistry, Corp. +// christmas : 2013-11-21 UNR Corp. christmas // chrome : 2014-07-24 Charleston Road Registry Inc. @@ -7718,7 +7749,7 @@ claims // cleaning : 2013-12-05 Binky Moon, LLC cleaning -// click : 2014-06-05 Uniregistry, Corp. +// click : 2014-06-05 UNR Corp. click // clinic : 2014-03-20 Binky Moon, LLC @@ -7733,7 +7764,7 @@ clothing // cloud : 2015-04-16 Aruba PEC S.p.A. cloud -// club : 2013-11-08 .CLUB DOMAINS, LLC +// club : 2013-11-08 Registry Services, LLC club // clubmed : 2015-06-25 Club Méditerranée S.A. @@ -7790,7 +7821,7 @@ contact // contractors : 2013-09-10 Binky Moon, LLC contractors -// cooking : 2013-11-21 Minds + Machines Group Limited +// cooking : 2013-11-21 Registry Services, LLC cooking // cookingchannel : 2015-07-02 Lifestyle Domain Holdings, Inc. @@ -7823,7 +7854,7 @@ credit // creditcard : 2014-03-20 Binky Moon, LLC creditcard -// creditunion : 2015-01-22 CUNA Performance Resources, LLC +// creditunion : 2015-01-22 DotCooperation LLC creditunion // cricket : 2014-10-09 dot Cricket Limited @@ -7880,7 +7911,7 @@ day // dclk : 2014-11-20 Charleston Road Registry Inc. dclk -// dds : 2015-05-07 Minds + Machines Group Limited +// dds : 2015-05-07 Registry Services, LLC dds // deal : 2015-06-25 Amazon Registry Services, Inc. @@ -7919,7 +7950,7 @@ dentist // desi : 2013-11-14 Desi Networks LLC desi -// design : 2014-11-07 Top Level Design, LLC +// design : 2014-11-07 Registry Services, LLC design // dev : 2014-10-16 Charleston Road Registry Inc. @@ -7931,7 +7962,7 @@ dhl // diamonds : 2013-09-22 Binky Moon, LLC diamonds -// diet : 2014-06-26 Uniregistry, Corp. +// diet : 2014-06-26 UNR Corp. diet // digital : 2014-03-06 Binky Moon, LLC @@ -7991,7 +8022,7 @@ duck // dunlop : 2015-07-02 The Goodyear Tire & Rubber Company dunlop -// dupont : 2015-06-25 E. I. du Pont de Nemours and Company +// dupont : 2015-06-25 DuPont Specialty Products USA, LLC dupont // durban : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry @@ -8054,9 +8085,6 @@ esq // estate : 2013-08-27 Binky Moon, LLC estate -// esurance : 2015-07-23 Esurance Insurance Company -esurance - // etisalat : 2015-09-03 Emirates Telecommunications Corporation (trading as Etisalat) etisalat @@ -8111,7 +8139,7 @@ farm // farmers : 2015-07-09 Farmers Insurance Exchange farmers -// fashion : 2014-07-03 Minds + Machines Group Limited +// fashion : 2014-07-03 Registry Services, LLC fashion // fast : 2014-12-18 Amazon Registry Services, Inc. @@ -8162,16 +8190,16 @@ firmdale // fish : 2013-12-12 Binky Moon, LLC fish -// fishing : 2013-11-21 Minds + Machines Group Limited +// fishing : 2013-11-21 Registry Services, LLC fishing -// fit : 2014-11-07 Minds + Machines Group Limited +// fit : 2014-11-07 Registry Services, LLC fit // fitness : 2014-03-06 Binky Moon, LLC fitness -// flickr : 2015-04-02 Yahoo! Domain Services Inc. +// flickr : 2015-04-02 Flickr, Inc. flickr // flights : 2013-12-05 Binky Moon, LLC @@ -8183,7 +8211,7 @@ flir // florist : 2013-11-07 Binky Moon, LLC florist -// flowers : 2014-10-09 Uniregistry, Corp. +// flowers : 2014-10-09 UNR Corp. flowers // fly : 2014-05-08 Charleston Road Registry Inc. @@ -8204,7 +8232,7 @@ football // ford : 2014-11-13 Ford Motor Company ford -// forex : 2014-12-11 Dotforex Registry Limited +// forex : 2014-12-11 Dog Beach, LLC forex // forsale : 2014-05-22 Dog Beach, LLC @@ -8243,10 +8271,7 @@ ftr // fujitsu : 2015-07-30 Fujitsu Limited fujitsu -// fujixerox : 2015-07-23 Xerox DNHC LLC -fujixerox - -// fun : 2016-01-14 DotSpace Inc. +// fun : 2016-01-14 Radix FZC fun // fund : 2014-03-20 Binky Moon, LLC @@ -8273,7 +8298,7 @@ gallo // gallup : 2015-02-19 Gallup, Inc. gallup -// game : 2015-05-28 Uniregistry, Corp. +// game : 2015-05-28 UNR Corp. game // games : 2015-05-28 Dog Beach, LLC @@ -8282,7 +8307,7 @@ games // gap : 2015-07-31 The Gap, Inc. gap -// garden : 2014-06-26 Minds + Machines Group Limited +// garden : 2014-06-26 Registry Services, LLC garden // gay : 2019-05-23 Top Level Design, LLC @@ -8411,7 +8436,7 @@ guge // guide : 2013-09-13 Binky Moon, LLC guide -// guitars : 2013-11-14 Uniregistry, Corp. +// guitars : 2013-11-14 UNR Corp. guitars // guru : 2013-08-27 Binky Moon, LLC @@ -8444,7 +8469,7 @@ health // healthcare : 2014-06-12 Binky Moon, LLC healthcare -// help : 2014-06-26 Uniregistry, Corp. +// help : 2014-06-26 UNR Corp. help // helsinki : 2015-02-05 City of Helsinki @@ -8459,7 +8484,7 @@ hermes // hgtv : 2015-07-02 Lifestyle Domain Holdings, Inc. hgtv -// hiphop : 2014-03-06 Uniregistry, Corp. +// hiphop : 2014-03-06 UNR Corp. hiphop // hisamitsu : 2015-07-16 Hisamitsu Pharmaceutical Co.,Inc. @@ -8468,7 +8493,7 @@ hisamitsu // hitachi : 2014-10-31 Hitachi, Ltd. hitachi -// hiv : 2014-03-13 Uniregistry, Corp. +// hiv : 2014-03-13 UNR Corp. hiv // hkt : 2015-05-14 PCCW-HKT DataCom Services Limited @@ -8489,7 +8514,7 @@ homedepot // homegoods : 2015-07-16 The TJX Companies, Inc. homegoods -// homes : 2014-01-09 DERHomes, LLC +// homes : 2014-01-09 XYZ.COM LLC homes // homesense : 2015-07-16 The TJX Companies, Inc. @@ -8498,16 +8523,16 @@ homesense // honda : 2014-12-18 Honda Motor Co., Ltd. honda -// horse : 2013-11-21 Minds + Machines Group Limited +// horse : 2013-11-21 Registry Services, LLC horse // hospital : 2016-10-20 Binky Moon, LLC hospital -// host : 2014-04-17 DotHost Inc. +// host : 2014-04-17 Radix FZC host -// hosting : 2014-05-29 Uniregistry, Corp. +// hosting : 2014-05-29 UNR Corp. hosting // hot : 2015-08-27 Amazon Registry Services, Inc. @@ -8597,9 +8622,6 @@ insurance // insure : 2014-03-20 Binky Moon, LLC insure -// intel : 2015-08-06 Intel Corporation -intel - // international : 2013-11-07 Binky Moon, LLC international @@ -8630,9 +8652,6 @@ itau // itv : 2015-07-09 ITV Services Limited itv -// iveco : 2015-09-03 CNH Industrial N.V. -iveco - // jaguar : 2014-11-13 Jaguar Land Rover Ltd jaguar @@ -8642,9 +8661,6 @@ java // jcb : 2014-11-20 JCB Co., Ltd. jcb -// jcp : 2015-04-23 JCP Media, Inc. -jcp - // jeep : 2015-07-30 FCA US LLC. jeep @@ -8681,7 +8697,7 @@ jpmorgan // jprs : 2014-09-18 Japan Registry Services Co., Ltd. jprs -// juegos : 2014-03-20 Uniregistry, Corp. +// juegos : 2014-03-20 UNR Corp. juegos // juniper : 2015-07-30 JUNIPER NETWORKS, INC. @@ -8708,6 +8724,9 @@ kfh // kia : 2015-07-09 KIA MOTORS CORPORATION kia +// kids : 2021-08-13 DotKids Foundation Limited +kids + // kim : 2013-09-23 Afilias Limited kim @@ -8786,13 +8805,13 @@ latino // latrobe : 2014-06-16 La Trobe University latrobe -// law : 2015-01-22 LW TLD Limited +// law : 2015-01-22 Registry Services, LLC law // lawyer : 2014-03-20 Dog Beach, LLC lawyer -// lds : 2014-03-20 IRI Domain Management, LLC ("Applicant") +// lds : 2014-03-20 IRI Domain Management, LLC lds // lease : 2014-03-06 Binky Moon, LLC @@ -8849,7 +8868,7 @@ lincoln // linde : 2014-12-04 Linde Aktiengesellschaft linde -// link : 2013-11-14 Uniregistry, Corp. +// link : 2013-11-14 UNR Corp. link // lipsy : 2015-06-25 Lipsy Ltd @@ -8867,7 +8886,7 @@ lixil // llc : 2017-12-14 Afilias Limited llc -// llp : 2019-08-26 Dot Registry LLC +// llp : 2019-08-26 UNR Corp. llp // loan : 2014-11-20 dot Loan Limited @@ -8885,7 +8904,7 @@ locus // loft : 2015-07-30 Annco, Inc. loft -// lol : 2015-01-30 Uniregistry, Corp. +// lol : 2015-01-30 UNR Corp. lol // london : 2013-11-14 Dot London Domains Limited @@ -8915,10 +8934,7 @@ ltda // lundbeck : 2015-08-06 H. Lundbeck A/S lundbeck -// lupin : 2014-11-07 LUPIN LIMITED -lupin - -// luxe : 2014-01-09 Minds + Machines Group Limited +// luxe : 2014-01-09 Registry Services, LLC luxe // luxury : 2013-10-17 Luxury Partners, LLC @@ -8957,7 +8973,7 @@ market // marketing : 2013-11-07 Binky Moon, LLC marketing -// markets : 2014-12-11 Dotmarkets Registry Limited +// markets : 2014-12-11 Dog Beach, LLC markets // marriott : 2014-10-09 Marriott Worldwide Corporation @@ -9005,9 +9021,6 @@ menu // merckmsd : 2016-07-14 MSD Registry Holdings, Inc. merckmsd -// metlife : 2015-05-07 MetLife Services and Solutions, LLC -metlife - // miami : 2013-12-19 Minds + Machines Group Limited miami @@ -9047,7 +9060,7 @@ moe // moi : 2014-12-18 Amazon Registry Services, Inc. moi -// mom : 2015-04-16 Uniregistry, Corp. +// mom : 2015-04-16 UNR Corp. mom // monash : 2013-09-30 Monash University @@ -9059,7 +9072,7 @@ money // monster : 2015-09-11 XYZ.COM LLC monster -// mormon : 2013-12-05 IRI Domain Management, LLC ("Applicant") +// mormon : 2013-12-05 IRI Domain Management, LLC mormon // mortgage : 2014-03-20 Dog Beach, LLC @@ -9071,7 +9084,7 @@ moscow // moto : 2015-06-04 Motorola Trademark Holdings, LLC moto -// motorcycles : 2014-01-09 DERMotorcycles, LLC +// motorcycles : 2014-01-09 XYZ.COM LLC motorcycles // mov : 2014-01-30 Charleston Road Registry Inc. @@ -9089,6 +9102,9 @@ mtn // mtr : 2015-03-12 MTR Corporation Limited mtr +// music : 2021-05-04 DotMusic Limited +music + // mutual : 2015-04-02 Northwestern Mutual MU TLD Registry, LLC mutual @@ -9098,9 +9114,6 @@ nab // nagoya : 2013-10-24 GMO Registry, Inc. nagoya -// nationwide : 2015-07-23 Nationwide Mutual Insurance Company -nationwide - // natura : 2015-03-12 NATURA COSMÉTICOS S.A. natura @@ -9122,15 +9135,12 @@ netflix // network : 2013-11-14 Binky Moon, LLC network -// neustar : 2013-12-05 Registry Services, LLC +// neustar : 2013-12-05 NeuStar, Inc. neustar // new : 2014-01-30 Charleston Road Registry Inc. new -// newholland : 2015-09-03 CNH Industrial N.V. -newholland - // news : 2014-12-18 Dog Beach, LLC news @@ -9176,7 +9186,7 @@ nokia // northwesternmutual : 2015-06-18 Northwestern Mutual Registry, LLC northwesternmutual -// norton : 2014-12-04 Symantec Corporation +// norton : 2014-12-04 NortonLifeLock Inc. norton // now : 2015-06-25 Amazon Registry Services, Inc. @@ -9203,7 +9213,7 @@ nyc // obi : 2014-09-25 OBI Group Holding SE & Co. KGaA obi -// observer : 2015-04-30 Top Level Spectrum, Inc. +// observer : 2015-04-30 Dog Beach, LLC observer // off : 2015-07-23 Johnson Shareholdings, Inc. @@ -9236,15 +9246,12 @@ one // ong : 2014-03-06 Public Interest Registry ong -// onl : 2013-09-16 I-Registry Ltd. +// onl : 2013-09-16 iRegistry GmbH onl -// online : 2015-01-15 DotOnline Inc. +// online : 2015-01-15 Radix FZC online -// onyourside : 2015-07-23 Nationwide Mutual Insurance Company -onyourside - // ooo : 2014-01-09 INFIBEAM AVENUES LIMITED ooo @@ -9323,7 +9330,7 @@ philips // phone : 2016-06-02 Dish DBS Corporation phone -// photo : 2013-11-14 Uniregistry, Corp. +// photo : 2013-11-14 UNR Corp. photo // photography : 2013-09-20 Binky Moon, LLC @@ -9335,7 +9342,7 @@ photos // physio : 2014-05-01 PhysBiz Pty Ltd physio -// pics : 2013-11-14 Uniregistry, Corp. +// pics : 2013-11-14 UNR Corp. pics // pictet : 2014-06-26 Pictet Europe S.A. @@ -9398,7 +9405,7 @@ pramerica // praxi : 2013-12-05 Praxi S.p.A. praxi -// press : 2014-04-03 DotPress Inc. +// press : 2014-04-03 Radix FZC press // prime : 2015-06-25 Amazon Registry Services, Inc. @@ -9422,7 +9429,7 @@ promo // properties : 2013-12-05 Binky Moon, LLC properties -// property : 2014-05-22 Uniregistry, Corp. +// property : 2014-05-22 UNR Corp. property // protection : 2015-04-23 XYZ.COM LLC @@ -9449,9 +9456,6 @@ quebec // quest : 2015-03-26 XYZ.COM LLC quest -// qvc : 2015-07-30 QVC, Inc. -qvc - // racing : 2014-12-04 Premier Registry Limited racing @@ -9470,7 +9474,7 @@ realestate // realtor : 2014-05-29 Real Estate Domains LLC realtor -// realty : 2015-03-19 Fegistry, LLC +// realty : 2015-03-19 Dog Beach, LLC realty // recipes : 2013-10-17 Binky Moon, LLC @@ -9533,7 +9537,7 @@ reviews // rexroth : 2015-06-18 Robert Bosch GMBH rexroth -// rich : 2013-11-21 I-Registry Ltd. +// rich : 2013-11-21 iRegistry GmbH rich // richardli : 2015-05-14 Pacific Century Asset Management (HK) Limited @@ -9542,9 +9546,6 @@ richardli // ricoh : 2014-11-20 Ricoh Company, Ltd. ricoh -// rightathome : 2015-07-23 Johnson Shareholdings, Inc. -rightathome - // ril : 2015-04-02 Reliance Industries Limited ril @@ -9554,16 +9555,13 @@ rio // rip : 2014-07-10 Dog Beach, LLC rip -// rmit : 2015-11-19 Royal Melbourne Institute of Technology -rmit - // rocher : 2014-12-18 Ferrero Trading Lux S.A. rocher // rocks : 2013-11-14 Dog Beach, LLC rocks -// rodeo : 2013-12-19 Minds + Machines Group Limited +// rodeo : 2013-12-19 Registry Services, LLC rodeo // rogers : 2015-08-06 Rogers Communications Canada Inc. @@ -9641,7 +9639,7 @@ saxo // sbi : 2015-03-12 STATE BANK OF INDIA sbi -// sbs : 2014-11-07 SPECIAL BROADCASTING SERVICE CORPORATION +// sbs : 2014-11-07 ShortDot SA sbs // sca : 2014-03-13 SVENSKA CELLULOSA AKTIEBOLAGET SCA (publ) @@ -9674,9 +9672,6 @@ science // scjohnson : 2015-07-23 Johnson Shareholdings, Inc. scjohnson -// scor : 2014-10-31 SCOR SE -scor - // scot : 2014-01-23 Dot Scot Registry Limited scot @@ -9716,7 +9711,7 @@ sew // sex : 2014-11-13 ICM Registry SX LLC sex -// sexy : 2013-09-11 Uniregistry, Corp. +// sexy : 2013-09-11 UNR Corp. sexy // sfr : 2015-08-13 Societe Francaise du Radiotelephone - SFR @@ -9749,7 +9744,7 @@ shop // shopping : 2016-03-31 Binky Moon, LLC shopping -// shouji : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +// shouji : 2015-01-08 Beijing Qihu Keji Co., Ltd. shouji // show : 2015-03-05 Binky Moon, LLC @@ -9758,9 +9753,6 @@ show // showtime : 2015-08-06 CBS Domains Inc. showtime -// shriram : 2014-01-23 Shriram Capital Ltd. -shriram - // silk : 2015-06-25 Amazon Registry Services, Inc. silk @@ -9770,7 +9762,7 @@ sina // singles : 2013-08-27 Binky Moon, LLC singles -// site : 2015-01-15 DotSite Inc. +// site : 2015-01-15 Radix FZC site // ski : 2015-04-09 Afilias Limited @@ -9830,7 +9822,7 @@ soy // spa : 2019-09-19 Asia Spa and Wellness Promotion Council Limited spa -// space : 2014-04-03 DotSpace Inc. +// space : 2014-04-03 Radix FZC space // sport : 2017-11-16 Global Association of International Sports Federations (GAISF) @@ -9839,9 +9831,6 @@ sport // spot : 2015-02-26 Amazon Registry Services, Inc. spot -// spreadbetting : 2014-12-11 Dotspreadbetting Registry Limited -spreadbetting - // srl : 2015-05-07 InterNetX, Corp srl @@ -9872,7 +9861,7 @@ stockholm // storage : 2014-12-22 XYZ.COM LLC storage -// store : 2015-04-09 DotStore Inc. +// store : 2015-04-09 Radix FZC store // stream : 2016-01-08 dot Stream Limited @@ -9899,7 +9888,7 @@ supply // support : 2013-10-24 Binky Moon, LLC support -// surf : 2014-01-09 Minds + Machines Group Limited +// surf : 2014-01-09 Registry Services, LLC surf // surgery : 2014-03-20 Binky Moon, LLC @@ -9911,18 +9900,12 @@ suzuki // swatch : 2015-01-08 The Swatch Group Ltd swatch -// swiftcover : 2015-07-23 Swiftcover Insurance Services Limited -swiftcover - // swiss : 2014-10-16 Swiss Confederation swiss // sydney : 2014-09-18 State of New South Wales, Department of Premier and Cabinet sydney -// symantec : 2014-12-04 Symantec Corporation -symantec - // systems : 2013-11-07 Binky Moon, LLC systems @@ -9947,7 +9930,7 @@ tatamotors // tatar : 2014-04-24 Limited Liability Company "Coordination Center of Regional Domain of Tatarstan Republic" tatar -// tattoo : 2013-08-30 Uniregistry, Corp. +// tattoo : 2013-08-30 UNR Corp. tattoo // tax : 2014-03-20 Binky Moon, LLC @@ -9965,7 +9948,7 @@ tdk // team : 2015-03-05 Binky Moon, LLC team -// tech : 2015-01-30 Personals TLD Inc. +// tech : 2015-01-30 Radix FZC tech // technology : 2013-09-13 Binky Moon, LLC @@ -9992,7 +9975,7 @@ theatre // tiaa : 2015-07-23 Teachers Insurance and Annuity Association of America tiaa -// tickets : 2015-02-05 Accent Media Limited +// tickets : 2015-02-05 XYZ.COM LLC tickets // tienda : 2013-11-14 Binky Moon, LLC @@ -10058,7 +10041,7 @@ toys // trade : 2014-01-23 Elite Registry Limited trade -// trading : 2014-12-11 Dottrading Registry Limited +// trading : 2014-12-11 Dog Beach, LLC trading // training : 2013-11-07 Binky Moon, LLC @@ -10076,7 +10059,7 @@ travelers // travelersinsurance : 2015-03-26 Travelers TLD, LLC travelersinsurance -// trust : 2014-10-16 NCC Group Inc. +// trust : 2014-10-16 UNR Corp. trust // trv : 2015-03-26 Travelers TLD, LLC @@ -10109,7 +10092,7 @@ unicom // university : 2014-03-06 Binky Moon, LLC university -// uno : 2013-09-11 DotSite Inc. +// uno : 2013-09-11 Radix FZC uno // uol : 2014-05-01 UBN INTERNET LTDA. @@ -10160,7 +10143,7 @@ villas // vin : 2015-06-18 Binky Moon, LLC vin -// vip : 2015-01-22 Minds + Machines Group Limited +// vip : 2015-01-22 Registry Services, LLC vip // virgin : 2014-09-25 Virgin Enterprises Limited @@ -10181,7 +10164,7 @@ vivo // vlaanderen : 2014-02-06 DNS.be vzw vlaanderen -// vodka : 2013-12-19 Minds + Machines Group Limited +// vodka : 2013-12-19 Registry Services, LLC vodka // volkswagen : 2015-05-14 Volkswagen Group of America Inc. @@ -10223,7 +10206,7 @@ wanggou // watch : 2013-11-14 Binky Moon, LLC watch -// watches : 2014-12-22 Richemont DNS Inc. +// watches : 2014-12-22 Afilias Limited watches // weather : 2015-01-08 International Business Machines Corporation @@ -10238,13 +10221,10 @@ webcam // weber : 2015-06-04 Saint-Gobain Weber SA weber -// website : 2014-04-03 DotWebsite Inc. +// website : 2014-04-03 Radix FZC website -// wed : 2013-10-01 Atgron, Inc. -wed - -// wedding : 2014-04-24 Minds + Machines Group Limited +// wedding : 2014-04-24 Registry Services, LLC wedding // weibo : 2015-03-05 Sina Corporation @@ -10286,7 +10266,7 @@ wolterskluwer // woodside : 2015-07-09 Woodside Petroleum Limited woodside -// work : 2013-12-19 Minds + Machines Group Limited +// work : 2013-12-19 Registry Services, LLC work // works : 2013-11-14 Binky Moon, LLC @@ -10313,7 +10293,7 @@ xerox // xfinity : 2015-07-09 Comcast IP Holdings I, LLC xfinity -// xihuan : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +// xihuan : 2015-01-08 Beijing Qihu Keji Co., Ltd. xihuan // xin : 2014-12-11 Elegant Leader Limited @@ -10337,9 +10317,6 @@ xin // xn--3ds443g : 2013-09-08 TLD REGISTRY LIMITED OY 在线 -// xn--3oq18vl8pn36a : 2015-07-02 Volkswagen (China) Investment Co., Ltd. -大众汽车 - // xn--3pxu8k : 2015-01-15 VeriSign Sarl 点看 @@ -10349,7 +10326,7 @@ xin // xn--45q11c : 2013-11-21 Zodiac Gemini Ltd 八卦 -// xn--4gbrim : 2013-10-04 Fans TLD Limited +// xn--4gbrim : 2013-10-04 Helium TLDs Ltd موقع // xn--55qw42g : 2013-11-08 China Organizational Name Administration Center @@ -10454,7 +10431,7 @@ xin // xn--fzys8d69uvgm : 2015-05-14 PCCW Enterprises Limited 電訊盈科 -// xn--g2xx48c : 2015-01-30 Minds + Machines Group Limited +// xn--g2xx48c : 2015-01-30 Nawang Heli(Xiamen) Network Service Co., LTD. 购物 // xn--gckr3f0f : 2015-02-26 Amazon Registry Services, Inc. @@ -10490,9 +10467,6 @@ xin // xn--kcrx77d1x4a : 2014-11-07 Koninklijke Philips N.V. 飞利浦 -// xn--kpu716f : 2014-12-22 Richemont DNS Inc. -手表 - // xn--kput3i : 2014-02-13 Beijing RITT-Net Technology Development Co., Ltd 手机 @@ -10547,9 +10521,6 @@ xin // xn--p1acf : 2013-12-12 Rusnames Limited рус -// xn--pbt977c : 2014-12-22 Richemont DNS Inc. -珠宝 - // xn--pssy2u : 2015-01-15 VeriSign Sarl 大拿 @@ -10607,10 +10578,10 @@ vermögensberatung // xyz : 2013-12-05 XYZ.COM LLC xyz -// yachts : 2014-01-09 DERYachts, LLC +// yachts : 2014-01-09 XYZ.COM LLC yachts -// yahoo : 2015-04-02 Yahoo! Domain Services Inc. +// yahoo : 2015-04-02 Oath Inc. yahoo // yamaxun : 2014-12-18 Amazon Registry Services, Inc. @@ -10622,7 +10593,7 @@ yandex // yodobashi : 2014-11-20 YODOBASHI CAMERA CO.,LTD. yodobashi -// yoga : 2014-05-29 Minds + Machines Group Limited +// yoga : 2014-05-29 Registry Services, LLC yoga // yokohama : 2013-12-12 GMO Registry, Inc. @@ -10634,7 +10605,7 @@ you // youtube : 2014-05-01 Charleston Road Registry Inc. youtube -// yun : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +// yun : 2015-01-08 Beijing Qihu Keji Co., Ltd. yun // zappos : 2015-06-25 Amazon Registry Services, Inc. @@ -10666,11 +10637,25 @@ cc.ua inf.ua ltd.ua +// 611coin : https://611project.org/ +611.to + +// Aaron Marais' Gitlab pages: https://lab.aaronleem.co.za +// Submitted by Aaron Marais +graphox.us + +// accesso Technology Group, plc. : https://accesso.com/ +// Submitted by accesso Team +*.devcdnaccesso.com + // Adobe : https://www.adobe.com/ -// Submitted by Ian Boston +// Submitted by Ian Boston and Lars Trieloff adobeaemcloud.com -adobeaemcloud.net *.dev.adobeaemcloud.com +hlx.live +adobeaemcloud.net +hlx.page +hlx3.page // Agnat sp. z o.o. : https://domena.pl // Submitted by Przemyslaw Plewa @@ -10685,6 +10670,10 @@ barsy.ca *.compute.estate *.alces.network +// all-inkl.com : https://all-inkl.com +// Submitted by Werner Kaltofen +kasserver.com + // Altervista: https://www.altervista.org // Submitted by Carlo Cannas altervista.org @@ -10732,6 +10721,10 @@ us-west-2.elasticbeanstalk.com *.elb.amazonaws.com *.elb.amazonaws.com.cn +// Amazon Global Accelerator : https://aws.amazon.com/global-accelerator/ +// Submitted by Daniel Massaguer +awsglobalaccelerator.com + // Amazon S3 : https://aws.amazon.com/s3/ // Submitted by Luke Wells s3.amazonaws.com @@ -10789,10 +10782,6 @@ s3-website.eu-west-2.amazonaws.com s3-website.eu-west-3.amazonaws.com s3-website.us-east-2.amazonaws.com -// Amsterdam Wireless: https://www.amsterdamwireless.nl/ -// Submitted by Imre Jonk -amsw.nl - // Amune : https://amune.org/ // Submitted by Team Amune t3l3p0rt.net @@ -10802,6 +10791,19 @@ tele.amune.org // Submitted by Apigee Security Team apigee.io +// Apphud : https://apphud.com +// Submitted by Alexander Selivanov +siiites.com + +// Appspace : https://www.appspace.com +// Submitted by Appspace Security Team +appspacehosted.com +appspaceusercontent.com + +// Appudo UG (haftungsbeschränkt) : https://www.appudo.com +// Submitted by Alexander Hochbaum +appudo.net + // Aptible : https://www.aptible.com/ // Submitted by Thomas Orozco on-aptible.com @@ -10827,15 +10829,27 @@ sweetpepper.org // Submitted by Vincent Tseng myasustor.com +// Atlassian : https://atlassian.com +// Submitted by Sam Smyth +cdn.prod.atlassian-dev.net + // AVM : https://avm.de // Submitted by Andreas Weise myfritz.net +// AVStack Pte. Ltd. : https://avstack.io +// Submitted by Jasper Hugo +onavstack.net + // AW AdvisorWebsites.com Software Inc : https://advisorwebsites.com // Submitted by James Kennedy *.awdev.ca *.advisor.ws +// AZ.pl sp. z.o.o: https://az.pl +// Submited by Krzysztof Wolski +ecommerce-shop.pl + // b-data GmbH : https://www.b-data.io // Submitted by Olivier Benz b-data.io @@ -10848,9 +10862,17 @@ backplaneapp.io // Submitted by Petros Angelatos balena-devices.com +// University of Banja Luka : https://unibl.org +// Domains for Republic of Srpska administrative entity. +// Submitted by Marko Ivanovic +rs.ba + // Banzai Cloud -// Submitted by Gabor Kozma +// Submitted by Janos Matyas +*.banzai.cloud app.banzaicloud.io +*.backyards.banzaicloud.io + // BetaInABox // Submitted by Adrian @@ -10860,14 +10882,30 @@ betainabox.com // Submitted by Nathan O'Sullivan bnr.la +// Bitbucket : http://bitbucket.org +// Submitted by Andy Ortlieb +bitbucket.io + // Blackbaud, Inc. : https://www.blackbaud.com // Submitted by Paul Crowder blackbaudcdn.net +// Blatech : http://www.blatech.net +// Submitted by Luke Bratch +of.je + +// Blue Bite, LLC : https://bluebite.com +// Submitted by Joshua Weiss +bluebite.io + // Boomla : https://boomla.com // Submitted by Tibor Halter boomla.net +// Boutir : https://www.boutir.com +// Submitted by Eric Ng Ka Ka +boutir.com + // Boxfuse : https://boxfuse.com // Submitted by Axel Fontaine boxfuse.io @@ -10881,6 +10919,10 @@ square7.de bplaced.net square7.net +// Brendly : https://brendly.rs +// Submitted by Dusan Radovanovic +shop.brendly.rs + // BrowserSafetyMark // Submitted by Dave Tharp browsersafetymark.io @@ -10891,46 +10933,54 @@ uk0.bigv.io dh.bytemark.co.uk vm.bytemark.co.uk +// Caf.js Labs LLC : https://www.cafjs.com +// Submitted by Antonio Lain +cafjs.com + // callidomus : https://www.callidomus.com/ // Submitted by Marcus Popp mycd.eu // Carrd : https://carrd.co // Submitted by AJ +drr.ac +uwu.ai carrd.co crd.co -uwu.ai +ju.mp // CentralNic : http://www.centralnic.com/names/domains // Submitted by registry ae.org -ar.com br.com cn.com com.de com.se de.com eu.com -gb.com gb.net -hu.com hu.net jp.net jpn.com -kr.com mex.com -no.com -qc.com ru.com sa.com se.net uk.com uk.net us.com -uy.com za.bz za.com +// No longer operated by CentralNic, these entries should be adopted and/or removed by current operators +// Submitted by Gavin Brown +ar.com +hu.com +kr.com +no.com +qc.com +uy.com + // Africa.com Web Solutions Ltd : https://registry.africa.com // Submitted by Gavin Brown africa.com @@ -10942,6 +10992,7 @@ gr.com // Radix FZC : http://domains.in.net // Submitted by Gavin Brown in.net +web.in // US REGISTRY LLC : http://us.org // Submitted by Gavin Brown @@ -10951,6 +11002,16 @@ us.org // Submitted by Gavin Brown co.com +// Roar Domains LLC : https://roar.basketball/ +// Submitted by Gavin Brown +aus.basketball +nz.basketball + +// BRS Media : https://brsmedia.com/ +// Submitted by Gavin Brown +radio.am +radio.fm + // c.la : http://www.c.la/ c.la @@ -10958,31 +11019,31 @@ c.la // Submitted by B. Blechschmidt certmgr.org -// Citrix : https://citrix.com -// Submitted by Alex Stoddard -xenapponazure.com +// Cityhost LLC : https://cityhost.ua +// Submitted by Maksym Rivtin +cx.ua // Civilized Discourse Construction Kit, Inc. : https://www.discourse.org/ // Submitted by Rishabh Nambiar & Michael Brown discourse.group discourse.team -// ClearVox : http://www.clearvox.nl/ -// Submitted by Leon Rowland -virtueeldomein.nl - // Clever Cloud : https://www.clever-cloud.com/ // Submitted by Quentin Adam cleverapps.io // Clerk : https://www.clerk.dev -// Submitted by Colin Sidoti +// Submitted by Colin Sidoti +clerk.app +clerkstage.app *.lcl.dev +*.lclstage.dev *.stg.dev +*.stgstage.dev -// Clic2000 : https://clic2000.fr -// Submitted by Mathilde Blanchemanche -clic2000.net +// ClickRising : https://clickrising.com/ +// Submitted by Umut Gumeli +clickrising.net // Cloud66 : https://www.cloud66.com/ // Submitted by Khash Sajadi @@ -11004,11 +11065,12 @@ cloudcontrolled.com cloudcontrolapp.com // Cloudera, Inc. : https://www.cloudera.com/ -// Submitted by Philip Langdale -cloudera.site +// Submitted by Kedarnath Waikar +*.cloudera.site // Cloudflare, Inc. : https://www.cloudflare.com/ -// Submitted by Jake Riesterer +// Submitted by Cloudflare Team +pages.dev trycloudflare.com workers.dev @@ -11049,10 +11111,6 @@ cloudns.pro cloudns.pw cloudns.us -// Cloudeity Inc : https://cloudeity.com -// Submitted by Stefan Dimitrov -cloudeity.net - // CNPY : https://cnpy.gdn // Submitted by Angelo Gladding cnpy.gdn @@ -11116,6 +11174,12 @@ curv.dev cyon.link cyon.site +// Danger Science Group: https://dangerscience.com/ +// Submitted by Skylar MacDonald +fnwk.site +folionetwork.site +platform0.app + // Daplie, Inc : https://daplie.com // Submitted by AJ ONeal daplie.me @@ -11151,18 +11215,41 @@ dyndns.dappnode.io // Submitted by Paul Biggar builtwithdark.com +// DataDetect, LLC. : https://datadetect.com +// Submitted by Andrew Banchich +demo.datadetect.com +instance.datadetect.com + // Datawire, Inc : https://www.datawire.io // Submitted by Richard Li edgestack.me +// DDNS5 : https://ddns5.com +// Submitted by Cameron Elliott +ddns5.com + // Debian : https://www.debian.org/ // Submitted by Peter Palfrader / Debian Sysadmin Team debian.net +// Deno Land Inc : https://deno.com/ +// Submitted by Luca Casonato +deno.dev +deno-staging.dev + // deSEC : https://desec.io/ // Submitted by Peter Thomassen dedyn.io +// Diher Solutions : https://diher.solutions +// Submitted by Didi Hermawan +*.rss.my.id +*.diher.solutions + +// DNS Africa Ltd https://dns.business +// Submitted by Calvin Browne +jozi.biz + // DNShome : https://www.dnshome.de/ // Submitted by Norbert Auler dnshome.de @@ -11176,6 +11263,10 @@ shop.th // Submitted by Paul Fang drayddns.com +// DreamCommerce : https://shoper.pl/ +// Submitted by Konrad Kotarba +shoparena.pl + // DreamHost : http://www.dreamhost.com/ // Submitted by Andrew Farmer dreamhosters.com @@ -11193,6 +11284,13 @@ drud.us // Submitted by Richard Harper duckdns.org +// Bip : https://bip.sh +// Submitted by Joel Kennedy +bip.sh + +// bitbridge.net : Submitted by Craig Welch, abeliidev@gmail.com +bitbridge.net + // dy.fi : http://dy.fi/ // Submitted by Heikki Hannikainen dy.fi @@ -11496,6 +11594,14 @@ ddnss.org definima.net definima.io +// DigitalOcean App Platform : https://www.digitalocean.com/products/app-platform/ +// Submitted by Braxton Huggins +ondigitalocean.app + +// DigitalOcean Spaces : https://www.digitalocean.com/products/spaces/ +// Submitted by Robin H. Johnson +*.digitaloceanspaces.com + // dnstrace.pro : https://dnstrace.pro/ // Submitted by Chris Partridge bci.dnstrace.pro @@ -11528,6 +11634,16 @@ dynv6.net // Submitted by Vladimir Dudr e4.cz +// eero : https://eero.com/ +// Submitted by Yue Kang +eero.online +eero-stage.online + +// Elementor : Elementor Ltd. +// Submitted by Anton Barkan +elementor.cloud +elementor.cool + // En root‽ : https://en-root.org // Submitted by Emmanuel Raviart en-root.fr @@ -11535,17 +11651,13 @@ en-root.fr // Enalean SAS: https://www.enalean.com // Submitted by Thomas Cottier mytuleap.com +tuleap-partners.com // ECG Robotics, Inc: https://ecgrobotics.org // Submitted by onred.one staging.onred.one -// Enonic : http://enonic.com/ -// Submitted by Erik Kaareng-Sunde -enonic.io -customer.enonic.io - // EU.org https://eu.org/ // Submitted by Pierre Beyssac eu.org @@ -11605,6 +11717,10 @@ tr.eu.org uk.eu.org us.eu.org +// Eurobyte : https://eurobyte.ru +// Submitted by Evgeniy Subbotin +eurodir.ru + // Evennode : http://www.evennode.com/ // Submitted by Michal Kralik eu-1.evennode.com @@ -11715,6 +11831,7 @@ u.channelsdvr.net // Fastly Inc. : http://www.fastly.com/ // Submitted by Fastly Security +edgecompute.app fastly-terrarium.com fastlylb.net map.fastlylb.net @@ -11728,16 +11845,11 @@ global.ssl.fastly.net // FASTVPS EESTI OU : https://fastvps.ru/ // Submitted by Likhachev Vasiliy -fastpanel.direct fastvps-server.com -myfast.space +fastvps.host myfast.host fastvps.site -fastvps.host - -// Featherhead : https://featherhead.xyz/ -// Submitted by Simon Menke -fhapp.xyz +myfast.space // Fedora : https://fedoraproject.org/ // submitted by Patrick Uiterwijk @@ -11749,15 +11861,20 @@ app.os.stg.fedoraproject.org // FearWorks Media Ltd. : https://fearworksmedia.co.uk // submitted by Keith Fairley -conn.uk -copro.uk couk.me ukco.me +conn.uk +copro.uk +hosp.uk // Fermax : https://fermax.com/ // submitted by Koen Van Isterdael mydobiss.com +// FH Muenster : https://www.fh-muenster.de +// Submitted by Robin Naundorf +fh-muenster.io + // Filegear Inc. : https://www.filegear.com // Submitted by Jason Zhu filegear.me @@ -11772,10 +11889,47 @@ filegear-sg.me // Submitted by Chris Raynor firebaseapp.com +// Firewebkit : https://www.firewebkit.com +// Submitted by Majid Qureshi +fireweb.app + +// FLAP : https://www.flap.cloud +// Submitted by Louis Chemineau +flap.id + +// FlashDrive : https://flashdrive.io +// Submitted by Eric Chan +onflashdrive.app +fldrv.com + +// fly.io: https://fly.io +// Submitted by Kurt Mackey +fly.dev +edgeapp.net +shw.io + // Flynn : https://flynn.io // Submitted by Jonathan Rudenberg flynnhosting.net +// Forgerock : https://www.forgerock.com +// Submitted by Roderick Parr +forgeblocks.com +id.forgerock.io + +// Framer : https://www.framer.com +// Submitted by Koen Rouwhorst +framer.app +framercanvas.com + +// Frusky MEDIA&PR : https://www.frusky.de +// Submitted by Victor Pupynin +*.frusky.de + +// RavPage : https://www.ravpage.co.il +// Submitted by Roni Horowitz +ravpage.co.il + // Frederik Braun https://frederik-braun.com // Submitted by Frederik Braun 0e.vc @@ -11793,6 +11947,14 @@ freeboxos.fr // Submitted by Daniel Stone freedesktop.org +// freemyip.com : https://freemyip.com +// Submitted by Cadence +freemyip.com + +// FunkFeuer - Verein zur Förderung freier Netze : https://www.funkfeuer.at +// Submitted by Daniel A. Maierhofer +wien.funkfeuer.at + // Futureweb OG : http://www.futureweb.at // Submitted by Andreas Schnederle-Wagner *.futurecms.at @@ -11816,30 +11978,59 @@ usercontent.jp // Gentlent, Inc. : https://www.gentlent.com // Submitted by Tom Klein gentapps.com +gentlentapis.com lab.ms +cdn-edges.net + +// Ghost Foundation : https://ghost.org +// Submitted by Matt Hanley +ghost.io + +// GignoSystemJapan: http://gsj.bz +// Submitted by GignoSystemJapan +gsj.bz // GitHub, Inc. // Submitted by Patrick Toomey -github.io githubusercontent.com +githubpreview.dev +github.io // GitLab, Inc. // Submitted by Alex Hanselka gitlab.io +// Gitplac.si - https://gitplac.si +// Submitted by Aljaž Starc +gitapp.si +gitpage.si + // Glitch, Inc : https://glitch.com // Submitted by Mads Hartmann glitch.me +// Global NOG Alliance : https://nogalliance.org/ +// Submitted by Sander Steffann +nog.community + +// Globe Hosting SRL : https://www.globehosting.com/ +// Submitted by Gavin Brown +co.ro +shop.ro + // GMO Pepabo, Inc. : https://pepabo.com/ // Submitted by dojineko lolipop.io // GOV.UK Platform as a Service : https://www.cloud.service.gov.uk/ -// Submitted by Tom Whitwell +// Submitted by Tom Whitwell cloudapps.digital london.cloudapps.digital +// GOV.UK Pay : https://www.payments.service.gov.uk/ +// Submitted by Richard Baker +pymnt.uk + // UKHomeOffice : https://www.gov.uk/government/organisations/home-office // Submitted by Jon Shanks homeoffice.gov.uk @@ -11847,7 +12038,6 @@ homeoffice.gov.uk // GlobeHosting, Inc. // Submitted by Zoltan Egresi ro.im -shop.ro // GoIP DNS Services : http://www.goip.de // Submitted by Christian Poulter @@ -11861,6 +12051,18 @@ web.app *.0emm.com appspot.com *.r.appspot.com +codespot.com +googleapis.com +googlecode.com +pagespeedmobilizer.com +publishproxy.com +withgoogle.com +withyoutube.com +*.gateway.dev +cloud.goog +translate.goog +*.usercontent.goog +cloudfunctions.net blogspot.ae blogspot.al blogspot.am @@ -11935,24 +12137,20 @@ blogspot.td blogspot.tw blogspot.ug blogspot.vn -cloudfunctions.net -cloud.goog -codespot.com -googleapis.com -googlecode.com -pagespeedmobilizer.com -publishproxy.com -withgoogle.com -withyoutube.com -// Aaron Marais' Gitlab pages: https://lab.aaronleem.co.za -// Submitted by Aaron Marais -graphox.us +// Goupile : https://goupile.fr +// Submitted by Niels Martignene +goupile.fr // Group 53, LLC : https://www.group53.com // Submitted by Tyler Todd awsmppl.com +// GünstigBestellen : https://günstigbestellen.de +// Submitted by Furkan Akkoc +günstigbestellen.de +günstigliefern.de + // Hakaran group: http://hakaran.cz // Submited by Arseniy Sokolov fin.ci @@ -11974,6 +12172,10 @@ hashbang.sh hasura.app hasura-app.io +// Heilbronn University of Applied Sciences - Faculty Informatics (GitLab Pages): https://www.hs-heilbronn.de +// Submitted by Richard Zowalla +pages.it.hs-heilbronn.de + // Hepforge : https://www.hepforge.org // Submitted by David Grellscheid hepforge.org @@ -11991,20 +12193,29 @@ ravendb.me development.run ravendb.run +// home.pl S.A.: https://home.pl +// Submited by Krzysztof Wolski +homesklep.pl + +// Hong Kong Productivity Council: https://www.hkpc.org/ +// Submitted by SECaaS Team +secaas.hk + // HOSTBIP REGISTRY : https://www.hostbip.com/ // Submitted by Atanunu Igbunuroghene -bpl.biz orx.biz -ng.city biz.gl -ng.ink col.ng firm.ng gen.ng ltd.ng ngo.ng -ng.school +edu.scot sch.so +org.yt + +// HostyHosting (hostyhosting.com) +hostyhosting.io // Häkkinen.fi // Submitted by Eero Häkkinen @@ -12019,6 +12230,19 @@ moonscale.net // Submitted by Hannu Aronsson iki.fi +// Impertrix Solutions : +// Submitted by Zhixiang Zhao +impertrixcdn.com +impertrix.com + +// Incsub, LLC: https://incsub.com/ +// Submitted by Aaron Edwards +smushcdn.com +wphostedmail.com +wpmucdn.com +tempurl.host +wpmudev.host + // Individual Network Berlin e.V. : https://www.in-berlin.de/ // Submitted by Christian Seitz dyn-berlin.de @@ -12074,6 +12298,14 @@ to.leg.br // Submitted by Wolfgang Schwarz pixolino.com +// Internet-Pro, LLP: https://netangels.ru/ +// Submited by Vasiliy Sheredeko +na4u.ru + +// iopsys software solutions AB : https://iopsys.eu/ +// Submitted by Roman Azarenko +iopsys.se + // IPiFony Systems, Inc. : https://www.ipifony.com/ // Submitted by Matthew Hardeman ipifony.net @@ -12089,6 +12321,92 @@ iserv.dev // Submitted by Yuji Minagawa iobb.net +// Jelastic, Inc. : https://jelastic.com/ +// Submited by Ihor Kolodyuk +mel.cloudlets.com.au +cloud.interhostsolutions.be +users.scale.virtualcloud.com.br +mycloud.by +alp1.ae.flow.ch +appengine.flow.ch +es-1.axarnet.cloud +diadem.cloud +vip.jelastic.cloud +jele.cloud +it1.eur.aruba.jenv-aruba.cloud +it1.jenv-aruba.cloud +keliweb.cloud +cs.keliweb.cloud +oxa.cloud +tn.oxa.cloud +uk.oxa.cloud +primetel.cloud +uk.primetel.cloud +ca.reclaim.cloud +uk.reclaim.cloud +us.reclaim.cloud +ch.trendhosting.cloud +de.trendhosting.cloud +jele.club +amscompute.com +clicketcloud.com +dopaas.com +hidora.com +paas.hosted-by-previder.com +rag-cloud.hosteur.com +rag-cloud-ch.hosteur.com +jcloud.ik-server.com +jcloud-ver-jpc.ik-server.com +demo.jelastic.com +kilatiron.com +paas.massivegrid.com +jed.wafaicloud.com +lon.wafaicloud.com +ryd.wafaicloud.com +j.scaleforce.com.cy +jelastic.dogado.eu +fi.cloudplatform.fi +demo.datacenter.fi +paas.datacenter.fi +jele.host +mircloud.host +paas.beebyte.io +sekd1.beebyteapp.io +jele.io +cloud-fr1.unispace.io +jc.neen.it +cloud.jelastic.open.tim.it +jcloud.kz +upaas.kazteleport.kz +cloudjiffy.net +fra1-de.cloudjiffy.net +west1-us.cloudjiffy.net +jls-sto1.elastx.net +jls-sto2.elastx.net +jls-sto3.elastx.net +faststacks.net +fr-1.paas.massivegrid.net +lon-1.paas.massivegrid.net +lon-2.paas.massivegrid.net +ny-1.paas.massivegrid.net +ny-2.paas.massivegrid.net +sg-1.paas.massivegrid.net +jelastic.saveincloud.net +nordeste-idc.saveincloud.net +j.scaleforce.net +jelastic.tsukaeru.net +sdscloud.pl +unicloud.pl +mircloud.ru +jelastic.regruhosting.ru +enscaled.sg +jele.site +jelastic.team +orangecloud.tn +j.layershift.co.uk +phx.enscaled.us +mircloud.us + // Jino : https://www.jino.ru // Submitted by Sergey Ulyashin myjino.ru @@ -12097,6 +12415,10 @@ myjino.ru *.spectrum.myjino.ru *.vps.myjino.ru +// Jotelulu S.L. : https://jotelulu.com +// Submitted by Daniel Fariña +jotelulu.cloud + // Joyent : https://www.joyent.com/ // Submitted by Brian Bennett *.triton.zone @@ -12128,10 +12450,20 @@ knightpoint.systems // Submitted by DisposaBoy oya.to +// Katholieke Universiteit Leuven: https://www.kuleuven.be +// Submitted by Abuse KU Leuven +kuleuven.cloud +ezproxy.kuleuven.be + // .KRD : http://nic.krd/data/krd/Registration%20Policy.pdf co.krd edu.krd +// Krellian Ltd. : https://krellian.com +// Submitted by Ben Francis +krellian.net +webthings.io + // LCube - Professional hosting e.K. : https://www.lcube-webhosting.de // Submitted by Lars Laehn git-repos.de @@ -12162,10 +12494,6 @@ co.technology // Submitted by Greg Holland app.lmpm.com -// Linki Tools UG : https://linki.tools -// Submitted by Paulo Matos -linkitools.space - // linkyard ldt: https://www.linkyard.ch/ // Submitted by Mario Siegenthaler linkyard.cloud @@ -12174,12 +12502,18 @@ linkyard-cloud.ch // Linode : https://linode.com // Submitted by members.linode.com -nodebalancer.linode.com +*.nodebalancer.linode.com +*.linodeobjects.com +ip.linodeusercontent.com // LiquidNet Ltd : http://www.liquidnetlimited.com/ // Submitted by Victor Velchev we.bs +// localzone.xyz +// Submitted by Kenny Niehage +localzone.xyz + // Log'in Line : https://www.loginline.com/ // Submitted by Rémi Mach loginline.app @@ -12188,6 +12522,14 @@ loginline.io loginline.services loginline.site +// Lokalized : https://lokalized.nl +// Submitted by Noah Taheij +servers.run + +// Lõhmus Family, The +// Submitted by Heiki Lõhmus +lohmus.me + // LubMAN UMCS Sp. z o.o : https://lubman.pl/ // Submitted by Ireneusz Maliszewski krasnik.pl @@ -12199,7 +12541,6 @@ swidnik.pl // Lug.org.uk : https://lug.org.uk // Submitted by Jon Spriggs -uklugs.org glug.org.uk lug.org.uk lugs.org.uk @@ -12225,6 +12566,7 @@ barsy.online barsy.org barsy.pro barsy.pub +barsy.ro barsy.shop barsy.site barsy.support @@ -12243,6 +12585,34 @@ mayfirst.org // Submitted by Ilya Zaretskiy hb.cldmail.ru +// Mail Transfer Platform : https://www.neupeer.com +// Submitted by Li Hui +cn.vu + +// Maze Play: https://www.mazeplay.com +// Submitted by Adam Humpherys +mazeplay.com + +// mcpe.me : https://mcpe.me +// Submitted by Noa Heyl +mcpe.me + +// McHost : https://mchost.ru +// Submitted by Evgeniy Subbotin +mcdir.me +mcdir.ru +mcpre.ru +vps.mcdir.ru + +// Mediatech : https://mediatech.by +// Submitted by Evgeniy Kozhuhovskiy +mediatech.by +mediatech.dev + +// Medicom Health : https://medicomhealth.com +// Submitted by Michael Olson +hra.health + // Memset hosting : https://www.memset.com // Submitted by Tom Whitwell miniserver.com @@ -12250,7 +12620,7 @@ memset.net // MetaCentrum, CESNET z.s.p.o. : https://www.metacentrum.cz/en/ // Submitted by Zdeněk Šustr -cloud.metacentrum.cz +*.cloud.metacentrum.cz custom.metacentrum.cz // MetaCentrum, CESNET z.s.p.o. : https://www.metacentrum.cz/en/ @@ -12267,11 +12637,29 @@ eu.meteorapp.com co.pl // Microsoft Corporation : http://microsoft.com -// Submitted by Mostafa Elzeiny +// Submitted by Mitch Webster *.azurecontainer.io azurewebsites.net azure-mobile.net cloudapp.net +azurestaticapps.net +centralus.azurestaticapps.net +eastasia.azurestaticapps.net +eastus2.azurestaticapps.net +westeurope.azurestaticapps.net +westus2.azurestaticapps.net + +// minion.systems : http://minion.systems +// Submitted by Robert Böttinger +csx.cc + +// Mintere : https://mintere.com/ +// Submitted by Ben Aubin +mintere.site + +// MobileEducation, LLC : https://joinforte.com +// Submitted by Grayson Martin +forte.id // Mozilla Corporation : https://mozilla.com // Submitted by Ben Francis @@ -12287,35 +12675,48 @@ net.ru org.ru pp.ru +// Mythic Beasts : https://www.mythic-beasts.com +// Submitted by Paul Cammish +hostedpi.com +customer.mythic-beasts.com +caracal.mythic-beasts.com +fentiger.mythic-beasts.com +lynx.mythic-beasts.com +ocelot.mythic-beasts.com +oncilla.mythic-beasts.com +onza.mythic-beasts.com +sphinx.mythic-beasts.com +vs.mythic-beasts.com +x.mythic-beasts.com +yali.mythic-beasts.com +cust.retrosnub.co.uk + // Nabu Casa : https://www.nabucasa.com // Submitted by Paulus Schoutsen ui.nabu.casa // Names.of.London : https://names.of.london/ -// Submitted by James Stevens or +// Submitted by James Stevens or pony.club of.fashion -on.fashion -of.football in.london of.london +from.marketing +with.marketing for.men +repair.men and.mom for.mom for.one +under.one for.sale -of.work +that.win +from.work to.work -// NCTU.ME : https://nctu.me/ -// Submitted by Tocknicsu -nctu.me - // Netlify : https://www.netlify.com // Submitted by Jessica Parsons -bitballoon.com netlify.app -netlify.com // Neustar Inc. // Submitted by Trung Tran @@ -12333,6 +12734,20 @@ nh-serv.co.uk // Submitted by Jeff Wheelhouse nfshost.com +// Noop : https://noop.app +// Submitted by Nathaniel Schweinberg +*.developer.app +noop.app + +// Northflank Ltd. : https://northflank.com/ +// Submitted by Marco Suter +*.northflank.app +*.code.run + +// Noticeable : https://noticeable.io +// Submitted by Laurent Pellegrino +noticeable.news + // Now-DNS : https://now-dns.com // Submitted by Steve Russell dnsking.ch @@ -12471,60 +12886,6 @@ pcloud.host // Submitted by Matthew Brown nyc.mn -// NymNom : https://nymnom.com/ -// Submitted by NymNom -nom.ae -nom.af -nom.ai -nom.al -nym.by -nom.bz -nym.bz -nom.cl -nym.ec -nom.gd -nom.ge -nom.gl -nym.gr -nom.gt -nym.gy -nym.hk -nom.hn -nym.ie -nom.im -nom.ke -nym.kz -nym.la -nym.lc -nom.li -nym.li -nym.lt -nym.lu -nom.lv -nym.me -nom.mk -nym.mn -nym.mx -nom.nu -nym.nz -nym.pe -nym.pt -nom.pw -nom.qa -nym.ro -nom.rs -nom.si -nym.sk -nom.st -nym.su -nym.sx -nom.tj -nym.tw -nom.ug -nom.uy -nom.vc -nom.vg - // Observable, Inc. : https://observablehq.com // Submitted by Mike Bostock static.observableusercontent.com @@ -12533,35 +12894,66 @@ static.observableusercontent.com // Submitted by Andrew Sampson cya.gg +// OMG.LOL : +// Submitted by Adam Newbold +omg.lol + // Omnibond Systems, LLC. : https://www.omnibond.com // Submitted by Cole Estep cloudycluster.net +// OmniWe Limited: https://omniwe.com +// Submitted by Vicary Archangel +omniwe.site + +// One.com: https://www.one.com/ +// Submitted by Jacob Bunk Nielsen +service.one + // One Fold Media : http://www.onefoldmedia.com/ // Submitted by Eddie Jones nid.io +// Open Social : https://www.getopensocial.com/ +// Submitted by Alexander Varwijk +opensocial.site + // OpenCraft GmbH : http://opencraft.com/ // Submitted by Sven Marnach opencraft.hosting +// OpenResearch GmbH: https://openresearch.com/ +// Submitted by Philipp Schmid +orsites.com + // Opera Software, A.S.A. // Submitted by Yngve Pettersen operaunite.com -// Oursky Limited : https://skygear.io/ -// Submited by Skygear Developer +// Oursky Limited : https://authgear.com/, https://skygear.io/ +// Submited by Authgear Team , Skygear Developer +authgear-staging.com +authgearapps.com skygearapp.com // OutSystems // Submitted by Duarte Santos outsystemscloud.com +// OVHcloud: https://ovhcloud.com +// Submitted by Vincent Cassé +*.webpaas.ovh.net +*.hosting.ovh.net + // OwnProvider GmbH: http://www.ownprovider.com // Submitted by Jan Moennich ownprovider.com own.pm +// OwO : https://whats-th.is/ +// Submitted by Dean Sheather +*.owo.codes + // OX : http://www.ox.rs // Submitted by Adam Grand ox.rs @@ -12578,6 +12970,21 @@ pgfog.com // Submitted by Jason Kriss pagefrontapp.com +// PageXL : https://pagexl.com +// Submitted by Yann Guichard +pagexl.com + +// Paywhirl, Inc : https://paywhirl.com/ +// Submitted by Daniel Netzer +*.paywhirl.com + +// pcarrier.ca Software Inc: https://pcarrier.ca/ +// Submitted by Pierre Carrier +bar0.net +bar1.net +bar2.net +rdv.to + // .pl domains (grandfathered) art.pl gliwice.pl @@ -12599,14 +13006,22 @@ mypep.link // Submitted by Kenneth Van Alstyne perspecta.cloud +// PE Ulyanov Kirill Sergeevich : https://airy.host +// Submitted by Kirill Ulyanov +lk3.ru + // Planet-Work : https://www.planet-work.com/ // Submitted by Frédéric VANNIÈRE on-web.fr // Platform.sh : https://platform.sh // Submitted by Nikola Kotur -*.platform.sh +bc.platform.sh +ent.platform.sh +eu.platform.sh +us.platform.sh *.platformsh.site +*.tst.site // Platter: https://platter.dev // Submitted by Patrick Flor @@ -12614,6 +13029,12 @@ platter-app.com platter-app.dev platterp.us +// Plesk : https://www.plesk.com/ +// Submitted by Anton Akhtyamov +pdns.page +plesk.page +pleskns.com + // Port53 : https://port53.io/ // Submitted by Maximilian Schieder dyn53.io @@ -12622,6 +13043,17 @@ dyn53.io // Submitted by Zulfais co.bn +// Postman, Inc : https://postman.com +// Submitted by Rahul Dhawan +postman-echo.com +pstmn.io +mock.pstmn.io +httpbin.org + +//prequalifyme.today : https://prequalifyme.today +//Submitted by DeepakTiwari deepak@ivylead.io +prequalifyme.today + // prgmr.com : https://prgmr.com/ // Submitted by Sarah Newman xen.prgmr.com @@ -12651,6 +13083,15 @@ byen.site // Submitted by Kor Nielsen pubtls.org +// PythonAnywhere LLP: https://www.pythonanywhere.com +// Submitted by Giles Thomas +pythonanywhere.com +eu.pythonanywhere.com + +// QOTO, Org. +// Submitted by Jeffrey Phillips Freeman +qoto.io + // Qualifio : https://qualifio.com/ // Submitted by Xavier De Cock qualifioapp.com @@ -12659,6 +13100,14 @@ qualifioapp.com // Submitted by Dani Biro qbuser.com +// Rad Web Hosting: https://radwebhosting.com +// Submitted by Scott Claeys +cloudsite.builders + +// Redgate Software: https://red-gate.com +// Submitted by Andrew Farries +instances.spawn.cc + // Redstar Consultants : https://www.redstarconsultants.com/ // Submitted by Jons Slemmer instantcloud.cn @@ -12696,6 +13145,10 @@ vaporcloud.io rackmaze.com rackmaze.net +// Rakuten Games, Inc : https://dev.viberplay.io +// Submitted by Joshua Zhang +g.vbrplsbx.io + // Rancher Labs, Inc : https://rancher.com // Submitted by Vincent Fiduccia *.on-k3s.io @@ -12718,6 +13171,7 @@ onrender.com // Repl.it : https://repl.it // Submitted by Mason Clayton repl.co +id.repl.co repl.run // Resin.io : https://resin.io @@ -12732,13 +13186,33 @@ hzc.io // Revitalised Limited : http://www.revitalised.co.uk // Submitted by Jack Price wellbeingzone.eu -ptplus.fit wellbeingzone.co.uk +// Rico Developments Limited : https://adimo.co +// Submitted by Colin Brown +adimo.co.uk + +// Riseup Networks : https://riseup.net +// Submitted by Micah Anderson +itcouldbewor.se + // Rochester Institute of Technology : http://www.rit.edu/ // Submitted by Jennifer Herting git-pages.rit.edu +// Rusnames Limited: http://rusnames.ru/ +// Submitted by Sergey Zotov +биз.рус +ком.рус +крым.рус +мир.рус +мск.рус +орг.рус +самара.рус +сочи.рус +спб.рус +я.рус + // Sandstorm Development Group, Inc. : https://sandcats.io/ // Submitted by Asheesh Laroia sandcats.io @@ -12755,6 +13229,7 @@ schokokeks.net // Scottish Government: https://www.gov.scot // Submitted by Martin Ellis gov.scot +service.gov.scot // Scry Security : http://www.scrysec.com // Submitted by Shante Adam @@ -12773,16 +13248,37 @@ my-firewall.org myfirewall.org spdns.org +// Seidat : https://www.seidat.com +// Submitted by Artem Kondratev +seidat.net + +// Sellfy : https://sellfy.com +// Submitted by Yuriy Romadin +sellfy.store + // Senseering GmbH : https://www.senseering.de // Submitted by Felix Mönckemeyer senseering.net +// Sendmsg: https://www.sendmsg.co.il +// Submitted by Assaf Stern +minisite.ms + +// Service Magnet : https://myservicemagnet.com +// Submitted by Dave Sanders +magnet.page + // Service Online LLC : http://drs.ua/ // Submitted by Serhii Bulakh biz.ua co.ua pp.ua +// Shift Crypto AG : https://shiftcrypto.ch +// Submitted by alex +shiftcrypto.dev +shiftcrypto.io + // ShiftEdit : https://shiftedit.net/ // Submitted by Adam Jimenez shiftedit.io @@ -12791,6 +13287,10 @@ shiftedit.io // Submitted by Alex Bowers myshopblocks.com +// Shopify : https://www.shopify.com +// Submitted by Alex Richter +myshopify.com + // Shopit : https://www.shopitcommerce.com/ // Submitted by Craig McMahon shopitsite.com @@ -12821,16 +13321,47 @@ bounty-full.com alpha.bounty-full.com beta.bounty-full.com +// Small Technology Foundation : https://small-tech.org +// Submitted by Aral Balkan +small-web.org + +// Smoove.io : https://www.smoove.io/ +// Submitted by Dan Kozak +vp4.me + +// Snowplow Analytics : https://snowplowanalytics.com/ +// Submitted by Ian Streeter +try-snowplow.com + +// SourceHut : https://sourcehut.org +// Submitted by Drew DeVault +srht.site + // Stackhero : https://www.stackhero.io // Submitted by Adrien Gillon stackhero-network.com +// Staclar : https://staclar.com +// Submitted by Matthias Merkel +novecore.site + // staticland : https://static.land // Submitted by Seth Vincent static.land dev.static.land sites.static.land +// Storebase : https://www.storebase.io +// Submitted by Tony Schirmer +storebase.store + +// Strategic System Consulting (eApps Hosting): https://www.eapps.com/ +// Submitted by Alex Oancea +vps-host.net +atl.jelastic.vps-host.net +njs.jelastic.vps-host.net +ric.jelastic.vps-host.net + // Sony Interactive Entertainment LLC : https://sie.com/ // Submitted by David Coles playstation-cloud.com @@ -12848,6 +13379,28 @@ spacekit.io // Submitted by Stefan Neufeind customer.speedpartner.de +// Spreadshop (sprd.net AG) : https://www.spreadshop.com/ +// Submitted by Martin Breest +myspreadshop.at +myspreadshop.com.au +myspreadshop.be +myspreadshop.ca +myspreadshop.ch +myspreadshop.com +myspreadshop.de +myspreadshop.dk +myspreadshop.es +myspreadshop.fi +myspreadshop.fr +myspreadshop.ie +myspreadshop.it +myspreadshop.net +myspreadshop.nl +myspreadshop.no +myspreadshop.pl +myspreadshop.se +myspreadshop.co.uk + // Standard Library : https://stdlib.com // Submitted by Jacob Lee api.stdlib.com @@ -12869,10 +13422,12 @@ user.srcf.net // Submitted by Dan Miller temp-dns.com -// Swisscom Application Cloud: https://developer.swisscom.com -// Submitted by Matthias.Winzeler -applicationcloud.io -scapp.io +// Supabase : https://supabase.io +// Submitted by Inian Parameshwaran +supabase.co +supabase.in +supabase.net +su.paba.se // Symfony, SAS : https://symfony.com/ // Submitted by Fabien Potencier @@ -12901,10 +13456,19 @@ synology.me vpnplus.to direct.quickconnect.to +// Tabit Technologies Ltd. : https://tabit.cloud/ +// Submitted by Oren Agiv +tabitorder.co.il + // TAIFUN Software AG : http://taifun-software.de // Submitted by Bjoern Henke taifun-dns.de +// Tailscale Inc. : https://www.tailscale.com +// Submitted by David Anderson +beta.tailscale.net +ts.net + // TASK geographical domains (www.task.gda.pl/uslugi/dns) gda.pl gdansk.pl @@ -12928,22 +13492,42 @@ gwiddle.co.uk // Thingdust AG : https://thingdust.com/ // Submitted by Adrian Imboden +*.firenet.ch +*.svc.firenet.ch +reservd.com thingdustdata.com cust.dev.thingdust.io cust.disrec.thingdust.io cust.prod.thingdust.io cust.testing.thingdust.io +reservd.dev.thingdust.io +reservd.disrec.thingdust.io +reservd.testing.thingdust.io + +// ticket i/O GmbH : https://ticket.io +// Submitted by Christian Franke +tickets.io // Tlon.io : https://tlon.io // Submitted by Mark Staarink arvo.network azimuth.network +tlon.network + +// Tor Project, Inc. : https://torproject.org +// Submitted by Antoine Beaupré bloxcms.com townnews-staging.com +// TradableBits: https://tradablebits.com +// Submitted by Dmitry Khrisanov dmitry@tradablebits.com +tbits.me + // TrafficPlex GmbH : https://www.trafficplex.de/ // Submitted by Phillipp Röll 12hp.at @@ -13009,6 +13593,10 @@ inc.hk virtualuser.de virtual-user.de +// Upli : https://upli.io +// Submitted by Lenny Bakkalian +upli.io + // urown.net : https://urown.net // Submitted by Hostmaster urown.cloud @@ -13022,6 +13610,12 @@ lib.de.us // Submitted by Danko Aleksejevs 2038.io +// Vercel, Inc : https://vercel.com/ +// Submitted by Connor Davis +vercel.app +vercel.dev +now.sh + // Viprinet Europe GmbH : http://www.viprinet.com // Submitted by Simon Kissel router.management @@ -13034,6 +13628,48 @@ v-info.info // Submitted by Nathan van Bakel voorloper.cloud +// Voxel.sh DNS : https://voxel.sh/dns/ +// Submitted by Mia Rehlinger +neko.am +nyaa.am +be.ax +cat.ax +es.ax +eu.ax +gg.ax +mc.ax +us.ax +xy.ax +nl.ci +xx.gl +app.gp +blog.gt +de.gt +to.gt +be.gy +cc.hn +blog.kg +io.kg +jp.kg +tv.kg +uk.kg +us.kg +de.ls +at.md +de.md +jp.md +to.md +indie.porn +vxl.sh +ch.tc +me.tc +we.tc +nyan.to +at.vg +blog.vu +dev.vu +me.vu + // V.UA Domain Administrator : https://domain.v.ua/ // Submitted by Serhii Rostilo v.ua @@ -13042,10 +13678,26 @@ v.ua // Submitted by Masayuki Note wafflecell.com +// WapBlog.ID : https://www.wapblog.id +// Submitted by Fajar Sodik +idnblogger.com +indowapblog.com +bloger.id +wblog.id +wbq.me +fastblog.net + // WebHare bv: https://www.webhare.com/ // Submitted by Arnold Hendriks *.webhare.dev +// WebHotelier Technologies Ltd: https://www.webhotelier.net/ +// Submitted by Apostolos Tsakpinis +reserve-online.net +reserve-online.com +bookonline.app +hotelwithflight.com + // WeDeploy by Liferay, Inc. : https://www.wedeploy.com // Submitted by Henrique Vicente wedeploy.io @@ -13056,6 +13708,10 @@ wedeploy.sh // Submitted by Jung Jin remotewd.com +// WIARD Enterprises : https://wiardweb.com +// Submitted by Kidd Hustle +pages.wiardweb.com + // Wikimedia Labs : https://wikitech.wikimedia.org // Submitted by Arturo Borrero Gonzalez wmflabs.org @@ -13069,12 +13725,30 @@ daemon.panel.gg // WoltLab GmbH : https://www.woltlab.com // Submitted by Tim Düsterhus +woltlab-demo.com myforum.community community-pro.de diskussionsbereich.de community-pro.net meinforum.net +// Woods Valldata : https://www.woodsvalldata.co.uk/ +// Submitted by Chris Whittle +affinitylottery.org.uk +raffleentry.org.uk +weeklylottery.org.uk + +// WP Engine : https://wpengine.com/ +// Submitted by Michael Smith +// Submitted by Brandon DuRette +wpenginepowered.com +js.wpenginepowered.com + +// Wix.com, Inc. : https://www.wix.com +// Submitted by Shahar Talmi +wixsite.com +editorx.io + // XenonCloud GbR: https://xenoncloud.net // Submitted by Julian Uphoff half.host @@ -13117,6 +13791,7 @@ ybo.trade // Yunohost : https://yunohost.org // Submitted by Valentin Grimaud +ynh.fr nohost.me noho.st @@ -13125,10 +13800,6 @@ noho.st za.net za.org -// Zeit, Inc. : https://zeit.domains/ -// Submitted by Olli Vanhoja -now.sh - // Zine EOOD : https://zine.bg/ // Submitted by Martin Angelov bss.design @@ -13139,8 +13810,4 @@ basicserver.io virtualserver.io enterprisecloud.nu -// Mintere : https://mintere.com/ -// Submitted by Ben Aubin -mintere.site - // ===END PRIVATE DOMAINS=== diff --git a/make/data/tzdata/VERSION b/make/data/tzdata/VERSION index 3a40c910333..bc830a3a5ef 100644 --- a/make/data/tzdata/VERSION +++ b/make/data/tzdata/VERSION @@ -21,4 +21,4 @@ # or visit www.oracle.com if you need additional information or have any # questions. # -tzdata2021e +tzdata2022a diff --git a/make/data/tzdata/africa b/make/data/tzdata/africa index 0f367713ea9..5466bbcc87b 100644 --- a/make/data/tzdata/africa +++ b/make/data/tzdata/africa @@ -941,6 +941,10 @@ Zone Indian/Mauritius 3:50:00 - LMT 1907 # Port Louis # (car (cdr (cdr a))) (calendar-month-name (car a) t) (car (cdr a)) # (car (cdr (cdr b))) (calendar-month-name (car b) t) (car (cdr b))))) # (setq islamic-year (+ 1 islamic-year)))) +# +# From Milamber (2021-03-31, 2022-03-10), confirming these predictions: +# https://www.mmsp.gov.ma/fr/actualites.aspx?id=2076 +# https://www.ecoactu.ma/horaires-administration-ramadan-gmtheure-gmt-a-partir-de-dimanche-27-mars/ # Rule NAME FROM TO - IN ON AT SAVE LETTER/S Rule Morocco 1939 only - Sep 12 0:00 1:00 - diff --git a/make/data/tzdata/asia b/make/data/tzdata/asia index cfe48745e24..4aaaf146b0f 100644 --- a/make/data/tzdata/asia +++ b/make/data/tzdata/asia @@ -3429,8 +3429,12 @@ Zone Asia/Karachi 4:28:12 - LMT 1907 # ... winter time will begin in Palestine from Friday 10-29, 01:00 AM # by 60 minutes backwards. # -# From Paul Eggert (2021-10-20): -# Guess future fall transitions on October's last Friday at 01:00. +# From Tim Parenti (2021-10-25), per Paul Eggert (2021-10-24): +# Guess future fall transitions at 01:00 on the Friday preceding October's +# last Sunday (i.e., Fri>=23), as this is more consistent with recent practice. + +# From Heba Hamad (2022-03-10): +# summer time will begin in Palestine from Sunday 03-27-2022, 00:00 AM. # Rule NAME FROM TO - IN ON AT SAVE LETTER/S Rule EgyptAsia 1957 only - May 10 0:00 1:00 S @@ -3466,9 +3470,10 @@ Rule Palestine 2016 2018 - Mar Sat>=24 1:00 1:00 S Rule Palestine 2016 2018 - Oct Sat>=24 1:00 0 - Rule Palestine 2019 only - Mar 29 0:00 1:00 S Rule Palestine 2019 only - Oct Sat>=24 0:00 0 - -Rule Palestine 2020 max - Mar Sat>=24 0:00 1:00 S +Rule Palestine 2020 2021 - Mar Sat>=24 0:00 1:00 S Rule Palestine 2020 only - Oct 24 1:00 0 - -Rule Palestine 2021 max - Oct lastFri 1:00 0 - +Rule Palestine 2021 max - Oct Fri>=23 1:00 0 - +Rule Palestine 2022 max - Mar Sun>=25 0:00 1:00 S # Zone NAME STDOFF RULES FORMAT [UNTIL] Zone Asia/Gaza 2:17:52 - LMT 1900 Oct diff --git a/make/data/tzdata/europe b/make/data/tzdata/europe index 9b0b64aa3eb..bc57e94e44f 100644 --- a/make/data/tzdata/europe +++ b/make/data/tzdata/europe @@ -2808,8 +2808,26 @@ Zone Europe/Kaliningrad 1:22:00 - LMT 1893 Apr # says he remembers that Samara opted out of the 1992-01-19 exception # 2 days before the switch. # -# -# From Paul Eggert (2016-03-18): +# From Alois Treindl (2022-02-15): +# the Russian wikipedia page +# https://ru.wikipedia.org/wiki/Московское_время#Перемещение_границы_применения_московского_времени_на_восток +# contains the sentence (in Google translation) "In the autumn of +# 1981, Arkhangelsk, Vologda, Yaroslavl, Ivanovo, Vladimir, Ryazan, +# Lipetsk, Voronezh, Rostov-on-Don, Krasnodar and regions to the east +# of those named (about 30 in total) parted ways with Moscow time. +# However, the convenience of common time with Moscow turned out to be +# decisive - in 1982, these regions again switched to Moscow time." +# Shanks International atlas has similar information, and also the +# Russian book Zaitsev A., Kutalev D. A new astrologer's reference +# book. Coordinates of cities and time corrections, - The World of +# Urania, 2012 (Russian: Зайцев А., Куталёв Д., Новый справочник +# астролога. Координаты городов и временные поправки). +# To me it seems that an extra zone is needed, which starts with LMT +# util 1919, later follows Moscow since 1930, but deviates from it +# between 1 October 1981 until 1 April 1982. +# +# +# From Paul Eggert (2022-02-15): # Given the above, we appear to be missing some Zone entries for the # chaotic early 1980s in Russia. It's not clear what these entries # should be. For now, sweep this under the rug and just document the @@ -2856,7 +2874,7 @@ Zone Europe/Simferopol 2:16:24 - LMT 1880 1:00 C-Eur CE%sT 1944 Apr 13 3:00 Russia MSK/MSD 1990 3:00 - MSK 1990 Jul 1 2:00 - 2:00 - EET 1992 + 2:00 - EET 1992 Mar 20 # Central Crimea used Moscow time 1994/1997. # # From Paul Eggert (2006-03-22): @@ -2866,7 +2884,7 @@ Zone Europe/Simferopol 2:16:24 - LMT 1880 # sometime between the 1994 DST switches. Shanks & Pottenger simply say # 1994-09-25 03:00, but that can't be right. For now, guess it # changed in May. - 2:00 E-Eur EE%sT 1994 May + 2:00 C-Eur EE%sT 1994 May # From IATA SSIM (1994/1997), which also says that Kerch is still like Kiev. 3:00 E-Eur MSK/MSD 1996 Mar 31 0:00s 3:00 1:00 MSD 1996 Oct 27 3:00s @@ -4033,6 +4051,27 @@ Link Europe/Istanbul Asia/Istanbul # Istanbul is in both continents. # Ukraine # +# From Alois Triendl (2014-03-01): +# REGULATION A N O V A on March 20, 1992 N 139 ... means that from +# 1992 on, Ukraine had DST with begin time at 02:00 am, on last Sunday +# in March, and end time 03:00 am, last Sunday in September.... +# CABINET OF MINISTERS OF UKRAINE RESOLUTION on May 13, 1996 N 509 +# "On the order of computation time on the territory of Ukraine" .... +# As this cabinet decision is from May 1996, it seems likely that the +# transition in March 1996, which predates it, was still at 2:00 am +# and not at 3:00 as would have been under EU rules. +# This is why I have set the change to EU rules into May 1996, +# so that the change in March is stil covered by the Ukraine rule. +# The next change in October 1996 happened under EU rules.... +# TZ database holds three other zones for Ukraine.... I have not yet +# worked out the consequences for these three zones, as we (me and my +# US colleague David Cochrane) are still trying to get more +# information upon these local deviations from Kiev rules. +# +# From Paul Eggert (2022-02-08): +# For now, assume that Ukraine's other three zones followed the same rules, +# except that Crimea switched to Moscow time in 1994 as described elsewhere. + # From Igor Karpov, who works for the Ukrainian Ministry of Justice, # via Garrett Wollman (2003-01-27): # BTW, I've found the official document on this matter. It's government @@ -4122,7 +4161,7 @@ Zone Europe/Kiev 2:02:04 - LMT 1880 1:00 C-Eur CE%sT 1943 Nov 6 3:00 Russia MSK/MSD 1990 Jul 1 2:00 2:00 1:00 EEST 1991 Sep 29 3:00 - 2:00 E-Eur EE%sT 1995 + 2:00 C-Eur EE%sT 1996 May 13 2:00 EU EE%sT # Transcarpathia used CET 1990/1991. # "Uzhhorod" is the transliteration of the Rusyn/Ukrainian pronunciation, but @@ -4135,8 +4174,8 @@ Zone Europe/Uzhgorod 1:29:12 - LMT 1890 Oct 3:00 Russia MSK/MSD 1990 3:00 - MSK 1990 Jul 1 2:00 1:00 - CET 1991 Mar 31 3:00 - 2:00 - EET 1992 - 2:00 E-Eur EE%sT 1995 + 2:00 - EET 1992 Mar 20 + 2:00 C-Eur EE%sT 1996 May 13 2:00 EU EE%sT # Zaporozh'ye and eastern Lugansk oblasts observed DST 1990/1991. # "Zaporizhia" is the transliteration of the Ukrainian name, but @@ -4149,7 +4188,8 @@ Zone Europe/Zaporozhye 2:20:40 - LMT 1880 3:00 - MSK 1941 Aug 25 1:00 C-Eur CE%sT 1943 Oct 25 3:00 Russia MSK/MSD 1991 Mar 31 2:00 - 2:00 E-Eur EE%sT 1995 + 2:00 E-Eur EE%sT 1992 Mar 20 + 2:00 C-Eur EE%sT 1996 May 13 2:00 EU EE%sT # Vatican City diff --git a/make/data/tzdata/leapseconds b/make/data/tzdata/leapseconds index cc514561ff1..776d25ab367 100644 --- a/make/data/tzdata/leapseconds +++ b/make/data/tzdata/leapseconds @@ -95,11 +95,11 @@ 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 2022 Jun 28 00:00:00 +#Expires 2022 Dec 28 00:00:00 # POSIX timestamps for the data in this file: #updated 1467936000 (2016-07-08 00:00:00 UTC) -#expires 1656374400 (2022-06-28 00:00:00 UTC) +#expires 1672185600 (2022-12-28 00:00:00 UTC) -# Updated through IERS Bulletin C62 -# File expires on: 28 June 2022 +# Updated through IERS Bulletin C63 +# File expires on: 28 December 2022 diff --git a/make/data/tzdata/southamerica b/make/data/tzdata/southamerica index 503ed65f580..b6e401ac252 100644 --- a/make/data/tzdata/southamerica +++ b/make/data/tzdata/southamerica @@ -1109,7 +1109,7 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914 # Chile -# From Paul Eggert (2015-04-03): +# From Paul Eggert (2022-03-15): # Shanks & Pottenger says America/Santiago introduced standard time in # 1890 and rounds its UT offset to 70W40; guess that in practice this # was the same offset as in 1916-1919. It also says Pacific/Easter @@ -1132,7 +1132,7 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914 # Historia de la hora oficial de Chile (retrieved 2012-10-24). See: # https://web.archive.org/web/20121024234627/http://www.horaoficial.cl/horaof.htm # A fancier Spanish version (requiring mouse-clicking) is at: -# http://www.horaoficial.cl/historia_hora.html +# http://www.horaoficial.cl/historia_hora.php # Conflicts between [1] and [2] were resolved as follows: # # - [1] says the 1910 transition was Jan 1, [2] says Jan 10 and cites @@ -1141,7 +1141,8 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914 # - [1] says SMT was -4:42:45, [2] says Chile's official time from # 1916 to 1919 was -4:42:46.3, the meridian of Chile's National # Astronomical Observatory (OAN), then located in what is now -# Quinta Normal in Santiago. Go with [2], rounding it to -4:42:46. +# Quinta Normal in Santiago. Go with [1], as this matches the meridian +# referred to by the relevant Chilean laws to this day. # # - [1] says the 1918 transition was Sep 1, [2] says Sep 10 and cites # Boletín No. 22, Aviso No. 129/1918 (1918-08-23). Go with [2]. @@ -1163,6 +1164,32 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914 # this is known to work for DST transitions starting in 2008 and # may well be true for earlier transitions. +# From Tim Parenti (2022-03-15): +# For a brief period of roughly six weeks in 1946, DST was only observed on an +# emergency basis in specific regions of central Chile; namely, "the national +# territory between the provinces of Coquimbo and Concepción, inclusive". +# This was enacted by Decree 3,891, dated 1946-07-13, and took effect +# 1946-07-14 24:00, advancing these central regions to -03. +# https://www.diariooficial.interior.gob.cl/versiones-anteriores/do-h/19460715/#page/1 +# The decree contemplated "[t]hat this advancement of the Official Time, even +# though it has been proposed for the cities of Santiago and Valparaíso only, +# must be agreed with that of other cities, due to the connection of various +# activities that require it, such as, for example, the operation of rail +# services". It was originally set to expire after 30 days but was extended +# through 1946-08-31 by Decree 4,506, dated 1946-08-13. +# https://www.diariooficial.interior.gob.cl/versiones-anteriores/do-h/19460814/#page/1 +# +# Law Number 8,522, promulgated 1946-08-27, reunified Chilean clocks at their +# new "Summer Time" of -04, reckoned as that of "the meridian of the +# Astronomical Observatory of Lo Espejo, advanced by 42 minutes and 45 +# seconds". +# https://www.diariooficial.interior.gob.cl/versiones-anteriores/do-h/19460828/#page/1 +# After a brief "Winter Time" stint at -05 beginning 1947-04-01, Law Number +# 8,777, promulgated 1947-05-17, established year-round -04 "from 23:00 on the +# second day after it is published in the 'Diario Oficial'." It was published +# on Monday 1947-05-19 and so took effect from Wednesday 1947-05-21 23:00. +# https://www.diariooficial.interior.gob.cl/versiones-anteriores/do-h/19470519/#page/1 + # From Eduardo Krell (1995-10-19): # The law says to switch to DST at midnight [24:00] on the second SATURDAY # of October.... The law is the same for March and October. @@ -1321,12 +1348,12 @@ Rule Chile 2019 max - Sep Sun>=2 4:00u 1:00 - # IATA SSIM anomalies: (1992-02) says 1992-03-14; # (1996-09) says 1998-03-08. Ignore these. # Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone America/Santiago -4:42:46 - LMT 1890 - -4:42:46 - SMT 1910 Jan 10 # Santiago Mean Time +Zone America/Santiago -4:42:45 - LMT 1890 + -4:42:45 - SMT 1910 Jan 10 # Santiago Mean Time -5:00 - -05 1916 Jul 1 - -4:42:46 - SMT 1918 Sep 10 + -4:42:45 - SMT 1918 Sep 10 -4:00 - -04 1919 Jul 1 - -4:42:46 - SMT 1927 Sep 1 + -4:42:45 - SMT 1927 Sep 1 -5:00 Chile -05/-04 1932 Sep 1 -4:00 - -04 1942 Jun 1 -5:00 - -05 1942 Aug 1 @@ -1336,11 +1363,11 @@ Zone America/Santiago -4:42:46 - LMT 1890 -5:00 - -05 1947 May 21 23:00 -4:00 Chile -04/-03 Zone America/Punta_Arenas -4:43:40 - LMT 1890 - -4:42:46 - SMT 1910 Jan 10 + -4:42:45 - SMT 1910 Jan 10 -5:00 - -05 1916 Jul 1 - -4:42:46 - SMT 1918 Sep 10 + -4:42:45 - SMT 1918 Sep 10 -4:00 - -04 1919 Jul 1 - -4:42:46 - SMT 1927 Sep 1 + -4:42:45 - SMT 1927 Sep 1 -5:00 Chile -05/-04 1932 Sep 1 -4:00 - -04 1942 Jun 1 -5:00 - -05 1942 Aug 1 diff --git a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java index 5fd7a583a42..267f93e733b 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java @@ -114,6 +114,7 @@ public class CLDRConverter { ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT); private static Set AVAILABLE_TZIDS; + static int copyrightYear; private static String zoneNameTempFile; private static String tzDataDir; private static final Map canonicalTZMap = new HashMap<>(); @@ -217,6 +218,10 @@ public static void main(String[] args) throws Exception { verbose = true; break; + case "-year": + copyrightYear = Integer.parseInt(args[++i]); + break; + case "-zntempfile": zoneNameTempFile = args[++i]; break; @@ -235,7 +240,7 @@ public static void main(String[] args) throws Exception { } } } catch (RuntimeException e) { - severe("unknown or imcomplete arg(s): " + currentArg); + severe("unknown or incomplete arg(s): " + currentArg); usage(); System.exit(1); } @@ -260,6 +265,10 @@ public static void main(String[] args) throws Exception { setupBaseLocales("en-US"); } + if (copyrightYear == 0) { + copyrightYear = ZonedDateTime.now(ZoneId.of("America/Los_Angeles")).getYear(); + } + bundleGenerator = new ResourceBundleGenerator(); // Parse data independent of locales @@ -292,6 +301,7 @@ private static void usage() { + "\t-basemodule generates bundles that go into java.base module%n" + "\t-baselocales loc(,loc)* locales that go into the base module%n" + "\t-o dir output directory (default: ./build/gensrc)%n" + + "\t-year year copyright year in output%n" + "\t-zntempfile template file for java.time.format.ZoneName.java%n" + "\t-tzdatadir tzdata directory for java.time.format.ZoneName.java%n" + "\t-utf8 use UTF-8 rather than \\uxxxx (for debug)%n"); diff --git a/make/jdk/src/classes/build/tools/cldrconverter/CopyrightHeaders.java b/make/jdk/src/classes/build/tools/cldrconverter/CopyrightHeaders.java index 16062de116f..d1ea90a54c6 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/CopyrightHeaders.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/CopyrightHeaders.java @@ -26,6 +26,7 @@ package build.tools.cldrconverter; import java.util.Calendar; +import java.util.Date; import java.util.GregorianCalendar; import java.util.Locale; import java.util.TimeZone; @@ -131,8 +132,7 @@ class CopyrightHeaders { " * questions.\n" + " */\n"; - static String getOracleCopyright() { - int year = getYear(); + static String getOracleCopyright(int year) { return String.format(year > 2012 ? ORACLE_AFTER2012 : ORACLE2012, year); } @@ -140,16 +140,10 @@ static String getUnicodeCopyright() { return UNICODE; } - static String getOpenJDKCopyright() { - int year = getYear(); + static String getOpenJDKCopyright(int year) { return String.format(year > 2012 ? OPENJDK_AFTER2012 : OPENJDK2012, year); } - private static int getYear() { - return new GregorianCalendar(TimeZone.getTimeZone("America/Los_Angeles"), - Locale.US).get(Calendar.YEAR); - } - // no instantiation private CopyrightHeaders() { } diff --git a/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java b/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java index 9c95717edb2..34ce822ab64 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java @@ -198,7 +198,7 @@ public void generateBundle(String packageName, String baseName, String localeID, try (PrintWriter out = new PrintWriter(file, encoding)) { // Output copyright headers - out.println(CopyrightHeaders.getOpenJDKCopyright()); + out.println(CopyrightHeaders.getOpenJDKCopyright(CLDRConverter.copyrightYear)); out.println(CopyrightHeaders.getUnicodeCopyright()); if (useJava) { @@ -266,7 +266,7 @@ public void generateMetaInfo(Map> metaInfo) throws IOE CLDRConverter.info("Generating file " + file); try (PrintWriter out = new PrintWriter(file, "us-ascii")) { - out.printf(CopyrightHeaders.getOpenJDKCopyright()); + out.printf(CopyrightHeaders.getOpenJDKCopyright(CLDRConverter.copyrightYear)); out.printf((CLDRConverter.isBaseModule ? "package sun.util.cldr;\n\n" : "package sun.util.resources.cldr.provider;\n\n") diff --git a/make/jdk/src/classes/build/tools/generatelsrequivmaps/EquivMapsGenerator.java b/make/jdk/src/classes/build/tools/generatelsrequivmaps/EquivMapsGenerator.java index 7d1b7b261d5..e25833670ed 100644 --- a/make/jdk/src/classes/build/tools/generatelsrequivmaps/EquivMapsGenerator.java +++ b/make/jdk/src/classes/build/tools/generatelsrequivmaps/EquivMapsGenerator.java @@ -30,13 +30,15 @@ import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Paths; -import java.time.ZoneId; -import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.TimeZone; import java.util.TreeMap; import java.util.stream.Collectors; @@ -52,17 +54,19 @@ public class EquivMapsGenerator { public static void main(String[] args) throws Exception { - if (args.length != 2) { + if (args.length != 3) { System.err.println("Usage: java EquivMapsGenerator" - + " language-subtag-registry.txt LocaleEquivalentMaps.java"); + + " language-subtag-registry.txt LocaleEquivalentMaps.java copyrightYear"); System.exit(1); } + copyrightYear = Integer.parseInt(args[2]); readLSRfile(args[0]); generateEquivalentMap(); generateSourceCode(args[1]); } private static String LSRrevisionDate; + private static int copyrightYear; private static Map initialLanguageMap = new TreeMap<>(); private static Map initialRegionVariantMap = @@ -246,9 +250,7 @@ private static String generateValuesString(String[] values) { + "}"; private static String getOpenJDKCopyright() { - int year = ZonedDateTime.now(ZoneId - .of("America/Los_Angeles")).getYear(); - return String.format(Locale.US, COPYRIGHT, year); + return String.format(Locale.US, COPYRIGHT, copyrightYear); } /** diff --git a/make/jdk/src/classes/build/tools/makezipreproducible/MakeZipReproducible.java b/make/jdk/src/classes/build/tools/makezipreproducible/MakeZipReproducible.java index 48f08541d67..4ea976a8cc5 100644 --- a/make/jdk/src/classes/build/tools/makezipreproducible/MakeZipReproducible.java +++ b/make/jdk/src/classes/build/tools/makezipreproducible/MakeZipReproducible.java @@ -34,18 +34,22 @@ import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; +import java.time.Instant; +import java.time.ZoneOffset; +import java.time.LocalDateTime; /** * Generate a zip file in a "reproducible" manner from the input zip file. * Standard zip tools rely on OS file list querying whose ordering can vary * by platform architecture, this class ensures the zip entries are ordered - * and also supports SOURCE_DATE_EPOCH timestamps. + * and also supports SOURCE_DATE_EPOCH timestamps which will set the ZipEntry + * local time in UTC. */ public class MakeZipReproducible { String input_file = null; String fname = null; String zname = ""; - long timestamp = -1L; + LocalDateTime timestamp = null; boolean verbose = false; // Keep a sorted Set of ZipEntrys to be processed, so that the zip is reproducible @@ -117,7 +121,9 @@ boolean parseArgs(String args[]) { break; case 't': // SOURCE_DATE_EPOCH timestamp specified - timestamp = Long.parseLong(args[++count]) * 1000; + long epochSeconds = Long.parseLong(args[++count]); + Instant instant = Instant.ofEpochSecond(epochSeconds); + timestamp = LocalDateTime.ofInstant(instant, ZoneOffset.UTC); break; case 'v': verbose = true; @@ -194,8 +200,8 @@ void addEntry(ZipOutputStream zos, ZipEntry entry, InputStream entryInputStream) } // Set to specified timestamp if set otherwise leave as original lastModified time - if (timestamp != -1L) { - entry.setTime(timestamp); + if (timestamp != null) { + entry.setTimeLocal(timestamp); } zos.putNextEntry(entry); diff --git a/make/modules/java.base/Gensrc.gmk b/make/modules/java.base/Gensrc.gmk index f1eb5ff7e80..9ea2d015d3b 100644 --- a/make/modules/java.base/Gensrc.gmk +++ b/make/modules/java.base/Gensrc.gmk @@ -62,6 +62,7 @@ $(CLDR_GEN_DONE): $(wildcard $(CLDR_DATA_DIR)/dtd/*.dtd) \ -baselocales "en-US" \ -o $(GENSRC_DIR) \ -basemodule \ + -year $(COPYRIGHT_YEAR) \ -zntempfile $(ZONENAME_TEMPLATE) \ -tzdatadir $(TZ_DATA_DIR)) $(TOUCH) $@ @@ -99,7 +100,7 @@ GENSRC_LSREQUIVMAPS := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/util/locale/Loc $(GENSRC_LSREQUIVMAPS): $(TOPDIR)/make/data/lsrdata/language-subtag-registry.txt $(BUILD_TOOLS_JDK) $(call MakeDir, $(@D)) - $(TOOL_GENERATELSREQUIVMAPS) $< $@ + $(TOOL_GENERATELSREQUIVMAPS) $< $@ $(COPYRIGHT_YEAR) TARGETS += $(GENSRC_LSREQUIVMAPS) diff --git a/make/modules/jdk.localedata/Gensrc.gmk b/make/modules/jdk.localedata/Gensrc.gmk index ce746e89732..09f014e8607 100644 --- a/make/modules/jdk.localedata/Gensrc.gmk +++ b/make/modules/jdk.localedata/Gensrc.gmk @@ -46,6 +46,7 @@ $(CLDR_GEN_DONE): $(wildcard $(CLDR_DATA_DIR)/dtd/*.dtd) \ $(call ExecuteWithLog, $@, \ $(TOOL_CLDRCONVERTER) -base $(CLDR_DATA_DIR) \ -baselocales "en-US" \ + -year $(COPYRIGHT_YEAR) \ -o $(GENSRC_DIR)) $(TOUCH) $@ diff --git a/src/hotspot/cpu/aarch64/immediate_aarch64.cpp b/src/hotspot/cpu/aarch64/immediate_aarch64.cpp index 3e38b7cca04..916494605bc 100644 --- a/src/hotspot/cpu/aarch64/immediate_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/immediate_aarch64.cpp @@ -129,8 +129,17 @@ static inline uint32_t uimm(uint32_t val, int hi, int lo) uint64_t replicate(uint64_t bits, int nbits, int count) { + assert(count > 0, "must be"); + assert(nbits > 0, "must be"); + assert(count * nbits <= 64, "must be"); + + // Special case nbits == 64 since the shift below with that nbits value + // would result in undefined behavior. + if (nbits == 64) { + return bits; + } + uint64_t result = 0; - // nbits may be 64 in which case we want mask to be -1 uint64_t mask = ones(nbits); for (int i = 0; i < count ; i++) { result <<= nbits; diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp index 6f9b320bc48..43fdd6020ec 100644 --- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, 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 @@ -5103,18 +5103,6 @@ class StubGenerator: public StubCodeGenerator { return entry; } - // code for comparing 16 bytes of strings with same encoding - void compare_string_16_bytes_same(Label &DIFF1, Label &DIFF2) { - Register result = r0, str1 = r1, cnt1 = r2, str2 = r3, tmp1 = r10, tmp2 = r11; - __ ldr(rscratch1, Address(__ post(str1, 8))); - __ eor(rscratch2, tmp1, tmp2); - __ ldr(cnt1, Address(__ post(str2, 8))); - __ cbnz(rscratch2, DIFF1); - __ ldr(tmp1, Address(__ post(str1, 8))); - __ eor(rscratch2, rscratch1, cnt1); - __ ldr(tmp2, Address(__ post(str2, 8))); - __ cbnz(rscratch2, DIFF2); - } // code for comparing 16 characters of strings with Latin1 and Utf16 encoding void compare_string_16_x_LU(Register tmpL, Register tmpU, Label &DIFF1, @@ -5321,97 +5309,108 @@ class StubGenerator: public StubCodeGenerator { : "compare_long_string_same_encoding UU"); address entry = __ pc(); Register result = r0, str1 = r1, cnt1 = r2, str2 = r3, cnt2 = r4, - tmp1 = r10, tmp2 = r11; - Label SMALL_LOOP, LARGE_LOOP_PREFETCH, CHECK_LAST, DIFF2, TAIL, - LENGTH_DIFF, DIFF, LAST_CHECK_AND_LENGTH_DIFF, - DIFF_LAST_POSITION, DIFF_LAST_POSITION2; + tmp1 = r10, tmp2 = r11, tmp1h = rscratch1, tmp2h = rscratch2; + + Label LARGE_LOOP_PREFETCH, LOOP_COMPARE16, DIFF, LESS16, LESS8, CAL_DIFFERENCE, LENGTH_DIFF; + // exit from large loop when less than 64 bytes left to read or we're about // to prefetch memory behind array border int largeLoopExitCondition = MAX2(64, SoftwarePrefetchHintDistance)/(isLL ? 1 : 2); - // cnt1/cnt2 contains amount of characters to compare. cnt1 can be re-used - // update cnt2 counter with already loaded 8 bytes + + // before jumping to stub, pre-load 8 bytes already, so do comparison directly + __ eor(rscratch2, tmp1, tmp2); + __ cbnz(rscratch2, CAL_DIFFERENCE); + __ sub(cnt2, cnt2, wordSize/(isLL ? 1 : 2)); // update pointers, because of previous read __ add(str1, str1, wordSize); __ add(str2, str2, wordSize); if (SoftwarePrefetchHintDistance >= 0) { + __ align(OptoLoopAlignment); __ bind(LARGE_LOOP_PREFETCH); __ prfm(Address(str1, SoftwarePrefetchHintDistance)); __ prfm(Address(str2, SoftwarePrefetchHintDistance)); - compare_string_16_bytes_same(DIFF, DIFF2); - compare_string_16_bytes_same(DIFF, DIFF2); + + for (int i = 0; i < 4; i++) { + __ ldp(tmp1, tmp1h, Address(str1, i * 16)); + __ ldp(tmp2, tmp2h, Address(str2, i * 16)); + __ cmp(tmp1, tmp2); + __ ccmp(tmp1h, tmp2h, 0, Assembler::EQ); + __ br(Assembler::NE, DIFF); + } __ sub(cnt2, cnt2, isLL ? 64 : 32); - compare_string_16_bytes_same(DIFF, DIFF2); + __ add(str1, str1, 64); + __ add(str2, str2, 64); __ subs(rscratch2, cnt2, largeLoopExitCondition); - compare_string_16_bytes_same(DIFF, DIFF2); - __ br(__ GT, LARGE_LOOP_PREFETCH); - __ cbz(cnt2, LAST_CHECK_AND_LENGTH_DIFF); // no more chars left? + __ br(Assembler::GE, LARGE_LOOP_PREFETCH); + __ cbz(cnt2, LENGTH_DIFF); // no more chars left? } - // less than 16 bytes left? - __ subs(cnt2, cnt2, isLL ? 16 : 8); - __ br(__ LT, TAIL); + + __ subs(rscratch1, cnt2, isLL ? 16 : 8); + __ br(Assembler::LE, LESS16); __ align(OptoLoopAlignment); - __ bind(SMALL_LOOP); - compare_string_16_bytes_same(DIFF, DIFF2); - __ subs(cnt2, cnt2, isLL ? 16 : 8); - __ br(__ GE, SMALL_LOOP); - __ bind(TAIL); - __ adds(cnt2, cnt2, isLL ? 16 : 8); - __ br(__ EQ, LAST_CHECK_AND_LENGTH_DIFF); + __ bind(LOOP_COMPARE16); + __ ldp(tmp1, tmp1h, Address(__ post(str1, 16))); + __ ldp(tmp2, tmp2h, Address(__ post(str2, 16))); + __ cmp(tmp1, tmp2); + __ ccmp(tmp1h, tmp2h, 0, Assembler::EQ); + __ br(Assembler::NE, DIFF); + __ sub(cnt2, cnt2, isLL ? 16 : 8); + __ subs(rscratch2, cnt2, isLL ? 16 : 8); + __ br(Assembler::LT, LESS16); + + __ ldp(tmp1, tmp1h, Address(__ post(str1, 16))); + __ ldp(tmp2, tmp2h, Address(__ post(str2, 16))); + __ cmp(tmp1, tmp2); + __ ccmp(tmp1h, tmp2h, 0, Assembler::EQ); + __ br(Assembler::NE, DIFF); + __ sub(cnt2, cnt2, isLL ? 16 : 8); + __ subs(rscratch2, cnt2, isLL ? 16 : 8); + __ br(Assembler::GE, LOOP_COMPARE16); + __ cbz(cnt2, LENGTH_DIFF); + + __ bind(LESS16); + // each 8 compare __ subs(cnt2, cnt2, isLL ? 8 : 4); - __ br(__ LE, CHECK_LAST); - __ eor(rscratch2, tmp1, tmp2); - __ cbnz(rscratch2, DIFF); + __ br(Assembler::LE, LESS8); __ ldr(tmp1, Address(__ post(str1, 8))); __ ldr(tmp2, Address(__ post(str2, 8))); + __ eor(rscratch2, tmp1, tmp2); + __ cbnz(rscratch2, CAL_DIFFERENCE); __ sub(cnt2, cnt2, isLL ? 8 : 4); - __ bind(CHECK_LAST); + + __ bind(LESS8); // directly load last 8 bytes if (!isLL) { - __ add(cnt2, cnt2, cnt2); // now in bytes + __ add(cnt2, cnt2, cnt2); } + __ ldr(tmp1, Address(str1, cnt2)); + __ ldr(tmp2, Address(str2, cnt2)); __ eor(rscratch2, tmp1, tmp2); - __ cbnz(rscratch2, DIFF); - __ ldr(rscratch1, Address(str1, cnt2)); - __ ldr(cnt1, Address(str2, cnt2)); - __ eor(rscratch2, rscratch1, cnt1); __ cbz(rscratch2, LENGTH_DIFF); - // Find the first different characters in the longwords and - // compute their difference. - __ bind(DIFF2); - __ rev(rscratch2, rscratch2); - __ clz(rscratch2, rscratch2); - __ andr(rscratch2, rscratch2, isLL ? -8 : -16); - __ lsrv(rscratch1, rscratch1, rscratch2); - if (isLL) { - __ lsrv(cnt1, cnt1, rscratch2); - __ uxtbw(rscratch1, rscratch1); - __ uxtbw(cnt1, cnt1); - } else { - __ lsrv(cnt1, cnt1, rscratch2); - __ uxthw(rscratch1, rscratch1); - __ uxthw(cnt1, cnt1); - } - __ subw(result, rscratch1, cnt1); - __ b(LENGTH_DIFF); + __ b(CAL_DIFFERENCE); + __ bind(DIFF); + __ cmp(tmp1, tmp2); + __ csel(tmp1, tmp1, tmp1h, Assembler::NE); + __ csel(tmp2, tmp2, tmp2h, Assembler::NE); + // reuse rscratch2 register for the result of eor instruction + __ eor(rscratch2, tmp1, tmp2); + + __ bind(CAL_DIFFERENCE); __ rev(rscratch2, rscratch2); __ clz(rscratch2, rscratch2); __ andr(rscratch2, rscratch2, isLL ? -8 : -16); __ lsrv(tmp1, tmp1, rscratch2); + __ lsrv(tmp2, tmp2, rscratch2); if (isLL) { - __ lsrv(tmp2, tmp2, rscratch2); __ uxtbw(tmp1, tmp1); __ uxtbw(tmp2, tmp2); } else { - __ lsrv(tmp2, tmp2, rscratch2); __ uxthw(tmp1, tmp1); __ uxthw(tmp2, tmp2); } __ subw(result, tmp1, tmp2); - __ b(LENGTH_DIFF); - __ bind(LAST_CHECK_AND_LENGTH_DIFF); - __ eor(rscratch2, tmp1, tmp2); - __ cbnz(rscratch2, DIFF); + __ bind(LENGTH_DIFF); __ ret(lr); return entry; diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp index 918ad1d7c89..32eb73b558b 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2021 SAP SE. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022 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 @@ -2942,16 +2942,17 @@ void MacroAssembler::compiler_fast_lock_object(ConditionRegister flag, Register // Store a non-null value into the box. std(box, BasicLock::displaced_header_offset_in_bytes(), box); + beq(flag, cont); -# ifdef ASSERT + // Check for recursive locking. + cmpd(flag, current_header, R16_thread); bne(flag, cont); - // We have acquired the monitor, check some invariants. - addi(/*monitor=*/temp, temp, -ObjectMonitor::owner_offset_in_bytes()); - // Invariant 1: _recursions should be 0. - //assert(ObjectMonitor::recursions_size_in_bytes() == 8, "unexpected size"); - asm_assert_mem8_is_zero(ObjectMonitor::recursions_offset_in_bytes(), temp, - "monitor->_recursions should be 0"); -# endif + + // Current thread already owns the lock. Just increment recursions. + Register recursions = displaced_header; + ld(recursions, ObjectMonitor::recursions_offset_in_bytes()-ObjectMonitor::owner_offset_in_bytes(), temp); + addi(recursions, recursions, 1); + std(recursions, ObjectMonitor::recursions_offset_in_bytes()-ObjectMonitor::owner_offset_in_bytes(), temp); #if INCLUDE_RTM_OPT } // use_rtm() @@ -2967,8 +2968,7 @@ void MacroAssembler::compiler_fast_unlock_object(ConditionRegister flag, Registe bool try_bias, bool use_rtm) { assert_different_registers(oop, box, temp, displaced_header, current_header); assert(flag != CCR0, "bad condition register"); - Label cont; - Label object_has_monitor; + Label cont, object_has_monitor, notRecursive; if (try_bias) { biased_locking_exit(flag, oop, current_header, cont); @@ -3039,11 +3039,16 @@ void MacroAssembler::compiler_fast_unlock_object(ConditionRegister flag, Registe #endif ld(displaced_header, ObjectMonitor::recursions_offset_in_bytes(), current_header); - xorr(temp, R16_thread, temp); // Will be 0 if we are the owner. - orr(temp, temp, displaced_header); // Will be 0 if there are 0 recursions. - cmpdi(flag, temp, 0); + + cmpd(flag, temp, R16_thread); bne(flag, cont); + addic_(displaced_header, displaced_header, -1); + blt(CCR0, notRecursive); // Not recursive if negative after decrement. + std(displaced_header, ObjectMonitor::recursions_offset_in_bytes(), current_header); + b(cont); // flag is already EQ here. + + bind(notRecursive); ld(temp, ObjectMonitor::EntryList_offset_in_bytes(), current_header); ld(displaced_header, ObjectMonitor::cxq_offset_in_bytes(), current_header); orr(temp, temp, displaced_header); // Will be 0 if both are 0. diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index 70b4cd84672..b69ef118666 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -7328,6 +7328,9 @@ void Assembler::pxor(XMMRegister dst, XMMRegister src) { void Assembler::vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { assert(UseAVX > 0, "requires some form of AVX"); + assert(vector_len == AVX_128bit ? VM_Version::supports_avx() : + vector_len == AVX_256bit ? VM_Version::supports_avx2() : + vector_len == AVX_512bit ? VM_Version::supports_evex() : 0, ""); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes); emit_int16((unsigned char)0xEF, (0xC0 | encode)); @@ -7335,6 +7338,9 @@ void Assembler::vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, int vec void Assembler::vpxor(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { assert(UseAVX > 0, "requires some form of AVX"); + assert(vector_len == AVX_128bit ? VM_Version::supports_avx() : + vector_len == AVX_256bit ? VM_Version::supports_avx2() : + vector_len == AVX_512bit ? VM_Version::supports_evex() : 0, ""); InstructionMark im(this); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_32bit); @@ -7947,12 +7953,12 @@ void Assembler::vpbroadcastq(XMMRegister dst, Address src, int vector_len) { void Assembler::evbroadcasti32x4(XMMRegister dst, Address src, int vector_len) { assert(vector_len != Assembler::AVX_128bit, ""); - assert(VM_Version::supports_avx512dq(), ""); + assert(VM_Version::supports_evex(), ""); assert(dst != xnoreg, "sanity"); InstructionMark im(this); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); attributes.set_rex_vex_w_reverted(); - attributes.set_address_attributes(/* tuple_type */ EVEX_T2, /* input_size_in_bits */ EVEX_64bit); + attributes.set_address_attributes(/* tuple_type */ EVEX_T4, /* input_size_in_bits */ EVEX_32bit); // swap src<->dst for encoding vex_prefix(src, 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); emit_int8(0x5A); diff --git a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp index a929908d003..6fc8833f7f1 100644 --- a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp @@ -452,7 +452,7 @@ class ZSaveLiveRegisters { void opmask_register_save(KRegister reg) { _spill_offset -= 8; - __ kmovql(Address(rsp, _spill_offset), reg); + __ kmov(Address(rsp, _spill_offset), reg); } void gp_register_restore(Register reg) { @@ -461,7 +461,7 @@ class ZSaveLiveRegisters { } void opmask_register_restore(KRegister reg) { - __ kmovql(reg, Address(rsp, _spill_offset)); + __ kmov(reg, Address(rsp, _spill_offset)); _spill_offset += 8; } diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index b7bbe49f754..5fbfb95bedc 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -1425,8 +1425,14 @@ class MacroAssembler: public Assembler { void vpxor(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len, Register scratch_reg = rscratch1); // Simple version for AVX2 256bit vectors - void vpxor(XMMRegister dst, XMMRegister src) { Assembler::vpxor(dst, dst, src, true); } - void vpxor(XMMRegister dst, Address src) { Assembler::vpxor(dst, dst, src, true); } + void vpxor(XMMRegister dst, XMMRegister src) { + assert(UseAVX >= 2, "Should be at least AVX2"); + Assembler::vpxor(dst, dst, src, AVX_256bit); + } + void vpxor(XMMRegister dst, Address src) { + assert(UseAVX >= 2, "Should be at least AVX2"); + Assembler::vpxor(dst, dst, src, AVX_256bit); + } void vpermd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { Assembler::vpermd(dst, nds, src, vector_len); } void vpermd(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len, Register scratch_reg); diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index 6c081c06d12..14f5c0a9f6f 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -148,12 +148,11 @@ class VM_Version : public Abstract_VM_Version { uint32_t LahfSahf : 1, CmpLegacy : 1, : 3, - lzcnt_intel : 1, lzcnt : 1, sse4a : 1, misalignsse : 1, prefetchw : 1, - : 22; + : 23; } bits; }; @@ -637,10 +636,10 @@ enum Extended_Family { // Intel features. if (is_intel()) { - if (_cpuid_info.ext_cpuid1_ecx.bits.lzcnt_intel != 0) + if (_cpuid_info.ext_cpuid1_ecx.bits.lzcnt != 0) { result |= CPU_LZCNT; - // for Intel, ecx.bits.misalignsse bit (bit 8) indicates support for prefetchw - if (_cpuid_info.ext_cpuid1_ecx.bits.misalignsse != 0) { + } + if (_cpuid_info.ext_cpuid1_ecx.bits.prefetchw != 0) { result |= CPU_3DNOW_PREFETCH; } if (_cpuid_info.sef_cpuid7_ebx.bits.clwb != 0) { @@ -650,10 +649,10 @@ enum Extended_Family { // ZX features. if (is_zx()) { - if (_cpuid_info.ext_cpuid1_ecx.bits.lzcnt_intel != 0) + if (_cpuid_info.ext_cpuid1_ecx.bits.lzcnt != 0) { result |= CPU_LZCNT; - // for ZX, ecx.bits.misalignsse bit (bit 8) indicates support for prefetchw - if (_cpuid_info.ext_cpuid1_ecx.bits.misalignsse != 0) { + } + if (_cpuid_info.ext_cpuid1_ecx.bits.prefetchw != 0) { result |= CPU_3DNOW_PREFETCH; } } diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index b6841c1bdd1..dd7894dbaf8 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2011, 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 @@ -1805,17 +1805,9 @@ const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType } break; case Op_VectorCastB2X: - if (size_in_bits == 256 && UseAVX < 2) { - return false; // Implementation limitation - } - break; case Op_VectorCastS2X: - if (is_integral_type(bt) && size_in_bits == 256 && UseAVX < 2) { - return false; - } - break; case Op_VectorCastI2X: - if (is_integral_type(bt) && size_in_bits == 256 && UseAVX < 2) { + if (bt != T_DOUBLE && size_in_bits == 256 && UseAVX < 2) { return false; } break; @@ -4333,7 +4325,8 @@ instruct insertF(vec dst, regF val, immU8 idx) %{ assert(vector_element_basic_type(this) == T_FLOAT, "sanity"); assert($idx$$constant < (int)vector_length(this), "out of bounds"); - __ insertps($dst$$XMMRegister, $val$$XMMRegister, $idx$$constant); + uint x_idx = $idx$$constant & right_n_bits(2); + __ insertps($dst$$XMMRegister, $val$$XMMRegister, x_idx << 4); %} ins_pipe( pipe_slow ); %} @@ -4353,13 +4346,13 @@ instruct vinsertF(vec dst, vec src, regF val, immU8 idx, vec vtmp) %{ uint y_idx = ($idx$$constant >> 2) & 1; int vlen_enc = Assembler::AVX_256bit; __ vextracti128($vtmp$$XMMRegister, $src$$XMMRegister, y_idx); - __ vinsertps($vtmp$$XMMRegister, $vtmp$$XMMRegister, $val$$XMMRegister, x_idx); + __ vinsertps($vtmp$$XMMRegister, $vtmp$$XMMRegister, $val$$XMMRegister, x_idx << 4); __ vinserti128($dst$$XMMRegister, $src$$XMMRegister, $vtmp$$XMMRegister, y_idx); } else { assert(vlen == 16, "sanity"); uint y_idx = ($idx$$constant >> 2) & 3; __ vextracti32x4($vtmp$$XMMRegister, $src$$XMMRegister, y_idx); - __ vinsertps($vtmp$$XMMRegister, $vtmp$$XMMRegister, $val$$XMMRegister, x_idx); + __ vinsertps($vtmp$$XMMRegister, $vtmp$$XMMRegister, $val$$XMMRegister, x_idx << 4); __ vinserti32x4($dst$$XMMRegister, $src$$XMMRegister, $vtmp$$XMMRegister, y_idx); } %} @@ -6605,11 +6598,12 @@ instruct vcastBtoX(vec dst, vec src) %{ case T_LONG: __ vpmovsxbq($dst$$XMMRegister, $src$$XMMRegister, vlen_enc); break; - case T_DOUBLE: - __ vpmovsxbd($dst$$XMMRegister, $src$$XMMRegister, vlen_enc); + case T_DOUBLE: { + int mid_vlen_enc = (vlen_enc == Assembler::AVX_512bit) ? Assembler::AVX_256bit : Assembler::AVX_128bit; + __ vpmovsxbd($dst$$XMMRegister, $src$$XMMRegister, mid_vlen_enc); __ vcvtdq2pd($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); break; - + } default: assert(false, "%s", type2name(to_elem_bt)); } %} @@ -6676,10 +6670,12 @@ instruct vcastStoX_evex(vec dst, vec src) %{ case T_LONG: __ vpmovsxwq($dst$$XMMRegister, $src$$XMMRegister, vlen_enc); break; - case T_DOUBLE: - __ vpmovsxwd($dst$$XMMRegister, $src$$XMMRegister, vlen_enc); + case T_DOUBLE: { + int mid_vlen_enc = (vlen_enc == Assembler::AVX_512bit) ? Assembler::AVX_256bit : Assembler::AVX_128bit; + __ vpmovsxwd($dst$$XMMRegister, $src$$XMMRegister, mid_vlen_enc); __ vcvtdq2pd($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); break; + } default: ShouldNotReachHere(); } diff --git a/src/hotspot/cpu/x86/x86_32.ad b/src/hotspot/cpu/x86/x86_32.ad index 0ebe4fa09c2..83bc7723c29 100644 --- a/src/hotspot/cpu/x86/x86_32.ad +++ b/src/hotspot/cpu/x86/x86_32.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 1997, 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 @@ -7810,9 +7810,9 @@ instruct divI_eReg(eAXRegI rax, eDXRegI rdx, eCXRegI div, eFlagsReg cr) %{ %} // Divide Register Long -instruct divL_eReg( eADXRegL dst, eRegL src1, eRegL src2, eFlagsReg cr, eCXRegI cx, eBXRegI bx ) %{ +instruct divL_eReg(eADXRegL dst, eRegL src1, eRegL src2) %{ match(Set dst (DivL src1 src2)); - effect( KILL cr, KILL cx, KILL bx ); + effect(CALL); ins_cost(10000); format %{ "PUSH $src1.hi\n\t" "PUSH $src1.lo\n\t" @@ -7858,9 +7858,9 @@ instruct modI_eReg(eDXRegI rdx, eAXRegI rax, eCXRegI div, eFlagsReg cr) %{ %} // Remainder Register Long -instruct modL_eReg( eADXRegL dst, eRegL src1, eRegL src2, eFlagsReg cr, eCXRegI cx, eBXRegI bx ) %{ +instruct modL_eReg(eADXRegL dst, eRegL src1, eRegL src2) %{ match(Set dst (ModL src1 src2)); - effect( KILL cr, KILL cx, KILL bx ); + effect(CALL); ins_cost(10000); format %{ "PUSH $src1.hi\n\t" "PUSH $src1.lo\n\t" diff --git a/src/hotspot/cpu/zero/zeroInterpreter_zero.cpp b/src/hotspot/cpu/zero/zeroInterpreter_zero.cpp index f2e8dc2fe23..453480c6565 100644 --- a/src/hotspot/cpu/zero/zeroInterpreter_zero.cpp +++ b/src/hotspot/cpu/zero/zeroInterpreter_zero.cpp @@ -611,6 +611,8 @@ int ZeroInterpreter::getter_entry(Method* method, intptr_t UNUSED, TRAPS) { stack->alloc(wordSize); topOfStack = stack->sp(); break; + default: + ; } // Read the field to stack(0) diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 099d0b8f65b..9220344b5c3 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -1,5 +1,6 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022 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 @@ -2171,6 +2172,34 @@ bool os::Linux::query_process_memory_info(os::Linux::meminfo_t* info) { return false; } +#ifdef __GLIBC__ +// For Glibc, print a one-liner with the malloc tunables. +// Most important and popular is MALLOC_ARENA_MAX, but we are +// thorough and print them all. +static void print_glibc_malloc_tunables(outputStream* st) { + static const char* var[] = { + // the new variant + "GLIBC_TUNABLES", + // legacy variants + "MALLOC_CHECK_", "MALLOC_TOP_PAD_", "MALLOC_PERTURB_", + "MALLOC_MMAP_THRESHOLD_", "MALLOC_TRIM_THRESHOLD_", + "MALLOC_MMAP_MAX_", "MALLOC_ARENA_TEST", "MALLOC_ARENA_MAX", + NULL}; + st->print("glibc malloc tunables: "); + bool printed = false; + for (int i = 0; var[i] != NULL; i ++) { + const char* const val = ::getenv(var[i]); + if (val != NULL) { + st->print("%s%s=%s", (printed ? ", " : ""), var[i], val); + printed = true; + } + } + if (!printed) { + st->print("(default)"); + } +} +#endif // __GLIBC__ + void os::Linux::print_process_memory_info(outputStream* st) { st->print_cr("Process Memory:"); @@ -2193,8 +2222,9 @@ void os::Linux::print_process_memory_info(outputStream* st) { st->print_cr("Could not open /proc/self/status to get process memory related information"); } - // Print glibc outstanding allocations. - // (note: there is no implementation of mallinfo for muslc) + // glibc only: + // - Print outstanding allocations using mallinfo + // - Print glibc tunables #ifdef __GLIBC__ size_t total_allocated = 0; bool might_have_wrapped = false; @@ -2202,9 +2232,10 @@ void os::Linux::print_process_memory_info(outputStream* st) { struct glibc_mallinfo2 mi = _mallinfo2(); total_allocated = mi.uordblks; } else if (_mallinfo != NULL) { - // mallinfo is an old API. Member names mean next to nothing and, beyond that, are int. - // So values may have wrapped around. Still useful enough to see how much glibc thinks - // we allocated. + // mallinfo is an old API. Member names mean next to nothing and, beyond that, are 32-bit signed. + // So for larger footprints the values may have wrapped around. We try to detect this here: if the + // process whole resident set size is smaller than 4G, malloc footprint has to be less than that + // and the numbers are reliable. struct glibc_mallinfo mi = _mallinfo(); total_allocated = (size_t)(unsigned)mi.uordblks; // Since mallinfo members are int, glibc values may have wrapped. Warn about this. @@ -2215,8 +2246,10 @@ void os::Linux::print_process_memory_info(outputStream* st) { total_allocated / K, might_have_wrapped ? " (may have wrapped)" : ""); } -#endif // __GLIBC__ - + // Tunables + print_glibc_malloc_tunables(st); + st->cr(); +#endif } bool os::Linux::print_ld_preload_file(outputStream* st) { @@ -2253,7 +2286,11 @@ bool os::Linux::print_container_info(outputStream* st) { int i = OSContainer::active_processor_count(); st->print("active_processor_count: "); if (i > 0) { - st->print_cr("%d", i); + if (ActiveProcessorCount > 0) { + st->print_cr("%d, but overridden by -XX:ActiveProcessorCount %d", i, ActiveProcessorCount); + } else { + st->print_cr("%d", i); + } } else { st->print_cr("not supported"); } @@ -5468,21 +5505,20 @@ bool os::supports_map_sync() { } void os::print_memory_mappings(char* addr, size_t bytes, outputStream* st) { + // Note: all ranges are "[..)" unsigned long long start = (unsigned long long)addr; unsigned long long end = start + bytes; FILE* f = ::fopen("/proc/self/maps", "r"); int num_found = 0; if (f != NULL) { - st->print("Range [%llx-%llx) contains: ", start, end); + st->print_cr("Range [%llx-%llx) contains: ", start, end); char line[512]; while(fgets(line, sizeof(line), f) == line) { - unsigned long long a1 = 0; - unsigned long long a2 = 0; - if (::sscanf(line, "%llx-%llx", &a1, &a2) == 2) { + unsigned long long segment_start = 0; + unsigned long long segment_end = 0; + if (::sscanf(line, "%llx-%llx", &segment_start, &segment_end) == 2) { // Lets print out every range which touches ours. - if ((a1 >= start && a1 < end) || // left leg in - (a2 >= start && a2 < end) || // right leg in - (a1 < start && a2 >= end)) { // superimposition + if (segment_start < end && segment_end > start) { num_found ++; st->print("%s", line); // line includes \n } @@ -5490,7 +5526,7 @@ void os::print_memory_mappings(char* addr, size_t bytes, outputStream* st) { } ::fclose(f); if (num_found == 0) { - st->print("nothing."); + st->print_cr("nothing."); } st->cr(); } diff --git a/src/hotspot/share/adlc/arena.cpp b/src/hotspot/share/adlc/adlArena.cpp similarity index 66% rename from src/hotspot/share/adlc/arena.cpp rename to src/hotspot/share/adlc/adlArena.cpp index 60a546e7961..7c6e9419d4f 100644 --- a/src/hotspot/share/adlc/arena.cpp +++ b/src/hotspot/share/adlc/adlArena.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -24,7 +24,7 @@ #include "adlc.hpp" -void* AllocateHeap(size_t size) { +void* AdlAllocateHeap(size_t size) { unsigned char* ptr = (unsigned char*) malloc(size); if (ptr == NULL && size != 0) { fprintf(stderr, "Error: Out of memory in ADLC\n"); // logging can cause crash! @@ -34,7 +34,7 @@ void* AllocateHeap(size_t size) { return ptr; } -void* ReAllocateHeap(void* old_ptr, size_t size) { +void* AdlReAllocateHeap(void* old_ptr, size_t size) { unsigned char* ptr = (unsigned char*) realloc(old_ptr, size); if (ptr == NULL && size != 0) { fprintf(stderr, "Error: Out of memory in ADLC\n"); // logging can cause crash! @@ -44,24 +44,24 @@ void* ReAllocateHeap(void* old_ptr, size_t size) { return ptr; } -void* Chunk::operator new(size_t requested_size, size_t length) throw() { - return CHeapObj::operator new(requested_size + length); +void* AdlChunk::operator new(size_t requested_size, size_t length) throw() { + return AdlCHeapObj::operator new(requested_size + length); } -void Chunk::operator delete(void* p, size_t length) { - CHeapObj::operator delete(p); +void AdlChunk::operator delete(void* p, size_t length) { + AdlCHeapObj::operator delete(p); } -Chunk::Chunk(size_t length) { +AdlChunk::AdlChunk(size_t length) { _next = NULL; // Chain on the linked list _len = length; // Save actual size } //------------------------------chop------------------------------------------- -void Chunk::chop() { - Chunk *k = this; +void AdlChunk::chop() { + AdlChunk *k = this; while( k ) { - Chunk *tmp = k->_next; + AdlChunk *tmp = k->_next; // clear out this chunk (to detect allocation bugs) memset(k, 0xBE, k->_len); free(k); // Free chunk (was malloc'd) @@ -69,52 +69,52 @@ void Chunk::chop() { } } -void Chunk::next_chop() { +void AdlChunk::next_chop() { _next->chop(); _next = NULL; } -//------------------------------Arena------------------------------------------ -Arena::Arena( size_t init_size ) { +//------------------------------AdlArena------------------------------------------ +AdlArena::AdlArena( size_t init_size ) { init_size = (init_size+3) & ~3; - _first = _chunk = new (init_size) Chunk(init_size); + _first = _chunk = new (init_size) AdlChunk(init_size); _hwm = _chunk->bottom(); // Save the cached hwm, max _max = _chunk->top(); set_size_in_bytes(init_size); } -Arena::Arena() { - _first = _chunk = new (Chunk::init_size) Chunk(Chunk::init_size); +AdlArena::AdlArena() { + _first = _chunk = new (AdlChunk::init_size) AdlChunk(AdlChunk::init_size); _hwm = _chunk->bottom(); // Save the cached hwm, max _max = _chunk->top(); - set_size_in_bytes(Chunk::init_size); + set_size_in_bytes(AdlChunk::init_size); } -Arena::Arena( Arena *a ) +AdlArena::AdlArena( AdlArena *a ) : _chunk(a->_chunk), _hwm(a->_hwm), _max(a->_max), _first(a->_first) { set_size_in_bytes(a->size_in_bytes()); } //------------------------------used------------------------------------------- -// Total of all Chunks in arena -size_t Arena::used() const { - size_t sum = _chunk->_len - (_max-_hwm); // Size leftover in this Chunk - Chunk *k = _first; - while( k != _chunk) { // Whilst have Chunks in a row - sum += k->_len; // Total size of this Chunk - k = k->_next; // Bump along to next Chunk +// Total of all AdlChunks in arena +size_t AdlArena::used() const { + size_t sum = _chunk->_len - (_max-_hwm); // Size leftover in this AdlChunk + AdlChunk *k = _first; + while( k != _chunk) { // Whilst have AdlChunks in a row + sum += k->_len; // Total size of this AdlChunk + k = k->_next; // Bump along to next AdlChunk } return sum; // Return total consumed space. } //------------------------------grow------------------------------------------- -// Grow a new Chunk -void* Arena::grow( size_t x ) { +// Grow a new AdlChunk +void* AdlArena::grow( size_t x ) { // Get minimal required size. Either real big, or even bigger for giant objs - size_t len = max(x, Chunk::size); + size_t len = max(x, AdlChunk::size); - Chunk *k = _chunk; // Get filled-up chunk address - _chunk = new (len) Chunk(len); + AdlChunk *k = _chunk; // Get filled-up chunk address + _chunk = new (len) AdlChunk(len); if( k ) k->_next = _chunk; // Append new chunk to end of linked list else _first = _chunk; @@ -127,8 +127,8 @@ void* Arena::grow( size_t x ) { } //------------------------------calloc----------------------------------------- -// Allocate zeroed storage in Arena -void *Arena::Acalloc( size_t items, size_t x ) { +// Allocate zeroed storage in AdlArena +void *AdlArena::Acalloc( size_t items, size_t x ) { size_t z = items*x; // Total size needed void *ptr = Amalloc(z); // Get space memset( ptr, 0, z ); // Zap space @@ -136,8 +136,8 @@ void *Arena::Acalloc( size_t items, size_t x ) { } //------------------------------realloc---------------------------------------- -// Reallocate storage in Arena. -void *Arena::Arealloc( void *old_ptr, size_t old_size, size_t new_size ) { +// Reallocate storage in AdlArena. +void *AdlArena::Arealloc( void *old_ptr, size_t old_size, size_t new_size ) { char *c_old = (char*)old_ptr; // Handy name // Stupid fast special case if( new_size <= old_size ) { // Shrink in-place @@ -161,32 +161,32 @@ void *Arena::Arealloc( void *old_ptr, size_t old_size, size_t new_size ) { } //------------------------------reset------------------------------------------ -// Reset this Arena to empty, and return this Arenas guts in a new Arena. -Arena *Arena::reset(void) { - Arena *a = new Arena(this); // New empty arena +// Reset this AdlArena to empty, and return this AdlArenas guts in a new AdlArena. +AdlArena *AdlArena::reset(void) { + AdlArena *a = new AdlArena(this); // New empty arena _first = _chunk = NULL; // Normal, new-arena initialization _hwm = _max = NULL; - return a; // Return Arena with guts + return a; // Return AdlArena with guts } //------------------------------contains--------------------------------------- -// Determine if pointer belongs to this Arena or not. -bool Arena::contains( const void *ptr ) const { +// Determine if pointer belongs to this AdlArena or not. +bool AdlArena::contains( const void *ptr ) const { if( (void*)_chunk->bottom() <= ptr && ptr < (void*)_hwm ) return true; // Check for in this chunk - for( Chunk *c = _first; c; c = c->_next ) + for( AdlChunk *c = _first; c; c = c->_next ) if( (void*)c->bottom() <= ptr && ptr < (void*)c->top()) - return true; // Check for every chunk in Arena - return false; // Not in any Chunk, so not in Arena + return true; // Check for every chunk in AdlArena + return false; // Not in any AdlChunk, so not in AdlArena } //----------------------------------------------------------------------------- // CHeapObj -void* CHeapObj::operator new(size_t size) throw() { - return (void *) AllocateHeap(size); +void* AdlCHeapObj::operator new(size_t size) throw() { + return (void *) AdlAllocateHeap(size); } -void CHeapObj::operator delete(void* p){ +void AdlCHeapObj::operator delete(void* p){ free(p); } diff --git a/src/hotspot/share/adlc/arena.hpp b/src/hotspot/share/adlc/adlArena.hpp similarity index 74% rename from src/hotspot/share/adlc/arena.hpp rename to src/hotspot/share/adlc/adlArena.hpp index d0dac9d45ca..9f693ba15d6 100644 --- a/src/hotspot/share/adlc/arena.hpp +++ b/src/hotspot/share/adlc/adlArena.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -22,11 +22,11 @@ * */ -#ifndef SHARE_ADLC_ARENA_HPP -#define SHARE_ADLC_ARENA_HPP +#ifndef SHARE_ADLC_ADLARENA_HPP +#define SHARE_ADLC_ADLARENA_HPP -void* AllocateHeap(size_t size); -void* ReAllocateHeap(void* old_ptr, size_t size); +void* AdlAllocateHeap(size_t size); +void* AdlReAllocateHeap(void* old_ptr, size_t size); // All classes in adlc may be derived // from one of the following allocation classes: @@ -35,10 +35,10 @@ void* ReAllocateHeap(void* old_ptr, size_t size); // - CHeapObj // // For classes used as name spaces. -// - AllStatic +// - AdlAllStatic // -class CHeapObj { +class AdlCHeapObj { public: void* operator new(size_t size) throw(); void operator delete(void* p); @@ -47,16 +47,16 @@ class CHeapObj { // Base class for classes that constitute name spaces. -class AllStatic { +class AdlAllStatic { public: void* operator new(size_t size) throw(); void operator delete(void* p); }; -//------------------------------Chunk------------------------------------------ +//------------------------------AdlChunk------------------------------------------ // Linked list of raw memory chunks -class Chunk: public CHeapObj { +class AdlChunk: public AdlCHeapObj { private: // This ordinary operator delete is needed even though not used, so the // below two-argument operator delete will be treated as a placement @@ -65,41 +65,41 @@ class Chunk: public CHeapObj { public: void* operator new(size_t size, size_t length) throw(); void operator delete(void* p, size_t length); - Chunk(size_t length); + AdlChunk(size_t length); enum { init_size = 1*1024, // Size of first chunk - size = 32*1024 // Default size of an Arena chunk (following the first) + size = 32*1024 // Default size of an AdlArena chunk (following the first) }; - Chunk* _next; // Next Chunk in list - size_t _len; // Size of this Chunk + AdlChunk* _next; // Next AdlChunk in list + size_t _len; // Size of this AdlChunk void chop(); // Chop this chunk void next_chop(); // Chop next chunk // Boundaries of data area (possibly unused) - char* bottom() const { return ((char*) this) + sizeof(Chunk); } + char* bottom() const { return ((char*) this) + sizeof(AdlChunk); } char* top() const { return bottom() + _len; } }; -//------------------------------Arena------------------------------------------ +//------------------------------AdlArena------------------------------------------ // Fast allocation of memory -class Arena: public CHeapObj { +class AdlArena: public AdlCHeapObj { protected: friend class ResourceMark; friend class HandleMark; friend class NoHandleMark; - Chunk *_first; // First chunk - Chunk *_chunk; // current chunk + AdlChunk *_first; // First chunk + AdlChunk *_chunk; // current chunk char *_hwm, *_max; // High water mark and max in current chunk - void* grow(size_t x); // Get a new Chunk of at least size x + void* grow(size_t x); // Get a new AdlChunk of at least size x size_t _size_in_bytes; // Size of arena (used for memory usage tracing) public: - Arena(); - Arena(size_t init_size); - Arena(Arena *old); - ~Arena() { _first->chop(); } + AdlArena(); + AdlArena(size_t init_size); + AdlArena(AdlArena *old); + ~AdlArena() { _first->chop(); } char* hwm() const { return _hwm; } // Fast allocate in the arena. Common case is: pointer test + increment. @@ -138,10 +138,10 @@ class Arena: public CHeapObj { void *Acalloc( size_t items, size_t x ); void *Arealloc( void *old_ptr, size_t old_size, size_t new_size ); - // Reset this Arena to empty, and return this Arenas guts in a new Arena. - Arena *reset(void); + // Reset this AdlArena to empty, and return this AdlArenas guts in a new AdlArena. + AdlArena *reset(void); - // Determine if pointer belongs to this Arena or not. + // Determine if pointer belongs to this AdlArena or not. bool contains( const void *ptr ) const; // Total of all chunks in use (not thread-safe) @@ -152,4 +152,4 @@ class Arena: public CHeapObj { void set_size_in_bytes(size_t size) { _size_in_bytes = size; } }; -#endif // SHARE_ADLC_ARENA_HPP +#endif // SHARE_ADLC_ADLARENA_HPP diff --git a/src/hotspot/share/adlc/adlc.hpp b/src/hotspot/share/adlc/adlc.hpp index 297d5cb0133..19567f05d40 100644 --- a/src/hotspot/share/adlc/adlc.hpp +++ b/src/hotspot/share/adlc/adlc.hpp @@ -93,7 +93,7 @@ typedef unsigned int uintptr_t; #define max(a, b) (((a)>(b)) ? (a) : (b)) // ADLC components -#include "arena.hpp" +#include "adlArena.hpp" #include "opto/adlcVMDeps.hpp" #include "filebuff.hpp" #include "dict2.hpp" diff --git a/src/hotspot/share/adlc/adlparse.cpp b/src/hotspot/share/adlc/adlparse.cpp index ecb722c56b2..283713bb1f8 100644 --- a/src/hotspot/share/adlc/adlparse.cpp +++ b/src/hotspot/share/adlc/adlparse.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -211,7 +211,7 @@ void ADLParser::instr_parse(void) { return; } assert(match_rules_cnt < 100," too many match rule clones"); - char* buf = (char*) AllocateHeap(strlen(instr->_ident) + 4); + char* buf = (char*) AdlAllocateHeap(strlen(instr->_ident) + 4); sprintf(buf, "%s_%d", instr->_ident, match_rules_cnt++); rule->_result = buf; // Check for commutative operations with tree operands. @@ -2805,7 +2805,7 @@ void ADLParser::ins_encode_parse_block(InstructForm& inst) { // Create a new encoding name based on the name of the instruction // definition, which should be unique. const char* prefix = "__ins_encode_"; - char* ec_name = (char*) AllocateHeap(strlen(inst._ident) + strlen(prefix) + 1); + char* ec_name = (char*) AdlAllocateHeap(strlen(inst._ident) + strlen(prefix) + 1); sprintf(ec_name, "%s%s", prefix, inst._ident); assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist"); @@ -3276,7 +3276,7 @@ void ADLParser::constant_parse(InstructForm& inst) { // Create a new encoding name based on the name of the instruction // definition, which should be unique. const char* prefix = "__constant_"; - char* ec_name = (char*) AllocateHeap(strlen(inst._ident) + strlen(prefix) + 1); + char* ec_name = (char*) AdlAllocateHeap(strlen(inst._ident) + strlen(prefix) + 1); sprintf(ec_name, "%s%s", prefix, inst._ident); assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist"); @@ -4409,7 +4409,7 @@ char* ADLParser::find_cpp_block(const char* description) { if (_AD._adlocation_debug) { char* location = get_line_string(line); char* end_loc = end_line_marker(); - char* result = (char *)AllocateHeap(strlen(location) + strlen(cppBlock) + strlen(end_loc) + 1); + char* result = (char *)AdlAllocateHeap(strlen(location) + strlen(cppBlock) + strlen(end_loc) + 1); strcpy(result, location); strcat(result, cppBlock); strcat(result, end_loc); @@ -4498,7 +4498,7 @@ char *ADLParser::get_paren_expr(const char *description, bool include_location) // Prepend location descriptor, for debugging. char* location = get_line_string(line); char* end_loc = end_line_marker(); - char* result = (char *)AllocateHeap(strlen(location) + strlen(token2) + strlen(end_loc) + 1); + char* result = (char *)AdlAllocateHeap(strlen(location) + strlen(token2) + strlen(end_loc) + 1); strcpy(result, location); strcat(result, token2); strcat(result, end_loc); @@ -4596,7 +4596,7 @@ char *ADLParser::get_ident_or_literal_constant(const char* description) { // Grab a constant expression. param = get_paren_expr(description); if (param[0] != '(') { - char* buf = (char*) AllocateHeap(strlen(param) + 3); + char* buf = (char*) AdlAllocateHeap(strlen(param) + 3); sprintf(buf, "(%s)", param); param = buf; } @@ -5204,7 +5204,7 @@ void ADLParser::next_line() { char* ADLParser::get_line_string(int linenum) { const char* file = _AD._ADL_file._name; int line = linenum ? linenum : this->linenum(); - char* location = (char *)AllocateHeap(strlen(file) + 100); + char* location = (char *)AdlAllocateHeap(strlen(file) + 100); sprintf(location, "\n#line %d \"%s\"\n", line, file); return location; } diff --git a/src/hotspot/share/adlc/dfa.cpp b/src/hotspot/share/adlc/dfa.cpp index b1556ab5f5e..5abc4365297 100644 --- a/src/hotspot/share/adlc/dfa.cpp +++ b/src/hotspot/share/adlc/dfa.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -72,7 +72,7 @@ class ProductionState { public: // cmpstr does string comparisions. hashstr computes a key. - ProductionState(Arena *arena) : _production(cmpstr, hashstr, arena) { initialize(); }; + ProductionState(AdlArena *arena) : _production(cmpstr, hashstr, arena) { initialize(); }; ~ProductionState() { }; void initialize(); // reset local and dictionary state @@ -817,7 +817,7 @@ bool Expr::check_buffers() { //------------------------------ExprDict--------------------------------------- // Constructor -ExprDict::ExprDict( CmpKey cmp, Hash hash, Arena *arena ) +ExprDict::ExprDict( CmpKey cmp, Hash hash, AdlArena *arena ) : _expr(cmp, hash, arena), _defines() { } ExprDict::~ExprDict() { diff --git a/src/hotspot/share/adlc/dict2.cpp b/src/hotspot/share/adlc/dict2.cpp index 2dc60b250bf..fb0a2adba94 100644 --- a/src/hotspot/share/adlc/dict2.cpp +++ b/src/hotspot/share/adlc/dict2.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -56,7 +56,7 @@ Dict::Dict(CmpKey initcmp, Hash inithash) : _hash(inithash), _cmp(initcmp), _are init(); } -Dict::Dict(CmpKey initcmp, Hash inithash, Arena *arena) : _hash(inithash), _cmp(initcmp), _arena(arena) { +Dict::Dict(CmpKey initcmp, Hash inithash, AdlArena *arena) : _hash(inithash), _cmp(initcmp), _arena(arena) { init(); } diff --git a/src/hotspot/share/adlc/dict2.hpp b/src/hotspot/share/adlc/dict2.hpp index a9790088dfb..c6b7da3368a 100644 --- a/src/hotspot/share/adlc/dict2.hpp +++ b/src/hotspot/share/adlc/dict2.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -43,7 +43,7 @@ typedef void (*FuncDict)(const void *key, const void *val, Dict *d); class Dict { // Dictionary structure private: - class Arena *_arena; // Where to draw storage from + class AdlArena *_arena; // Where to draw storage from class bucket *_bin; // Hash table is array of buckets int _size; // Size (# of slots) in hash table int _cnt; // Number of key-value pairs in hash table @@ -56,7 +56,7 @@ class Dict { // Dictionary structure // cmp is a key comparision routine. hash is a routine to hash a key. Dict( CmpKey cmp, Hash hash ); - Dict( CmpKey cmp, Hash hash, Arena *arena ); + Dict( CmpKey cmp, Hash hash, AdlArena *arena ); void init(); ~Dict(); diff --git a/src/hotspot/share/adlc/forms.cpp b/src/hotspot/share/adlc/forms.cpp index cdd053f25b5..9b4eda3de50 100644 --- a/src/hotspot/share/adlc/forms.cpp +++ b/src/hotspot/share/adlc/forms.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -27,9 +27,9 @@ //------------------------------Static Initializers---------------------------- // allocate arena used by forms -Arena *Form::arena = Form::generate_arena(); // = Form::generate_arena(); -Arena *Form::generate_arena() { - return (new Arena); +AdlArena *Form::arena = Form::generate_arena(); // = Form::generate_arena(); +AdlArena *Form::generate_arena() { + return (new AdlArena); } //------------------------------NameList--------------------------------------- @@ -40,7 +40,7 @@ const char *NameList::_signal3 = "$$SIGNAL3$$"; // Constructor and Destructor NameList::NameList() : _cur(0), _max(4), _iter(0), _justReset(true) { - _names = (const char**) AllocateHeap(_max*sizeof(char*)); + _names = (const char**) AdlAllocateHeap(_max*sizeof(char*)); } NameList::~NameList() { // The following free is a double-free, and crashes the program: @@ -49,7 +49,7 @@ NameList::~NameList() { void NameList::addName(const char *name) { if (_cur == _max) { - _names = (const char**) ReAllocateHeap(_names, (_max *=2)*sizeof(char*)); + _names = (const char**) AdlReAllocateHeap(_names, (_max *=2)*sizeof(char*)); } _names[_cur++] = name; } @@ -310,7 +310,7 @@ FormList::~FormList() { //------------------------------FormDict--------------------------------------- // Constructor -FormDict::FormDict( CmpKey cmp, Hash hash, Arena *arena ) +FormDict::FormDict( CmpKey cmp, Hash hash, AdlArena *arena ) : _form(cmp, hash, arena) { } FormDict::~FormDict() { diff --git a/src/hotspot/share/adlc/forms.hpp b/src/hotspot/share/adlc/forms.hpp index b4e115229c3..6586ea88311 100644 --- a/src/hotspot/share/adlc/forms.hpp +++ b/src/hotspot/share/adlc/forms.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -97,7 +97,7 @@ class FormDict { public: // cmp is a key comparision routine. hash is a routine to hash a key. // FormDict( CmpKey cmp, Hash hash ); - FormDict( CmpKey cmp, Hash hash, Arena *arena ); + FormDict( CmpKey cmp, Hash hash, AdlArena *arena ); FormDict( const FormDict & fd ); // Deep-copy guts ~FormDict(); @@ -119,9 +119,9 @@ class FormDict { //------------------------------Form------------------------------------------- class Form { public: - static Arena *arena; // arena used by forms + static AdlArena *arena; // arena used by forms private: - static Arena *generate_arena(); // allocate arena used by forms + static AdlArena *generate_arena(); // allocate arena used by forms protected: int _ftype; // Indicator for derived class type @@ -573,7 +573,7 @@ class ExprDict { public: // cmp is a key comparision routine. hash is a routine to hash a key. - ExprDict( CmpKey cmp, Hash hash, Arena *arena ); + ExprDict( CmpKey cmp, Hash hash, AdlArena *arena ); ~ExprDict(); // Return # of key-value pairs in dict diff --git a/src/hotspot/share/adlc/formsopt.cpp b/src/hotspot/share/adlc/formsopt.cpp index 351904bbb29..6f1a5997511 100644 --- a/src/hotspot/share/adlc/formsopt.cpp +++ b/src/hotspot/share/adlc/formsopt.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -206,7 +206,7 @@ RegDef::RegDef(char *regname, char *callconv, char *c_conv, char * idealtype, ch _concrete(concrete), _register_num(0) { - // Chunk and register mask are determined by the register number + // AdlChunk and register mask are determined by the register number // _register_num is set when registers are added to an allocation class } RegDef::~RegDef() { // Destructor diff --git a/src/hotspot/share/adlc/formssel.cpp b/src/hotspot/share/adlc/formssel.cpp index 3b244ceda1f..ca30abf7efa 100644 --- a/src/hotspot/share/adlc/formssel.cpp +++ b/src/hotspot/share/adlc/formssel.cpp @@ -1366,7 +1366,7 @@ void InstructForm::set_unique_opnds() { // component back to an index and any DEF always goes at 0 so the // length of the array has to be the number of components + 1. _uniq_idx_length = _components.count() + 1; - uniq_idx = (uint*) AllocateHeap(sizeof(uint) * _uniq_idx_length); + uniq_idx = (uint*) AdlAllocateHeap(sizeof(uint) * _uniq_idx_length); for (i = 0; i < _uniq_idx_length; i++) { uniq_idx[i] = i; } @@ -3475,7 +3475,7 @@ void MatchNode::build_internalop( ) { rstr = (_rChild) ? ((_rChild->_internalop) ? _rChild->_internalop : _rChild->_opType) : ""; len += (int)strlen(lstr) + (int)strlen(rstr); - subtree = (char *)AllocateHeap(len); + subtree = (char *)AdlAllocateHeap(len); sprintf(subtree,"_%s_%s_%s", _opType, lstr, rstr); // Hash the subtree string in _internalOps; if a name exists, use it iop = (char *)_AD._internalOps[subtree]; @@ -3898,7 +3898,7 @@ void MatchRule::matchrule_swap_commutative_op(const char* instr_ident, int count MatchRule* clone = new MatchRule(_AD, this); // Swap operands of commutative operation ((MatchNode*)clone)->swap_commutative_op(true, count); - char* buf = (char*) AllocateHeap(strlen(instr_ident) + 4); + char* buf = (char*) AdlAllocateHeap(strlen(instr_ident) + 4); sprintf(buf, "%s_%d", instr_ident, match_rules_cnt++); clone->_result = buf; diff --git a/src/hotspot/share/c1/c1_GraphBuilder.cpp b/src/hotspot/share/c1/c1_GraphBuilder.cpp index 1c93452d478..eb3cd3ecf3f 100644 --- a/src/hotspot/share/c1/c1_GraphBuilder.cpp +++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp @@ -1865,22 +1865,17 @@ void GraphBuilder::invoke(Bytecodes::Code code) { log->identify(target), Bytecodes::name(code)); - // invoke-special-super - if (bc_raw == Bytecodes::_invokespecial && !target->is_object_initializer()) { - ciInstanceKlass* sender_klass = calling_klass; - if (sender_klass->is_interface()) { - int index = state()->stack_size() - (target->arg_size_no_receiver() + 1); - Value receiver = state()->stack_at(index); - CheckCast* c = new CheckCast(sender_klass, receiver, copy_state_before()); - c->set_invokespecial_receiver_check(); - state()->stack_at_put(index, append_split(c)); - } - } - // Some methods are obviously bindable without any type checks so // convert them directly to an invokespecial or invokestatic. if (target->is_loaded() && !target->is_abstract() && target->can_be_statically_bound()) { switch (bc_raw) { + case Bytecodes::_invokeinterface: + // convert to invokespecial if the target is the private interface method. + if (target->is_private()) { + assert(holder->is_interface(), "How did we get a non-interface method here!"); + code = Bytecodes::_invokespecial; + } + break; case Bytecodes::_invokevirtual: code = Bytecodes::_invokespecial; break; @@ -1897,6 +1892,26 @@ void GraphBuilder::invoke(Bytecodes::Code code) { } } + if (code == Bytecodes::_invokespecial) { + // Additional receiver subtype checks for interface calls via invokespecial or invokeinterface. + ciKlass* receiver_constraint = nullptr; + + if (bc_raw == Bytecodes::_invokeinterface) { + receiver_constraint = holder; + } else if (bc_raw == Bytecodes::_invokespecial && !target->is_object_initializer() && calling_klass->is_interface()) { + receiver_constraint = calling_klass; + } + + if (receiver_constraint != nullptr) { + int index = state()->stack_size() - (target->arg_size_no_receiver() + 1); + Value receiver = state()->stack_at(index); + CheckCast* c = new CheckCast(receiver_constraint, receiver, copy_state_before()); + // go to uncommon_trap when checkcast fails + c->set_invokespecial_receiver_check(); + state()->stack_at_put(index, append_split(c)); + } + } + // Push appendix argument (MethodType, CallSite, etc.), if one. bool patch_for_appendix = false; int patching_appendix_arg = 0; @@ -2025,9 +2040,11 @@ void GraphBuilder::invoke(Bytecodes::Code code) { } // check if we could do inlining - if (!PatchALot && Inline && target->is_loaded() && callee_holder->is_linked() && !patch_for_appendix) { + if (!PatchALot && Inline && target->is_loaded() && !patch_for_appendix && + callee_holder->is_loaded()) { // the effect of symbolic reference resolution + // callee is known => check if we have static binding - if ((code == Bytecodes::_invokestatic && callee_holder->is_initialized()) || // invokestatic involves an initialization barrier on resolved klass + if ((code == Bytecodes::_invokestatic && klass->is_initialized()) || // invokestatic involves an initialization barrier on declaring class code == Bytecodes::_invokespecial || (code == Bytecodes::_invokevirtual && target->is_final_method()) || code == Bytecodes::_invokedynamic) { diff --git a/src/hotspot/share/c1/c1_RangeCheckElimination.cpp b/src/hotspot/share/c1/c1_RangeCheckElimination.cpp index fc5df4a4201..f5275eb9d5c 100644 --- a/src/hotspot/share/c1/c1_RangeCheckElimination.cpp +++ b/src/hotspot/share/c1/c1_RangeCheckElimination.cpp @@ -365,7 +365,12 @@ void RangeCheckEliminator::update_bound(IntegerStack &pushed, Value v, Instructi bool RangeCheckEliminator::loop_invariant(BlockBegin *loop_header, Instruction *instruction) { assert(loop_header, "Loop header must not be null!"); if (!instruction) return true; - return instruction->dominator_depth() < loop_header->dominator_depth(); + for (BlockBegin *d = loop_header->dominator(); d != NULL; d = d->dominator()) { + if (d == instruction->block()) { + return true; + } + } + return false; } // Update bound. Pushes a new bound onto the stack. Tries to do a conjunction with the current bound. diff --git a/src/hotspot/share/ci/bcEscapeAnalyzer.cpp b/src/hotspot/share/ci/bcEscapeAnalyzer.cpp index a10a9d3d551..7fd8b5c04f3 100644 --- a/src/hotspot/share/ci/bcEscapeAnalyzer.cpp +++ b/src/hotspot/share/ci/bcEscapeAnalyzer.cpp @@ -416,11 +416,11 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl // Avoid calling get_constant() which will try to allocate // unloaded constant. We need only constant's type. int index = s.get_constant_pool_index(); - constantTag tag = s.get_constant_pool_tag(index); - if (tag.is_long() || tag.is_double()) { + BasicType con_bt = s.get_basic_type_for_constant_at(index); + if (con_bt == T_LONG || con_bt == T_DOUBLE) { // Only longs and doubles use 2 stack slots. state.lpush(); - } else if (tag.basic_type() == T_OBJECT) { + } else if (con_bt == T_OBJECT) { state.apush(unknown_obj); } else { state.spush(); diff --git a/src/hotspot/share/ci/ciConstant.hpp b/src/hotspot/share/ci/ciConstant.hpp index c9351771d17..25591699045 100644 --- a/src/hotspot/share/ci/ciConstant.hpp +++ b/src/hotspot/share/ci/ciConstant.hpp @@ -127,6 +127,17 @@ class ciConstant { bool is_valid() const { return basic_type() != T_ILLEGAL; } + + bool is_loaded() const { + if (is_valid()) { + if (is_reference_type(basic_type())) { + return as_object()->is_loaded(); + } else { + return true; + } + } + return false; + } // Debugging output void print(); }; diff --git a/src/hotspot/share/ci/ciEnv.cpp b/src/hotspot/share/ci/ciEnv.cpp index e8030859be3..6348c60d17f 100644 --- a/src/hotspot/share/ci/ciEnv.cpp +++ b/src/hotspot/share/ci/ciEnv.cpp @@ -432,13 +432,6 @@ ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass, domain = Handle(current, accessing_klass->protection_domain()); } - // setup up the proper type to return on OOM - ciKlass* fail_type; - if (sym->char_at(0) == JVM_SIGNATURE_ARRAY) { - fail_type = _unloaded_ciobjarrayklass; - } else { - fail_type = _unloaded_ciinstance_klass; - } Klass* found_klass; { ttyUnlocker ttyul; // release tty lock to avoid ordering problems @@ -520,7 +513,6 @@ ciKlass* ciEnv::get_klass_by_index_impl(const constantPoolHandle& cpool, int index, bool& is_accessible, ciInstanceKlass* accessor) { - EXCEPTION_CONTEXT; Klass* klass = NULL; Symbol* klass_name = NULL; @@ -528,7 +520,7 @@ ciKlass* ciEnv::get_klass_by_index_impl(const constantPoolHandle& cpool, klass_name = cpool->symbol_at(index); } else { // Check if it's resolved if it's not a symbol constant pool entry. - klass = ConstantPool::klass_at_if_loaded(cpool, index); + klass = ConstantPool::klass_at_if_loaded(cpool, index); // Try to look it up by name. if (klass == NULL) { klass_name = cpool->klass_name_at(index); @@ -588,7 +580,6 @@ ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool, int pool_index, int cache_index, ciInstanceKlass* accessor) { bool ignore_will_link; - EXCEPTION_CONTEXT; int index = pool_index; if (cache_index >= 0) { assert(index < 0, "only one kind of index at a time"); @@ -599,12 +590,14 @@ ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool, return ciConstant(T_OBJECT, get_object(NULL)); } BasicType bt = T_OBJECT; - if (cpool->tag_at(index).is_dynamic_constant()) + if (cpool->tag_at(index).is_dynamic_constant()) { bt = Signature::basic_type(cpool->uncached_signature_ref_at(index)); - if (is_reference_type(bt)) { - } else { + } + if (!is_reference_type(bt)) { // we have to unbox the primitive value - if (!is_java_primitive(bt)) return ciConstant(); + if (!is_java_primitive(bt)) { + return ciConstant(); + } jvalue value; BasicType bt2 = java_lang_boxing_object::get_value(obj, &value); assert(bt2 == bt, ""); @@ -639,6 +632,7 @@ ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool, } else if (tag.is_double()) { return ciConstant((jdouble)cpool->double_at(index)); } else if (tag.is_string()) { + EXCEPTION_CONTEXT; oop string = NULL; assert(cache_index >= 0, "should have a cache index"); string = cpool->string_at(index, cache_index, THREAD); @@ -655,24 +649,18 @@ ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool, return ciConstant(T_OBJECT, constant); } } else if (tag.is_unresolved_klass_in_error()) { - return ciConstant(); + return ciConstant(T_OBJECT, get_unloaded_klass_mirror(NULL)); } else if (tag.is_klass() || tag.is_unresolved_klass()) { - // 4881222: allow ldc to take a class type ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore_will_link, accessor); - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; - record_out_of_memory_failure(); - return ciConstant(); - } assert (klass->is_instance_klass() || klass->is_array_klass(), "must be an instance or array klass "); return ciConstant(T_OBJECT, klass->java_mirror()); - } else if (tag.is_method_type()) { + } else if (tag.is_method_type() || tag.is_method_type_in_error()) { // must execute Java code to link this CP entry into cache[i].f1 ciSymbol* signature = get_symbol(cpool->method_type_signature_at(index)); ciObject* ciobj = get_unloaded_method_type_constant(signature); return ciConstant(T_OBJECT, ciobj); - } else if (tag.is_method_handle()) { + } else if (tag.is_method_handle() || tag.is_method_handle_in_error()) { // must execute Java code to link this CP entry into cache[i].f1 int ref_kind = cpool->method_handle_ref_kind_at(index); int callee_index = cpool->method_handle_klass_index_at(index); @@ -681,10 +669,10 @@ ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool, ciSymbol* signature = get_symbol(cpool->method_handle_signature_ref_at(index)); ciObject* ciobj = get_unloaded_method_handle_constant(callee, name, signature, ref_kind); return ciConstant(T_OBJECT, ciobj); - } else if (tag.is_dynamic_constant()) { - return ciConstant(); + } else if (tag.is_dynamic_constant() || tag.is_dynamic_constant_in_error()) { + return ciConstant(); // not supported } else { - ShouldNotReachHere(); + assert(false, "unknown tag: %d (%s)", tag.value(), tag.internal_name()); return ciConstant(); } } diff --git a/src/hotspot/share/ci/ciStreams.cpp b/src/hotspot/share/ci/ciStreams.cpp index 4e9895bfaed..46f52f19412 100644 --- a/src/hotspot/share/ci/ciStreams.cpp +++ b/src/hotspot/share/ci/ciStreams.cpp @@ -251,6 +251,14 @@ constantTag ciBytecodeStream::get_constant_pool_tag(int index) const { return _method->get_Method()->constants()->constant_tag_at(index); } +// ------------------------------------------------------------------ +// ciBytecodeStream::get_basic_type_for_constant_at +// +BasicType ciBytecodeStream::get_basic_type_for_constant_at(int index) const { + VM_ENTRY_MARK; + return _method->get_Method()->constants()->basic_type_for_constant_at(index); +} + // ------------------------------------------------------------------ // ciBytecodeStream::get_field_index // @@ -476,8 +484,9 @@ ciKlass* ciBytecodeStream::get_declared_method_holder() { constantPoolHandle cpool(THREAD, _method->get_Method()->constants()); bool ignore; // report as MethodHandle for invokedynamic, which is syntactically classless - if (cur_bc() == Bytecodes::_invokedynamic) - return CURRENT_ENV->get_klass_by_name(_holder, ciSymbols::java_lang_invoke_MethodHandle(), false); + if (cur_bc() == Bytecodes::_invokedynamic) { + return CURRENT_ENV->MethodHandle_klass(); + } return CURRENT_ENV->get_klass_by_index(cpool, get_method_holder_index(), ignore, _holder); } diff --git a/src/hotspot/share/ci/ciStreams.hpp b/src/hotspot/share/ci/ciStreams.hpp index 84f12952da5..b8e6791caf2 100644 --- a/src/hotspot/share/ci/ciStreams.hpp +++ b/src/hotspot/share/ci/ciStreams.hpp @@ -140,7 +140,7 @@ class ciBytecodeStream : StackObj { bool is_wide() const { return ( _pc == _was_wide ); } - // Does this instruction contain an index which refes into the CP cache? + // Does this instruction contain an index which refers into the CP cache? bool has_cache_index() const { return Bytecodes::uses_cp_cache(cur_bc_raw()); } int get_index_u1() const { @@ -224,8 +224,9 @@ class ciBytecodeStream : StackObj { // constant. Do not attempt to resolve it, since that would require // execution of Java code. If it is not resolved, return an unloaded // object (ciConstant.as_object()->is_loaded() == false). - ciConstant get_constant(); + ciConstant get_constant(); constantTag get_constant_pool_tag(int index) const; + BasicType get_basic_type_for_constant_at(int index) const; // True if the klass-using bytecode points to an unresolved klass bool is_unresolved_klass() const { @@ -233,9 +234,17 @@ class ciBytecodeStream : StackObj { return tag.is_unresolved_klass(); } - bool is_unresolved_klass_in_error() const { - constantTag tag = get_constant_pool_tag(get_klass_index()); - return tag.is_unresolved_klass_in_error(); + bool is_in_error() const { + assert(cur_bc() == Bytecodes::_ldc || + cur_bc() == Bytecodes::_ldc_w || + cur_bc() == Bytecodes::_ldc2_w, "not supported: %s", Bytecodes::name(cur_bc())); + + int index = get_constant_pool_index(); + constantTag tag = get_constant_pool_tag(index); + return tag.is_unresolved_klass_in_error() || + tag.is_method_handle_in_error() || + tag.is_method_type_in_error() || + tag.is_dynamic_constant_in_error(); } // If this bytecode is one of get_field, get_static, put_field, diff --git a/src/hotspot/share/ci/ciTypeFlow.cpp b/src/hotspot/share/ci/ciTypeFlow.cpp index 802ba97db2e..2c274ec1baf 100644 --- a/src/hotspot/share/ci/ciTypeFlow.cpp +++ b/src/hotspot/share/ci/ciTypeFlow.cpp @@ -720,6 +720,11 @@ void ciTypeFlow::StateVector::do_jsr(ciBytecodeStream* str) { // ------------------------------------------------------------------ // ciTypeFlow::StateVector::do_ldc void ciTypeFlow::StateVector::do_ldc(ciBytecodeStream* str) { + if (str->is_in_error()) { + trap(str, NULL, Deoptimization::make_trap_request(Deoptimization::Reason_unhandled, + Deoptimization::Action_none)); + return; + } ciConstant con = str->get_constant(); if (con.is_valid()) { BasicType basic_type = con.basic_type(); @@ -735,14 +740,10 @@ void ciTypeFlow::StateVector::do_ldc(ciBytecodeStream* str) { push_translate(ciType::make(basic_type)); } } else { - if (str->is_unresolved_klass_in_error()) { - trap(str, NULL, Deoptimization::make_trap_request(Deoptimization::Reason_unhandled, - Deoptimization::Action_none)); - } else { - // OutOfMemoryError in the CI while loading constant - push_null(); - outer()->record_failure("ldc did not link"); - } + // OutOfMemoryError in the CI while loading constant. + // Unresolved condy also lands here (not yet supported). + push_null(); + outer()->record_failure("ldc did not link"); } } @@ -2173,7 +2174,7 @@ bool ciTypeFlow::can_trap(ciBytecodeStream& str) { case Bytecodes::_ldc: case Bytecodes::_ldc_w: case Bytecodes::_ldc2_w: - return str.is_unresolved_klass_in_error(); + return str.is_in_error(); case Bytecodes::_aload_0: // These bytecodes can trap for rewriting. We need to assume that diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index 6a067c13c42..4eef51df665 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -4119,11 +4119,20 @@ void java_lang_invoke_MethodType::serialize_offsets(SerializeClosure* f) { void java_lang_invoke_MethodType::print_signature(oop mt, outputStream* st) { st->print("("); objArrayOop pts = ptypes(mt); - for (int i = 0, limit = pts->length(); i < limit; i++) { - java_lang_Class::print_signature(pts->obj_at(i), st); + if (pts != NULL) { + for (int i = 0, limit = pts->length(); i < limit; i++) { + java_lang_Class::print_signature(pts->obj_at(i), st); + } + } else { + st->print("NULL"); } st->print(")"); - java_lang_Class::print_signature(rtype(mt), st); + oop rt = rtype(mt); + if (rt != NULL) { + java_lang_Class::print_signature(rt, st); + } else { + st->print("NULL"); + } } Symbol* java_lang_invoke_MethodType::as_signature(oop mt, bool intern_if_not_found) { diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index 8db26511494..51b767acf03 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -2013,8 +2013,9 @@ Method* SystemDictionary::find_method_handle_intrinsic(vmIntrinsicID iid, spe = NULL; // Must create lots of stuff here, but outside of the SystemDictionary lock. m = Method::make_method_handle_intrinsic(iid, signature, CHECK_NULL); - if (!Arguments::is_interpreter_only()) { + if (!Arguments::is_interpreter_only() || iid == vmIntrinsics::_linkToNative) { // Generate a compiled form of the MH intrinsic. + // linkToNative doesn't have interpreter-specific implementation, so always has to go through compiled version. AdapterHandlerLibrary::create_native_wrapper(m); // Check if have the compiled code. if (!m->has_compiled_code()) { @@ -2077,9 +2078,9 @@ static Method* unpack_method_and_appendix(Handle mname, Method* SystemDictionary::find_method_handle_invoker(Klass* klass, Symbol* name, Symbol* signature, - Klass* accessing_klass, - Handle *appendix_result, - TRAPS) { + Klass* accessing_klass, + Handle* appendix_result, + TRAPS) { assert(THREAD->can_call_java() ,""); Handle method_type = SystemDictionary::find_method_handle_type(signature, accessing_klass, CHECK_NULL); diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index 0eab2bc5a48..f70d6253d68 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -487,7 +487,7 @@ CodeBlob* CodeCache::next_blob(CodeHeap* heap, CodeBlob* cb) { */ CodeBlob* CodeCache::allocate(int size, int code_blob_type, bool handle_alloc_failure, int orig_code_blob_type) { // Possibly wakes up the sweeper thread. - NMethodSweeper::report_allocation(code_blob_type); + NMethodSweeper::report_allocation(); assert_locked_or_safepoint(CodeCache_lock); assert(size > 0, "Code cache allocation request must be > 0 but is %d", size); if (size <= 0) { @@ -512,7 +512,7 @@ CodeBlob* CodeCache::allocate(int size, int code_blob_type, bool handle_alloc_fa // Fallback solution: Try to store code in another code heap. // NonNMethod -> MethodNonProfiled -> MethodProfiled (-> MethodNonProfiled) // Note that in the sweeper, we check the reverse_free_ratio of the code heap - // and force stack scanning if less than 10% of the code heap are free. + // and force stack scanning if less than 10% of the entire code cache are free. int type = code_blob_type; switch (type) { case CodeBlobType::NonNMethod: @@ -889,20 +889,17 @@ size_t CodeCache::max_capacity() { return max_cap; } -/** - * Returns the reverse free ratio. E.g., if 25% (1/4) of the code heap - * is free, reverse_free_ratio() returns 4. - */ -double CodeCache::reverse_free_ratio(int code_blob_type) { - CodeHeap* heap = get_code_heap(code_blob_type); - if (heap == NULL) { - return 0; - } - double unallocated_capacity = MAX2((double)heap->unallocated_capacity(), 1.0); // Avoid division by 0; - double max_capacity = (double)heap->max_capacity(); - double result = max_capacity / unallocated_capacity; - assert (max_capacity >= unallocated_capacity, "Must be"); +// Returns the reverse free ratio. E.g., if 25% (1/4) of the code cache +// is free, reverse_free_ratio() returns 4. +// Since code heap for each type of code blobs falls forward to the next +// type of code heap, return the reverse free ratio for the entire +// code cache. +double CodeCache::reverse_free_ratio() { + double unallocated = MAX2((double)unallocated_capacity(), 1.0); // Avoid division by 0; + double max = (double)max_capacity(); + double result = max / unallocated; + assert (max >= unallocated, "Must be"); assert (result >= 1.0, "reverse_free_ratio must be at least 1. It is %f", result); return result; } diff --git a/src/hotspot/share/code/codeCache.hpp b/src/hotspot/share/code/codeCache.hpp index d889d006d57..b1219de485e 100644 --- a/src/hotspot/share/code/codeCache.hpp +++ b/src/hotspot/share/code/codeCache.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -211,7 +211,7 @@ class CodeCache : AllStatic { static size_t unallocated_capacity(); static size_t max_capacity(); - static double reverse_free_ratio(int code_blob_type); + static double reverse_free_ratio(); static void clear_inline_caches(); // clear all inline caches static void cleanup_inline_caches(); // clean unloaded/zombie nmethods from inline caches diff --git a/src/hotspot/share/code/codeHeapState.cpp b/src/hotspot/share/code/codeHeapState.cpp index 30948e4f718..32bd6ed98b8 100644 --- a/src/hotspot/share/code/codeHeapState.cpp +++ b/src/hotspot/share/code/codeHeapState.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2019 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -755,18 +755,17 @@ void CodeHeapState::aggregate(outputStream* out, CodeHeap* heap, size_t granular CodeBlob* cb = (CodeBlob*)heap->find_start(h); cbType = get_cbType(cb); // Will check for cb == NULL and other safety things. if (cbType != noType) { - const char* blob_name = os::strdup(cb->name()); + const char* blob_name = nullptr; unsigned int nm_size = 0; int temperature = 0; nmethod* nm = cb->as_nmethod_or_null(); if (nm != NULL) { // no is_readable check required, nm = (nmethod*)cb. ResourceMark rm; Method* method = nm->method(); - if (nm->is_in_use()) { - blob_name = os::strdup(method->name_and_sig_as_C_string()); - } - if (nm->is_not_entrant()) { + if (nm->is_in_use() || nm->is_not_entrant()) { blob_name = os::strdup(method->name_and_sig_as_C_string()); + } else { + blob_name = os::strdup(cb->name()); } nm_size = nm->total_size(); @@ -814,6 +813,8 @@ void CodeHeapState::aggregate(outputStream* out, CodeHeap* heap, size_t granular default: break; } + } else { + blob_name = os::strdup(cb->name()); } //------------------------------------------ diff --git a/src/hotspot/share/compiler/compilationPolicy.cpp b/src/hotspot/share/compiler/compilationPolicy.cpp index 1f9902895f1..1dde9824da7 100644 --- a/src/hotspot/share/compiler/compilationPolicy.cpp +++ b/src/hotspot/share/compiler/compilationPolicy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -315,7 +315,7 @@ double CompilationPolicy::threshold_scale(CompLevel level, int feedback_k) { // The main intention is to keep enough free space for C2 compiled code // to achieve peak performance if the code cache is under stress. if (CompilerConfig::is_tiered() && !CompilationModeFlag::disable_intermediate() && is_c1_compile(level)) { - double current_reverse_free_ratio = CodeCache::reverse_free_ratio(CodeCache::get_code_blob_type(level)); + double current_reverse_free_ratio = CodeCache::reverse_free_ratio(); if (current_reverse_free_ratio > _increase_threshold_at_ratio) { k *= exp(current_reverse_free_ratio - _increase_threshold_at_ratio); } diff --git a/src/hotspot/share/compiler/compileBroker.cpp b/src/hotspot/share/compiler/compileBroker.cpp index b715f7783d5..cef2da21a77 100644 --- a/src/hotspot/share/compiler/compileBroker.cpp +++ b/src/hotspot/share/compiler/compileBroker.cpp @@ -224,11 +224,13 @@ class CompilationLog : public StringEventLog { } void log_metaspace_failure(const char* reason) { + // Note: This method can be called from non-Java/compiler threads to + // log the global metaspace failure that might affect profiling. ResourceMark rm; StringLogMessage lm; lm.print("%4d COMPILE PROFILING SKIPPED: %s", -1, reason); lm.print("\n"); - log(JavaThread::current(), "%s", (const char*)lm); + log(Thread::current(), "%s", (const char*)lm); } }; @@ -2003,6 +2005,8 @@ void CompileBroker::compiler_thread_loop() { method->clear_queued_for_compilation(); task->set_failure_reason("compilation is disabled"); } + } else { + task->set_failure_reason("breakpoints are present"); } if (UseDynamicNumberOfCompilerThreads) { diff --git a/src/hotspot/share/compiler/compilerDefinitions.cpp b/src/hotspot/share/compiler/compilerDefinitions.cpp index a6445c161b2..47be522910f 100644 --- a/src/hotspot/share/compiler/compilerDefinitions.cpp +++ b/src/hotspot/share/compiler/compilerDefinitions.cpp @@ -124,10 +124,17 @@ intx CompilerConfig::scaled_freq_log(intx freq_log) { // Returns threshold scaled with the value of scale. // If scale < 0.0, threshold is returned without scaling. intx CompilerConfig::scaled_compile_threshold(intx threshold, double scale) { + assert(threshold >= 0, "must be"); if (scale == 1.0 || scale < 0.0) { return threshold; } else { - return (intx)(threshold * scale); + double v = threshold * scale; + assert(v >= 0, "must be"); + if (v > max_intx) { + return max_intx; + } else { + return (intx)(v); + } } } diff --git a/src/hotspot/share/interpreter/bootstrapInfo.cpp b/src/hotspot/share/interpreter/bootstrapInfo.cpp index 4f52b19fcc6..830c015cc39 100644 --- a/src/hotspot/share/interpreter/bootstrapInfo.cpp +++ b/src/hotspot/share/interpreter/bootstrapInfo.cpp @@ -67,7 +67,7 @@ bool BootstrapInfo::resolve_previously_linked_invokedynamic(CallInfo& result, TR if (!cpce->is_f1_null()) { methodHandle method( THREAD, cpce->f1_as_method()); Handle appendix( THREAD, cpce->appendix_if_resolved(_pool)); - result.set_handle(method, appendix, THREAD); + result.set_handle(vmClasses::MethodHandle_klass(), method, appendix, THREAD); Exceptions::wrap_dynamic_exception(/* is_indy */ true, CHECK_false); return true; } else if (cpce->indy_resolution_failed()) { @@ -221,7 +221,7 @@ bool BootstrapInfo::save_and_throw_indy_exc(TRAPS) { void BootstrapInfo::resolve_newly_linked_invokedynamic(CallInfo& result, TRAPS) { assert(is_resolved(), ""); - result.set_handle(resolved_method(), resolved_appendix(), CHECK); + result.set_handle(vmClasses::MethodHandle_klass(), resolved_method(), resolved_appendix(), CHECK); } void BootstrapInfo::print_msg_on(outputStream* st, const char* msg) { diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp index 84589092397..fa8072fb207 100644 --- a/src/hotspot/share/interpreter/linkResolver.cpp +++ b/src/hotspot/share/interpreter/linkResolver.cpp @@ -94,11 +94,6 @@ void CallInfo::set_virtual(Klass* resolved_klass, assert(!resolved_method->is_compiled_lambda_form(), "these must be handled via an invokehandle call"); } -void CallInfo::set_handle(const methodHandle& resolved_method, - Handle resolved_appendix, TRAPS) { - set_handle(vmClasses::MethodHandle_klass(), resolved_method, resolved_appendix, CHECK); -} - void CallInfo::set_handle(Klass* resolved_klass, const methodHandle& resolved_method, Handle resolved_appendix, TRAPS) { @@ -476,14 +471,12 @@ Method* LinkResolver::lookup_polymorphic_method(const LinkInfo& link_info, } Handle appendix; - Handle method_type; - Method* result = SystemDictionary::find_method_handle_invoker( - klass, - name, - full_signature, - link_info.current_klass(), - &appendix, - CHECK_NULL); + Method* result = SystemDictionary::find_method_handle_invoker(klass, + name, + full_signature, + link_info.current_klass(), + &appendix, + CHECK_NULL); if (lt_mh.is_enabled()) { LogStream ls(lt_mh); ls.print("lookup_polymorphic_method => (via Java) "); @@ -621,7 +614,7 @@ Method* LinkResolver::resolve_method_statically(Bytecodes::Code code, Klass* resolved_klass = link_info.resolved_klass(); if (pool->has_preresolution() - || (resolved_klass == vmClasses::MethodHandle_klass() && + || ((resolved_klass == vmClasses::MethodHandle_klass() || resolved_klass == vmClasses::VarHandle_klass()) && MethodHandles::is_signature_polymorphic_name(resolved_klass, link_info.name()))) { Method* result = ConstantPool::method_at_if_loaded(pool, index); if (result != NULL) { @@ -1679,15 +1672,31 @@ void LinkResolver::resolve_invokeinterface(CallInfo& result, Handle recv, const resolve_interface_call(result, recv, recvrKlass, link_info, true, CHECK); } +bool LinkResolver::resolve_previously_linked_invokehandle(CallInfo& result, const LinkInfo& link_info, const constantPoolHandle& pool, int index, TRAPS) { + int cache_index = ConstantPool::decode_cpcache_index(index, true); + ConstantPoolCacheEntry* cpce = pool->cache()->entry_at(cache_index); + if (!cpce->is_f1_null()) { + Klass* resolved_klass = link_info.resolved_klass(); + methodHandle method(THREAD, cpce->f1_as_method()); + Handle appendix(THREAD, cpce->appendix_if_resolved(pool)); + result.set_handle(resolved_klass, method, appendix, CHECK_false); + return true; + } else { + return false; + } +} void LinkResolver::resolve_invokehandle(CallInfo& result, const constantPoolHandle& pool, int index, TRAPS) { - // This guy is reached from InterpreterRuntime::resolve_invokehandle. LinkInfo link_info(pool, index, CHECK); if (log_is_enabled(Info, methodhandles)) { ResourceMark rm(THREAD); log_info(methodhandles)("resolve_invokehandle %s %s", link_info.name()->as_C_string(), link_info.signature()->as_C_string()); } + { // Check if the call site has been bound already, and short circuit: + bool is_done = resolve_previously_linked_invokehandle(result, link_info, pool, index, CHECK); + if (is_done) return; + } resolve_handle_call(result, link_info, CHECK); } @@ -1699,7 +1708,7 @@ void LinkResolver::resolve_handle_call(CallInfo& result, assert(resolved_klass == vmClasses::MethodHandle_klass() || resolved_klass == vmClasses::VarHandle_klass(), ""); assert(MethodHandles::is_signature_polymorphic_name(link_info.name()), ""); - Handle resolved_appendix; + Handle resolved_appendix; Method* resolved_method = lookup_polymorphic_method(link_info, &resolved_appendix, CHECK); result.set_handle(resolved_klass, methodHandle(THREAD, resolved_method), resolved_appendix, CHECK); } diff --git a/src/hotspot/share/interpreter/linkResolver.hpp b/src/hotspot/share/interpreter/linkResolver.hpp index 9eeb10cc6fd..e0b2c0b4378 100644 --- a/src/hotspot/share/interpreter/linkResolver.hpp +++ b/src/hotspot/share/interpreter/linkResolver.hpp @@ -66,8 +66,6 @@ class CallInfo : public StackObj { const methodHandle& resolved_method, const methodHandle& selected_method, int vtable_index, TRAPS); - void set_handle(const methodHandle& resolved_method, - Handle resolved_appendix, TRAPS); void set_handle(Klass* resolved_klass, const methodHandle& resolved_method, Handle resolved_appendix, TRAPS); @@ -249,6 +247,11 @@ class LinkResolver: AllStatic { Klass* recv_klass, bool check_null_and_abstract, TRAPS); + static bool resolve_previously_linked_invokehandle(CallInfo& result, + const LinkInfo& link_info, + const constantPoolHandle& pool, + int index, TRAPS); + static void check_field_accessability(Klass* ref_klass, Klass* resolved_klass, Klass* sel_klass, @@ -337,7 +340,6 @@ class LinkResolver: AllStatic { const methodHandle& attached_method, Bytecodes::Code byte, TRAPS); - public: // Only resolved method known. static void throw_abstract_method_error(const methodHandle& resolved_method, TRAPS) { throw_abstract_method_error(resolved_method, methodHandle(), NULL, CHECK); diff --git a/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp b/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp index 4e8bd4f9bee..a22b4adfdd6 100644 --- a/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp +++ b/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp @@ -2548,6 +2548,8 @@ void BytecodeInterpreter::run(interpreterState istate) { SET_STACK_OBJECT(ts->earlyret_oop(), 0); MORE_STACK(1); break; + default: + ShouldNotReachHere(); } ts->clr_earlyret_value(); diff --git a/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp b/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp index 861dad66d02..5645ed396d8 100644 --- a/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp +++ b/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -549,14 +549,16 @@ void JfrJavaSupport::throw_runtime_exception(const char* message, TRAPS) { void JfrJavaSupport::abort(jstring errorMsg, JavaThread* t) { DEBUG_ONLY(check_java_thread_in_vm(t)); - ResourceMark rm(t); - const char* const error_msg = c_str(errorMsg, t); - if (error_msg != NULL) { - log_error(jfr, system)("%s",error_msg); + abort(c_str(errorMsg, t)); +} + +void JfrJavaSupport::abort(const char* error_msg, bool dump_core /* true */) { + if (error_msg != nullptr) { + log_error(jfr, system)("%s", error_msg); } log_error(jfr, system)("%s", "An irrecoverable error in Jfr. Shutting down VM..."); - vm_abort(); + vm_abort(dump_core); } JfrJavaSupport::CAUSE JfrJavaSupport::_cause = JfrJavaSupport::VM_ERROR; diff --git a/src/hotspot/share/jfr/jni/jfrJavaSupport.hpp b/src/hotspot/share/jfr/jni/jfrJavaSupport.hpp index 6a2f200322c..d167e82edee 100644 --- a/src/hotspot/share/jfr/jni/jfrJavaSupport.hpp +++ b/src/hotspot/share/jfr/jni/jfrJavaSupport.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -100,6 +100,7 @@ class JfrJavaSupport : public AllStatic { // critical static void abort(jstring errorMsg, TRAPS); + static void abort(const char* error_msg, bool dump_core = true); static void uncaught_exception(jthrowable throwable, JavaThread* t); // asserts diff --git a/src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp b/src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp index dd232fdd026..f8900a13b4d 100644 --- a/src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp +++ b/src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp @@ -25,8 +25,8 @@ #ifndef SHARE_JFR_WRITERS_JFRSTREAMWRITERHOST_INLINE_HPP #define SHARE_JFR_WRITERS_JFRSTREAMWRITERHOST_INLINE_HPP +#include "jfr/jni/jfrJavaSupport.hpp" #include "jfr/writers/jfrStreamWriterHost.hpp" - #include "runtime/os.hpp" template @@ -77,6 +77,9 @@ inline void StreamWriterHost::write_bytes(const u1* buf, intptr_t l while (len > 0) { const unsigned int nBytes = len > INT_MAX ? INT_MAX : (unsigned int)len; const ssize_t num_written = (ssize_t)os::write(_fd, buf, nBytes); + if (errno == ENOSPC) { + JfrJavaSupport::abort("Failed to write to jfr stream because no space left on device", false); + } guarantee(num_written > 0, "Nothing got written, or os::write() failed"); _stream_pos += num_written; len -= num_written; diff --git a/src/hotspot/share/logging/logConfiguration.cpp b/src/hotspot/share/logging/logConfiguration.cpp index 4c371e8506e..264afd43afc 100644 --- a/src/hotspot/share/logging/logConfiguration.cpp +++ b/src/hotspot/share/logging/logConfiguration.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -365,9 +365,9 @@ bool LogConfiguration::parse_command_line_arguments(const char* opts) { // Find the next colon or quote char* next = strpbrk(str, ":\""); #ifdef _WINDOWS - // Skip over Windows paths such as "C:\..." - // Handle both C:\... and file=C:\..." - if (next != NULL && next[0] == ':' && next[1] == '\\') { + // Skip over Windows paths such as "C:\..." and "C:/...". + // Handles both "C:\..." and "file=C:\...". + if (next != NULL && next[0] == ':' && (next[1] == '\\' || next[1] == '/')) { if (next == str + 1 || (strncmp(str, "file=", 5) == 0)) { next = strpbrk(next + 1, ":\""); } diff --git a/src/hotspot/share/logging/logOutput.cpp b/src/hotspot/share/logging/logOutput.cpp index c21ed51f322..9c74967514d 100644 --- a/src/hotspot/share/logging/logOutput.cpp +++ b/src/hotspot/share/logging/logOutput.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -334,6 +334,11 @@ void LogOutput::update_config_string(const size_t on_level[LogLevel::Count]) { assert(n_deviates < deviating_tagsets, "deviating tag set array overflow"); assert(prev_deviates > n_deviates, "number of deviating tag sets must never grow"); + + if (n_deviates == 1 && n_selections == 0) { + // we're done as we couldn't reduce things any further + break; + } } FREE_C_HEAP_ARRAY(LogTagSet*, deviates); FREE_C_HEAP_ARRAY(Selection, selections); diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp index 9f2a9e34a94..8ba5fae9cb7 100644 --- a/src/hotspot/share/memory/universe.cpp +++ b/src/hotspot/share/memory/universe.cpp @@ -1236,6 +1236,7 @@ bool Universe::release_fullgc_alot_dummy() { if (_fullgc_alot_dummy_next >= fullgc_alot_dummy_array->length()) { // No more dummies to release, release entire array instead _fullgc_alot_dummy_array.release(Universe::vm_global()); + _fullgc_alot_dummy_array = OopHandle(); // NULL out OopStorage pointer. return false; } diff --git a/src/hotspot/share/oops/constantPool.cpp b/src/hotspot/share/oops/constantPool.cpp index c37a3cfa876..c7dc3499f61 100644 --- a/src/hotspot/share/oops/constantPool.cpp +++ b/src/hotspot/share/oops/constantPool.cpp @@ -884,11 +884,9 @@ void ConstantPool::save_and_throw_exception(const constantPoolHandle& this_cp, i constantTag ConstantPool::constant_tag_at(int which) { constantTag tag = tag_at(which); - if (tag.is_dynamic_constant() || - tag.is_dynamic_constant_in_error()) { + if (tag.is_dynamic_constant()) { BasicType bt = basic_type_for_constant_at(which); - // dynamic constant could return an array, treat as object - return constantTag::ofBasicType(is_reference_type(bt) ? T_OBJECT : bt); + return constantTag(constantTag::type2tag(bt)); } return tag; } @@ -975,7 +973,6 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, switch (tag.value()) { case JVM_CONSTANT_UnresolvedClass: - case JVM_CONSTANT_UnresolvedClassInError: case JVM_CONSTANT_Class: { assert(cache_index == _no_index_sentinel, "should not have been set"); @@ -1043,14 +1040,6 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, result_oop = string_at_impl(this_cp, index, cache_index, CHECK_NULL); break; - case JVM_CONSTANT_DynamicInError: - case JVM_CONSTANT_MethodHandleInError: - case JVM_CONSTANT_MethodTypeInError: - { - throw_resolution_error(this_cp, index, CHECK_NULL); - break; - } - case JVM_CONSTANT_MethodHandle: { int ref_kind = this_cp->method_handle_ref_kind_at(index); @@ -1064,11 +1053,14 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, callee_index, name->as_C_string(), signature->as_C_string()); } - Klass* callee = klass_at_impl(this_cp, callee_index, CHECK_NULL); + Klass* callee = klass_at_impl(this_cp, callee_index, THREAD); + if (HAS_PENDING_EXCEPTION) { + save_and_throw_exception(this_cp, index, tag, CHECK_NULL); + } // Check constant pool method consistency if ((callee->is_interface() && m_tag.is_method()) || - ((!callee->is_interface() && m_tag.is_interface_method()))) { + (!callee->is_interface() && m_tag.is_interface_method())) { ResourceMark rm(THREAD); stringStream ss; ss.print("Inconsistent constant pool data in classfile for class %s. " @@ -1080,17 +1072,18 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, index, callee->is_interface() ? "CONSTANT_MethodRef" : "CONSTANT_InterfaceMethodRef", callee->is_interface() ? "CONSTANT_InterfaceMethodRef" : "CONSTANT_MethodRef"); - THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string()); + Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_IncompatibleClassChangeError(), "%s", ss.as_string()); + save_and_throw_exception(this_cp, index, tag, CHECK_NULL); } Klass* klass = this_cp->pool_holder(); Handle value = SystemDictionary::link_method_handle_constant(klass, ref_kind, callee, name, signature, THREAD); - result_oop = value(); if (HAS_PENDING_EXCEPTION) { save_and_throw_exception(this_cp, index, tag, CHECK_NULL); } + result_oop = value(); break; } @@ -1135,10 +1128,15 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, result_oop = java_lang_boxing_object::create(T_DOUBLE, &prim_value, CHECK_NULL); break; + case JVM_CONSTANT_UnresolvedClassInError: + case JVM_CONSTANT_DynamicInError: + case JVM_CONSTANT_MethodHandleInError: + case JVM_CONSTANT_MethodTypeInError: + throw_resolution_error(this_cp, index, CHECK_NULL); + break; + default: - DEBUG_ONLY( tty->print_cr("*** %p: tag at CP[%d/%d] = %d", - this_cp(), index, cache_index, tag.value())); - assert(false, "unexpected constant tag"); + fatal("unexpected constant tag at CP %p[%d/%d] = %d", this_cp(), index, cache_index, tag.value()); break; } diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp index ae75527f19b..3241128875b 100644 --- a/src/hotspot/share/oops/method.cpp +++ b/src/hotspot/share/oops/method.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -1186,7 +1186,7 @@ void Method::unlink_method() { void Method::link_method(const methodHandle& h_method, TRAPS) { // If the code cache is full, we may reenter this function for the // leftover methods that weren't linked. - if (_i2i_entry != NULL) { + if (adapter() != NULL) { return; } assert( _code == NULL, "nothing compiled yet" ); diff --git a/src/hotspot/share/opto/arraycopynode.cpp b/src/hotspot/share/opto/arraycopynode.cpp index 11560f6419b..b0f30703f91 100644 --- a/src/hotspot/share/opto/arraycopynode.cpp +++ b/src/hotspot/share/opto/arraycopynode.cpp @@ -189,9 +189,8 @@ Node* ArrayCopyNode::try_clone_instance(PhaseGVN *phase, bool can_reshape, int c } MergeMemNode* mem = phase->transform(MergeMemNode::make(in_mem))->as_MergeMem(); - PhaseIterGVN* igvn = phase->is_IterGVN(); - if (igvn != NULL) { - igvn->_worklist.push(mem); + if (can_reshape) { + phase->is_IterGVN()->_worklist.push(mem); } if (!inst_src->klass_is_exact()) { @@ -294,9 +293,17 @@ bool ArrayCopyNode::prepare_array_copy(PhaseGVN *phase, bool can_reshape, uint header = arrayOopDesc::base_offset_in_bytes(dest_elem); src_offset = Compile::conv_I2X_index(phase, src_offset, ary_src->size()); + if (src_offset->is_top()) { + // Offset is out of bounds (the ArrayCopyNode will be removed) + return false; + } dest_offset = Compile::conv_I2X_index(phase, dest_offset, ary_dest->size()); - if (src_offset->is_top() || dest_offset->is_top()) { + if (dest_offset->is_top()) { // Offset is out of bounds (the ArrayCopyNode will be removed) + if (can_reshape) { + // record src_offset, so it can be deleted later (if it is dead) + phase->is_IterGVN()->_worklist.push(src_offset); + } return false; } @@ -316,9 +323,6 @@ bool ArrayCopyNode::prepare_array_copy(PhaseGVN *phase, bool can_reshape, disjoint_bases = true; - adr_src = phase->transform(new AddPNode(base_src, base_src, src_offset)); - adr_dest = phase->transform(new AddPNode(base_dest, base_dest, dest_offset)); - BasicType elem = ary_src->klass()->as_array_klass()->element_type()->basic_type(); if (is_reference_type(elem)) { elem = T_OBJECT; @@ -329,6 +333,9 @@ bool ArrayCopyNode::prepare_array_copy(PhaseGVN *phase, bool can_reshape, return false; } + adr_src = phase->transform(new AddPNode(base_src, base_src, src_offset)); + adr_dest = phase->transform(new AddPNode(base_dest, base_dest, dest_offset)); + // The address is offseted to an aligned address where a raw copy would start. // If the clone copy is decomposed into load-stores - the address is adjusted to // point at where the array starts. @@ -566,6 +573,8 @@ Node *ArrayCopyNode::Ideal(PhaseGVN *phase, bool can_reshape) { if (!prepare_array_copy(phase, can_reshape, adr_src, base_src, adr_dest, base_dest, copy_type, value_type, disjoint_bases)) { + assert(adr_src == NULL, "no node can be left behind"); + assert(adr_dest == NULL, "no node can be left behind"); return NULL; } @@ -629,6 +638,10 @@ Node *ArrayCopyNode::Ideal(PhaseGVN *phase, bool can_reshape) { } if (!finish_transform(phase, can_reshape, ctl, mem)) { + if (can_reshape) { + // put in worklist, so that if it happens to be dead it is removed + phase->is_IterGVN()->_worklist.push(mem); + } return NULL; } diff --git a/src/hotspot/share/opto/callGenerator.cpp b/src/hotspot/share/opto/callGenerator.cpp index e9c376e4289..7819965f57d 100644 --- a/src/hotspot/share/opto/callGenerator.cpp +++ b/src/hotspot/share/opto/callGenerator.cpp @@ -416,6 +416,13 @@ class LateInlineMHCallGenerator : public LateInlineCallGenerator { }; bool LateInlineMHCallGenerator::do_late_inline_check(Compile* C, JVMState* jvms) { + // When inlining a virtual call, the null check at the call and the call itself can throw. These 2 paths have different + // expression stacks which causes late inlining to break. The MH invoker is not expected to be called from a method wih + // exception handlers. When there is no exception handler, GraphKit::builtin_throw() pops the stack which solves the issue + // of late inlining with exceptions. + assert(!jvms->method()->has_exception_handlers() || + (method()->intrinsic_id() != vmIntrinsics::_linkToVirtual && + method()->intrinsic_id() != vmIntrinsics::_linkToInterface), "no exception handler expected"); // Even if inlining is not allowed, a virtual call can be strength-reduced to a direct call. bool allow_inline = C->inlining_incrementally(); bool input_not_const = true; @@ -519,12 +526,20 @@ bool LateInlineVirtualCallGenerator::do_late_inline_check(Compile* C, JVMState* Node* receiver = jvms->map()->argument(jvms, 0); const Type* recv_type = C->initial_gvn()->type(receiver); if (recv_type->maybe_null()) { + if (C->print_inlining() || C->print_intrinsics()) { + C->print_inlining(method(), jvms->depth()-1, call_node()->jvms()->bci(), + "late call devirtualization failed (receiver may be null)"); + } return false; } // Even if inlining is not allowed, a virtual call can be strength-reduced to a direct call. bool allow_inline = C->inlining_incrementally(); if (!allow_inline && _callee->holder()->is_interface()) { // Don't convert the interface call to a direct call guarded by an interface subtype check. + if (C->print_inlining() || C->print_intrinsics()) { + C->print_inlining(method(), jvms->depth()-1, call_node()->jvms()->bci(), + "late call devirtualization failed (interface call)"); + } return false; } CallGenerator* cg = C->call_generator(_callee, diff --git a/src/hotspot/share/opto/callnode.cpp b/src/hotspot/share/opto/callnode.cpp index 52abb0d919c..d83ba2846c4 100644 --- a/src/hotspot/share/opto/callnode.cpp +++ b/src/hotspot/share/opto/callnode.cpp @@ -1654,6 +1654,7 @@ AllocateNode::AllocateNode(Compile* C, const TypeFunc *atype, init_req( KlassNode , klass_node); init_req( InitialTest , initial_test); init_req( ALength , topnode); + init_req( ValidLengthTest , topnode); C->add_macro_node(this); } @@ -1686,54 +1687,6 @@ Node *AllocateNode::make_ideal_mark(PhaseGVN *phase, Node* obj, Node* control, N return mark_node; } -//============================================================================= -Node* AllocateArrayNode::Ideal(PhaseGVN *phase, bool can_reshape) { - if (remove_dead_region(phase, can_reshape)) return this; - // Don't bother trying to transform a dead node - if (in(0) && in(0)->is_top()) return NULL; - - const Type* type = phase->type(Ideal_length()); - if (type->isa_int() && type->is_int()->_hi < 0) { - if (can_reshape) { - PhaseIterGVN *igvn = phase->is_IterGVN(); - // Unreachable fall through path (negative array length), - // the allocation can only throw so disconnect it. - Node* proj = proj_out_or_null(TypeFunc::Control); - Node* catchproj = NULL; - if (proj != NULL) { - for (DUIterator_Fast imax, i = proj->fast_outs(imax); i < imax; i++) { - Node *cn = proj->fast_out(i); - if (cn->is_Catch()) { - catchproj = cn->as_Multi()->proj_out_or_null(CatchProjNode::fall_through_index); - break; - } - } - } - if (catchproj != NULL && catchproj->outcnt() > 0 && - (catchproj->outcnt() > 1 || - catchproj->unique_out()->Opcode() != Op_Halt)) { - assert(catchproj->is_CatchProj(), "must be a CatchProjNode"); - Node* nproj = catchproj->clone(); - igvn->register_new_node_with_optimizer(nproj); - - Node *frame = new ParmNode( phase->C->start(), TypeFunc::FramePtr ); - frame = phase->transform(frame); - // Halt & Catch Fire - Node* halt = new HaltNode(nproj, frame, "unexpected negative array length"); - phase->C->root()->add_req(halt); - phase->transform(halt); - - igvn->replace_node(catchproj, phase->C->top()); - return this; - } - } else { - // Can't correct it during regular GVN so register for IGVN - phase->C->record_for_igvn(this); - } - } - return NULL; -} - // Retrieve the length from the AllocateArrayNode. Narrow the type with a // CastII, if appropriate. If we are not allowed to create new nodes, and // a CastII is appropriate, return NULL. diff --git a/src/hotspot/share/opto/callnode.hpp b/src/hotspot/share/opto/callnode.hpp index 7c8baefbca9..1017a76a25e 100644 --- a/src/hotspot/share/opto/callnode.hpp +++ b/src/hotspot/share/opto/callnode.hpp @@ -913,6 +913,7 @@ class AllocateNode : public CallNode { KlassNode, // type (maybe dynamic) of the obj. InitialTest, // slow-path test (may be constant) ALength, // array length (or TOP if none) + ValidLengthTest, ParmLimit }; @@ -922,6 +923,7 @@ class AllocateNode : public CallNode { fields[KlassNode] = TypeInstPtr::NOTNULL; fields[InitialTest] = TypeInt::BOOL; fields[ALength] = t; // length (can be a bad length) + fields[ValidLengthTest] = TypeInt::BOOL; const TypeTuple *domain = TypeTuple::make(ParmLimit, fields); @@ -1016,18 +1018,16 @@ class AllocateNode : public CallNode { // class AllocateArrayNode : public AllocateNode { public: - AllocateArrayNode(Compile* C, const TypeFunc *atype, Node *ctrl, Node *mem, Node *abio, - Node* size, Node* klass_node, Node* initial_test, - Node* count_val - ) + AllocateArrayNode(Compile* C, const TypeFunc* atype, Node* ctrl, Node* mem, Node* abio, Node* size, Node* klass_node, + Node* initial_test, Node* count_val, Node* valid_length_test) : AllocateNode(C, atype, ctrl, mem, abio, size, klass_node, initial_test) { init_class_id(Class_AllocateArray); set_req(AllocateNode::ALength, count_val); + set_req(AllocateNode::ValidLengthTest, valid_length_test); } virtual int Opcode() const; - virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); // Dig the length operand out of a array allocation site. Node* Ideal_length() { diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index 71cc378790b..0b48e742ca1 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -2631,6 +2631,17 @@ const Type* CatchNode::Value(PhaseGVN* phase) const { // Rethrows always throw exceptions, never return if (call->entry_point() == OptoRuntime::rethrow_stub()) { f[CatchProjNode::fall_through_index] = Type::TOP; + } else if (call->is_AllocateArray()) { + Node* klass_node = call->in(AllocateNode::KlassNode); + Node* length = call->in(AllocateNode::ALength); + const Type* length_type = phase->type(length); + const Type* klass_type = phase->type(klass_node); + Node* valid_length_test = call->in(AllocateNode::ValidLengthTest); + const Type* valid_length_test_t = phase->type(valid_length_test); + if (length_type == Type::TOP || klass_type == Type::TOP || valid_length_test_t == Type::TOP || + valid_length_test_t->is_int()->is_con(0)) { + f[CatchProjNode::fall_through_index] = Type::TOP; + } } else if( call->req() > TypeFunc::Parms ) { const Type *arg0 = phase->type( call->in(TypeFunc::Parms) ); // Check for null receiver to virtual or interface calls diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 91b6427df25..fb596a55f78 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -3740,7 +3740,7 @@ bool Compile::final_graph_reshaping() { // 'fall-thru' path, so expected kids is 1 less. if (n->is_PCTable() && n->in(0) && n->in(0)->in(0)) { if (n->in(0)->in(0)->is_Call()) { - CallNode *call = n->in(0)->in(0)->as_Call(); + CallNode* call = n->in(0)->in(0)->as_Call(); if (call->entry_point() == OptoRuntime::rethrow_stub()) { required_outcnt--; // Rethrow always has 1 less kid } else if (call->req() > TypeFunc::Parms && @@ -3749,22 +3749,25 @@ bool Compile::final_graph_reshaping() { // detected that the virtual call will always result in a null // pointer exception. The fall-through projection of this CatchNode // will not be populated. - Node *arg0 = call->in(TypeFunc::Parms); + Node* arg0 = call->in(TypeFunc::Parms); if (arg0->is_Type() && arg0->as_Type()->type()->higher_equal(TypePtr::NULL_PTR)) { required_outcnt--; } - } else if (call->entry_point() == OptoRuntime::new_array_Java() && - call->req() > TypeFunc::Parms+1 && - call->is_CallStaticJava()) { - // Check for negative array length. In such case, the optimizer has + } else if (call->entry_point() == OptoRuntime::new_array_Java() || + call->entry_point() == OptoRuntime::new_array_nozero_Java()) { + // Check for illegal array length. In such case, the optimizer has // detected that the allocation attempt will always result in an // exception. There is no fall-through projection of this CatchNode . - Node *arg1 = call->in(TypeFunc::Parms+1); - if (arg1->is_Type() && - arg1->as_Type()->type()->join(TypeInt::POS)->empty()) { + assert(call->is_CallStaticJava(), "static call expected"); + assert(call->req() == call->jvms()->endoff() + 1, "missing extra input"); + Node* valid_length_test = call->in(call->req()-1); + call->del_req(call->req()-1); + if (valid_length_test->find_int_con(1) == 0) { required_outcnt--; } + assert(n->outcnt() == required_outcnt, "malformed control flow"); + continue; } } } @@ -3773,6 +3776,14 @@ bool Compile::final_graph_reshaping() { record_method_not_compilable("malformed control flow"); return true; // Not all targets reachable! } + } else if (n->is_PCTable() && n->in(0) && n->in(0)->in(0) && n->in(0)->in(0)->is_Call()) { + CallNode* call = n->in(0)->in(0)->as_Call(); + if (call->entry_point() == OptoRuntime::new_array_Java() || + call->entry_point() == OptoRuntime::new_array_nozero_Java()) { + assert(call->is_CallStaticJava(), "static call expected"); + assert(call->req() == call->jvms()->endoff() + 1, "missing extra input"); + call->del_req(call->req()-1); // valid length test useless now + } } // Check that I actually visited all kids. Unreached kids // must be infinite loops. diff --git a/src/hotspot/share/opto/doCall.cpp b/src/hotspot/share/opto/doCall.cpp index a0a042ca010..d343075e8aa 100644 --- a/src/hotspot/share/opto/doCall.cpp +++ b/src/hotspot/share/opto/doCall.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -67,13 +67,17 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool JVMState* jvms, bool allow_inline, float prof_factor, ciKlass* speculative_receiver_type, bool allow_intrinsics) { - ciMethod* caller = jvms->method(); - int bci = jvms->bci(); - Bytecodes::Code bytecode = caller->java_code_at_bci(bci); - guarantee(callee != NULL, "failed method resolution"); + assert(callee != NULL, "failed method resolution"); + + ciMethod* caller = jvms->method(); + int bci = jvms->bci(); + Bytecodes::Code bytecode = caller->java_code_at_bci(bci); + ciMethod* orig_callee = caller->get_method_at_bci(bci); const bool is_virtual_or_interface = (bytecode == Bytecodes::_invokevirtual) || - (bytecode == Bytecodes::_invokeinterface); + (bytecode == Bytecodes::_invokeinterface) || + (orig_callee->intrinsic_id() == vmIntrinsics::_linkToVirtual) || + (orig_callee->intrinsic_id() == vmIntrinsics::_linkToInterface); // Dtrace currently doesn't work unless all calls are vanilla if (env()->dtrace_method_probes()) { diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index ccafbf6fbb2..f923422d81c 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -615,6 +615,13 @@ void GraphKit::builtin_throw(Deoptimization::DeoptReason reason, Node* arg) { const TypeOopPtr* val_type = TypeOopPtr::make_from_klass(env()->String_klass()); Node *store = access_store_at(ex_node, adr, adr_typ, null(), val_type, T_OBJECT, IN_HEAP); + if (!method()->has_exception_handlers()) { + // We don't need to preserve the stack if there's no handler as the entire frame is going to be popped anyway. + // This prevents issues with exception handling and late inlining. + set_sp(0); + clean_stack(0); + } + add_exception_state(make_exception_state(ex_node)); return; } @@ -2737,7 +2744,9 @@ void GraphKit::make_slow_call_ex(Node* call, ciInstanceKlass* ex_klass, bool sep // Make a catch node with just two handlers: fall-through and catch-all Node* i_o = _gvn.transform( new ProjNode(call, TypeFunc::I_O, separate_io_proj) ); Node* catc = _gvn.transform( new CatchNode(control(), i_o, 2) ); - Node* norm = _gvn.transform( new CatchProjNode(catc, CatchProjNode::fall_through_index, CatchProjNode::no_handler_bci) ); + Node* norm = new CatchProjNode(catc, CatchProjNode::fall_through_index, CatchProjNode::no_handler_bci); + _gvn.set_type_bottom(norm); + C->record_for_igvn(norm); Node* excp = _gvn.transform( new CatchProjNode(catc, CatchProjNode::catch_all_index, CatchProjNode::no_handler_bci) ); { PreserveJVMState pjvms(this); @@ -3976,20 +3985,28 @@ Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable) initial_slow_test = initial_slow_test->as_Bool()->as_int_value(&_gvn); } + const TypeOopPtr* ary_type = _gvn.type(klass_node)->is_klassptr()->as_instance_type(); + Node* valid_length_test = _gvn.intcon(1); + if (ary_type->klass()->is_array_klass()) { + BasicType bt = ary_type->klass()->as_array_klass()->element_type()->basic_type(); + jint max = TypeAryPtr::max_array_length(bt); + Node* valid_length_cmp = _gvn.transform(new CmpUNode(length, intcon(max))); + valid_length_test = _gvn.transform(new BoolNode(valid_length_cmp, BoolTest::le)); + } + // Create the AllocateArrayNode and its result projections AllocateArrayNode* alloc = new AllocateArrayNode(C, AllocateArrayNode::alloc_type(TypeInt::INT), control(), mem, i_o(), size, klass_node, initial_slow_test, - length); + length, valid_length_test); // Cast to correct type. Note that the klass_node may be constant or not, // and in the latter case the actual array type will be inexact also. // (This happens via a non-constant argument to inline_native_newArray.) // In any case, the value of klass_node provides the desired array type. const TypeInt* length_type = _gvn.find_int_type(length); - const TypeOopPtr* ary_type = _gvn.type(klass_node)->is_klassptr()->as_instance_type(); if (ary_type->isa_aryptr() && length_type != NULL) { // Try to get a better type than POS for the size ary_type = ary_type->is_aryptr()->cast_to_size(length_type); diff --git a/src/hotspot/share/opto/ifnode.cpp b/src/hotspot/share/opto/ifnode.cpp index 38b40a68b1f..03f3a9e3728 100644 --- a/src/hotspot/share/opto/ifnode.cpp +++ b/src/hotspot/share/opto/ifnode.cpp @@ -1721,6 +1721,16 @@ Node* IfProjNode::Identity(PhaseGVN* phase) { // will cause this node to be reprocessed once the dead branch is killed. in(0)->outcnt() == 1))) { // IfNode control + if (in(0)->is_BaseCountedLoopEnd()) { + // CountedLoopEndNode may be eliminated by if subsuming, replace CountedLoopNode with LoopNode to + // avoid mismatching between CountedLoopNode and CountedLoopEndNode in the following optimization. + Node* head = unique_ctrl_out(); + if (head != NULL && head->is_BaseCountedLoop() && head->in(LoopNode::LoopBackControl) == this) { + Node* new_head = new LoopNode(head->in(LoopNode::EntryControl), this); + phase->is_IterGVN()->register_new_node_with_optimizer(new_head); + phase->is_IterGVN()->replace_node(head, new_head); + } + } return in(0)->in(0); } // no progress diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 9439f998c7f..dbb663923c2 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -1073,7 +1073,6 @@ bool LibraryCallKit::inline_preconditions_checkIndex(BasicType bt) { result = _gvn.transform(result); set_result(result); replace_in_map(index, result); - clear_upper_avx(); return true; } @@ -1561,7 +1560,7 @@ bool LibraryCallKit::inline_string_char_access(bool is_store) { if (is_store) { access_store_at(value, adr, TypeAryPtr::BYTES, ch, TypeInt::CHAR, T_CHAR, IN_HEAP | MO_UNORDERED | C2_MISMATCHED); } else { - ch = access_load_at(value, adr, TypeAryPtr::BYTES, TypeInt::CHAR, T_CHAR, IN_HEAP | MO_UNORDERED | C2_MISMATCHED | C2_CONTROL_DEPENDENT_LOAD); + ch = access_load_at(value, adr, TypeAryPtr::BYTES, TypeInt::CHAR, T_CHAR, IN_HEAP | MO_UNORDERED | C2_MISMATCHED | C2_CONTROL_DEPENDENT_LOAD | C2_UNKNOWN_CONTROL_LOAD); set_result(ch); } return true; diff --git a/src/hotspot/share/opto/loopPredicate.cpp b/src/hotspot/share/opto/loopPredicate.cpp index 6fd40b6447d..cf8b90d67d1 100644 --- a/src/hotspot/share/opto/loopPredicate.cpp +++ b/src/hotspot/share/opto/loopPredicate.cpp @@ -1012,13 +1012,15 @@ class PathFrequency { GrowableArray _freqs; // cache frequencies PhaseIdealLoop* _phase; - void set_rounding(int mode) { - // fesetround is broken on windows - NOT_WINDOWS(fesetround(mode);) - } - - void check_frequency(float f) { - NOT_WINDOWS(assert(f <= 1 && f >= 0, "Incorrect frequency");) + float check_and_truncate_frequency(float f) { + assert(f >= 0, "Incorrect frequency"); + // We do not perform an exact (f <= 1) check + // this would be error prone with rounding of floats. + // Performing a check like (f <= 1+eps) would be of benefit, + // however, it is not evident how to determine such an eps, + // given that an arbitrary number of add/mul operations + // are performed on these frequencies. + return (f > 1) ? 1 : f; } public: @@ -1028,7 +1030,6 @@ class PathFrequency { float to(Node* n) { // post order walk on the CFG graph from n to _dom - set_rounding(FE_TOWARDZERO); // make sure rounding doesn't push frequency above 1 IdealLoopTree* loop = _phase->get_loop(_dom); Node* c = n; for (;;) { @@ -1055,14 +1056,12 @@ class PathFrequency { inner_head = inner_loop->_head->as_Loop(); inner_head->verify_strip_mined(1); } - set_rounding(FE_UPWARD); // make sure rounding doesn't push frequency above 1 float loop_exit_cnt = 0.0f; for (uint i = 0; i < inner_loop->_body.size(); i++) { Node *n = inner_loop->_body[i]; float c = inner_loop->compute_profile_trip_cnt_helper(n); loop_exit_cnt += c; } - set_rounding(FE_TOWARDZERO); float cnt = -1; if (n->in(0)->is_If()) { IfNode* iff = n->in(0)->as_If(); @@ -1082,9 +1081,9 @@ class PathFrequency { cnt = p * jmp->_fcnt; } float this_exit_f = cnt > 0 ? cnt / loop_exit_cnt : 0; - check_frequency(this_exit_f); + this_exit_f = check_and_truncate_frequency(this_exit_f); f = f * this_exit_f; - check_frequency(f); + f = check_and_truncate_frequency(f); } else { float p = -1; if (n->in(0)->is_If()) { @@ -1097,7 +1096,7 @@ class PathFrequency { p = n->in(0)->as_Jump()->_probs[n->as_JumpProj()->_con]; } f = f * p; - check_frequency(f); + f = check_and_truncate_frequency(f); } _freqs.at_put_grow(n->_idx, (float)f, -1); _stack.pop(); @@ -1105,7 +1104,7 @@ class PathFrequency { float prev_f = _freqs_stack.pop(); float new_f = f; f = new_f + prev_f; - check_frequency(f); + f = check_and_truncate_frequency(f); uint i = _stack.index(); if (i < n->req()) { c = n->in(i); @@ -1118,9 +1117,7 @@ class PathFrequency { } } if (_stack.size() == 0) { - set_rounding(FE_TONEAREST); - check_frequency(f); - return f; + return check_and_truncate_frequency(f); } } else if (c->is_Loop()) { ShouldNotReachHere(); diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index a9d28dfbbf5..6c0e7f19ea8 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -1197,7 +1197,7 @@ Node *PhaseIdealLoop::clone_up_backedge_goo(Node *back_ctrl, Node *preheader_ctr } Node* PhaseIdealLoop::cast_incr_before_loop(Node* incr, Node* ctrl, Node* loop) { - Node* castii = new CastIINode(incr, TypeInt::INT, ConstraintCastNode::StrongDependency); + Node* castii = new CastIINode(incr, TypeInt::INT, ConstraintCastNode::UnconditionalDependency); castii->set_req(0, ctrl); register_new_node(castii, ctrl); for (DUIterator_Fast imax, i = incr->fast_outs(imax); i < imax; i++) { @@ -1910,6 +1910,12 @@ bool IdealLoopTree::is_invariant(Node* n) const { } void PhaseIdealLoop::update_main_loop_skeleton_predicates(Node* ctrl, CountedLoopNode* loop_head, Node* init, int stride_con) { + if (init->Opcode() == Op_CastII) { + // skip over the cast added by PhaseIdealLoop::cast_incr_before_loop() when pre/post/main loops are created because + // it can get in the way of type propagation + assert(((CastIINode*)init)->carry_dependency() && loop_head->skip_predicates() == init->in(0), "casted iv phi from pre loop expected"); + init = init->in(1); + } // Search for skeleton predicates and update them according to the new stride Node* entry = ctrl; Node* prev_proj = ctrl; @@ -3370,6 +3376,11 @@ bool IdealLoopTree::do_one_iteration_loop(PhaseIdealLoop *phase) { //============================================================================= //------------------------------iteration_split_impl--------------------------- bool IdealLoopTree::iteration_split_impl(PhaseIdealLoop *phase, Node_List &old_new) { + if (!_head->is_Loop()) { + // Head could be a region with a NeverBranch that was added in beautify loops but the region was not + // yet transformed into a LoopNode. Bail out and wait until beautify loops turns it into a Loop node. + return false; + } // Compute loop trip count if possible. compute_trip_count(phase); @@ -3849,10 +3860,17 @@ bool PhaseIdealLoop::intrinsify_fill(IdealLoopTree* lpt) { index = new LShiftXNode(index, shift->in(2)); _igvn.register_new_node_with_optimizer(index); } - index = new AddPNode(base, base, index); - _igvn.register_new_node_with_optimizer(index); - Node* from = new AddPNode(base, index, offset); + Node* from = new AddPNode(base, base, index); _igvn.register_new_node_with_optimizer(from); + // For normal array fills, C2 uses two AddP nodes for array element + // addressing. But for array fills with Unsafe call, there's only one + // AddP node adding an absolute offset, so we do a NULL check here. + assert(offset != NULL || C->has_unsafe_access(), + "Only array fills with unsafe have no extra offset"); + if (offset != NULL) { + from = new AddPNode(base, from, offset); + _igvn.register_new_node_with_optimizer(from); + } // Compute the number of elements to copy Node* len = new SubINode(head->limit(), head->init_trip()); _igvn.register_new_node_with_optimizer(len); diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 54f92b23841..7a384ef82a6 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -683,8 +683,7 @@ SafePointNode* PhaseIdealLoop::find_safepoint(Node* back_control, Node* x, Ideal Node* mem = safepoint->in(TypeFunc::Memory); - // We can only use that safepoint if there's not side effect - // between the backedge and the safepoint. + // We can only use that safepoint if there's no side effect between the backedge and the safepoint. // mm is used for book keeping MergeMemNode* mm = NULL; @@ -1241,16 +1240,6 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ return false; } - if (x->in(LoopNode::LoopBackControl)->Opcode() == Op_SafePoint && - ((iv_bt == T_INT && LoopStripMiningIter != 0) || - iv_bt == T_LONG)) { - // Leaving the safepoint on the backedge and creating a - // CountedLoop will confuse optimizations. We can't move the - // safepoint around because its jvm state wouldn't match a new - // location. Give up on that loop. - return false; - } - Node* iftrue = back_control; uint iftrue_op = iftrue->Opcode(); Node* iff = iftrue->in(0); @@ -1479,6 +1468,37 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ } } + Node* sfpt = NULL; + if (loop->_child == NULL) { + sfpt = find_safepoint(back_control, x, loop); + } else { + sfpt = iff->in(0); + if (sfpt->Opcode() != Op_SafePoint) { + sfpt = NULL; + } + } + + if (x->in(LoopNode::LoopBackControl)->Opcode() == Op_SafePoint) { + Node* backedge_sfpt = x->in(LoopNode::LoopBackControl); + if (((iv_bt == T_INT && LoopStripMiningIter != 0) || + iv_bt == T_LONG) && + sfpt == NULL) { + // Leaving the safepoint on the backedge and creating a + // CountedLoop will confuse optimizations. We can't move the + // safepoint around because its jvm state wouldn't match a new + // location. Give up on that loop. + return false; + } + if (is_deleteable_safept(backedge_sfpt)) { + lazy_replace(backedge_sfpt, iftrue); + if (loop->_safepts != NULL) { + loop->_safepts->yank(backedge_sfpt); + } + loop->_tail = iftrue; + } + } + + #ifdef ASSERT if (iv_bt == T_INT && !x->as_Loop()->is_transformed_long_inner_loop() && @@ -1517,18 +1537,6 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ } set_subtree_ctrl(adjusted_limit, false); - if (iv_bt == T_INT && LoopStripMiningIter == 0) { - // Check for SafePoint on backedge and remove - Node *sfpt = x->in(LoopNode::LoopBackControl); - if (sfpt->Opcode() == Op_SafePoint && is_deleteable_safept(sfpt)) { - lazy_replace( sfpt, iftrue ); - if (loop->_safepts != NULL) { - loop->_safepts->yank(sfpt); - } - loop->_tail = iftrue; - } - } - // Build a canonical trip test. // Clone code, as old values may be in use. incr = incr->clone(); @@ -1600,13 +1608,11 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ assert(iff->outcnt() == 0, "should be dead now"); lazy_replace( iff, le ); // fix 'get_ctrl' - Node *sfpt2 = le->in(0); - Node* entry_control = init_control; bool strip_mine_loop = iv_bt == T_INT && LoopStripMiningIter > 1 && loop->_child == NULL && - sfpt2->Opcode() == Op_SafePoint && + sfpt != NULL && !loop->_has_call; IdealLoopTree* outer_ilt = NULL; if (strip_mine_loop) { @@ -1632,30 +1638,30 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ if (iv_bt == T_INT && (LoopStripMiningIter == 0 || strip_mine_loop)) { // Check for immediately preceding SafePoint and remove - if (sfpt2->Opcode() == Op_SafePoint && (LoopStripMiningIter != 0 || is_deleteable_safept(sfpt2))) { + if (sfpt != NULL && (LoopStripMiningIter != 0 || is_deleteable_safept(sfpt))) { if (strip_mine_loop) { Node* outer_le = outer_ilt->_tail->in(0); - Node* sfpt = sfpt2->clone(); - sfpt->set_req(0, iffalse); - outer_le->set_req(0, sfpt); + Node* sfpt_clone = sfpt->clone(); + sfpt_clone->set_req(0, iffalse); + outer_le->set_req(0, sfpt_clone); - Node* polladdr = sfpt->in(TypeFunc::Parms); + Node* polladdr = sfpt_clone->in(TypeFunc::Parms); if (polladdr != nullptr && polladdr->is_Load()) { // Polling load should be pinned outside inner loop. Node* new_polladdr = polladdr->clone(); new_polladdr->set_req(0, iffalse); _igvn.register_new_node_with_optimizer(new_polladdr, polladdr); set_ctrl(new_polladdr, iffalse); - sfpt->set_req(TypeFunc::Parms, new_polladdr); + sfpt_clone->set_req(TypeFunc::Parms, new_polladdr); } // When this code runs, loop bodies have not yet been populated. const bool body_populated = false; - register_control(sfpt, outer_ilt, iffalse, body_populated); - set_idom(outer_le, sfpt, dom_depth(sfpt)); + register_control(sfpt_clone, outer_ilt, iffalse, body_populated); + set_idom(outer_le, sfpt_clone, dom_depth(sfpt_clone)); } - lazy_replace( sfpt2, sfpt2->in(TypeFunc::Control)); + lazy_replace(sfpt, sfpt->in(TypeFunc::Control)); if (loop->_safepts != NULL) { - loop->_safepts->yank(sfpt2); + loop->_safepts->yank(sfpt); } } } @@ -3288,7 +3294,7 @@ void IdealLoopTree::counted_loop( PhaseIdealLoop *phase ) { if (_head->is_CountedLoop() || phase->is_counted_loop(_head, loop, T_INT)) { - if (LoopStripMiningIter == 0 || (LoopStripMiningIter > 1 && _child == NULL)) { + if (LoopStripMiningIter == 0 || _head->as_CountedLoop()->is_strip_mined()) { // Indicate we do not need a safepoint here _has_sfpt = 1; } @@ -3714,11 +3720,11 @@ bool PhaseIdealLoop::only_has_infinite_loops() { //----------------------------build_and_optimize------------------------------- // Create a PhaseLoop. Build the ideal Loop tree. Map each Ideal Node to // its corresponding LoopNode. If 'optimize' is true, do some loop cleanups. -void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { +void PhaseIdealLoop::build_and_optimize() { assert(!C->post_loop_opts_phase(), "no loop opts allowed"); - bool do_split_ifs = (mode == LoopOptsDefault); - bool skip_loop_opts = (mode == LoopOptsNone); + bool do_split_ifs = (_mode == LoopOptsDefault); + bool skip_loop_opts = (_mode == LoopOptsNone); int old_progress = C->major_progress(); uint orig_worklist_size = _igvn._worklist.size(); @@ -3789,9 +3795,9 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); // Nothing to do, so get out bool stop_early = !C->has_loops() && !skip_loop_opts && !do_split_ifs && !_verify_me && !_verify_only && - !bs->is_gc_specific_loop_opts_pass(mode); + !bs->is_gc_specific_loop_opts_pass(_mode); bool do_expensive_nodes = C->should_optimize_expensive_nodes(_igvn); - bool strip_mined_loops_expanded = bs->strip_mined_loops_expanded(mode); + bool strip_mined_loops_expanded = bs->strip_mined_loops_expanded(_mode); if (stop_early && !do_expensive_nodes) { return; } @@ -3883,7 +3889,7 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { if (_verify_only) { C->restore_major_progress(old_progress); - assert(C->unique() == unique, "verification mode made Nodes? ? ?"); + assert(C->unique() == unique, "verification _mode made Nodes? ? ?"); assert(_igvn._worklist.size() == orig_worklist_size, "shouldn't push anything"); return; } @@ -3913,8 +3919,8 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { #ifndef PRODUCT C->verify_graph_edges(); if (_verify_me) { // Nested verify pass? - // Check to see if the verify mode is broken - assert(C->unique() == unique, "non-optimize mode made Nodes? ? ?"); + // Check to see if the verify _mode is broken + assert(C->unique() == unique, "non-optimize _mode made Nodes? ? ?"); return; } if (VerifyLoopOptimizations) verify(); @@ -3928,7 +3934,7 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { return; } - if (mode == LoopOptsMaxUnroll) { + if (_mode == LoopOptsMaxUnroll) { for (LoopTreeIterator iter(_ltree_root); !iter.done(); iter.next()) { IdealLoopTree* lpt = iter.current(); if (lpt->is_innermost() && lpt->_allow_optimizations && !lpt->_has_call && lpt->is_counted()) { @@ -3949,7 +3955,7 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { return; } - if (bs->optimize_loops(this, mode, visited, nstack, worklist)) { + if (bs->optimize_loops(this, _mode, visited, nstack, worklist)) { return; } @@ -4090,7 +4096,14 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { sw.transform_loop(lpt, true); } } else if (cl->is_main_loop()) { - sw.transform_loop(lpt, true); + if (!sw.transform_loop(lpt, true)) { + // Instigate more unrolling for optimization when vectorization fails. + if (cl->has_passed_slp()) { + C->set_major_progress(); + cl->set_notpassed_slp(); + cl->mark_do_unroll_only(); + } + } } } } @@ -5353,38 +5366,45 @@ void PhaseIdealLoop::build_loop_late_post_work(Node *n, bool pinned) { } assert(early == legal || legal != C->root(), "bad dominance of inputs"); + if (least != early) { + // Move the node above predicates as far up as possible so a + // following pass of loop predication doesn't hoist a predicate + // that depends on it above that node. + Node* new_ctrl = least; + for (;;) { + if (!new_ctrl->is_Proj()) { + break; + } + CallStaticJavaNode* call = new_ctrl->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none); + if (call == NULL) { + break; + } + int req = call->uncommon_trap_request(); + Deoptimization::DeoptReason trap_reason = Deoptimization::trap_request_reason(req); + if (trap_reason != Deoptimization::Reason_loop_limit_check && + trap_reason != Deoptimization::Reason_predicate && + trap_reason != Deoptimization::Reason_profile_predicate) { + break; + } + Node* c = new_ctrl->in(0)->in(0); + if (is_dominator(c, early) && c != early) { + break; + } + new_ctrl = c; + } + least = new_ctrl; + } // Try not to place code on a loop entry projection // which can inhibit range check elimination. - if (least != early) { + if (least != early && !BarrierSet::barrier_set()->barrier_set_c2()->is_gc_specific_loop_opts_pass(_mode)) { Node* ctrl_out = least->unique_ctrl_out(); if (ctrl_out && ctrl_out->is_Loop() && - least == ctrl_out->in(LoopNode::EntryControl)) { - // Move the node above predicates as far up as possible so a - // following pass of loop predication doesn't hoist a predicate - // that depends on it above that node. - Node* new_ctrl = least; - for (;;) { - if (!new_ctrl->is_Proj()) { - break; - } - CallStaticJavaNode* call = new_ctrl->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none); - if (call == NULL) { - break; - } - int req = call->uncommon_trap_request(); - Deoptimization::DeoptReason trap_reason = Deoptimization::trap_request_reason(req); - if (trap_reason != Deoptimization::Reason_loop_limit_check && - trap_reason != Deoptimization::Reason_predicate && - trap_reason != Deoptimization::Reason_profile_predicate) { - break; - } - Node* c = new_ctrl->in(0)->in(0); - if (is_dominator(c, early) && c != early) { - break; - } - new_ctrl = c; + least == ctrl_out->in(LoopNode::EntryControl) && + (ctrl_out->is_CountedLoop() || ctrl_out->is_OuterStripMinedLoop())) { + Node* least_dom = idom(least); + if (get_loop(least_dom)->is_member(get_loop(least))) { + least = least_dom; } - least = new_ctrl; } } diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index 863be3b67ba..fd2e4978e91 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -1050,9 +1050,10 @@ class PhaseIdealLoop : public PhaseTransform { Node **_idom; // Array of immediate dominators uint *_dom_depth; // Used for fast LCA test GrowableArray* _dom_stk; // For recomputation of dom depth + LoopOptsMode _mode; // build the loop tree and perform any requested optimizations - void build_and_optimize(LoopOptsMode mode); + void build_and_optimize(); // Dominators for the sea of nodes void Dominators(); @@ -1063,9 +1064,10 @@ class PhaseIdealLoop : public PhaseTransform { _igvn(igvn), _verify_me(nullptr), _verify_only(false), + _mode(mode), _nodes_required(UINT_MAX) { assert(mode != LoopOptsVerify, "wrong constructor to verify IdealLoop"); - build_and_optimize(mode); + build_and_optimize(); } #ifndef PRODUCT @@ -1076,8 +1078,9 @@ class PhaseIdealLoop : public PhaseTransform { _igvn(igvn), _verify_me(verify_me), _verify_only(verify_me == nullptr), + _mode(LoopOptsVerify), _nodes_required(UINT_MAX) { - build_and_optimize(LoopOptsVerify); + build_and_optimize(); } #endif diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index f523c1f8248..622d0cfc8f9 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -3728,6 +3728,8 @@ void PhaseIdealLoop::reorg_offsets(IdealLoopTree *loop) { set_ctrl(neg_stride, C->root()); Node *post = new AddINode(opaq, neg_stride); register_new_node(post, c); + post = new CastIINode(post, phi->bottom_type()); // preserve the iv phi's type + register_new_node(post, c); _igvn.rehash_node_delayed(use); for (uint j = 1; j < use->req(); j++) { if (use->in(j) == phi) diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp index d502d9a96d2..1b0947c86e2 100644 --- a/src/hotspot/share/opto/macro.cpp +++ b/src/hotspot/share/opto/macro.cpp @@ -1208,7 +1208,8 @@ void PhaseMacroExpand::expand_allocate_common( AllocateNode* alloc, // allocation node to be expanded Node* length, // array length for an array allocation const TypeFunc* slow_call_type, // Type of slow call - address slow_call_address // Address of slow call + address slow_call_address, // Address of slow call + Node* valid_length_test // whether length is valid or not ) { Node* ctrl = alloc->in(TypeFunc::Control); @@ -1394,6 +1395,12 @@ void PhaseMacroExpand::expand_allocate_common( // Copy debug information and adjust JVMState information, then replace // allocate node with the call call->copy_call_debug_info(&_igvn, alloc); + // For array allocations, copy the valid length check to the call node so Compile::final_graph_reshaping() can verify + // that the call has the expected number of CatchProj nodes (in case the allocation always fails and the fallthrough + // path dies). + if (valid_length_test != NULL) { + call->add_req(valid_length_test); + } if (expand_fast_path) { call->set_cnt(PROB_UNLIKELY_MAG(4)); // Same effect as RC_UNCOMMON. } else { @@ -1875,11 +1882,12 @@ Node* PhaseMacroExpand::prefetch_allocation(Node* i_o, Node*& needgc_false, void PhaseMacroExpand::expand_allocate(AllocateNode *alloc) { expand_allocate_common(alloc, NULL, OptoRuntime::new_instance_Type(), - OptoRuntime::new_instance_Java()); + OptoRuntime::new_instance_Java(), NULL); } void PhaseMacroExpand::expand_allocate_array(AllocateArrayNode *alloc) { Node* length = alloc->in(AllocateNode::ALength); + Node* valid_length_test = alloc->in(AllocateNode::ValidLengthTest); InitializeNode* init = alloc->initialization(); Node* klass_node = alloc->in(AllocateNode::KlassNode); ciKlass* k = _igvn.type(klass_node)->is_klassptr()->klass(); @@ -1894,7 +1902,7 @@ void PhaseMacroExpand::expand_allocate_array(AllocateArrayNode *alloc) { } expand_allocate_common(alloc, length, OptoRuntime::new_array_Type(), - slow_call_address); + slow_call_address, valid_length_test); } //-------------------mark_eliminated_box---------------------------------- diff --git a/src/hotspot/share/opto/macro.hpp b/src/hotspot/share/opto/macro.hpp index b65b97fec87..c028120a0fc 100644 --- a/src/hotspot/share/opto/macro.hpp +++ b/src/hotspot/share/opto/macro.hpp @@ -92,8 +92,8 @@ class PhaseMacroExpand : public Phase { void expand_allocate_common(AllocateNode* alloc, Node* length, const TypeFunc* slow_call_type, - address slow_call_address); - void yank_initalize_node(InitializeNode* node); + address slow_call_address, + Node* valid_length_test); void yank_alloc_node(AllocateNode* alloc); Node *value_from_mem(Node *mem, Node *ctl, BasicType ft, const Type *ftype, const TypeOopPtr *adr_t, AllocateNode *alloc); Node *value_from_mem_phi(Node *mem, BasicType ft, const Type *ftype, const TypeOopPtr *adr_t, AllocateNode *alloc, Node_Stack *value_phis, int level); diff --git a/src/hotspot/share/opto/movenode.cpp b/src/hotspot/share/opto/movenode.cpp index d7b445ea768..4e22a35aaec 100644 --- a/src/hotspot/share/opto/movenode.cpp +++ b/src/hotspot/share/opto/movenode.cpp @@ -75,21 +75,25 @@ // Return a node which is more "ideal" than the current node. // Move constants to the right. Node *CMoveNode::Ideal(PhaseGVN *phase, bool can_reshape) { - if( in(0) && remove_dead_region(phase, can_reshape) ) return this; + if (in(0) != NULL && remove_dead_region(phase, can_reshape)) { + return this; + } // Don't bother trying to transform a dead node - if( in(0) && in(0)->is_top() ) return NULL; + if (in(0) != NULL && in(0)->is_top()) { + return NULL; + } assert(in(Condition) != this && - in(IfFalse) != this && - in(IfTrue) != this, "dead loop in CMoveNode::Ideal" ); - if( phase->type(in(Condition)) == Type::TOP ) - return NULL; // return NULL when Condition is dead - - if( in(IfFalse)->is_Con() && !in(IfTrue)->is_Con() ) { - if( in(Condition)->is_Bool() ) { - BoolNode* b = in(Condition)->as_Bool(); - BoolNode* b2 = b->negate(phase); - return make(in(Control), phase->transform(b2), in(IfTrue), in(IfFalse), _type); - } + in(IfFalse) != this && + in(IfTrue) != this, "dead loop in CMoveNode::Ideal"); + if (phase->type(in(Condition)) == Type::TOP || + phase->type(in(IfFalse)) == Type::TOP || + phase->type(in(IfTrue)) == Type::TOP) { + return NULL; + } + // Canonicalize the node by moving constants to the right input. + if (in(Condition)->is_Bool() && phase->type(in(IfFalse))->singleton() && !phase->type(in(IfTrue))->singleton()) { + BoolNode* b = in(Condition)->as_Bool()->negate(phase); + return make(in(Control), phase->transform(b), in(IfTrue), in(IfFalse), _type); } return NULL; } @@ -191,14 +195,10 @@ Node *CMoveINode::Ideal(PhaseGVN *phase, bool can_reshape) { // If zero is on the left (false-case, no-move-case) it must mean another // constant is on the right (otherwise the shared CMove::Ideal code would - // have moved the constant to the right). This situation is bad for Intel - // and a don't-care for Sparc. It's bad for Intel because the zero has to - // be manifested in a register with a XOR which kills flags, which are live - // on input to the CMoveI, leading to a situation which causes excessive - // spilling on Intel. For Sparc, if the zero in on the left the Sparc will - // zero a register via G0 and conditionally-move the other constant. If the - // zero is on the right, the Sparc will load the first constant with a - // 13-bit set-lo and conditionally move G0. See bug 4677505. + // have moved the constant to the right). This situation is bad for x86 because + // the zero has to be manifested in a register with a XOR which kills flags, + // which are live on input to the CMoveI, leading to a situation which causes + // excessive spilling. See bug 4677505. if( phase->type(in(IfFalse)) == TypeInt::ZERO && !(phase->type(in(IfTrue)) == TypeInt::ZERO) ) { if( in(Condition)->is_Bool() ) { BoolNode* b = in(Condition)->as_Bool(); diff --git a/src/hotspot/share/opto/parse2.cpp b/src/hotspot/share/opto/parse2.cpp index becd187a5ed..924d008925a 100644 --- a/src/hotspot/share/opto/parse2.cpp +++ b/src/hotspot/share/opto/parse2.cpp @@ -1876,33 +1876,35 @@ void Parse::do_one_bytecode() { case Bytecodes::_bipush: push(intcon(iter().get_constant_u1())); break; case Bytecodes::_sipush: push(intcon(iter().get_constant_u2())); break; case Bytecodes::_aconst_null: push(null()); break; + case Bytecodes::_ldc: case Bytecodes::_ldc_w: - case Bytecodes::_ldc2_w: - // If the constant is unresolved, run this BC once in the interpreter. - { - ciConstant constant = iter().get_constant(); - if (!constant.is_valid() || - (constant.basic_type() == T_OBJECT && - !constant.as_object()->is_loaded())) { - int index = iter().get_constant_pool_index(); - constantTag tag = iter().get_constant_pool_tag(index); - uncommon_trap(Deoptimization::make_trap_request - (Deoptimization::Reason_unloaded, - Deoptimization::Action_reinterpret, - index), - NULL, tag.internal_name()); - break; - } + case Bytecodes::_ldc2_w: { + ciConstant constant = iter().get_constant(); + if (constant.is_loaded()) { assert(constant.basic_type() != T_OBJECT || constant.as_object()->is_instance(), "must be java_mirror of klass"); const Type* con_type = Type::make_from_constant(constant); if (con_type != NULL) { push_node(con_type->basic_type(), makecon(con_type)); } - } + } else { + // If the constant is unresolved or in error state, run this BC in the interpreter. + if (iter().is_in_error()) { + uncommon_trap(Deoptimization::make_trap_request(Deoptimization::Reason_unhandled, + Deoptimization::Action_none), + NULL, "constant in error state", true /* must_throw */); + } else { + int index = iter().get_constant_pool_index(); + uncommon_trap(Deoptimization::make_trap_request(Deoptimization::Reason_unloaded, + Deoptimization::Action_reinterpret, + index), + NULL, "unresolved constant", false /* must_throw */); + } + } break; + } case Bytecodes::_aload_0: push( local(0) ); diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index 1ff359e2b42..8215efe1e94 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -1510,13 +1510,13 @@ void PhaseIterGVN::add_users_to_worklist0( Node *n ) { // Return counted loop Phi if as a counted loop exit condition, cmp // compares the the induction variable with n -static PhiNode* countedloop_phi_from_cmp(CmpINode* cmp, Node* n) { +static PhiNode* countedloop_phi_from_cmp(CmpNode* cmp, Node* n) { for (DUIterator_Fast imax, i = cmp->fast_outs(imax); i < imax; i++) { Node* bol = cmp->fast_out(i); for (DUIterator_Fast i2max, i2 = bol->fast_outs(i2max); i2 < i2max; i2++) { Node* iff = bol->fast_out(i2); - if (iff->is_CountedLoopEnd()) { - CountedLoopEndNode* cle = iff->as_CountedLoopEnd(); + if (iff->is_BaseCountedLoopEnd()) { + BaseCountedLoopEndNode* cle = iff->as_BaseCountedLoopEnd(); if (cle->limit() == n) { PhiNode* phi = cle->phi(); if (phi != NULL) { @@ -1693,7 +1693,7 @@ bool PhaseIterGVN::no_dependent_zero_check(Node* n) const { case Op_DivI: case Op_ModI: { // Type of divisor includes 0? - if (n->in(2)->is_top()) { + if (type(n->in(2)) == Type::TOP) { // 'n' is dead. Treat as if zero check is still there to avoid any further optimizations. return false; } @@ -1703,7 +1703,7 @@ bool PhaseIterGVN::no_dependent_zero_check(Node* n) const { case Op_DivL: case Op_ModL: { // Type of divisor includes 0? - if (n->in(2)->is_top()) { + if (type(n->in(2)) == Type::TOP) { // 'n' is dead. Treat as if zero check is still there to avoid any further optimizations. return false; } @@ -1834,8 +1834,8 @@ void PhaseCCP::analyze() { // If n is used in a counted loop exit condition then the type // of the counted loop's Phi depends on the type of n. See // PhiNode::Value(). - if (m_op == Op_CmpI) { - PhiNode* phi = countedloop_phi_from_cmp((CmpINode*)m, n); + if (m_op == Op_CmpI || m_op == Op_CmpL) { + PhiNode* phi = countedloop_phi_from_cmp(m->as_Cmp(), n); if (phi != NULL) { worklist.push(phi); } diff --git a/src/hotspot/share/opto/split_if.cpp b/src/hotspot/share/opto/split_if.cpp index 6bf835926e5..325b8ba0436 100644 --- a/src/hotspot/share/opto/split_if.cpp +++ b/src/hotspot/share/opto/split_if.cpp @@ -128,8 +128,8 @@ bool PhaseIdealLoop::split_up( Node *n, Node *blk1, Node *blk2 ) { } } else { // We might see an Opaque1 from a loop limit check here - assert(use->is_If() || use->is_CMove() || use->Opcode() == Op_Opaque1, "unexpected node type"); - Node *use_c = use->is_If() ? use->in(0) : get_ctrl(use); + assert(use->is_If() || use->is_CMove() || use->Opcode() == Op_Opaque1 || use->is_AllocateArray(), "unexpected node type"); + Node *use_c = (use->is_If() || use->is_AllocateArray()) ? use->in(0) : get_ctrl(use); if (use_c == blk1 || use_c == blk2) { assert(use->is_CMove(), "unexpected node type"); continue; @@ -166,14 +166,15 @@ bool PhaseIdealLoop::split_up( Node *n, Node *blk1, Node *blk2 ) { --j; } else { // We might see an Opaque1 from a loop limit check here - assert(u->is_If() || u->is_CMove() || u->Opcode() == Op_Opaque1, "unexpected node type"); - assert(u->in(1) == bol, ""); + assert(u->is_If() || u->is_CMove() || u->Opcode() == Op_Opaque1 || u->is_AllocateArray(), "unexpected node type"); + assert(u->is_AllocateArray() || u->in(1) == bol, ""); + assert(!u->is_AllocateArray() || u->in(AllocateNode::ValidLengthTest) == bol, "wrong input to AllocateArray"); // Get control block of either the CMove or the If input - Node *u_ctrl = u->is_If() ? u->in(0) : get_ctrl(u); + Node *u_ctrl = (u->is_If() || u->is_AllocateArray()) ? u->in(0) : get_ctrl(u); assert((u_ctrl != blk1 && u_ctrl != blk2) || u->is_CMove(), "won't converge"); Node *x = bol->clone(); register_new_node(x, u_ctrl); - _igvn.replace_input_of(u, 1, x); + _igvn.replace_input_of(u, u->is_AllocateArray() ? AllocateNode::ValidLengthTest : 1, x); --j; } } @@ -200,6 +201,24 @@ bool PhaseIdealLoop::split_up( Node *n, Node *blk1, Node *blk2 ) { return true; } } + if (n->Opcode() == Op_OpaqueLoopStride || n->Opcode() == Op_OpaqueLoopInit) { + Unique_Node_List wq; + wq.push(n); + for (uint i = 0; i < wq.size(); i++) { + Node* m = wq.at(i); + if (m->is_If()) { + assert(skeleton_predicate_has_opaque(m->as_If()), "opaque node not reachable from if?"); + Node* bol = clone_skeleton_predicate_bool(m, NULL, NULL, m->in(0)); + _igvn.replace_input_of(m, 1, bol); + } else { + assert(!m->is_CFG(), "not CFG expected"); + for (DUIterator_Fast jmax, j = m->fast_outs(jmax); j < jmax; j++) { + Node* u = m->fast_out(j); + wq.push(u); + } + } + } + } // See if splitting-up a Store. Any anti-dep loads must go up as // well. An anti-dep load might be in the wrong block, because in diff --git a/src/hotspot/share/opto/subtypenode.cpp b/src/hotspot/share/opto/subtypenode.cpp index 508d62fd04c..7aed5e65ef3 100644 --- a/src/hotspot/share/opto/subtypenode.cpp +++ b/src/hotspot/share/opto/subtypenode.cpp @@ -135,7 +135,7 @@ Node *SubTypeCheckNode::Ideal(PhaseGVN* phase, bool can_reshape) { Node* obj = AddPNode::Ideal_base_and_offset(addr, phase, con); if (con == oopDesc::klass_offset_in_bytes() && obj != NULL) { assert(is_oop(phase, obj), "only for oop input"); - set_req(ObjOrSubKlass, obj); + set_req_X(ObjOrSubKlass, obj, phase); return this; } } @@ -144,7 +144,7 @@ Node *SubTypeCheckNode::Ideal(PhaseGVN* phase, bool can_reshape) { Node* allocated_klass = AllocateNode::Ideal_klass(obj_or_subklass, phase); if (allocated_klass != NULL) { assert(is_oop(phase, obj_or_subklass), "only for oop input"); - set_req(ObjOrSubKlass, allocated_klass); + set_req_X(ObjOrSubKlass, allocated_klass, phase); return this; } diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index e9199dd44e6..987ab27f309 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -95,38 +95,48 @@ SuperWord::SuperWord(PhaseIdealLoop* phase) : static const bool _do_vector_loop_experimental = false; // Experimental vectorization which uses data from loop unrolling. //------------------------------transform_loop--------------------------- -void SuperWord::transform_loop(IdealLoopTree* lpt, bool do_optimization) { +bool SuperWord::transform_loop(IdealLoopTree* lpt, bool do_optimization) { assert(UseSuperWord, "should be"); // SuperWord only works with power of two vector sizes. int vector_width = Matcher::vector_width_in_bytes(T_BYTE); if (vector_width < 2 || !is_power_of_2(vector_width)) { - return; + return false; } assert(lpt->_head->is_CountedLoop(), "must be"); CountedLoopNode *cl = lpt->_head->as_CountedLoop(); - if (!cl->is_valid_counted_loop(T_INT)) return; // skip malformed counted loop + if (!cl->is_valid_counted_loop(T_INT)) { + return false; // skip malformed counted loop + } bool post_loop_allowed = (PostLoopMultiversioning && Matcher::has_predicated_vectors() && cl->is_post_loop()); if (post_loop_allowed) { - if (cl->is_reduction_loop()) return; // no predication mapping + if (cl->is_reduction_loop()) { + return false; // no predication mapping + } Node *limit = cl->limit(); - if (limit->is_Con()) return; // non constant limits only + if (limit->is_Con()) { + return false; // non constant limits only + } // Now check the limit for expressions we do not handle if (limit->is_Add()) { Node *in2 = limit->in(2); if (in2->is_Con()) { int val = in2->get_int(); // should not try to program these cases - if (val < 0) return; + if (val < 0) { + return false; + } } } } // skip any loop that has not been assigned max unroll by analysis if (do_optimization) { - if (SuperWordLoopUnrollAnalysis && cl->slp_max_unroll() == 0) return; + if (SuperWordLoopUnrollAnalysis && cl->slp_max_unroll() == 0) { + return false; + } } // Check for no control flow in body (other than exit) @@ -141,28 +151,32 @@ void SuperWord::transform_loop(IdealLoopTree* lpt, bool do_optimization) { lpt->dump_head(); } #endif - return; + return false; } // Make sure the are no extra control users of the loop backedge if (cl->back_control()->outcnt() != 1) { - return; + return false; } // Skip any loops already optimized by slp - if (cl->is_vectorized_loop()) return; + if (cl->is_vectorized_loop()) { + return false; + } - if (cl->is_unroll_only()) return; + if (cl->is_unroll_only()) { + return false; + } if (cl->is_main_loop()) { // Check for pre-loop ending with CountedLoopEnd(Bool(Cmp(x,Opaque1(limit)))) CountedLoopEndNode* pre_end = find_pre_loop_end(cl); if (pre_end == NULL) { - return; + return false; } Node* pre_opaq1 = pre_end->limit(); if (pre_opaq1->Opcode() != Op_Opaque1) { - return; + return false; } set_pre_loop_end(pre_end); } @@ -175,9 +189,10 @@ void SuperWord::transform_loop(IdealLoopTree* lpt, bool do_optimization) { // For now, define one block which is the entire loop body set_bb(cl); + bool success = true; if (do_optimization) { assert(_packset.length() == 0, "packset must be empty"); - SLP_extract(); + success = SLP_extract(); if (PostLoopMultiversioning && Matcher::has_predicated_vectors()) { if (cl->is_vectorized_loop() && cl->is_main_loop() && !cl->is_reduction_loop()) { IdealLoopTree *lpt_next = lpt->_next; @@ -192,6 +207,7 @@ void SuperWord::transform_loop(IdealLoopTree* lpt, bool do_optimization) { } } } + return success; } //------------------------------early unrolling analysis------------------------------ @@ -451,7 +467,7 @@ void SuperWord::unrolling_analysis(int &local_loop_unroll_factor) { // inserting scalar promotion, vector creation from multiple scalars, and // extraction of scalar values from vectors. // -void SuperWord::SLP_extract() { +bool SuperWord::SLP_extract() { #ifndef PRODUCT if (_do_vector_loop && TraceSuperWord) { @@ -466,7 +482,7 @@ void SuperWord::SLP_extract() { #endif // Ready the block if (!construct_bb()) { - return; // Exit if no interesting nodes or complex graph. + return false; // Exit if no interesting nodes or complex graph. } // build _dg, _disjoint_ptrs @@ -483,7 +499,7 @@ void SuperWord::SLP_extract() { hoist_loads_in_graph(); // this only rebuild the graph; all basic structs need rebuild explicitly if (!construct_bb()) { - return; // Exit if no interesting nodes or complex graph. + return false; // Exit if no interesting nodes or complex graph. } dependence_graph(); compute_max_depth(); @@ -511,7 +527,7 @@ void SuperWord::SLP_extract() { find_adjacent_refs(); if (align_to_ref() == NULL) { - return; // Did not find memory reference to align vectors + return false; // Did not find memory reference to align vectors } extend_packlist(); @@ -563,15 +579,15 @@ void SuperWord::SLP_extract() { // map base types for vector usage compute_vector_element_type(); } else { - return; + return false; } } else { // for some reason we could not map the slp analysis state of the vectorized loop - return; + return false; } } - output(); + return output(); } //------------------------------find_adjacent_refs--------------------------- @@ -2385,17 +2401,11 @@ void SuperWord::print_loop(bool whole) { //------------------------------output--------------------------- // Convert packs into vector node operations -void SuperWord::output() { +bool SuperWord::output() { CountedLoopNode *cl = lpt()->_head->as_CountedLoop(); Compile* C = _phase->C; if (_packset.length() == 0) { - if (cl->is_main_loop()) { - // Instigate more unrolling for optimization when vectorization fails. - C->set_major_progress(); - cl->set_notpassed_slp(); - cl->mark_do_unroll_only(); - } - return; + return false; } #ifndef PRODUCT @@ -2429,7 +2439,7 @@ void SuperWord::output() { if (do_reserve_copy() && !make_reversable.has_reserved()) { NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: loop was not reserved correctly, exiting SuperWord");}) - return; + return false; } for (int i = 0; i < _block.length(); i++) { @@ -2474,7 +2484,7 @@ void SuperWord::output() { if (val == NULL) { if (do_reserve_copy()) { NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: val should not be NULL, exiting SuperWord");}) - return; //and reverse to backup IG + return false; //and reverse to backup IG } ShouldNotReachHere(); } @@ -2518,7 +2528,7 @@ void SuperWord::output() { if (in1 == NULL) { if (do_reserve_copy()) { NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: in1 should not be NULL, exiting SuperWord");}) - return; //and reverse to backup IG + return false; //and reverse to backup IG } ShouldNotReachHere(); } @@ -2527,7 +2537,7 @@ void SuperWord::output() { if (in2 == NULL) { if (do_reserve_copy()) { NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: in2 should not be NULL, exiting SuperWord");}) - return; //and reverse to backup IG + return false; //and reverse to backup IG } ShouldNotReachHere(); } @@ -2561,7 +2571,7 @@ void SuperWord::output() { } else if (is_cmov_pack(p)) { if (can_process_post_loop) { // do not refactor of flow in post loop context - return; + return false; } if (!n->is_CMove()) { continue; @@ -2578,7 +2588,7 @@ void SuperWord::output() { if (!bol->is_Bool()) { if (do_reserve_copy()) { NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: expected %d bool node, exiting SuperWord", bol->_idx); bol->dump();}) - return; //and reverse to backup IG + return false; //and reverse to backup IG } ShouldNotReachHere(); } @@ -2594,7 +2604,7 @@ void SuperWord::output() { if (src1 == NULL) { if (do_reserve_copy()) { NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: src1 should not be NULL, exiting SuperWord");}) - return; //and reverse to backup IG + return false; //and reverse to backup IG } ShouldNotReachHere(); } @@ -2602,7 +2612,7 @@ void SuperWord::output() { if (src2 == NULL) { if (do_reserve_copy()) { NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: src2 should not be NULL, exiting SuperWord");}) - return; //and reverse to backup IG + return false; //and reverse to backup IG } ShouldNotReachHere(); } @@ -2626,7 +2636,7 @@ void SuperWord::output() { } else { if (do_reserve_copy()) { NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: ShouldNotReachHere, exiting SuperWord");}) - return; //and reverse to backup IG + return false; //and reverse to backup IG } ShouldNotReachHere(); } @@ -2635,7 +2645,7 @@ void SuperWord::output() { if (vn == NULL) { if (do_reserve_copy()){ NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: got NULL node, cannot proceed, exiting SuperWord");}) - return; //and reverse to backup IG + return false; //and reverse to backup IG } ShouldNotReachHere(); } @@ -2653,7 +2663,7 @@ void SuperWord::output() { // first check if the vector size if the maximum vector which we can use on the machine, // other vector size have reduced values for predicated data mapping. if (vlen_in_bytes != (uint)MaxVectorSize) { - return; + return false; } } @@ -2726,7 +2736,7 @@ void SuperWord::output() { make_reversable.use_new(); } NOT_PRODUCT(if(is_trace_loop_reverse()) {tty->print_cr("\n Final loop after SuperWord"); print_loop(true);}) - return; + return true; } //------------------------------vector_opd--------------------------- diff --git a/src/hotspot/share/opto/superword.hpp b/src/hotspot/share/opto/superword.hpp index ddddfc83663..9c92365865a 100644 --- a/src/hotspot/share/opto/superword.hpp +++ b/src/hotspot/share/opto/superword.hpp @@ -286,7 +286,7 @@ class SuperWord : public ResourceObj { public: SuperWord(PhaseIdealLoop* phase); - void transform_loop(IdealLoopTree* lpt, bool do_optimization); + bool transform_loop(IdealLoopTree* lpt, bool do_optimization); void unrolling_analysis(int &local_loop_unroll_factor); @@ -422,7 +422,7 @@ class SuperWord : public ResourceObj { // methods // Extract the superword level parallelism - void SLP_extract(); + bool SLP_extract(); // Find the adjacent memory references and create pack pairs for them. void find_adjacent_refs(); // Tracing support @@ -509,7 +509,7 @@ class SuperWord : public ResourceObj { Node* find_last_mem_state(Node_List* pk, Node* first_mem); // Convert packs into vector node operations - void output(); + bool output(); // Create a vector operand for the nodes in pack p for operand: in(opd_idx) Node* vector_opd(Node_List* p, int opd_idx); // Can code be generated for pack p? diff --git a/src/hotspot/share/opto/vector.cpp b/src/hotspot/share/opto/vector.cpp index b6b157e328f..65f32178865 100644 --- a/src/hotspot/share/opto/vector.cpp +++ b/src/hotspot/share/opto/vector.cpp @@ -315,6 +315,21 @@ Node* PhaseVector::expand_vbox_node_helper(Node* vbox, } new_phi = C->initial_gvn()->transform(new_phi); return new_phi; + } else if (vbox->is_Phi() && (vect->is_Vector() || vect->is_LoadVector())) { + // Handle the case when the allocation input to VectorBoxNode is a phi + // but the vector input is not, which can definitely be the case if the + // vector input has been value-numbered. It seems to be safe to do by + // construction because VectorBoxNode and VectorBoxAllocate come in a + // specific order as a result of expanding an intrinsic call. After that, if + // any of the inputs to VectorBoxNode are value-numbered they can only + // move up and are guaranteed to dominate. + Node* new_phi = new PhiNode(vbox->as_Phi()->region(), box_type); + for (uint i = 1; i < vbox->req(); i++) { + Node* new_box = expand_vbox_node_helper(vbox->in(i), vect, box_type, vect_type); + new_phi->set_req(i, new_box); + } + new_phi = C->initial_gvn()->transform(new_phi); + return new_phi; } else if (vbox->is_Proj() && vbox->in(0)->Opcode() == Op_VectorBoxAllocate) { VectorBoxAllocateNode* vbox_alloc = static_cast(vbox->in(0)); return expand_vbox_alloc_node(vbox_alloc, vect, box_type, vect_type); diff --git a/src/hotspot/share/prims/vectorSupport.cpp b/src/hotspot/share/prims/vectorSupport.cpp index 4797857b9f6..f749ff11fe4 100644 --- a/src/hotspot/share/prims/vectorSupport.cpp +++ b/src/hotspot/share/prims/vectorSupport.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -171,17 +171,17 @@ Handle VectorSupport::allocate_vector_payload(InstanceKlass* ik, frame* fr, Regi return allocate_vector_payload_helper(ik, fr, reg_map, location, THREAD); // safepoint } #ifdef ASSERT - // Other payload values are: 'oop' type location and Scalar-replaced boxed vector representation. + // Other payload values are: 'oop' type location and scalar-replaced boxed vector representation. // They will be processed in Deoptimization::reassign_fields() after all objects are reallocated. else { Location::Type loc_type = location.type(); assert(loc_type == Location::oop || loc_type == Location::narrowoop, "expected 'oop'(%d) or 'narrowoop'(%d) types location but got: %d", Location::oop, Location::narrowoop, loc_type); } - } else if (!payload->is_object()) { + } else if (!payload->is_object() && !payload->is_constant_oop()) { stringStream ss; payload->print_on(&ss); - assert(payload->is_object(), "expected 'object' value for scalar-replaced boxed vector but got: %s", ss.as_string()); + assert(false, "expected 'object' value for scalar-replaced boxed vector but got: %s", ss.as_string()); #endif } return Handle(THREAD, nullptr); diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 145fa8e1bac..d264beca52c 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -2006,6 +2006,14 @@ WB_ENTRY(jboolean, WB_IsJFRIncluded(JNIEnv* env)) #endif // INCLUDE_JFR WB_END +WB_ENTRY(jboolean, WB_IsDTraceIncluded(JNIEnv* env)) +#if defined(DTRACE_ENABLED) + return true; +#else + return false; +#endif // DTRACE_ENABLED +WB_END + #if INCLUDE_CDS WB_ENTRY(jint, WB_GetOffsetForName(JNIEnv* env, jobject o, jstring name)) @@ -2586,6 +2594,7 @@ static JNINativeMethod methods[] = { {CC"areOpenArchiveHeapObjectsMapped", CC"()Z", (void*)&WB_AreOpenArchiveHeapObjectsMapped}, {CC"isCDSIncluded", CC"()Z", (void*)&WB_IsCDSIncluded }, {CC"isJFRIncluded", CC"()Z", (void*)&WB_IsJFRIncluded }, + {CC"isDTraceIncluded", CC"()Z", (void*)&WB_IsDTraceIncluded }, {CC"isC2OrJVMCIIncluded", CC"()Z", (void*)&WB_isC2OrJVMCIIncluded }, {CC"isJVMCISupportedByGC", CC"()Z", (void*)&WB_IsJVMCISupportedByGC}, {CC"isJavaHeapArchiveSupported", CC"()Z", (void*)&WB_IsJavaHeapArchiveSupported }, diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp index 0e3b3214243..4234a8d5865 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.cpp +++ b/src/hotspot/share/runtime/abstract_vm_version.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -199,11 +199,7 @@ const char* Abstract_VM_Version::internal_vm_info_string() { #ifndef HOTSPOT_BUILD_COMPILER #ifdef _MSC_VER - #if _MSC_VER == 1600 - #define HOTSPOT_BUILD_COMPILER "MS VC++ 10.0 (VS2010)" - #elif _MSC_VER == 1700 - #define HOTSPOT_BUILD_COMPILER "MS VC++ 11.0 (VS2012)" - #elif _MSC_VER == 1800 + #if _MSC_VER == 1800 #define HOTSPOT_BUILD_COMPILER "MS VC++ 12.0 (VS2013)" #elif _MSC_VER == 1900 #define HOTSPOT_BUILD_COMPILER "MS VC++ 14.0 (VS2015)" @@ -239,6 +235,10 @@ const char* Abstract_VM_Version::internal_vm_info_string() { #define HOTSPOT_BUILD_COMPILER "MS VC++ 16.8 / 16.9 (VS2019)" #elif _MSC_VER == 1929 #define HOTSPOT_BUILD_COMPILER "MS VC++ 16.10 / 16.11 (VS2019)" + #elif _MSC_VER == 1930 + #define HOTSPOT_BUILD_COMPILER "MS VC++ 17.0 (VS2022)" + #elif _MSC_VER == 1931 + #define HOTSPOT_BUILD_COMPILER "MS VC++ 17.1 (VS2022)" #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 3587b08f309..23074224280 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -2881,6 +2881,18 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* patch_m jio_fprintf(defaultStream::error_stream(), "ExtendedDTraceProbes flag is not applicable for this configuration\n"); return JNI_EINVAL; + } else if (match_option(option, "-XX:+DTraceMethodProbes")) { + jio_fprintf(defaultStream::error_stream(), + "DTraceMethodProbes flag is not applicable for this configuration\n"); + return JNI_EINVAL; + } else if (match_option(option, "-XX:+DTraceAllocProbes")) { + jio_fprintf(defaultStream::error_stream(), + "DTraceAllocProbes flag is not applicable for this configuration\n"); + return JNI_EINVAL; + } else if (match_option(option, "-XX:+DTraceMonitorProbes")) { + jio_fprintf(defaultStream::error_stream(), + "DTraceMonitorProbes flag is not applicable for this configuration\n"); + return JNI_EINVAL; #endif // defined(DTRACE_ENABLED) #ifdef ASSERT } else if (match_option(option, "-XX:+FullGCALot")) { diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 680becce195..852186aa272 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -683,6 +683,21 @@ void Deoptimization::unwind_callee_save_values(frame* f, vframeArray* vframe_arr assert(f->is_interpreted_frame(), "must be interpreted"); } +#ifndef PRODUCT +static bool falls_through(Bytecodes::Code bc) { + switch (bc) { + // List may be incomplete. Here we really only care about bytecodes where compiled code + // can deoptimize. + case Bytecodes::_goto: + case Bytecodes::_goto_w: + case Bytecodes::_athrow: + return false; + default: + return true; + } +} +#endif + // Return BasicType of value being returned JRT_LEAF(BasicType, Deoptimization::unpack_frames(JavaThread* thread, int exec_mode)) @@ -791,7 +806,7 @@ JRT_LEAF(BasicType, Deoptimization::unpack_frames(JavaThread* thread, int exec_m // calls. It seems to be hard to tell whether the compiler // has emitted debug information matching the "state before" // a given bytecode or the state after, so we try both - if (!Bytecodes::is_invoke(cur_code) && cur_code != Bytecodes::_athrow) { + if (!Bytecodes::is_invoke(cur_code) && falls_through(cur_code)) { // Get expression stack size for the next bytecode InterpreterOopMap next_mask; OopMapCache::compute_one_oop_map(mh, str.bci(), &next_mask); diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp index d662ffe0770..287a75fed11 100644 --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -233,19 +233,6 @@ OopStorage* ObjectMonitor::_oop_storage = NULL; // * See also http://blogs.sun.com/dave -void* ObjectMonitor::operator new (size_t size) throw() { - return AllocateHeap(size, mtInternal); -} -void* ObjectMonitor::operator new[] (size_t size) throw() { - return operator new (size); -} -void ObjectMonitor::operator delete(void* p) { - FreeHeap(p); -} -void ObjectMonitor::operator delete[] (void *p) { - operator delete(p); -} - // Check that object() and set_object() are called from the right context: static void check_object_context() { #ifdef ASSERT diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp index b36a724e43b..da3a4b09827 100644 --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -203,11 +203,6 @@ class ObjectMonitor : public CHeapObj { static int Knob_SpinLimit; - void* operator new (size_t size) throw(); - void* operator new[] (size_t size) throw(); - void operator delete(void* p); - void operator delete[] (void* p); - // TODO-FIXME: the "offset" routines should return a type of off_t instead of int ... // ByteSize would also be an appropriate type. static int header_offset_in_bytes() { return offset_of(ObjectMonitor, _header); } diff --git a/src/hotspot/share/runtime/sweeper.cpp b/src/hotspot/share/runtime/sweeper.cpp index 6df1161b6f0..37d3196e6c2 100644 --- a/src/hotspot/share/runtime/sweeper.cpp +++ b/src/hotspot/share/runtime/sweeper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -229,19 +229,19 @@ void NMethodSweeper::sweeper_loop() { /** * Wakes up the sweeper thread to sweep if code cache space runs low */ -void NMethodSweeper::report_allocation(int code_blob_type) { - if (should_start_aggressive_sweep(code_blob_type)) { +void NMethodSweeper::report_allocation() { + if (should_start_aggressive_sweep()) { MonitorLocker waiter(CodeSweeper_lock, Mutex::_no_safepoint_check_flag); _should_sweep = true; CodeSweeper_lock->notify(); } } -bool NMethodSweeper::should_start_aggressive_sweep(int code_blob_type) { +bool NMethodSweeper::should_start_aggressive_sweep() { // Makes sure that we do not invoke the sweeper too often during startup. double start_threshold = 100.0 / (double)StartAggressiveSweepingAt; double aggressive_sweep_threshold = MAX2(start_threshold, 1.1); - return (CodeCache::reverse_free_ratio(code_blob_type) >= aggressive_sweep_threshold); + return (CodeCache::reverse_free_ratio() >= aggressive_sweep_threshold); } /** @@ -546,8 +546,7 @@ void NMethodSweeper::possibly_flush(nmethod* nm) { // ReservedCodeCacheSize int reset_val = hotness_counter_reset_val(); int time_since_reset = reset_val - nm->hotness_counter(); - int code_blob_type = CodeCache::get_code_blob_type(nm); - double threshold = -reset_val + (CodeCache::reverse_free_ratio(code_blob_type) * NmethodSweepActivity); + double threshold = -reset_val + (CodeCache::reverse_free_ratio() * NmethodSweepActivity); // The less free space in the code cache we have - the bigger reverse_free_ratio() is. // I.e., 'threshold' increases with lower available space in the code cache and a higher // NmethodSweepActivity. If the current hotness counter - which decreases from its initial diff --git a/src/hotspot/share/runtime/sweeper.hpp b/src/hotspot/share/runtime/sweeper.hpp index 9ba2298e9ef..5f4e0ed7796 100644 --- a/src/hotspot/share/runtime/sweeper.hpp +++ b/src/hotspot/share/runtime/sweeper.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -113,11 +113,11 @@ class NMethodSweeper : public AllStatic { static CodeBlobClosure* prepare_mark_active_nmethods(); static void sweeper_loop(); - static bool should_start_aggressive_sweep(int code_blob_type); + static bool should_start_aggressive_sweep(); static void force_sweep(); static int hotness_counter_reset_val(); static void report_state_change(nmethod* nm); - static void report_allocation(int code_blob_type); // Possibly start the sweeper thread. + static void report_allocation(); // Possibly start the sweeper thread. static void possibly_flush(nmethod* nm); static void print(outputStream* out); // Printing/debugging static void print() { print(tty); } diff --git a/src/hotspot/share/services/diagnosticArgument.cpp b/src/hotspot/share/services/diagnosticArgument.cpp index f10fe6c4641..3dd75009175 100644 --- a/src/hotspot/share/services/diagnosticArgument.cpp +++ b/src/hotspot/share/services/diagnosticArgument.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -28,6 +28,7 @@ #include "memory/resourceArea.hpp" #include "runtime/thread.hpp" #include "services/diagnosticArgument.hpp" +#include "utilities/globalDefinitions.hpp" StringArrayArgument::StringArrayArgument() { _array = new (ResourceObj::C_HEAP, mtServiceability) GrowableArray(32, mtServiceability); @@ -114,13 +115,12 @@ template <> void DCmdArgument::parse_value(const char* str, || sscanf(str, JLONG_FORMAT "%n", &_value, &scanned) != 1 || (size_t)scanned != len) { - ResourceMark rm; - - char* buf = NEW_RESOURCE_ARRAY(char, len + 1); - strncpy(buf, str, len); - buf[len] = '\0'; + const int maxprint = 64; Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_IllegalArgumentException(), - "Integer parsing error in command argument '%s'. Could not parse: %s.\n", _name, buf); + "Integer parsing error in command argument '%s'. Could not parse: %.*s%s.\n", _name, + MIN2((int)len, maxprint), + (str == NULL ? "" : str), + (len > maxprint ? "..." : "")); } } diff --git a/src/hotspot/share/utilities/constantTag.hpp b/src/hotspot/share/utilities/constantTag.hpp index 4926eafa81c..d826fc0acc0 100644 --- a/src/hotspot/share/utilities/constantTag.hpp +++ b/src/hotspot/share/utilities/constantTag.hpp @@ -86,6 +86,13 @@ class constantTag { return _tag == JVM_CONSTANT_DynamicInError; } + bool is_in_error() const { + return is_unresolved_klass_in_error() || + is_method_handle_in_error() || + is_method_type_in_error() || + is_dynamic_constant_in_error(); + } + bool is_klass_index() const { return _tag == JVM_CONSTANT_ClassIndex; } bool is_string_index() const { return _tag == JVM_CONSTANT_StringIndex; } @@ -121,18 +128,24 @@ class constantTag { _tag = tag; } - static constantTag ofBasicType(BasicType bt) { - if (is_subword_type(bt)) bt = T_INT; + static jbyte type2tag(BasicType bt) { + if (is_subword_type(bt)) { + bt = T_INT; + } + if (bt == T_ARRAY) { + bt = T_OBJECT; + } switch (bt) { - case T_OBJECT: return constantTag(JVM_CONSTANT_String); - case T_INT: return constantTag(JVM_CONSTANT_Integer); - case T_LONG: return constantTag(JVM_CONSTANT_Long); - case T_FLOAT: return constantTag(JVM_CONSTANT_Float); - case T_DOUBLE: return constantTag(JVM_CONSTANT_Double); - default: break; + case T_INT: return JVM_CONSTANT_Integer; + case T_LONG: return JVM_CONSTANT_Long; + case T_FLOAT: return JVM_CONSTANT_Float; + case T_DOUBLE: return JVM_CONSTANT_Double; + case T_OBJECT: return JVM_CONSTANT_String; + + default: + assert(false, "not supported: %s", type2name(bt)); + return JVM_CONSTANT_Invalid; } - assert(false, "bad basic type for tag"); - return constantTag(); } jbyte value() const { return _tag; } diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp index 04be7ddd6eb..1054c34cc0d 100644 --- a/src/hotspot/share/utilities/vmError.cpp +++ b/src/hotspot/share/utilities/vmError.cpp @@ -115,7 +115,7 @@ static const char* env_list[] = { "DYLD_INSERT_LIBRARIES", // defined on Windows - "OS", "PROCESSOR_IDENTIFIER", "_ALT_JAVA_HOME_DIR", + "OS", "PROCESSOR_IDENTIFIER", "_ALT_JAVA_HOME_DIR", "TMP", "TEMP", (const char *)0 }; diff --git a/src/java.base/macosx/classes/apple/security/KeychainStore.java b/src/java.base/macosx/classes/apple/security/KeychainStore.java index cf97d4e04c0..e4a77e61cca 100644 --- a/src/java.base/macosx/classes/apple/security/KeychainStore.java +++ b/src/java.base/macosx/classes/apple/security/KeychainStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -68,6 +68,25 @@ static class TrustedCertEntry { Certificate cert; long certRef; // SecCertificateRef for this key + + // Each KeyStore.TrustedCertificateEntry have 2 attributes: + // 1. "trustSettings" -> trustSettings.toString() + // 2. "2.16.840.1.113894.746875.1.1" -> trustedKeyUsageValue + // The 1st one is mainly for debugging use. The 2nd one is similar + // to the attribute with the same key in a PKCS12KeyStore. + + // The SecTrustSettingsCopyTrustSettings() output for this certificate + // inside the KeyChain in its original array of CFDictionaryRef objects + // structure with values dumped as strings. For each trust, an extra + // entry "SecPolicyOid" is added whose value is the OID for this trust. + // The extra entries are used to construct trustedKeyUsageValue. + List> trustSettings; + + // One or more OIDs defined in http://oidref.com/1.2.840.113635.100.1. + // It can also be "2.5.29.37.0" for a self-signed certificate with + // an empty trust settings. This value is never empty. When there are + // multiple OID values, it takes the form of "[1.1.1, 1.1.2]". + String trustedKeyUsageValue; }; /** @@ -300,6 +319,35 @@ public Certificate engineGetCertificate(String alias) { } } + private record LocalAttr(String name, String value) + implements KeyStore.Entry.Attribute { + + @Override + public String getName() { + return name; + } + + @Override + public String getValue() { + return value; + } + } + + @Override + public KeyStore.Entry engineGetEntry(String alias, KeyStore.ProtectionParameter protParam) + throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableEntryException { + if (engineIsCertificateEntry(alias)) { + Object entry = entries.get(alias.toLowerCase()); + if (entry instanceof TrustedCertEntry tEntry) { + return new KeyStore.TrustedCertificateEntry( + tEntry.cert, Set.of( + new LocalAttr(KnownOIDs.ORACLE_TrustedKeyUsage.value(), tEntry.trustedKeyUsageValue), + new LocalAttr("trustSettings", tEntry.trustSettings.toString()))); + } + } + return super.engineGetEntry(alias, protParam); + } + /** * Returns the creation date of the entry identified by the given alias. * @@ -453,55 +501,12 @@ public void engineSetKeyEntry(String alias, byte[] key, } /** - * Assigns the given certificate to the given alias. - * - *

If the given alias already exists in this keystore and identifies a - * trusted certificate entry, the certificate associated with it is - * overridden by the given certificate. - * - * @param alias the alias name - * @param cert the certificate - * - * @exception KeyStoreException if the given alias already exists and does - * not identify a trusted certificate entry, or this operation - * fails for some other reason. + * Adding trusted certificate entry is not supported. */ public void engineSetCertificateEntry(String alias, Certificate cert) - throws KeyStoreException - { - permissionCheck(); - - synchronized(entries) { - - Object entry = entries.get(alias.toLowerCase()); - if ((entry != null) && (entry instanceof KeyEntry)) { - throw new KeyStoreException - ("Cannot overwrite key entry with certificate"); - } - - // This will be slow, but necessary. Enumerate the values and then see if the cert matches the one in the trusted cert entry. - // Security framework doesn't support the same certificate twice in a keychain. - Collection allValues = entries.values(); - - for (Object value : allValues) { - if (value instanceof TrustedCertEntry) { - TrustedCertEntry tce = (TrustedCertEntry)value; - if (tce.cert.equals(cert)) { - throw new KeyStoreException("Keychain does not support mulitple copies of same certificate."); - } - } - } - - TrustedCertEntry trustedCertEntry = new TrustedCertEntry(); - trustedCertEntry.cert = cert; - trustedCertEntry.date = new Date(); - String lowerAlias = alias.toLowerCase(); - if (entries.get(lowerAlias) != null) { - deletedEntries.put(lowerAlias, entries.get(lowerAlias)); - } - entries.put(lowerAlias, trustedCertEntry); - addedEntries.put(lowerAlias, trustedCertEntry); - } + throws KeyStoreException { + throw new KeyStoreException("Cannot set trusted certificate entry." + + " Use the macOS \"security add-trusted-cert\" command instead."); } /** @@ -680,10 +685,7 @@ public void engineStore(OutputStream stream, char[] password) String alias = e.nextElement(); Object entry = addedEntries.get(alias); if (entry instanceof TrustedCertEntry) { - TrustedCertEntry tce = (TrustedCertEntry)entry; - Certificate certElem; - certElem = tce.cert; - tce.certRef = addCertificateToKeychain(alias, certElem); + // Cannot set trusted certificate entry } else { KeyEntry keyEntry = (KeyEntry)entry; @@ -778,9 +780,28 @@ public void engineLoad(InputStream stream, char[] password) private native void _scanKeychain(); /** - * Callback method from _scanKeychain. If a trusted certificate is found, this method will be called. + * Callback method from _scanKeychain. If a trusted certificate is found, + * this method will be called. + * + * inputTrust is a list of strings in groups. Each group contains key/value + * pairs for one trust setting and ends with a null. Thus the size of the + * whole list is (2 * s_1 + 1) + (2 * s_2 + 1) + ... + (2 * s_n + 1), + * where s_i is the size of mapping for the i'th trust setting, + * and n is the number of trust settings. Ex: + * + * key1 for trust1 + * value1 for trust1 + * .. + * null (end of trust1) + * key1 for trust2 + * value1 for trust2 + * ... + * null (end of trust2) + * ... + * null (end if trust_n) */ - private void createTrustedCertEntry(String alias, long keychainItemRef, long creationDate, byte[] derStream) { + private void createTrustedCertEntry(String alias, List inputTrust, + long keychainItemRef, long creationDate, byte[] derStream) { TrustedCertEntry tce = new TrustedCertEntry(); try { @@ -791,6 +812,69 @@ private void createTrustedCertEntry(String alias, long keychainItemRef, long cre tce.cert = cert; tce.certRef = keychainItemRef; + tce.trustSettings = new ArrayList<>(); + Map tmpMap = new LinkedHashMap<>(); + for (int i = 0; i < inputTrust.size(); i++) { + if (inputTrust.get(i) == null) { + tce.trustSettings.add(tmpMap); + if (i < inputTrust.size() - 1) { + // Prepare an empty map for the next trust setting. + // Do not just clear(), must be a new object. + // Only create if not at end of list. + tmpMap = new LinkedHashMap<>(); + } + } else { + tmpMap.put(inputTrust.get(i), inputTrust.get(i+1)); + i++; + } + } + + boolean isSelfSigned; + try { + cert.verify(cert.getPublicKey()); + isSelfSigned = true; + } catch (Exception e) { + isSelfSigned = false; + } + if (tce.trustSettings.isEmpty()) { + if (isSelfSigned) { + // If a self-signed certificate has an empty trust settings, + // trust it for all purposes + tce.trustedKeyUsageValue = KnownOIDs.anyExtendedKeyUsage.value(); + } else { + // Otherwise, return immediately. The certificate is not + // added into entries. + return; + } + } else { + List values = new ArrayList<>(); + for (var oneTrust : tce.trustSettings) { + var result = oneTrust.get("kSecTrustSettingsResult"); + // https://developer.apple.com/documentation/security/sectrustsettingsresult?language=objc + // 1 = kSecTrustSettingsResultTrustRoot, 2 = kSecTrustSettingsResultTrustAsRoot + // If missing, a default value of kSecTrustSettingsResultTrustRoot is assumed + // for self-signed certificates (see doc for SecTrustSettingsCopyTrustSettings). + // Note that the same SecPolicyOid can appear in multiple trust settings + // for different kSecTrustSettingsAllowedError and/or kSecTrustSettingsPolicyString. + if ((result == null && isSelfSigned) + || "1".equals(result) || "2".equals(result)) { + // When no kSecTrustSettingsPolicy, it means everything + String oid = oneTrust.getOrDefault("SecPolicyOid", + KnownOIDs.anyExtendedKeyUsage.value()); + if (!values.contains(oid)) { + values.add(oid); + } + } + } + if (values.isEmpty()) { + return; + } + if (values.size() == 1) { + tce.trustedKeyUsageValue = values.get(0); + } else { + tce.trustedKeyUsageValue = values.toString(); + } + } // Make a creation date. if (creationDate != 0) tce.date = new Date(creationDate); diff --git a/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m b/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m index f427737b9a8..3f0c1de962d 100644 --- a/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m +++ b/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -368,6 +368,14 @@ static void addIdentitiesToKeystore(JNIEnv *env, jobject keyStore) } } +#define ADD(list, str) { \ + jobject localeObj = (*env)->NewStringUTF(env, [str UTF8String]); \ + (*env)->CallBooleanMethod(env, list, jm_listAdd, localeObj); \ + (*env)->DeleteLocalRef(env, localeObj); \ +} + +#define ADDNULL(list) (*env)->CallBooleanMethod(env, list, jm_listAdd, NULL) + static void addCertificatesToKeystore(JNIEnv *env, jobject keyStore) { // Search the user keychain list for all X509 certificates. @@ -379,8 +387,15 @@ static void addCertificatesToKeystore(JNIEnv *env, jobject keyStore) jclass jc_KeychainStore = (*env)->FindClass(env, "apple/security/KeychainStore"); CHECK_NULL(jc_KeychainStore); jmethodID jm_createTrustedCertEntry = (*env)->GetMethodID( - env, jc_KeychainStore, "createTrustedCertEntry", "(Ljava/lang/String;JJ[B)V"); + env, jc_KeychainStore, "createTrustedCertEntry", "(Ljava/lang/String;Ljava/util/List;JJ[B)V"); CHECK_NULL(jm_createTrustedCertEntry); + jclass jc_arrayListClass = (*env)->FindClass(env, "java/util/ArrayList"); + CHECK_NULL(jc_arrayListClass); + jmethodID jm_arrayListCons = (*env)->GetMethodID(env, jc_arrayListClass, "", "()V"); + CHECK_NULL(jm_arrayListCons); + jmethodID jm_listAdd = (*env)->GetMethodID(env, jc_arrayListClass, "add", "(Ljava/lang/Object;)Z"); + CHECK_NULL(jm_listAdd); + do { searchResult = SecKeychainSearchCopyNext(keychainItemSearch, &theItem); @@ -401,12 +416,50 @@ static void addCertificatesToKeystore(JNIEnv *env, jobject keyStore) goto errOut; } + // Only add certificates with trusted settings + CFArrayRef trustSettings; + if (SecTrustSettingsCopyTrustSettings(certRef, kSecTrustSettingsDomainUser, &trustSettings) + == errSecItemNotFound) { + continue; + } + + // See KeychainStore::createTrustedCertEntry for content of inputTrust + jobject inputTrust = (*env)->NewObject(env, jc_arrayListClass, jm_arrayListCons); + CHECK_NULL(inputTrust); + + // Dump everything inside trustSettings into inputTrust + CFIndex count = CFArrayGetCount(trustSettings); + for (int i = 0; i < count; i++) { + CFDictionaryRef oneTrust = (CFDictionaryRef) CFArrayGetValueAtIndex(trustSettings, i); + CFIndex size = CFDictionaryGetCount(oneTrust); + const void * keys [size]; + const void * values [size]; + CFDictionaryGetKeysAndValues(oneTrust, keys, values); + for (int j = 0; j < size; j++) { + NSString* s = [NSString stringWithFormat:@"%@", keys[j]]; + ADD(inputTrust, s); + s = [NSString stringWithFormat:@"%@", values[j]]; + ADD(inputTrust, s); + } + SecPolicyRef certPolicy; + certPolicy = (SecPolicyRef)CFDictionaryGetValue(oneTrust, kSecTrustSettingsPolicy); + if (certPolicy != NULL) { + CFDictionaryRef policyDict = SecPolicyCopyProperties(certPolicy); + ADD(inputTrust, @"SecPolicyOid"); + NSString* s = [NSString stringWithFormat:@"%@", CFDictionaryGetValue(policyDict, @"SecPolicyOid")]; + ADD(inputTrust, s); + CFRelease(policyDict); + } + ADDNULL(inputTrust); + } + CFRelease(trustSettings); + // Find the creation date. jlong creationDate = getModDateFromItem(env, theItem); // Call back to the Java object to create Java objects corresponding to this security object. jlong nativeRef = ptr_to_jlong(certRef); - (*env)->CallVoidMethod(env, keyStore, jm_createTrustedCertEntry, alias, nativeRef, creationDate, certData); + (*env)->CallVoidMethod(env, keyStore, jm_createTrustedCertEntry, alias, inputTrust, nativeRef, creationDate, certData); JNU_CHECK_EXCEPTION(env); } } while (searchResult == noErr); @@ -522,8 +575,8 @@ static void addCertificatesToKeystore(JNIEnv *env, jobject keyStore) /* * Class: apple_security_KeychainStore * Method: _addItemToKeychain - * Signature: (Ljava/lang/String;[B)I -*/ + * Signature: (Ljava/lang/String;Z[B[C)J + */ JNIEXPORT jlong JNICALL Java_apple_security_KeychainStore__1addItemToKeychain (JNIEnv *env, jobject this, jstring alias, jboolean isCertificate, jbyteArray rawDataObj, jcharArray passwordObj) { diff --git a/src/java.base/share/classes/java/io/ClassCache.java b/src/java.base/share/classes/java/io/ClassCache.java new file mode 100644 index 00000000000..48e7a36c05a --- /dev/null +++ b/src/java.base/share/classes/java/io/ClassCache.java @@ -0,0 +1,116 @@ +/* + * 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. 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 java.io; + +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.SoftReference; +import java.util.Objects; + +// Maps Class instances to values of type T. Under memory pressure, the +// mapping is released (under soft references GC policy) and would be +// recomputed the next time it is queried. The mapping is bound to the +// lifetime of the class: when the class is unloaded, the mapping is +// removed too. +abstract class ClassCache { + + private static class CacheRef extends SoftReference { + private final Class type; + private T strongReferent; + + CacheRef(T referent, ReferenceQueue queue, Class type) { + super(referent, queue); + this.type = type; + this.strongReferent = referent; + } + + Class getType() { + return type; + } + + T getStrong() { + return strongReferent; + } + + void clearStrong() { + strongReferent = null; + } + } + + private final ReferenceQueue queue; + private final ClassValue> map; + + protected abstract T computeValue(Class cl); + + protected ClassCache() { + queue = new ReferenceQueue<>(); + map = new ClassValue<>() { + @Override + protected CacheRef computeValue(Class type) { + T v = ClassCache.this.computeValue(type); + Objects.requireNonNull(v); + return new CacheRef<>(v, queue, type); + } + }; + } + + T get(Class cl) { + while (true) { + processQueue(); + + CacheRef ref = map.get(cl); + + // Case 1: A recently created CacheRef. + // We might still have strong referent, and can return it. + // This guarantees progress for at least one thread on every CacheRef. + // Clear the strong referent before returning to make the cache soft. + T strongVal = ref.getStrong(); + if (strongVal != null) { + ref.clearStrong(); + return strongVal; + } + + // Case 2: Older or recently cleared CacheRef. + // Check if its soft referent is still available, and return it. + T val = ref.get(); + if (val != null) { + return val; + } + + // Case 3: The reference was cleared. + // Clear the mapping and retry. + map.remove(cl); + } + } + + private void processQueue() { + Reference ref; + while((ref = queue.poll()) != null) { + CacheRef cacheRef = (CacheRef)ref; + map.remove(cacheRef.getType()); + } + } +} diff --git a/src/java.base/share/classes/java/io/File.java b/src/java.base/share/classes/java/io/File.java index 049d1b23a91..36a465ba53f 100644 --- a/src/java.base/share/classes/java/io/File.java +++ b/src/java.base/share/classes/java/io/File.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 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 @@ -175,8 +175,9 @@ private static enum PathStatus { INVALID, CHECKED }; /** * Check if the file has an invalid path. Currently, the inspection of - * a file path is very limited, and it only covers Nul character check. - * Returning true means the path is definitely invalid/garbage. But + * a file path is very limited, and it only covers Nul character check + * unless further checking is explicitly enabled by a system property. + * Returning true means the path is definitely invalid/garbage, but * returning false does not guarantee that the path is valid. * * @return true if the file path is invalid. @@ -184,8 +185,7 @@ private static enum PathStatus { INVALID, CHECKED }; final boolean isInvalid() { PathStatus s = status; if (s == null) { - s = (this.path.indexOf('\u0000') < 0) ? PathStatus.CHECKED - : PathStatus.INVALID; + s = fs.isInvalid(this) ? PathStatus.INVALID : PathStatus.CHECKED; status = s; } return s == PathStatus.INVALID; diff --git a/src/java.base/share/classes/java/io/FileSystem.java b/src/java.base/share/classes/java/io/FileSystem.java index a1cea852d95..b41120bf360 100644 --- a/src/java.base/share/classes/java/io/FileSystem.java +++ b/src/java.base/share/classes/java/io/FileSystem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -87,6 +87,11 @@ abstract class FileSystem { */ public abstract boolean isAbsolute(File f); + /** + * Tell whether the given abstract pathname is invalid. + */ + public abstract boolean isInvalid(File f); + /** * Resolve the given abstract pathname into absolute form. Invoked by the * getAbsolutePath and getCanonicalPath methods in the File class. diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java index ca69dde2926..b3e063b3dd8 100644 --- a/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -26,11 +26,9 @@ package java.io; import java.io.ObjectInputFilter.Config; -import java.io.ObjectStreamClass.WeakClassKey; import java.io.ObjectStreamClass.RecordSupport; import java.lang.System.Logger; import java.lang.invoke.MethodHandle; -import java.lang.ref.ReferenceQueue; import java.lang.reflect.Array; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Modifier; @@ -43,10 +41,6 @@ import java.util.Arrays; import java.util.Map; import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import static java.io.ObjectStreamClass.processQueue; import jdk.internal.access.SharedSecrets; import jdk.internal.event.DeserializationEvent; @@ -276,12 +270,13 @@ public class ObjectInputStream private static class Caches { /** cache of subclass security audit results */ - static final ConcurrentMap subclassAudits = - new ConcurrentHashMap<>(); - - /** queue for WeakReferences to audited subclasses */ - static final ReferenceQueue> subclassAuditsQueue = - new ReferenceQueue<>(); + static final ClassValue subclassAudits = + new ClassValue<>() { + @Override + protected Boolean computeValue(Class type) { + return auditSubclass(type); + } + }; /** * Property to permit setting a filter after objects @@ -1616,13 +1611,7 @@ private void verifySubclass() { if (sm == null) { return; } - processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits); - WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue); - Boolean result = Caches.subclassAudits.get(key); - if (result == null) { - result = auditSubclass(cl); - Caches.subclassAudits.putIfAbsent(key, result); - } + boolean result = Caches.subclassAudits.get(cl); if (!result) { sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); } diff --git a/src/java.base/share/classes/java/io/ObjectOutputStream.java b/src/java.base/share/classes/java/io/ObjectOutputStream.java index d647c0c0e65..be52df020fc 100644 --- a/src/java.base/share/classes/java/io/ObjectOutputStream.java +++ b/src/java.base/share/classes/java/io/ObjectOutputStream.java @@ -25,17 +25,12 @@ package java.io; -import java.io.ObjectStreamClass.WeakClassKey; -import java.lang.ref.ReferenceQueue; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.StringJoiner; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import static java.io.ObjectStreamClass.processQueue; import sun.reflect.misc.ReflectUtil; /** @@ -169,12 +164,13 @@ public class ObjectOutputStream private static class Caches { /** cache of subclass security audit results */ - static final ConcurrentMap subclassAudits = - new ConcurrentHashMap<>(); - - /** queue for WeakReferences to audited subclasses */ - static final ReferenceQueue> subclassAuditsQueue = - new ReferenceQueue<>(); + static final ClassValue subclassAudits = + new ClassValue<>() { + @Override + protected Boolean computeValue(Class type) { + return auditSubclass(type); + } + }; } /** filter stream for handling block data conversion */ @@ -1060,13 +1056,7 @@ private void verifySubclass() { if (sm == null) { return; } - processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits); - WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue); - Boolean result = Caches.subclassAudits.get(key); - if (result == null) { - result = auditSubclass(cl); - Caches.subclassAudits.putIfAbsent(key, result); - } + boolean result = Caches.subclassAudits.get(cl); if (!result) { sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); } diff --git a/src/java.base/share/classes/java/io/ObjectStreamClass.java b/src/java.base/share/classes/java/io/ObjectStreamClass.java index 1eff6c27278..afb3d844769 100644 --- a/src/java.base/share/classes/java/io/ObjectStreamClass.java +++ b/src/java.base/share/classes/java/io/ObjectStreamClass.java @@ -28,10 +28,6 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.SoftReference; -import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -59,7 +55,6 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import jdk.internal.misc.Unsafe; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; @@ -108,19 +103,22 @@ public class ObjectStreamClass implements Serializable { private static class Caches { /** cache mapping local classes -> descriptors */ - static final ConcurrentMap> localDescs = - new ConcurrentHashMap<>(); + static final ClassCache localDescs = + new ClassCache<>() { + @Override + protected ObjectStreamClass computeValue(Class type) { + return new ObjectStreamClass(type); + } + }; /** cache mapping field group/local desc pairs -> field reflectors */ - static final ConcurrentMap> reflectors = - new ConcurrentHashMap<>(); - - /** queue for WeakReferences to local classes */ - private static final ReferenceQueue> localDescsQueue = - new ReferenceQueue<>(); - /** queue for WeakReferences to field reflectors keys */ - private static final ReferenceQueue> reflectorsQueue = - new ReferenceQueue<>(); + static final ClassCache> reflectors = + new ClassCache<>() { + @Override + protected Map computeValue(Class type) { + return new ConcurrentHashMap<>(); + } + }; } /** class associated with this descriptor (if any) */ @@ -362,136 +360,7 @@ static ObjectStreamClass lookup(Class cl, boolean all) { if (!(all || Serializable.class.isAssignableFrom(cl))) { return null; } - processQueue(Caches.localDescsQueue, Caches.localDescs); - WeakClassKey key = new WeakClassKey(cl, Caches.localDescsQueue); - Reference ref = Caches.localDescs.get(key); - Object entry = null; - if (ref != null) { - entry = ref.get(); - } - EntryFuture future = null; - if (entry == null) { - EntryFuture newEntry = new EntryFuture(); - Reference newRef = new SoftReference<>(newEntry); - do { - if (ref != null) { - Caches.localDescs.remove(key, ref); - } - ref = Caches.localDescs.putIfAbsent(key, newRef); - if (ref != null) { - entry = ref.get(); - } - } while (ref != null && entry == null); - if (entry == null) { - future = newEntry; - } - } - - if (entry instanceof ObjectStreamClass) { // check common case first - return (ObjectStreamClass) entry; - } - if (entry instanceof EntryFuture) { - future = (EntryFuture) entry; - if (future.getOwner() == Thread.currentThread()) { - /* - * Handle nested call situation described by 4803747: waiting - * for future value to be set by a lookup() call further up the - * stack will result in deadlock, so calculate and set the - * future value here instead. - */ - entry = null; - } else { - entry = future.get(); - } - } - if (entry == null) { - try { - entry = new ObjectStreamClass(cl); - } catch (Throwable th) { - entry = th; - } - if (future.set(entry)) { - Caches.localDescs.put(key, new SoftReference<>(entry)); - } else { - // nested lookup call already set future - entry = future.get(); - } - } - - if (entry instanceof ObjectStreamClass) { - return (ObjectStreamClass) entry; - } else if (entry instanceof RuntimeException) { - throw (RuntimeException) entry; - } else if (entry instanceof Error) { - throw (Error) entry; - } else { - throw new InternalError("unexpected entry: " + entry); - } - } - - /** - * Placeholder used in class descriptor and field reflector lookup tables - * for an entry in the process of being initialized. (Internal) callers - * which receive an EntryFuture belonging to another thread as the result - * of a lookup should call the get() method of the EntryFuture; this will - * return the actual entry once it is ready for use and has been set(). To - * conserve objects, EntryFutures synchronize on themselves. - */ - private static class EntryFuture { - - private static final Object unset = new Object(); - private final Thread owner = Thread.currentThread(); - private Object entry = unset; - - /** - * Attempts to set the value contained by this EntryFuture. If the - * EntryFuture's value has not been set already, then the value is - * saved, any callers blocked in the get() method are notified, and - * true is returned. If the value has already been set, then no saving - * or notification occurs, and false is returned. - */ - synchronized boolean set(Object entry) { - if (this.entry != unset) { - return false; - } - this.entry = entry; - notifyAll(); - return true; - } - - /** - * Returns the value contained by this EntryFuture, blocking if - * necessary until a value is set. - */ - @SuppressWarnings("removal") - synchronized Object get() { - boolean interrupted = false; - while (entry == unset) { - try { - wait(); - } catch (InterruptedException ex) { - interrupted = true; - } - } - if (interrupted) { - AccessController.doPrivileged( - new PrivilegedAction<>() { - public Void run() { - Thread.currentThread().interrupt(); - return null; - } - } - ); - } - return entry; - } - - /** - * Returns the thread that created this EntryFuture. - */ - Thread getOwner() { - return owner; - } + return Caches.localDescs.get(cl); } /** @@ -2250,82 +2119,39 @@ private static FieldReflector getReflector(ObjectStreamField[] fields, { // class irrelevant if no fields Class cl = (localDesc != null && fields.length > 0) ? - localDesc.cl : null; - processQueue(Caches.reflectorsQueue, Caches.reflectors); - FieldReflectorKey key = new FieldReflectorKey(cl, fields, - Caches.reflectorsQueue); - Reference ref = Caches.reflectors.get(key); - Object entry = null; - if (ref != null) { - entry = ref.get(); - } - EntryFuture future = null; - if (entry == null) { - EntryFuture newEntry = new EntryFuture(); - Reference newRef = new SoftReference<>(newEntry); - do { - if (ref != null) { - Caches.reflectors.remove(key, ref); - } - ref = Caches.reflectors.putIfAbsent(key, newRef); - if (ref != null) { - entry = ref.get(); - } - } while (ref != null && entry == null); - if (entry == null) { - future = newEntry; - } - } + localDesc.cl : Void.class; - if (entry instanceof FieldReflector) { // check common case first - return (FieldReflector) entry; - } else if (entry instanceof EntryFuture) { - entry = ((EntryFuture) entry).get(); - } else if (entry == null) { - try { - entry = new FieldReflector(matchFields(fields, localDesc)); - } catch (Throwable th) { - entry = th; - } - future.set(entry); - Caches.reflectors.put(key, new SoftReference<>(entry)); - } - - if (entry instanceof FieldReflector) { - return (FieldReflector) entry; - } else if (entry instanceof InvalidClassException) { - throw (InvalidClassException) entry; - } else if (entry instanceof RuntimeException) { - throw (RuntimeException) entry; - } else if (entry instanceof Error) { - throw (Error) entry; - } else { - throw new InternalError("unexpected entry: " + entry); + var clReflectors = Caches.reflectors.get(cl); + var key = new FieldReflectorKey(fields); + var reflector = clReflectors.get(key); + if (reflector == null) { + reflector = new FieldReflector(matchFields(fields, localDesc)); + var oldReflector = clReflectors.putIfAbsent(key, reflector); + if (oldReflector != null) { + reflector = oldReflector; + } } + return reflector; } /** * FieldReflector cache lookup key. Keys are considered equal if they - * refer to the same class and equivalent field formats. + * refer to equivalent field formats. */ - private static class FieldReflectorKey extends WeakReference> { + private static class FieldReflectorKey { private final String[] sigs; private final int hash; - private final boolean nullClass; - FieldReflectorKey(Class cl, ObjectStreamField[] fields, - ReferenceQueue> queue) + FieldReflectorKey(ObjectStreamField[] fields) { - super(cl, queue); - nullClass = (cl == null); sigs = new String[2 * fields.length]; for (int i = 0, j = 0; i < fields.length; i++) { ObjectStreamField f = fields[i]; sigs[j++] = f.getName(); sigs[j++] = f.getSignature(); } - hash = System.identityHashCode(cl) + Arrays.hashCode(sigs); + hash = Arrays.hashCode(sigs); } public int hashCode() { @@ -2333,19 +2159,9 @@ public int hashCode() { } public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (obj instanceof FieldReflectorKey other) { - Class referent; - return (nullClass ? other.nullClass - : ((referent = get()) != null) && - (other.refersTo(referent))) && - Arrays.equals(sigs, other.sigs); - } else { - return false; - } + return obj == this || + obj instanceof FieldReflectorKey other && + Arrays.equals(sigs, other.sigs); } } @@ -2409,68 +2225,6 @@ private static ObjectStreamField[] matchFields(ObjectStreamField[] fields, return matches; } - /** - * Removes from the specified map any keys that have been enqueued - * on the specified reference queue. - */ - static void processQueue(ReferenceQueue> queue, - ConcurrentMap>, ?> map) - { - Reference> ref; - while((ref = queue.poll()) != null) { - map.remove(ref); - } - } - - /** - * Weak key for Class objects. - * - **/ - static class WeakClassKey extends WeakReference> { - /** - * saved value of the referent's identity hash code, to maintain - * a consistent hash code after the referent has been cleared - */ - private final int hash; - - /** - * Create a new WeakClassKey to the given object, registered - * with a queue. - */ - WeakClassKey(Class cl, ReferenceQueue> refQueue) { - super(cl, refQueue); - hash = System.identityHashCode(cl); - } - - /** - * Returns the identity hash code of the original referent. - */ - public int hashCode() { - return hash; - } - - /** - * Returns true if the given object is this identical - * WeakClassKey instance, or, if this object's referent has not - * been cleared, if the given object is another WeakClassKey - * instance with the identical non-null referent as this one. - */ - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (obj instanceof WeakClassKey) { - Class referent = get(); - return (referent != null) && - (((WeakClassKey) obj).refersTo(referent)); - } else { - return false; - } - } - } - /** * A LRA cache of record deserialization constructors. */ diff --git a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index 15f5e8d92a8..35b87a44cf0 100644 --- a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -682,6 +682,7 @@ private String getInternalName(Class c) { } private static MemberName resolveFrom(String name, MethodType type, Class holder) { + assert(!UNSAFE.shouldBeInitialized(holder)) : holder + "not initialized"; MemberName member = new MemberName(holder, name, type, REF_invokeStatic); MemberName resolvedMember = MemberName.getFactory().resolveOrNull(REF_invokeStatic, member, holder, LM_TRUSTED); traceLambdaForm(name, type, holder, resolvedMember); diff --git a/src/java.base/share/classes/java/lang/invoke/VarForm.java b/src/java.base/share/classes/java/lang/invoke/VarForm.java index 7b118dbe470..1308c48cebb 100644 --- a/src/java.base/share/classes/java/lang/invoke/VarForm.java +++ b/src/java.base/share/classes/java/lang/invoke/VarForm.java @@ -109,9 +109,14 @@ final MethodType getMethodType(int type) { @ForceInline final MemberName getMemberName(int mode) { - MemberName mn = getMemberNameOrNull(mode); + // Can be simplified by calling getMemberNameOrNull, but written in this + // form to improve interpreter/coldpath performance. + MemberName mn = memberName_table[mode]; if (mn == null) { - throw new UnsupportedOperationException(); + mn = resolveMemberName(mode); + if (mn == null) { + throw new UnsupportedOperationException(); + } } return mn; } diff --git a/src/java.base/share/classes/java/net/doc-files/net-properties.html b/src/java.base/share/classes/java/net/doc-files/net-properties.html index ea0311b7161..8e7d986ab2e 100644 --- a/src/java.base/share/classes/java/net/doc-files/net-properties.html +++ b/src/java.base/share/classes/java/net/doc-files/net-properties.html @@ -214,6 +214,22 @@

Misc HTTP URL stream protocol handler properties

property is defined, then its value will be used as the domain name.

+
  • {@systemProperty jdk.https.negotiate.cbt} (default: <never>)
    + This controls the generation and sending of TLS channel binding tokens (CBT) when Kerberos + or the Negotiate authentication scheme using Kerberos are employed over HTTPS with + {@code HttpsURLConnection}. There are three possible settings:

    +
      +
    1. "never". This is also the default value if the property is not set. In this case, + CBTs are never sent.

      +
    2. "always". CBTs are sent for all Kerberos authentication attempts over HTTPS.

      +
    3. "domain:<comma separated domain list>" Each domain in the list specifies destination + host or hosts for which a CBT is sent. Domains can be single hosts like foo, or foo.com, + or literal IP addresses as specified in RFC 2732, or wildcards like *.foo.com which matches + all hosts under foo.com and its sub-domains. CBTs are not sent to any destinations + that don't match one of the list entries

      +
    +

    The channel binding tokens generated are of the type "tls-server-end-point" as defined in + RFC 5929.

    All these properties are checked only once at startup.

    diff --git a/src/java.base/share/classes/java/util/jar/JarVerifier.java b/src/java.base/share/classes/java/util/jar/JarVerifier.java index a601e6cb482..c9ab1ac06bf 100644 --- a/src/java.base/share/classes/java/util/jar/JarVerifier.java +++ b/src/java.base/share/classes/java/util/jar/JarVerifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -96,6 +96,10 @@ class JarVerifier { /** collect -DIGEST-MANIFEST values for deny list */ private List manifestDigests; + /* A cache mapping code signers to the algorithms used to digest jar + entries, and whether or not the algorithms are permitted. */ + private Map> signersToAlgs; + public JarVerifier(String name, byte rawBytes[]) { manifestName = name; manifestRawBytes = rawBytes; @@ -105,6 +109,7 @@ public JarVerifier(String name, byte rawBytes[]) { pendingBlocks = new ArrayList<>(); baos = new ByteArrayOutputStream(); manifestDigests = new ArrayList<>(); + signersToAlgs = new HashMap<>(); } /** @@ -244,7 +249,8 @@ private void processEntry(ManifestEntryVerifier mev) if (!parsingBlockOrSF) { JarEntry je = mev.getEntry(); if ((je != null) && (je.signers == null)) { - je.signers = mev.verify(verifiedSigners, sigFileSigners); + je.signers = mev.verify(verifiedSigners, sigFileSigners, + signersToAlgs); je.certs = mapSignersToCertArray(je.signers); } } else { diff --git a/src/java.base/share/classes/java/util/regex/PatternSyntaxException.java b/src/java.base/share/classes/java/util/regex/PatternSyntaxException.java index f58034aad3c..2b5da62f5bd 100644 --- a/src/java.base/share/classes/java/util/regex/PatternSyntaxException.java +++ b/src/java.base/share/classes/java/util/regex/PatternSyntaxException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -107,7 +107,9 @@ public String getMessage() { sb.append(pattern); if (index >= 0 && pattern != null && index < pattern.length()) { sb.append(System.lineSeparator()); - for (int i = 0; i < index; i++) sb.append(' '); + for (int i = 0; i < index; i++) { + sb.append((pattern.charAt(i) == '\t') ? '\t' : ' '); + } sb.append('^'); } return sb.toString(); diff --git a/src/java.base/share/classes/java/util/zip/Deflater.java b/src/java.base/share/classes/java/util/zip/Deflater.java index b637d4dc9b2..88da99ba629 100644 --- a/src/java.base/share/classes/java/util/zip/Deflater.java +++ b/src/java.base/share/classes/java/util/zip/Deflater.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -898,6 +898,16 @@ private void ensureOpen() { throw new NullPointerException("Deflater has been closed"); } + /** + * Returns the value of 'finish' flag. + * 'finish' will be set to true if def.finish() method is called. + */ + boolean shouldFinish() { + synchronized (zsRef) { + return finish; + } + } + private static native long init(int level, int strategy, boolean nowrap); private static native void setDictionary(long addr, byte[] b, int off, int len); diff --git a/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java b/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java index 365bc676b08..c856d8999b3 100644 --- a/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java +++ b/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -220,9 +220,15 @@ public void write(byte[] b, int off, int len) throws IOException { */ public void finish() throws IOException { if (!def.finished()) { - def.finish(); - while (!def.finished()) { - deflate(); + try{ + def.finish(); + while (!def.finished()) { + deflate(); + } + } catch(IOException e) { + if (usesDefaultDeflater) + def.end(); + throw e; } } } @@ -234,9 +240,12 @@ public void finish() throws IOException { */ public void close() throws IOException { if (!closed) { - finish(); - if (usesDefaultDeflater) - def.end(); + try { + finish(); + } finally { + if (usesDefaultDeflater) + def.end(); + } out.close(); closed = true; } diff --git a/src/java.base/share/classes/java/util/zip/GZIPOutputStream.java b/src/java.base/share/classes/java/util/zip/GZIPOutputStream.java index 153af0959b1..cdfac329cfa 100644 --- a/src/java.base/share/classes/java/util/zip/GZIPOutputStream.java +++ b/src/java.base/share/classes/java/util/zip/GZIPOutputStream.java @@ -157,24 +157,30 @@ public synchronized void write(byte[] buf, int off, int len) */ public void finish() throws IOException { if (!def.finished()) { - def.finish(); - while (!def.finished()) { - int len = def.deflate(buf, 0, buf.length); - if (def.finished() && len <= buf.length - TRAILER_SIZE) { - // last deflater buffer. Fit trailer at the end - writeTrailer(buf, len); - len = len + TRAILER_SIZE; - out.write(buf, 0, len); - return; + try { + def.finish(); + while (!def.finished()) { + int len = def.deflate(buf, 0, buf.length); + if (def.finished() && len <= buf.length - TRAILER_SIZE) { + // last deflater buffer. Fit trailer at the end + writeTrailer(buf, len); + len = len + TRAILER_SIZE; + out.write(buf, 0, len); + return; + } + if (len > 0) + out.write(buf, 0, len); } - if (len > 0) - out.write(buf, 0, len); + // if we can't fit the trailer at the end of the last + // deflater buffer, we write it separately + byte[] trailer = new byte[TRAILER_SIZE]; + writeTrailer(trailer, 0); + out.write(trailer); + } catch (IOException e) { + if (usesDefaultDeflater) + def.end(); + throw e; } - // if we can't fit the trailer at the end of the last - // deflater buffer, we write it separately - byte[] trailer = new byte[TRAILER_SIZE]; - writeTrailer(trailer, 0); - out.write(trailer); } } diff --git a/src/java.base/share/classes/java/util/zip/ZipOutputStream.java b/src/java.base/share/classes/java/util/zip/ZipOutputStream.java index c6dfa69536e..eeee48c8908 100644 --- a/src/java.base/share/classes/java/util/zip/ZipOutputStream.java +++ b/src/java.base/share/classes/java/util/zip/ZipOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -144,11 +144,14 @@ public ZipOutputStream(OutputStream out, Charset charset) { * ZIP file comment is greater than 0xFFFF bytes */ public void setComment(String comment) { + byte[] bytes = null; if (comment != null) { - this.comment = zc.getBytes(comment); - if (this.comment.length > 0xffff) - throw new IllegalArgumentException("ZIP file comment too long."); + bytes = zc.getBytes(comment); + if (bytes.length > 0xffff) { + throw new IllegalArgumentException("ZIP file comment too long"); + } } + this.comment = bytes; } /** @@ -256,58 +259,64 @@ public void putNextEntry(ZipEntry e) throws IOException { public void closeEntry() throws IOException { ensureOpen(); if (current != null) { - ZipEntry e = current.entry; - switch (e.method) { - case DEFLATED -> { - def.finish(); - while (!def.finished()) { - deflate(); - } - if ((e.flag & 8) == 0) { - // verify size, compressed size, and crc-32 settings - if (e.size != def.getBytesRead()) { - throw new ZipException( - "invalid entry size (expected " + e.size + - " but got " + def.getBytesRead() + " bytes)"); - } - if (e.csize != def.getBytesWritten()) { - throw new ZipException( - "invalid entry compressed size (expected " + - e.csize + " but got " + def.getBytesWritten() + " bytes)"); + try { + ZipEntry e = current.entry; + switch (e.method) { + case DEFLATED -> { + def.finish(); + while (!def.finished()) { + deflate(); + } + if ((e.flag & 8) == 0) { + // verify size, compressed size, and crc-32 settings + if (e.size != def.getBytesRead()) { + throw new ZipException( + "invalid entry size (expected " + e.size + + " but got " + def.getBytesRead() + " bytes)"); + } + if (e.csize != def.getBytesWritten()) { + throw new ZipException( + "invalid entry compressed size (expected " + + e.csize + " but got " + def.getBytesWritten() + " bytes)"); + } + if (e.crc != crc.getValue()) { + throw new ZipException( + "invalid entry CRC-32 (expected 0x" + + Long.toHexString(e.crc) + " but got 0x" + + Long.toHexString(crc.getValue()) + ")"); + } + } else { + e.size = def.getBytesRead(); + e.csize = def.getBytesWritten(); + e.crc = crc.getValue(); + writeEXT(e); + } + def.reset(); + written += e.csize; } - if (e.crc != crc.getValue()) { - throw new ZipException( - "invalid entry CRC-32 (expected 0x" + - Long.toHexString(e.crc) + " but got 0x" + - Long.toHexString(crc.getValue()) + ")"); + case STORED -> { + // we already know that both e.size and e.csize are the same + if (e.size != written - locoff) { + throw new ZipException( + "invalid entry size (expected " + e.size + + " but got " + (written - locoff) + " bytes)"); + } + if (e.crc != crc.getValue()) { + throw new ZipException( + "invalid entry crc-32 (expected 0x" + + Long.toHexString(e.crc) + " but got 0x" + + Long.toHexString(crc.getValue()) + ")"); + } } - } else { - e.size = def.getBytesRead(); - e.csize = def.getBytesWritten(); - e.crc = crc.getValue(); - writeEXT(e); - } - def.reset(); - written += e.csize; - } - case STORED -> { - // we already know that both e.size and e.csize are the same - if (e.size != written - locoff) { - throw new ZipException( - "invalid entry size (expected " + e.size + - " but got " + (written - locoff) + " bytes)"); - } - if (e.crc != crc.getValue()) { - throw new ZipException( - "invalid entry crc-32 (expected 0x" + - Long.toHexString(e.crc) + " but got 0x" + - Long.toHexString(crc.getValue()) + ")"); + default -> throw new ZipException("invalid compression method"); } + crc.reset(); + current = null; + } catch (IOException e) { + if (def.shouldFinish() && usesDefaultDeflater && !(e instanceof ZipException)) + def.end(); + throw e; } - default -> throw new ZipException("invalid compression method"); - } - crc.reset(); - current = null; } } diff --git a/src/java.base/share/classes/javax/crypto/EncryptedPrivateKeyInfo.java b/src/java.base/share/classes/javax/crypto/EncryptedPrivateKeyInfo.java index 09c69748d5a..90b38d9041f 100644 --- a/src/java.base/share/classes/javax/crypto/EncryptedPrivateKeyInfo.java +++ b/src/java.base/share/classes/javax/crypto/EncryptedPrivateKeyInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -83,12 +83,12 @@ public EncryptedPrivateKeyInfo(byte[] encoded) throws IOException { "must be non-null"); } - DerValue val = new DerValue(encoded); + this.encoded = encoded.clone(); + DerValue val = DerValue.wrap(this.encoded); if (val.tag != DerValue.tag_Sequence) { throw new IOException("DER header error: no SEQ tag"); } - this.encoded = encoded.clone(); DerValue[] seq = new DerValue[2]; seq[0] = val.data.getDerValue(); diff --git a/src/java.base/share/classes/jdk/internal/module/ModulePath.java b/src/java.base/share/classes/jdk/internal/module/ModulePath.java index 99713872588..e8ce2acf08f 100644 --- a/src/java.base/share/classes/jdk/internal/module/ModulePath.java +++ b/src/java.base/share/classes/jdk/internal/module/ModulePath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -663,11 +663,12 @@ private ModuleReference readJar(Path file) throws IOException { // -- exploded directories -- private Set explodedPackages(Path dir) { + String separator = dir.getFileSystem().getSeparator(); try { return Files.find(dir, Integer.MAX_VALUE, ((path, attrs) -> attrs.isRegularFile() && !isHidden(path))) .map(path -> dir.relativize(path)) - .map(this::toPackageName) + .map(path -> toPackageName(path, separator)) .flatMap(Optional::stream) .collect(Collectors.toSet()); } catch (IOException x) { @@ -738,7 +739,7 @@ private Optional toPackageName(String name) { * @throws InvalidModuleDescriptorException if the name is a class file in * the top-level directory (and it's not module-info.class) */ - private Optional toPackageName(Path file) { + private Optional toPackageName(Path file, String separator) { assert file.getRoot() == null; Path parent = file.getParent(); @@ -752,7 +753,7 @@ private Optional toPackageName(Path file) { return Optional.empty(); } - String pn = parent.toString().replace(File.separatorChar, '.'); + String pn = parent.toString().replace(separator, "."); if (Checks.isPackageName(pn)) { return Optional.of(pn); } else { diff --git a/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java b/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java index 1d64432979d..d47043b89aa 100644 --- a/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java +++ b/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java @@ -1186,10 +1186,10 @@ public static double computeNextExponential(RandomGenerator rng) { // For the exponential distribution, every overhang is convex. final double[] X = DoubleZigguratTables.exponentialX; final double[] Y = DoubleZigguratTables.exponentialY; - for (;; U1 = (rng.nextLong() >>> 1)) { + // At this point, the high-order bits of U1 have not been used yet, + // but we need the value in U1 to be positive. + for (U1 = (U1 >>> 1);; U1 = (rng.nextLong() >>> 1)) { long U2 = (rng.nextLong() >>> 1); - // Compute the actual x-coordinate of the randomly chosen point. - double x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1); // Does the point lie below the curve? long Udiff = U2 - U1; if (Udiff < 0) { @@ -1200,11 +1200,13 @@ public static double computeNextExponential(RandomGenerator rng) { U2 = U1; U1 -= Udiff; } + // Compute the actual x-coordinate of the randomly chosen point. + double x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1); if (Udiff >= DoubleZigguratTables.exponentialConvexMargin) { return x + extra; // The chosen point is way below the curve; accept it. } // Compute the actual y-coordinate of the randomly chosen point. - double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2); + double y = (Y[j] * 0x1.0p63) + ((Y[j-1] - Y[j]) * (double)U2); // Now see how that y-coordinate compares to the curve if (y <= Math.exp(-x)) { return x + extra; // The chosen point is below the curve; accept it. @@ -1323,7 +1325,7 @@ public static double computeNextGaussian(RandomGenerator rng) { continue; // The chosen point is way above the curve; reject it. } // Compute the actual y-coordinate of the randomly chosen point. - double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2); + double y = (Y[j] * 0x1.0p63) + ((Y[j-1] - Y[j]) * (double)U2); // Now see how that y-coordinate compares to the curve if (y <= Math.exp(-0.5*x*x)) { break; // The chosen point is below the curve; accept it. @@ -1348,8 +1350,6 @@ public static double computeNextGaussian(RandomGenerator rng) { } else if (j < DoubleZigguratTables.normalInflectionIndex) { // Convex overhang for (;; U1 = (rng.nextLong() >>> 1)) { long U2 = (rng.nextLong() >>> 1); - // Compute the actual x-coordinate of the randomly chosen point. - x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1); // Does the point lie below the curve? long Udiff = U2 - U1; if (Udiff < 0) { @@ -1360,11 +1360,13 @@ public static double computeNextGaussian(RandomGenerator rng) { U2 = U1; U1 -= Udiff; } + // Compute the actual x-coordinate of the randomly chosen point. + x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1); if (Udiff >= DoubleZigguratTables.normalConvexMargin) { break; // The chosen point is way below the curve; accept it. } // Compute the actual y-coordinate of the randomly chosen point. - double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2); + double y = (Y[j] * 0x1.0p63) + ((Y[j-1] - Y[j]) * (double)U2); // Now see how that y-coordinate compares to the curve if (y <= Math.exp(-0.5*x*x)) break; // The chosen point is below the curve; accept it. // Otherwise, we reject this sample and have to try again. @@ -1384,7 +1386,7 @@ public static double computeNextGaussian(RandomGenerator rng) { continue; // The chosen point is way above the curve; reject it. } // Compute the actual y-coordinate of the randomly chosen point. - double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2); + double y = (Y[j] * 0x1.0p63) + ((Y[j-1] - Y[j]) * (double)U2); // Now see how that y-coordinate compares to the curve if (y <= Math.exp(-0.5*x*x)) { break; // The chosen point is below the curve; accept it. diff --git a/src/java.base/share/classes/sun/net/www/http/HttpClient.java b/src/java.base/share/classes/sun/net/www/http/HttpClient.java index 4b3c40b4fc0..8993f0c2a0a 100644 --- a/src/java.base/share/classes/sun/net/www/http/HttpClient.java +++ b/src/java.base/share/classes/sun/net/www/http/HttpClient.java @@ -144,12 +144,27 @@ private static int getDefaultPort(String proto) { // Traffic capture tool, if configured. See HttpCapture class for info private HttpCapture capture = null; + /* "jdk.https.negotiate.cbt" property can be set to "always" (always sent), "never" (never sent) or + * "domain:a,c.d,*.e.f" (sent to host a, or c.d or to the domain e.f and any of its subdomains). This is + * a comma separated list of arbitrary length with no white-space allowed. + * If enabled (for a particular destination) then Negotiate/SPNEGO authentication requests will include + * a channel binding token for the destination server. The default behavior and setting for the + * property is "never" + */ + private static final String spnegoCBT; + private static final PlatformLogger logger = HttpURLConnection.getHttpLogger(); + private static void logFinest(String msg) { if (logger.isLoggable(PlatformLogger.Level.FINEST)) { logger.finest(msg); } } + private static void logError(String msg) { + if (logger.isLoggable(PlatformLogger.Level.SEVERE)) { + logger.severe(msg); + } + } protected volatile String authenticatorKey; @@ -165,6 +180,18 @@ int getKeepAliveTimeout() { return keepAliveTimeout; } + static String normalizeCBT(String s) { + if (s == null || s.equals("never")) { + return "never"; + } + if (s.equals("always") || s.startsWith("domain:")) { + return s; + } else { + logError("Unexpected value for \"jdk.https.negotiate.cbt\" system property"); + return "never"; + } + } + static { Properties props = GetPropertyAction.privilegedGetProperties(); String keepAlive = props.getProperty("http.keepAlive"); @@ -172,6 +199,9 @@ int getKeepAliveTimeout() { String cacheNTLM = props.getProperty("jdk.ntlm.cache"); String cacheSPNEGO = props.getProperty("jdk.spnego.cache"); + String s = props.getProperty("jdk.https.negotiate.cbt"); + spnegoCBT = normalizeCBT(s); + if (keepAlive != null) { keepAliveProp = Boolean.parseBoolean(keepAlive); } else { @@ -206,6 +236,10 @@ public boolean getHttpKeepAliveSet() { } + public String getSpnegoCBT() { + return spnegoCBT; + } + protected HttpClient() { } diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/HttpCallerInfo.java b/src/java.base/share/classes/sun/net/www/protocol/http/HttpCallerInfo.java index 038f7adfe90..5afed084c7f 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/HttpCallerInfo.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/HttpCallerInfo.java @@ -29,6 +29,7 @@ import java.net.Authenticator.RequestorType; import java.net.InetAddress; import java.net.URL; +import java.security.cert.X509Certificate; /** * Used in HTTP/Negotiate, to feed HTTP request info into JGSS as a HttpCaller, @@ -51,6 +52,9 @@ public final class HttpCallerInfo { public final InetAddress addr; public final RequestorType authType; public final Authenticator authenticator; + // Used to obtain server cert for SPNEGO CBT. + // May be null in which case CBT is not set + public final X509Certificate serverCert; /** * Create a schemed object based on an un-schemed one. @@ -65,13 +69,19 @@ public HttpCallerInfo(HttpCallerInfo old, String scheme) { this.authType = old.authType; this.scheme = scheme; this.authenticator = old.authenticator; + this.serverCert = old.serverCert; } /** * Constructor an un-schemed object for site access. */ public HttpCallerInfo(URL url, Authenticator a) { + this(url, null, a); + } + + public HttpCallerInfo(URL url, X509Certificate serverCert, Authenticator a) { this.url= url; + this.serverCert= serverCert; prompt = ""; host = url.getHost(); @@ -100,9 +110,14 @@ public HttpCallerInfo(URL url, Authenticator a) { * Constructor an un-schemed object for proxy access. */ public HttpCallerInfo(URL url, String host, int port, Authenticator a) { + this(url, host, port, null, a); + } + + public HttpCallerInfo(URL url, String host, int port, X509Certificate serverCert, Authenticator a) { this.url= url; this.host = host; this.port = port; + this.serverCert = serverCert; prompt = ""; addr = null; protocol = url.getProtocol(); diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index cba385f04fa..fec467887d1 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -1740,7 +1740,7 @@ private InputStream getInputStream0() throws IOException { AuthenticationHeader authhdr = new AuthenticationHeader ( "Proxy-Authenticate", responses, - new HttpCallerInfo(url, + getHttpCallerInfo(url, http.getProxyHostUsed(), http.getProxyPortUsed(), authenticator), @@ -1815,7 +1815,7 @@ private InputStream getInputStream0() throws IOException { srvHdr = new AuthenticationHeader ( "WWW-Authenticate", responses, - new HttpCallerInfo(url, authenticator), + getHttpCallerInfo(url, authenticator), dontUseNegotiate ); @@ -2211,7 +2211,7 @@ private void doTunneling0() throws IOException { AuthenticationHeader authhdr = new AuthenticationHeader( "Proxy-Authenticate", responses, - new HttpCallerInfo(url, + getHttpCallerInfo(url, http.getProxyHostUsed(), http.getProxyPortUsed(), authenticator), @@ -2280,6 +2280,21 @@ private void doTunneling0() throws IOException { responses.reset(); } + /** + * Overridden in https to also include the server certificate + */ + protected HttpCallerInfo getHttpCallerInfo(URL url, String proxy, int port, + Authenticator authenticator) { + return new HttpCallerInfo(url, proxy, port, authenticator); + } + + /** + * Overridden in https to also include the server certificate + */ + protected HttpCallerInfo getHttpCallerInfo(URL url, Authenticator authenticator) { + return new HttpCallerInfo(url, authenticator); + } + static String connectRequestURI(URL url) { String host = url.getHost(); int port = url.getPort(); diff --git a/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java index 3828eb3cd29..ff54e474b8e 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java @@ -1,4 +1,4 @@ -/* +/** * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -25,10 +25,13 @@ package sun.net.www.protocol.https; +import java.net.Authenticator; import java.net.URL; import java.net.Proxy; import java.net.SecureCacheResponse; import java.security.Principal; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; import java.io.IOException; import java.util.List; import java.util.Optional; @@ -36,6 +39,7 @@ import javax.net.ssl.SSLPeerUnverifiedException; import sun.net.www.http.*; import sun.net.www.protocol.http.HttpURLConnection; +import sun.net.www.protocol.http.HttpCallerInfo; /** * HTTPS URL connection support. @@ -309,4 +313,72 @@ SSLSession getSSLSession() { return ((HttpsClient)http).getSSLSession(); } + + /* + * If no SSL Session available or if the system config does not allow it + * don't use the extended caller info (the server cert). + * Otherwise return true to include the server cert + */ + private boolean useExtendedCallerInfo(URL url) { + HttpsClient https = (HttpsClient)http; + if (https.getSSLSession() == null) { + return false; + } + String prop = http.getSpnegoCBT(); + if (prop.equals("never")) { + return false; + } + String target = url.getHost(); + if (prop.startsWith("domain:")) { + String[] domains = prop.substring(7).split(","); + for (String domain : domains) { + if (target.equalsIgnoreCase(domain)) { + return true; + } + if (domain.startsWith("*.") && target.regionMatches( + true, target.length() - domain.length() + 1, domain, 1, domain.length() - 1)) { + return true; + } + } + return false; + } + return true; + } + + @Override + protected HttpCallerInfo getHttpCallerInfo(URL url, String proxy, int port, + Authenticator authenticator) + { + if (!useExtendedCallerInfo(url)) { + return super.getHttpCallerInfo(url, proxy, port, authenticator); + } + HttpsClient https = (HttpsClient)http; + try { + Certificate[] certs = https.getServerCertificates(); + if (certs[0] instanceof X509Certificate x509Cert) { + return new HttpCallerInfo(url, proxy, port, x509Cert, authenticator); + } + } catch (SSLPeerUnverifiedException e) { + // ignore + } + return super.getHttpCallerInfo(url, proxy, port, authenticator); + } + + @Override + protected HttpCallerInfo getHttpCallerInfo(URL url, Authenticator authenticator) + { + if (!useExtendedCallerInfo(url)) { + return super.getHttpCallerInfo(url, authenticator); + } + HttpsClient https = (HttpsClient)http; + try { + Certificate[] certs = https.getServerCertificates(); + if (certs[0] instanceof X509Certificate x509Cert) { + return new HttpCallerInfo(url, x509Cert, authenticator); + } + } catch (SSLPeerUnverifiedException e) { + // ignore + } + return super.getHttpCallerInfo(url, authenticator); + } } diff --git a/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java b/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java index c4cc4ccdec7..60419b0d92a 100644 --- a/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java +++ b/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java @@ -658,8 +658,8 @@ private void readObject(java.io.ObjectInputStream s) if (!(memberType.isInstance(value) || value instanceof ExceptionProxy)) { value = new AnnotationTypeMismatchExceptionProxy( - value.getClass() + "[" + value + "]").setMember( - annotationType.members().get(name)); + objectToString(value)) + .setMember(annotationType.members().get(name)); } } mv.put(name, value); @@ -669,6 +669,15 @@ private void readObject(java.io.ObjectInputStream s) UnsafeAccessor.setMemberValues(this, mv); } + /* + * Create a textual representation of the argument without calling + * any overridable methods of the argument. + */ + private static String objectToString(Object value) { + return value.getClass().getName() + "@" + + Integer.toHexString(System.identityHashCode(value)); + } + private static class UnsafeAccessor { private static final jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe(); diff --git a/src/java.base/share/classes/sun/security/provider/DSA.java b/src/java.base/share/classes/sun/security/provider/DSA.java index a7c42a1f35a..6cbc7d0fbc9 100644 --- a/src/java.base/share/classes/sun/security/provider/DSA.java +++ b/src/java.base/share/classes/sun/security/provider/DSA.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -362,7 +362,8 @@ protected boolean engineVerify(byte[] signature, int offset, int length) s = new BigInteger(1, s.toByteArray()); } - if ((r.compareTo(presetQ) == -1) && (s.compareTo(presetQ) == -1)) { + if ((r.compareTo(presetQ) == -1) && (s.compareTo(presetQ) == -1) + && r.signum() > 0 && s.signum() > 0) { BigInteger w = generateW(presetP, presetQ, presetG, s); BigInteger v = generateV(presetY, presetP, presetQ, presetG, w, r); return v.equals(r); diff --git a/src/java.base/share/classes/sun/security/tools/keytool/Main.java b/src/java.base/share/classes/sun/security/tools/keytool/Main.java index 2d38c08bdb6..cc98cf36091 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/Main.java +++ b/src/java.base/share/classes/sun/security/tools/keytool/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -2208,6 +2208,9 @@ private void doPrintEntry(String label, String alias, PrintStream out) out.println(mf); dumpCert(cert, out); } else if (debug) { + for (var attr : keyStore.getEntry(alias, null).getAttributes()) { + System.out.println("Attribute " + attr.getName() + ": " + attr.getValue()); + } out.println(cert.toString()); } else { out.println("trustedCertEntry, "); diff --git a/src/java.base/share/classes/sun/security/util/ChannelBindingException.java b/src/java.base/share/classes/sun/security/util/ChannelBindingException.java new file mode 100644 index 00000000000..847cd0741a0 --- /dev/null +++ b/src/java.base/share/classes/sun/security/util/ChannelBindingException.java @@ -0,0 +1,60 @@ +/* + * 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. 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.security.GeneralSecurityException; + +/** + * Thrown by TlsChannelBinding if an error occurs + */ +public class ChannelBindingException extends GeneralSecurityException { + + @java.io.Serial + private static final long serialVersionUID = -5021387249782788460L; + + /** + * Constructs a ChannelBindingException with no detail message. A detail + * message is a String that describes this particular exception. + */ + public ChannelBindingException() { + super(); + } + + /** + * Constructs a ChannelBindingException with a detail message and + * specified cause. + */ + public ChannelBindingException(String msg, Exception e) { + super(msg, e); + } + + /** + * Constructs a ChannelBindingException with a detail message + */ + public ChannelBindingException(String msg) { + super(msg); + } +} diff --git a/src/java.base/share/classes/sun/security/util/DerIndefLenConverter.java b/src/java.base/share/classes/sun/security/util/DerIndefLenConverter.java index f2b88560ca3..018a0e7e5d3 100644 --- a/src/java.base/share/classes/sun/security/util/DerIndefLenConverter.java +++ b/src/java.base/share/classes/sun/security/util/DerIndefLenConverter.java @@ -144,15 +144,14 @@ private void parseTag() throws IOException { * then skip the tag and its 1 byte length of zero. */ private void writeTag() { - if (dataPos == dataSize) { - return; - } - assert dataPos + 1 < dataSize; - if (isEOC(data, dataPos)) { - dataPos += 2; // skip tag and length - writeTag(); - } else { - newData[newDataPos++] = data[dataPos++]; + while (dataPos < dataSize) { + assert dataPos + 1 < dataSize; + if (isEOC(data, dataPos)) { + dataPos += 2; // skip tag and length + } else { + newData[newDataPos++] = data[dataPos++]; + break; + } } } 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 725c6b9af98..2739515d039 100644 --- a/src/java.base/share/classes/sun/security/util/DerValue.java +++ b/src/java.base/share/classes/sun/security/util/DerValue.java @@ -302,6 +302,34 @@ public static DerValue wrap(byte tag, DerOutputStream out) { return new DerValue(tag, out.buf(), 0, out.size(), false); } + /** + * Wraps a byte array as a single DerValue. + * + * Attention: no cloning is made. + * + * @param buf the byte array containing the DER-encoded datum + * @returns a new DerValue + */ + public static DerValue wrap(byte[] buf) + throws IOException { + return wrap(buf, 0, buf.length); + } + + /** + * Wraps a byte array as a single DerValue. + * + * Attention: no cloning is made. + * + * @param buf the byte array containing the DER-encoded datum + * @param offset where the encoded datum starts inside {@code buf} + * @param len length of bytes to parse inside {@code buf} + * @returns a new DerValue + */ + public static DerValue wrap(byte[] buf, int offset, int len) + throws IOException { + return new DerValue(buf, offset, len, true, false); + } + /** * Parse an ASN.1/BER encoded datum. The entire encoding must hold exactly * one datum, including its tag and length. diff --git a/src/java.base/share/classes/sun/security/util/ManifestEntryVerifier.java b/src/java.base/share/classes/sun/security/util/ManifestEntryVerifier.java index 43d0e751dee..97315291cc6 100644 --- a/src/java.base/share/classes/sun/security/util/ManifestEntryVerifier.java +++ b/src/java.base/share/classes/sun/security/util/ManifestEntryVerifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -192,7 +192,8 @@ public JarEntry getEntry() * */ public CodeSigner[] verify(Hashtable verifiedSigners, - Hashtable sigFileSigners) + Hashtable sigFileSigners, + Map> signersToAlgs) throws JarException { if (skip) { @@ -207,38 +208,60 @@ public CodeSigner[] verify(Hashtable verifiedSigners, return signers; } - JarConstraintsParameters params = - getParams(verifiedSigners, sigFileSigners); + CodeSigner[] entrySigners = sigFileSigners.get(name); + Map algsPermittedStatus = + algsPermittedStatusForSigners(signersToAlgs, entrySigners); + // Flag that indicates if only disabled algorithms are used and jar + // entry should be treated as unsigned. + boolean disabledAlgs = true; + JarConstraintsParameters params = null; for (int i=0; i < digests.size(); i++) { MessageDigest digest = digests.get(i); - if (params != null) { - try { - params.setExtendedExceptionMsg(JarFile.MANIFEST_NAME, - name + " entry"); - DisabledAlgorithmConstraints.jarConstraints() - .permits(digest.getAlgorithm(), params); - } catch (GeneralSecurityException e) { - if (debug != null) { - debug.println("Digest algorithm is restricted: " + e); + String digestAlg = digest.getAlgorithm(); + + // Check if this algorithm is permitted, skip if false. + if (algsPermittedStatus != null) { + Boolean permitted = algsPermittedStatus.get(digestAlg); + if (permitted == null) { + if (params == null) { + params = new JarConstraintsParameters(entrySigners); } - return null; + if (!checkConstraints(digestAlg, params)) { + algsPermittedStatus.put(digestAlg, Boolean.FALSE); + continue; + } else { + algsPermittedStatus.put(digestAlg, Boolean.TRUE); + } + } else if (!permitted) { + continue; } } + + // A non-disabled algorithm was used. + disabledAlgs = false; + byte [] manHash = manifestHashes.get(i); byte [] theHash = digest.digest(); if (debug != null) { debug.println("Manifest Entry: " + - name + " digest=" + digest.getAlgorithm()); + name + " digest=" + digestAlg); debug.println(" manifest " + HexFormat.of().formatHex(manHash)); debug.println(" computed " + HexFormat.of().formatHex(theHash)); debug.println(); } - if (!MessageDigest.isEqual(theHash, manHash)) - throw new SecurityException(digest.getAlgorithm()+ + if (!MessageDigest.isEqual(theHash, manHash)) { + throw new SecurityException(digestAlg + " digest error for "+name); + } + } + + // If there were only disabled algorithms used, return null and jar + // entry will be treated as unsigned. + if (disabledAlgs) { + return null; } // take it out of sigFileSigners and put it in verifiedSigners... @@ -249,40 +272,36 @@ public CodeSigner[] verify(Hashtable verifiedSigners, return signers; } - /** - * Get constraints parameters for JAR. The constraints should be - * checked against all code signers. Returns the parameters, - * or null if the signers for this entry have already been checked - * or there are no signers for this entry. - */ - private JarConstraintsParameters getParams( - Map verifiedSigners, - Map sigFileSigners) { - - // verifiedSigners is usually preloaded with the Manifest's signers. - // If verifiedSigners contains the Manifest, then it will have all of - // the signers of the JAR. But if it doesn't then we need to fallback - // and check verifiedSigners to see if the signers of this entry have - // been checked already. - if (verifiedSigners.containsKey(manifestFileName)) { - if (verifiedSigners.size() > 1) { - // this means we already checked it previously - return null; - } else { - return new JarConstraintsParameters( - verifiedSigners.get(manifestFileName)); + // Gets the algorithms permitted status for the signers of this entry. + private static Map algsPermittedStatusForSigners( + Map> signersToAlgs, + CodeSigner[] signers) { + if (signers != null) { + Map algs = signersToAlgs.get(signers); + // create new HashMap if absent + if (algs == null) { + algs = new HashMap<>(); + signersToAlgs.put(signers, algs); } - } else { + return algs; + } + return null; + } + + // Checks the algorithm constraints against the signers of this entry. + private boolean checkConstraints(String algorithm, + JarConstraintsParameters params) { + try { + params.setExtendedExceptionMsg(JarFile.MANIFEST_NAME, + name + " entry"); + DisabledAlgorithmConstraints.jarConstraints() + .permits(algorithm, params); + return true; + } catch (GeneralSecurityException e) { if (debug != null) { - debug.println(manifestFileName + " not present in verifiedSigners"); - } - CodeSigner[] signers = sigFileSigners.get(name); - if (signers == null || verifiedSigners.containsValue(signers)) { - return null; - } else { - return new JarConstraintsParameters(signers); + debug.println("Digest algorithm is restricted: " + e); } + return false; } } } - diff --git a/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java b/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java index 9c7bfafa139..9025fe0788f 100644 --- a/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java +++ b/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -365,7 +365,7 @@ private int[] toIntArray() { if ((encoding[i] & 0x80) == 0) { // one section [fromPos..i] if (i - fromPos + 1 > 4) { - BigInteger big = new BigInteger(pack(encoding, + BigInteger big = new BigInteger(1, pack(encoding, fromPos, i-fromPos+1, 7, 8)); if (fromPos == 0) { result[which++] = 2; @@ -434,7 +434,7 @@ public String toString() { sb.append('.'); } if (i - fromPos + 1 > 4) { // maybe big integer - BigInteger big = new BigInteger( + BigInteger big = new BigInteger(1, pack(encoding, fromPos, i-fromPos+1, 7, 8)); if (fromPos == 0) { // first section encoded with more than 4 bytes, @@ -684,6 +684,10 @@ private static void checkOtherComponent( } private static void checkOidSize(int oidLength) throws IOException { + if (oidLength < 0) { + throw new IOException("ObjectIdentifier encoded length was " + + "negative: " + oidLength); + } if (oidLength > MAXIMUM_OID_SIZE) { throw new IOException( "ObjectIdentifier encoded length exceeds " + diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/TlsChannelBinding.java b/src/java.base/share/classes/sun/security/util/TlsChannelBinding.java similarity index 82% rename from src/java.naming/share/classes/com/sun/jndi/ldap/sasl/TlsChannelBinding.java rename to src/java.base/share/classes/sun/security/util/TlsChannelBinding.java index 922fa18028c..8f7ac50bb5e 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/TlsChannelBinding.java +++ b/src/java.base/share/classes/sun/security/util/TlsChannelBinding.java @@ -22,10 +22,9 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.sun.jndi.ldap.sasl; -import javax.naming.NamingException; -import javax.security.sasl.SaslException; +package sun.security.util; + import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateEncodingException; @@ -47,14 +46,6 @@ public class TlsChannelBinding { - // TLS channel binding type property - public static final String CHANNEL_BINDING_TYPE = - "com.sun.jndi.ldap.tls.cbtype"; - - // internal TLS channel binding property - public static final String CHANNEL_BINDING = - "jdk.internal.sasl.tlschannelbinding"; - public enum TlsChannelBindingType { /** @@ -80,19 +71,18 @@ public String getName() { } /** - * Parse value of "com.sun.jndi.ldap.tls.cbtype" property + * Parse given value to see if it is a recognized and supported channel binding type + * * @param cbType - * @return TLS Channel Binding type or null if - * "com.sun.jndi.ldap.tls.cbtype" property has not been set. - * @throws NamingException + * @return TLS Channel Binding type or null if given string is null + * @throws ChannelBindingException */ - public static TlsChannelBindingType parseType(String cbType) throws NamingException { + public static TlsChannelBindingType parseType(String cbType) throws ChannelBindingException { if (cbType != null) { if (cbType.equals(TlsChannelBindingType.TLS_SERVER_END_POINT.getName())) { return TlsChannelBindingType.TLS_SERVER_END_POINT; } else { - throw new NamingException("Illegal value for " + - CHANNEL_BINDING_TYPE + " property."); + throw new ChannelBindingException("Illegal value for channel binding type: " + cbType); } } return null; @@ -104,9 +94,9 @@ public static TlsChannelBindingType parseType(String cbType) throws NamingExcept /** * Construct tls-server-end-point Channel Binding data * @param serverCertificate - * @throws SaslException + * @throws ChannelBindingException */ - public static TlsChannelBinding create(X509Certificate serverCertificate) throws SaslException { + public static TlsChannelBinding create(X509Certificate serverCertificate) throws ChannelBindingException { try { final byte[] prefix = TlsChannelBindingType.TLS_SERVER_END_POINT.getName().concat(":").getBytes(); @@ -127,7 +117,7 @@ public static TlsChannelBinding create(X509Certificate serverCertificate) throws System.arraycopy(hash, 0, cbData, prefix.length, hash.length); return new TlsChannelBinding(TlsChannelBindingType.TLS_SERVER_END_POINT, cbData); } catch (NoSuchAlgorithmException | CertificateEncodingException e) { - throw new SaslException("Cannot create TLS channel binding data", e); + throw new ChannelBindingException("Cannot create TLS channel binding data", e); } } diff --git a/src/java.base/share/legal/public_suffix.md b/src/java.base/share/legal/public_suffix.md index 3c015a4427b..61d9607177e 100644 --- a/src/java.base/share/legal/public_suffix.md +++ b/src/java.base/share/legal/public_suffix.md @@ -11,7 +11,7 @@ If you do not wish to use the Public Suffix List, you may remove the The Source Code of this file is available under the Mozilla Public License, v. 2.0 and is located at -https://raw.githubusercontent.com/publicsuffix/list/cbbba1d234670453df9c930dfbf510c0474d4301/public_suffix_list.dat. +https://raw.githubusercontent.com/publicsuffix/list/3c213aab32b3c014f171b1673d4ce9b5cd72bf1c/public_suffix_list.dat. If a copy of the MPL was not distributed with this file, you can obtain one at https://mozilla.org/MPL/2.0/. diff --git a/src/java.base/share/man/java.1 b/src/java.base/share/man/java.1 index 0d2ae06a71b..e867e290a10 100644 --- a/src/java.base/share/man/java.1 +++ b/src/java.base/share/man/java.1 @@ -1,4 +1,4 @@ -.\" Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved. +.\" Copyright (c) 1994, 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 @@ -1078,8 +1078,10 @@ Require using shared class data, otherwise fail. .RS .PP \f[B]Note:\f[R] The \f[CB]\-Xshare:on\f[R] option is used for testing -purposes only and may cause intermittent failures due to the use of -address space layout randomization by the operation system. +purposes only. +It may cause the VM to unexpectedly exit during start\-up when the CDS +archive cannot be used (for example, when certain VM parameters are +changed, or when a different JDK is used). This option should not be used in production environments. .RE .TP @@ -5287,293 +5289,83 @@ who\[aq]s running the application, because administrators by default don\[aq]t have the privilege to lock pages in memory. .SH APPLICATION CLASS DATA SHARING .PP -Application Class Data Sharing (AppCDS) extends class data sharing (CDS) -to enable application classes to be placed in a shared archive. +Application Class Data Sharing (AppCDS) stores classes used by your +applications in an archive file. +Since these classes are stored in a format that can be loaded very +quickly (compared to classes stored in a JAR file), AppCDS can improve +the start\-up time of your applications. +In addition, AppCDS can reduce the runtime memory footprint by sharing +parts of these classes across multiple processes. .PP -In addition to the core library classes, AppCDS supports \f[B]Class Data -Sharing\f[R] -[https://docs.oracle.com/en/java/javase/12/vm/class\-data\-sharing.html#GUID\-7EAA3411\-8CF0\-4D19\-BD05\-DF5E1780AA91] -from the following locations: -.IP \[bu] 2 -Platform classes from the runtime image -.IP \[bu] 2 -Application classes from the runtime image -.IP \[bu] 2 -Application classes from the class path -.IP \[bu] 2 -Application classes from the module path +Classes in the CDS archive are stored in an optimized format that\[aq]s +about 2 to 5 times larger than classes stored in JAR files or the JDK +runtime image. +Therefore, it\[aq]s a good idea to archive only those classes that are +actually used by your application. +These usually are just a small portion of all available classes. +For example, your application may use only a few APIs provided by a +large library. +.SS Using CDS Archives .PP -Archiving application classes provides better start up time at runtime. -When running multiple JVM processes, AppCDS also reduces the runtime -footprint with memory sharing for read\-only metadata. +By default, in most JDK distributions, unless \f[CB]\-Xshare:off\f[R] is +specified, the JVM starts up with a default CDS archive, which is +usually located in \f[CB]JAVA_HOME/lib/server/classes.jsa\f[R] (or +\f[CB]JAVA_HOME\\bin\\server\\classes.jsa\f[R] on Windows). +This archive contains about 1300 core library classes that are used by +most applications. .PP -CDS/AppCDS supports archiving classes from JAR files only. +To use CDS for the exact set of classes used by your application, you +can use the \f[CB]\-XX:SharedArchiveFile\f[R] option, which has the +general form: +.RS .PP -Prior to JDK 11, a non\-empty directory was reported as a fatal error in -the following conditions: -.IP \[bu] 2 -For base CDS, a non\-empty directory cannot exist in the -\f[CB]\-Xbootclasspath/a\f[R] path +\f[CB]\-XX:SharedArchiveFile=:\f[R] +.RE .IP \[bu] 2 -With \f[CB]\-XX:+UseAppCDS\f[R], a non\-empty directory could not exist in -the \f[CB]\-Xbootclasspath/a\f[R] path, class path, and module path. -.PP -In JDK 11 and later, \f[CB]\-XX:+UseAppCDS\f[R] is obsolete and the -behavior for a non\-empty directory is based on the class types in the -classlist. -A non\-empty directory is reported as a fatal error in the following -conditions: +The \f[CB]\f[R] overrides the default CDS archive. .IP \[bu] 2 -If application classes or platform classes are not loaded, dump time -only reports an error if a non\-empty directory exists in -\f[CB]\-Xbootclasspath/a\f[R] path +The \f[CB]\f[R] provides additional classes that can be +loaded on top of those in the \f[CB]\f[R]. .IP \[bu] 2 -If application classes or platform classes are loaded, dump time reports -an error for a non\-empty directory that exists in -\f[CB]\-Xbootclasspath/a\f[R] path, class path, or module path -.PP -In JDK 11 and later, using -\f[CB]\-XX:DumpLoadedClassList=\f[R]\f[I]class_list_file\f[R] results a -generated classlist with all classes (both system library classes and -application classes) included. -You no longer have to specify \f[CB]\-XX:+UseAppCDS\f[R] with -\f[CB]\-XX:DumpLoadedClassList\f[R] to produce a complete class list. +On Windows, the above path delimiter \f[CB]:\f[R] should be replaced with +\f[CB];\f[R] .PP -In JDK 11 and later, because \f[CB]UseAppCDS\f[R] is obsolete, -\f[CB]SharedArchiveFile\f[R] becomes a product flag by default. -Specifying \f[CB]+UnlockDiagnosticVMOptions\f[R] for -\f[CB]SharedArchiveFile\f[R] is no longer needed in any configuration. +(The names "static" and "dyanmic" are used for historical reasons. +The only significance is that the "static" archive is loaded first and +the "dynamic" archive is loaded second). .PP -Class Data Sharing (CDS)/AppCDS does not support archiving array classes -in a class list. -When an array in the class list is encountered, CDS dump time gives the -explicit error message: +The JVM can use up to two archives. +To use only a single \f[CB]\f[R], you can omit the +\f[CB]\f[R] portion: .RS .PP -\f[CB]Preload\ Warning:\ Cannot\ find\f[R] \f[I]array_name\f[R] +\f[CB]\-XX:SharedArchiveFile=\f[R] .RE .PP -Although an array in the class list is not allowed, some array classes -can still be created at CDS/AppCDS dump time. -Those arrays are created during the execution of the Java code used by -the Java class loaders (\f[CB]PlatformClassLoader\f[R] and the system -class loader) to load classes at dump time. -The created arrays are archived with the rest of the loaded classes. -.SS Extending Class Data Sharing to Support the Module Path -.PP -In JDK 11, Class Data Sharing (CDS) has been improved to support -archiving classes from the module path. -.IP \[bu] 2 -To create a CDS archive using the \f[CB]\-\-module\-path\f[R] VM option, -use the following command line syntax: -.RS 2 -.RS -.PP -\f[CB]java\ \-Xshare:dump\ \-XX:SharedClassListFile=\f[R]\f[I]class_list_file\f[R] -\f[CB]\-XX:SharedArchiveFile=\f[R]\f[I]shared_archive_file\f[R] -\f[CB]\-\-module\-path=\f[R]\f[I]path_to_modular_jar\f[R] \f[CB]\-m\f[R] -\f[I]module_name\f[R] -.RE -.RE -.IP \[bu] 2 -To run with a CDS archive using the \f[CB]\-\-module\-path\f[R] VM option, -use the following the command line syntax: -.RS 2 +For convenience, the \f[CB]\f[R] records the location of +the \f[CB]\f[R]. +Therefore, you can omit the \f[CB]\f[R] by saying only: .RS .PP -\f[CB]java\ \-XX:SharedArchiveFile=\f[R]\f[I]shared_archive_file\f[R] -\f[CB]\-\-module\-path=\f[R]\f[I]path_to_modular_jar\f[R] \f[CB]\-m\f[R] -\f[I]module_name\f[R] -.RE +\f[CB]\-XX:SharedArchiveFile=\f[R] .RE +.SS Creating CDS Archives .PP -The following table describes how the VM options related to module paths -can be used along with the \f[CB]\-Xshare\f[R] option. -.PP -.TS -tab(@); -l l l. -T{ -Option -T}@T{ -\-Xshare:dump -T}@T{ -\-Xshare:{on,auto} -T} -_ -T{ -\f[CB]\-\-module\-path\f[R][1] \f[I]mp\f[R] -T}@T{ -Allowed -T}@T{ -Allowed[2] -T} -T{ -\f[CB]\-\-module\f[R] -T}@T{ -Allowed -T}@T{ -Allowed -T} -T{ -\f[CB]\-\-add\-module\f[R] -T}@T{ -Allowed -T}@T{ -Allowed -T} -T{ -\f[CB]\-\-upgrade\-module\-path\f[R][3] -T}@T{ -Disallowed (exits if specified) -T}@T{ -Allowed (disables CDS) -T} -T{ -\f[CB]\-\-patch\-module\f[R][4] -T}@T{ -Disallowed (exits if specified) -T}@T{ -Allowed (disables CDS) -T} -T{ -\f[CB]\-\-limit\-modules\f[R][5] -T}@T{ -Disallowed (exits if specified) -T}@T{ -Allowed (disables CDS) -T} -.TE -.PP -[1] Although there are two ways of specifying a module in a -\f[CB]\-\-module\-path\f[R], that is, modular JAR or exploded module, only -modular JARs are supported. -.PP -[2] Different \f[I]mp\f[R] can be specified during dump time versus run -time. -If an archived class K was loaded from \f[CB]mp1.jar\f[R] at dump time, -but changes in \f[I]mp\f[R] cause it to be available from a different -\f[CB]mp2.jar\f[R] at run time, then the archived version of K will be -disregarded at run time; K will be loaded dynamically. -.PP -[3] Currently, only two system modules are upgradeable -(\f[CB]java.compiler\f[R] and \f[CB]jdk.internal.vm.compiler\f[R]). -However, these modules are seldom upgraded in production software. -.PP -[4] As documented in JEP 261, using \f[CB]\-\-patch\-module\f[R] is -strongly discouraged for production use. -.PP -[5] \f[CB]\-\-limit\-modules\f[R] is intended for testing purposes. -It is seldom used in production software. -.PP -If \f[CB]\-\-upgrade\-module\-path\f[R], \f[CB]\-\-patch\-module\f[R], or -\f[CB]\-\-limit\-modules\f[R] is specified at dump time, an error will be -printed and the JVM will exit. -For example, if the \f[CB]\-\-limit\-modules\f[R] option is specified at -dump time, the user will see the following error: -.IP -.nf -\f[CB] -Error\ occurred\ during\ initialization\ of\ VM -Cannot\ use\ the\ following\ option\ when\ dumping\ the\ shared\ archive:\ \-\-limit\-modules -\f[R] -.fi -.PP -If \f[CB]\-\-upgrade\-module\-path\f[R], \f[CB]\-\-patch\-module\f[R], or -\f[CB]\-\-limit\-modules\f[R] is specified at run time, a warning message -will be printed indicating that CDS is disabled. -For example, if the \f[CB]\-\-limit\-modules\f[R] options is specified at -run time, the user will see the following warning: -.IP -.nf -\f[CB] -Java\ HotSpot(TM)\ 64\-Bit\ Server\ VM\ warning:\ CDS\ is\ disabled\ when\ the\ \-\-limit\-modules\ option\ is\ specified. -\f[R] -.fi -.PP -Several other noteworthy things include: -.IP \[bu] 2 -Any valid combinations of \f[CB]\-cp\f[R] and \f[CB]\-\-module\-path\f[R] -are supported. -.IP \[bu] 2 -A non\-empty directory in the module path causes a fatal error. -The user will see the following error messages: -.RS 2 -.IP -.nf -\f[CB] -Error:\ non\-empty\ directory\ \ Hint:\ enable\ \-Xlog:class+path=info\ to\ diagnose\ the\ failure\ Error\ occurred\ during\ initialization\ of\ VM\ Cannot\ have\ non\-empty\ directory\ in\ paths -\f[R] -.fi -.RE +CDS archives can be created with several methods: .IP \[bu] 2 -Unlike the class path, there\[aq]s no restriction that the module path -at dump time must be equal to or be a prefix of the module path at run -time. +\f[CB]\-Xshare:dump\f[R] .IP \[bu] 2 -The archive is invalidated if an existing JAR in the module path is -updated after archive generation. +\f[CB]\-XX:ArchiveClassesAtExit\f[R] .IP \[bu] 2 -Removing a JAR from the module path does not invalidate the shared -archive. -Archived classes from the removed JAR are not used at runtime. -.SS Dynamic CDS archive -.PP -Dynamic CDS archive extends AppCDS to allow archiving of classes when a -Java application exits. -It improves the usability of AppCDS by eliminating the trial run step -for creating a class list for each application. -The archived classes include all loaded application classes and library -classes that are not present in the default CDS archive which is -included in the JDK. -.PP -A base archive is required when creating a dynamic archive. -If the base archive is not specified, the default CDS archive is used as -the base archive. +\f[CB]jcmd\ VM.cds\f[R] .PP -To create a dynamic CDS archive with the default CDS archive as the base -archive, just add the -\f[CB]\-XX:ArchiveClassesAtExit=\f[R] option to the -command line for running the Java application. +One common operation in all these methods is a "trial run", where you +run the application once to determine the classes that should be stored +in the archive. +.SS Creating a Static CDS Archive File with \-Xshare:dump .PP -If the default CDS archive does not exist, the VM will exit with the -following error: -.IP -.nf -\f[CB] -ArchiveClassesAtExit\ not\ supported\ when\ base\ CDS\ archive\ is\ not\ loaded -\f[R] -.fi -.PP -To run the Java application using a dynamic CDS archive, just add the -\f[CB]\-XX:SharedArchiveFile=\f[R] option to the command -line for running the Java application. -.PP -The base archive is not required to be specified in the command line. -The base archive information, including its name and full path, will be -retrieved from the dynamic archive header. -Note that the user could also use the \f[CB]\-XX:SharedArchiveFile\f[R] -option for specifying a regular AppCDS archive. -Therefore, the specified archive in the \f[CB]\-XX:SharedArchiveFile\f[R] -option could be either a regular or dynamic archive. -During VM start up the specified archive header will be read. -If \f[CB]\-XX:SharedArchiveFile\f[R] refers to a regular archive, then the -behavior will be unchanged. -If \f[CB]\-XX:SharedArchiveFile\f[R] refers to a dynamic archive, the VM -will retrieve the base archive location from the dynamic archive. -If the dynamic archive was created with the default CDS archive, then -the current default CDS archive will be used, and will be found relative -to the current run time environment. -.PP -Please refer to \f[B]JDK\-8221706\f[R] -[https://bugs.openjdk.java.net/browse/JDK\-8221706] for details on error -checking during dynamic CDS archive dump time and run time. -.SS Creating a Shared Archive File and Using It to Run an Application -.SS AppCDS archive -.PP -The following steps create a shared archive file that contains all the -classes used by the \f[CB]test.Hello\f[R] application. -The last step runs the application with the shared archive file. +The following steps create a static CDS archive file that contains all +the classes used by the \f[CB]test.Hello\f[R] application. .IP "1." 3 Create a list of all classes used by the \f[CB]test.Hello\f[R] application. @@ -5585,23 +5377,20 @@ contains a list of all classes used by this application: \f[CB]java\ \-Xshare:off\ \-XX:DumpLoadedClassList=hello.classlist\ \-cp\ hello.jar\ test.Hello\f[R] .RE .PP -Note that the classpath specified by the \f[CB]\-cp\f[R] parameter must -contain only JAR files. +The classpath specified by the \f[CB]\-cp\f[R] parameter must contain only +JAR files. .RE .IP "2." 3 -Create a shared archive, named \f[CB]hello.jsa\f[R], that contains all the +Create a static archive, named \f[CB]hello.jsa\f[R], that contains all the classes in \f[CB]hello.classlist\f[R]: .RS 4 .RS .PP \f[CB]java\ \-Xshare:dump\ \-XX:SharedArchiveFile=hello.jsa\ \-XX:SharedClassListFile=hello.classlist\ \-cp\ hello.jar\f[R] .RE -.PP -Note that the classpath used at archive creation time must be the same -as (or a prefix of) the classpath used at run time. .RE .IP "3." 3 -Run the application \f[CB]test.Hello\f[R] with the shared archive +Run the application \f[CB]test.Hello\f[R] with the archive \f[CB]hello.jsa\f[R]: .RS 4 .RS @@ -5615,23 +5404,27 @@ using the class contained in the \f[CB]hello.jsa\f[R] shared archive: .RS 4 .RS .PP -\f[CB]java\ \-XX:SharedArchiveFile=hello.jsa\ \-cp\ hello.jar\ \-verbose:class\ test.Hello\f[R] +\f[CB]java\ \-XX:SharedArchiveFile=hello.jsa\ \-cp\ hello.jar\ \-Xlog:class+load\ test.Hello\f[R] .RE .PP The output of this command should contain the following text: -.IP -.nf -\f[CB] -Loaded\ test.Hello\ from\ shared\ objects\ file\ by\ sun/misc/Launcher$AppClassLoader -\f[R] -.fi +.RS +.PP +\f[CB][info][class,load]\ test.Hello\ source:\ shared\ objects\ file\f[R] +.RE .RE -.SS Dynamic CDS archive +.SS Creating a Dynamic CDS Archive File with \-XX:SharedArchiveFile +.PP +Advantages of dynamic CDS archives are: +.IP \[bu] 2 +They usually use less disk space, since they don\[aq]t need to store the +classes that are already in the static archive. +.IP \[bu] 2 +They are created with one fewer step than the comparable static archive. .PP The following steps create a dynamic CDS archive file that contains the -classes used by the \f[CB]test.Hello\f[R] application and are not included -in the default CDS archive. -The second step runs the application with the dynamic CDS archive. +classes that are used by the \f[CB]test.Hello\f[R] application, excluding +those that are already in the default CDS archive. .IP "1." 3 Create a dynamic CDS archive, named \f[CB]hello.jsa\f[R], that contains all the classes in \f[CB]hello.jar\f[R] loaded by the application @@ -5641,9 +5434,6 @@ all the classes in \f[CB]hello.jar\f[R] loaded by the application .PP \f[CB]java\ \-XX:ArchiveClassesAtExit=hello.jsa\ \-cp\ hello.jar\ Hello\f[R] .RE -.PP -Note that the classpath used at archive creation time must be the same -as (or a prefix of) the classpath used at run time. .RE .IP "2." 3 Run the application \f[CB]test.Hello\f[R] with the shared archive @@ -5659,218 +5449,87 @@ Run the application \f[CB]test.Hello\f[R] with the shared archive the \f[CB]test.Hello\f[R] application is using the class contained in the \f[CB]hello.jsa\f[R] shared archive. .PP -To automate the above steps 1 and 2, one can write a script such as the -following: -.IP -.nf -\f[CB] -\ \ \ \ ARCHIVE=hello.jsa -\ \ \ \ if\ test\ \-f\ $ARCHIVE;\ then -\ \ \ \ \ \ \ \ FLAG="\-XX:SharedArchiveFile=$ARCHIVE" -\ \ \ \ else -\ \ \ \ \ \ \ \ FLAG="\-XX:ArchiveClassesAtExit=$ARCHIVE" -\ \ \ \ fi -\ \ \ \ $JAVA_HOME/bin/java\ \-cp\ hello.jar\ $FLAG\ test.Hello -\f[R] -.fi -.PP -Like an AppCDS archive, the archive needs to be re\-generated if the -Java version has changed. -The above script could be adjusted to account for the Java version as -follows: -.IP -.nf -\f[CB] -\ \ \ \ ARCHIVE=hello.jsa -\ \ \ \ VERSION=foo.version -\ \ \ \ if\ test\ \-f\ $ARCHIVE\ \-a\ \-f\ $VERSION\ &&\ cmp\ \-s\ $VERSION\ $JAVA_HOME/release;\ then -\ \ \ \ \ \ \ \ FLAG="\-XX:SharedArchiveFile=$ARCHIVE" -\ \ \ \ else -\ \ \ \ \ \ \ \ FLAG="\-XX:ArchiveClassesAtExit=$ARCHIVE" -\ \ \ \ \ \ \ \ cp\ \-f\ $JAVA_HOME/release\ $VERSION -\ \ \ \ fi -\ \ \ \ $JAVA_HOME/bin/java\ \-cp\ hello.jar\ $FLAG\ test.Hello -\f[R] -.fi -.PP -Currently, we don\[aq]t support concurrent dumping operations to the -same CDS archive. -Care should be taken to avoid multiple writers to the same CDS archive. -.PP -The user could also create a dynamic CDS archive with a specific base -archive, e.g. -named as \f[CB]base.jsa\f[R] as follows: +It\[aq]s also possible to create a dynamic CDS archive with a +non\-default static CDS archive. +E.g., .RS .PP \f[CB]java\ \-XX:SharedArchiveFile=base.jsa\ \-XX:ArchiveClassesAtExit=hello.jsa\ \-cp\ hello.jar\ Hello\f[R] .RE .PP -To run the application using the dynamic CDS archive \f[CB]hello.jsa\f[R] -and a specific base CDS archive \f[CB]base.jsa\f[R]: +To run the application using this dynamic CDS archive: .RS .PP \f[CB]java\ \-XX:SharedArchiveFile=base.jsa:hello.jsa\ \-cp\ hello.jar\ Hello\f[R] .RE .PP -Note that on Windows, the above path delimiter \f[CB]:\f[R] should be -replaced with \f[CB];\f[R]. -.PP -The above command for specifying a base archive is useful if the base -archive used for creating the dynamic archive has been moved. -Normally, just specifying the dynamic archive should be sufficient since -the base archive info can be retrieved from the dynamic archive header. -.SS Sharing a Shared Archive Across Multiple Application Processes -.PP -You can share the same archive file across multiple applications -processes. -This reduces memory usage because the archive is memory\-mapped into the -address space of the processes. -The operating system automatically shares the read\-only pages across -these processes. -.PP -The following steps demonstrate how to create a common archive that can -be shared by different applications. -Classes from \f[CB]common.jar\f[R], \f[CB]hello.jar\f[R] and \f[CB]hi.jar\f[R] -are archived in the \f[CB]common.jsa\f[R] because they are all in the -classpath during the archiving step (step 3). -.PP -To include classes from \f[CB]hello.jar\f[R] and \f[CB]hi.jar\f[R], the -\f[CB]\&.jar\f[R] files must be added to the classpath specified by the -\f[CB]\-cp\f[R] parameter. -.IP "1." 3 -Create a list of all classes used by the \f[CB]Hello\f[R] application and -another list for the \f[CB]Hi\f[R] application: -.RS 4 -.RS -.PP -\f[CB]java\ \-XX:DumpLoadedClassList=hello.classlist\ \-cp\ common.jar:hello.jar\ Hello\f[R] -.RE -.RS -.PP -\f[CB]java\ \-XX:DumpLoadedClassList=hi.classlist\ \-cp\ common.jar:hi.jar\ Hi\f[R] -.RE -.RE -.IP "2." 3 -Create a single list of classes used by all the applications that will -share the shared archive file. -.RS 4 +(On Windows, the above path delimiter \f[CB]:\f[R] should be replaced with +\f[CB];\f[R]) .PP -\f[B]Linux and macOS\f[R] The following commands combine the files -\f[CB]hello.classlist\f[R] and \f[CB]hi.classlist\f[R] into one file, -\f[CB]common.classlist\f[R]: +As mention above, the name of the static archive can be skipped: .RS .PP -\f[CB]cat\ hello.classlist\ hi.classlist\ >\ common.classlist\f[R] +\f[CB]java\ \-XX:SharedArchiveFile=hello.jsa\ \-cp\ hello.jar\ Hello\f[R] .RE +.SS Creating CDS Archive Files with jcmd .PP -\f[B]Windows\f[R] The following commands combine the files -\f[CB]hello.classlist\f[R] and \f[CB]hi.classlist\f[R] into one file, -\f[CB]common.classlist\f[R]: -.RS +The previous two sections require you to modify the application\[aq]s +start\-up script in order to create a CDS archive. +Sometimes this could be difficult, for example, if the application\[aq]s +class path is set up by complex routines. .PP -\f[CB]type\ hello.classlist\ hi.classlist\ >\ common.classlist\f[R] -.RE -.RE -.IP "3." 3 -Create a shared archive named \f[CB]common.jsa\f[R] that contains all the -classes in \f[CB]common.classlist\f[R]: -.RS 4 +The \f[CB]jcmd\ VM.cds\f[R] command provides a less intrusive way for +creating a CDS archive by connecting to a running JVM process. +You can create either a static: .RS .PP -\f[CB]java\ \-Xshare:dump\ \-XX:SharedArchiveFile=common.jsa\ \-XX:SharedClassListFile=common.classlist\ \-cp\ common.jar:hello.jar:hi.jar\f[R] +\f[CB]jcmd\ \ VM.cds\ static_dump\ my_static_archive.jsa\f[R] .RE .PP -The classpath parameter used is the common class path prefix shared by -the \f[CB]Hello\f[R] and \f[CB]Hi\f[R] applications. -.RE -.IP "4." 3 -Run the \f[CB]Hello\f[R] and \f[CB]Hi\f[R] applications with the same shared -archive: -.RS 4 -.RS -.PP -\f[CB]java\ \-XX:SharedArchiveFile=common.jsa\ \-cp\ common.jar:hello.jar:hi.jar\ Hello\f[R] -.RE +or a dynamic archive: .RS .PP -\f[CB]java\ \-XX:SharedArchiveFile=common.jsa\ \-cp\ common.jar:hello.jar:hi.jar\ Hi\f[R] -.RE +\f[CB]jcmd\ \ VM.cds\ dynamic_dump\ my_dynamic_archive.jsa\f[R] .RE -.SS Specifying Additional Shared Data Added to an Archive File .PP -The \f[CB]SharedArchiveConfigFile\f[R] option is used to specify -additional shared data to add to the archive file. +To use the resulting archive file in a subsequent run of the application +without modifying the application\[aq]s start\-up script, you can use +the following technique: .RS .PP -\f[CB]\-XX:SharedArchiveConfigFile=\f[R]\f[I]shared_config_file\f[R] +\f[CB]env\ JAVA_TOOL_OPTIONS=\-XX:SharedArchiveFile=my_static_archive.jsa\ bash\ app_start.sh\f[R] .RE .PP -JDK 9 and later supports adding both symbols and string objects to an -archive for memory sharing when you have multiple JVM processes running -on the same host. -An example of this is having multiple JVM processes that use the same -set of Java EE classes. -When these common classes are loaded and used, new symbols and strings -may be created and added to the JVM\[aq]s internal "symbol" and "string" -tables. -At runtime, the symbols or string objects mapped from the archive file -can be shared across multiple JVM processes, resulting in a reduction of -overall memory usage. -In addition, archiving strings also provides added performance benefits -in both startup time and runtime execution. -.PP -In JDK 10 and later, CONSTANT_String entries in archived classes are -resolved to interned String objects at dump time, and all interned -String objects are archived. -However, even though all CONSTANT_String literals in all archived -classes are resolved, it might still beneficial to add additional -strings that are not string literals in class files, but are likely to -be used by your application at run time. -.PP -Symbol data should be generated by the \f[CB]jcmd\f[R] tool attaching to a -running JVM process. -See \f[B]jcmd\f[R]. -.PP -The following is an example of the symbol dumping command in -\f[CB]jcmd\f[R]: +Note: to use \f[CB]jcmd\ \ VM.cds\ dynamic_dump\f[R], the JVM process +identified by \f[CB]\f[R] must be started with +\f[CB]\-XX:+RecordDynamicDumpInfo\f[R], which can also be passed to the +application start\-up script with the same technique: .RS .PP -\f[CB]jcmd\f[R] \f[I]pid\f[R] \f[CB]VM.symboltable\ \-verbose\f[R] +\f[CB]env\ JAVA_TOOL_OPTIONS=\-XX:+RecordDynamicDumpInfo\ bash\ app_start.sh\f[R] .RE -.RS -.PP -\f[B]Note:\f[R] The first line (process ID) and the second line -(\f[CB]\@VERSION\ ...\f[R]) of this \f[CB]jcmd\f[R] output should be -excluded from the configuration file. -.RE -.SS Example of a Configuration File -.PP -The following is an example of a configuration file: -.IP -.nf -\f[CB] -VERSION:\ 1.0 -\@SECTION:\ Symbol -10\ \-1:\ linkMethod -\f[R] -.fi -.PP -In the configuration file example, the \f[CB]\@SECTION:\ Symbol\f[R] entry -uses the following format: -.RS -.PP -\f[I]length\f[R] \f[I]refcount\f[R]\f[CB]:\f[R] \f[I]symbol\f[R] -.RE -.PP -The \f[I]refcount\f[R] for a shared symbol is always \f[CB]\-1\f[R]. -.PP -\f[CB]\@SECTION\f[R] specifies the type of the section that follows it. -All data within the section must be the same type that\[aq]s specified -by \f[CB]\@SECTION\f[R]. -Different types of data can\[aq]t be mixed. -Multiple separated data sections for the same type specified by -different \f[CB]\@SECTION\f[R] are allowed within one -\f[CB]shared_config_file\f[R] . +.SS Restrictions on Class Path and Module Path +.IP \[bu] 2 +Neither the class path (\f[CB]\-classpath\f[R] and +\f[CB]\-Xbootclasspath/a\f[R]) nor the module path +(\f[CB]\-\-module\-path\f[R]) can contain non\-empty directories. +.IP \[bu] 2 +Only modular JAR files are supported in \f[CB]\-\-module\-path\f[R]. +Exploded modules are not supported. +.IP \[bu] 2 +The class path used at archive creation time must be the same as (or a +prefix of) the class path used at run time. +(There\[aq]s no such requirement for the module path.) +.IP \[bu] 2 +The CDS archive cannot be loaded if any JAR files in the class path or +module path are modified after the archive is generated. +.IP \[bu] 2 +If any of the VM options \f[CB]\-\-upgrade\-module\-path\f[R], +\f[CB]\-\-patch\-module\f[R] or \f[CB]\-\-limit\-modules\f[R] are specified, +CDS is disabled. +This means that the JVM will execute without loading any CDS archives. +In addition, if you try to create a CDS archive with any of these 3 +options specified, the JVM will report an error. .SH PERFORMANCE TUNING EXAMPLES .PP You can use the Java advanced runtime options to optimize the diff --git a/src/java.base/unix/classes/java/io/UnixFileSystem.java b/src/java.base/unix/classes/java/io/UnixFileSystem.java index e03825ff458..501b5d8883b 100644 --- a/src/java.base/unix/classes/java/io/UnixFileSystem.java +++ b/src/java.base/unix/classes/java/io/UnixFileSystem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -141,6 +141,11 @@ public boolean isAbsolute(File f) { return (f.getPrefixLength() != 0); } + @Override + public boolean isInvalid(File f) { + return f.getPath().indexOf('\u0000') < 0 ? false : true; + } + @Override public String resolve(File f) { if (isAbsolute(f)) return f.getPath(); diff --git a/src/java.base/windows/classes/java/io/WinNTFileSystem.java b/src/java.base/windows/classes/java/io/WinNTFileSystem.java index f30717f9ea6..2e0493a095d 100644 --- a/src/java.base/windows/classes/java/io/WinNTFileSystem.java +++ b/src/java.base/windows/classes/java/io/WinNTFileSystem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -26,6 +26,7 @@ package java.io; import java.io.File; +import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.util.BitSet; import java.util.Locale; @@ -45,6 +46,20 @@ class WinNTFileSystem extends FileSystem { private final char semicolon; private final String userDir; + // Whether to enable alternative data streams (ADS) by suppressing + // checking the path for invalid characters, in particular ":". + // By default, ADS support is enabled and will be disabled if and + // only if the property is set, ignoring case, to the string "false". + private static final boolean ENABLE_ADS; + static { + String enableADS = GetPropertyAction.privilegedGetProperty("jdk.io.File.enableADS"); + if (enableADS != null) { + ENABLE_ADS = !enableADS.equalsIgnoreCase(Boolean.FALSE.toString()); + } else { + ENABLE_ADS = true; + } + } + public WinNTFileSystem() { Properties props = GetPropertyAction.privilegedGetProperties(); slash = props.getProperty("file.separator").charAt(0); @@ -305,6 +320,36 @@ public boolean isAbsolute(File f) { || (pl == 3)); } + @Override + public boolean isInvalid(File f) { + if (f.getPath().indexOf('\u0000') >= 0) + return true; + + if (ENABLE_ADS) + return false; + + // Invalid if there is a ":" at a position greater than 1, or if there + // is a ":" at position 1 and the first character is not a letter + String pathname = f.getPath(); + int lastColon = pathname.lastIndexOf(":"); + + // Valid if there is no ":" present or if the last ":" present is + // at index 1 and the first character is a latter + if (lastColon < 0 || + (lastColon == 1 && isLetter(pathname.charAt(0)))) + return false; + + // Invalid if path creation fails + Path path = null; + try { + path = sun.nio.fs.DefaultFileSystemProvider.theFileSystem().getPath(pathname); + return false; + } catch (InvalidPathException ignored) { + } + + return true; + } + @Override public String resolve(File f) { String path = f.getPath(); diff --git a/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c b/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c index 879422f096f..cdf239c4946 100644 --- a/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c +++ b/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c @@ -359,18 +359,17 @@ JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderA JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getNumberPattern (JNIEnv *env, jclass cls, jint numberStyle, jstring jlangtag) { const jchar *langtag; - jstring ret; + jstring ret = NULL; WCHAR * pattern; langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); CHECK_NULL_RETURN(langtag, NULL); pattern = getNumberPattern(langtag, numberStyle); - CHECK_NULL_RETURN(pattern, NULL); - + if (!IS_NULL(pattern)) { + ret = (*env)->NewString(env, pattern, (jsize)wcslen(pattern)); + free(pattern); + } (*env)->ReleaseStringChars(env, jlangtag, langtag); - ret = (*env)->NewString(env, pattern, (jsize)wcslen(pattern)); - free(pattern); - return ret; } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonLabeledUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonLabeledUI.java index 3a9ed6b12f5..3c21b325f36 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonLabeledUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonLabeledUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -170,7 +170,7 @@ public synchronized void paint(final Graphics g, final JComponent c) { } int offset = 0; - if (b.isFocusOwner()) { + if (b.isFocusOwner() && b.isFocusPainted()) { offset = 2; altIcon = AquaFocus.createFocusedIcon(altIcon, c, 2); } diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CRobot.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CRobot.java index 49125443b2e..5dba06cb612 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CRobot.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CRobot.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -168,9 +168,9 @@ public void keyRelease(final int keycode) { */ @Override public int getRGBPixel(int x, int y) { - int[] c = new int[1]; - double scale = fDevice.getScaleFactor(); - getScreenPixels(new Rectangle(x, y, (int) scale, (int) scale), c); + int scale = fDevice.getScaleFactor(); + int[] c = new int[scale * scale]; + getScreenPixels(new Rectangle(x, y, scale, scale), c); return c[0]; } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m index 9d90086677d..55df129960f 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -321,6 +321,11 @@ static inline void autoDelay(BOOL isMove) { jint picY = y; jint picWidth = width; jint picHeight = height; + jsize size = (*env)->GetArrayLength(env, pixels); + if (size < (long) picWidth * picHeight || picWidth < 0 || picHeight < 0) { + JNU_ThrowInternalError(env, "Invalid arguments to get screen pixels"); + return; + } CGRect screenRect = CGRectMake(picX / scale, picY / scale, picWidth / scale, picHeight / scale); diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.m index 06e998ec409..173ad891051 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.m @@ -161,8 +161,8 @@ void initializeActions() { [sActions setObject:NSAccessibilityPressAction forKey:@"click"]; [sActions setObject:NSAccessibilityIncrementAction forKey:@"increment"]; [sActions setObject:NSAccessibilityDecrementAction forKey:@"decrement"]; - [sActions setObject:NSAccessibilityShowMenuAction forKey:@"togglePopup"]; - [sActions setObject:NSAccessibilityPressAction forKey:@"toggleExpand"]; + [sActions setObject:NSAccessibilityShowMenuAction forKey:@"toggle popup"]; + [sActions setObject:NSAccessibilityPressAction forKey:@"toggleexpand"]; sActionSelectors = [[NSMutableDictionary alloc] initWithCapacity:actionsCount]; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.h index ef67c92a06d..103f2c31912 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.h @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.m index c44309a1e3c..ba91dbb8b6f 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.m @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.h index a78afaa924b..80f633f4a91 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.h @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.m index 238b82f609e..fb41511275b 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.m @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.h index 4a39938a826..cfdd1faee61 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.h @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.m index 0fd70eb8151..0029436579f 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.m @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.m index 92dcfba518e..201fe5c3591 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.m @@ -1092,11 +1092,11 @@ - (id)accessibilityHitTest:(NSPoint)point { JNIEnv* env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBILITY_CLASS_RETURN(nil); DECLARE_CLASS_RETURN(jc_Container, "java/awt/Container", nil); DECLARE_STATIC_METHOD_RETURN(jm_accessibilityHitTest, sjc_CAccessibility, "accessibilityHitTest", "(Ljava/awt/Container;FF)Ljavax/accessibility/Accessible;", nil); - GET_CACCESSIBILITY_CLASS_RETURN(nil); // Make it into java screen coords point.y = [[[[self view] window] screen] frame].size.height - point.y; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComponentWrapperAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComponentWrapperAccessibility.h index fd1e774c274..269ea2d5ff8 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComponentWrapperAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComponentWrapperAccessibility.h @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComponentWrapperAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComponentWrapperAccessibility.m index 2101d7042fe..c2ce3260871 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComponentWrapperAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComponentWrapperAccessibility.m @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.h index ddfcd2217f8..88f55f99c34 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.h @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.m index 4dc958886bb..fc75efc6029 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.m @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.h index 130d12721e6..2b3b4412beb 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.h @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.m index 8b30080c85b..dc9e617d43c 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.m @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.h index 33a05318b5a..ebf314c7394 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.h @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.m index 84d8785e205..138d502f10f 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.m @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.h index 48074b209e0..2992d82cbe4 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.h @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.m index acc5727cd6b..cdf6dbbd4ab 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.m @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.h index 8cc8e1760c6..4185c0a27b9 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.h @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.m index e4d7e66027d..4653821283d 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.m @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.h index 0b497d4afc2..892225cf2ac 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.h @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.m index 4caf97c21cb..2b9bebd1db7 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.m @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.h index c99b18c904e..c660ff0e780 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.h @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.m index 76fafc0faaf..06375fc2934 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.m @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.h index 5fe04aa257f..6fa9fd0b636 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.h @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.m index d6382822e1e..d9d18b24fce 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.m @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.h index afa9eb44e3f..d9c19ccbc42 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.h @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.m index 31636dd99bb..890ac973311 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.m @@ -5,7 +5,9 @@ * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java index 2e1c2db03ca..29c40da43c3 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java @@ -67,6 +67,7 @@ import com.sun.imageio.plugins.common.I18N; import com.sun.imageio.plugins.common.ImageUtil; +import com.sun.imageio.plugins.common.ReaderUtil; /** This class is the Java Image IO plugin reader for BMP images. * It may subsample the image, clip the image, select sub-bands, @@ -1542,9 +1543,8 @@ private void readRLE8(byte[] bdata) throws IOException { } // Read till we have the whole image - byte[] values = new byte[imSize]; - int bytesRead = 0; - iis.readFully(values, 0, imSize); + byte[] values = ReaderUtil. + staggeredReadByteStream(iis, imSize); // Since data is compressed, decompress it decodeRLE8(imSize, padding, values, bdata); @@ -1726,8 +1726,8 @@ private void readRLE4(byte[] bdata) throws IOException { } // Read till we have the whole image - byte[] values = new byte[imSize]; - iis.readFully(values, 0, imSize); + byte[] values = ReaderUtil. + staggeredReadByteStream(iis, imSize); // Decompress the RLE4 compressed data. decodeRLE4(imSize, padding, values, bdata); 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 95c4d9ec597..26a318c3474 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 @@ -63,7 +63,7 @@ public boolean equals(Object o) { } public int hashCode() { - return theInstance.hashCode(); + return System.identityHashCode(theInstance); } public float[] toRGB(float[] colorvalue) { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java index 9d8cd29a950..717af6d7925 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java @@ -35,6 +35,7 @@ import javax.imageio.plugins.jpeg.JPEGImageReadParam; import javax.imageio.plugins.jpeg.JPEGQTable; import javax.imageio.plugins.jpeg.JPEGHuffmanTable; +import com.sun.imageio.plugins.common.SimpleCMYKColorSpace; import java.awt.Point; import java.awt.Rectangle; @@ -164,6 +165,12 @@ public Void run() { /** If we need to post-convert in Java, convert with this op */ private ColorConvertOp convert = null; + /** If reading CMYK as an Image, flip the bytes */ + private boolean invertCMYK = false; + + /** Whether to read as a raster */ + private boolean readAsRaster = false; + /** The image we are going to fill */ private BufferedImage image = null; @@ -938,6 +945,32 @@ private Iterator getImageTypesOnThread(int imageIndex) ArrayList list = new ArrayList(1); switch (colorSpaceCode) { + case JPEG.JCS_YCCK: + case JPEG.JCS_CMYK: + // There's no standard CMYK ColorSpace in JDK so raw.getType() + // will return null so skip that. + // And we can't add RGB because the number of bands is different. + // So need to create our own special that is 4 channels and uses + // the iccCS ColorSpace based on profile data in the image, and + // if there is none, on the internal CMYKColorSpace class + if (iccCS == null) { + iccCS = SimpleCMYKColorSpace.getInstance(); + } + if (iccCS != null) { + list.add(new ImageTypeProducer(colorSpaceCode) { + @Override + protected ImageTypeSpecifier produce() { + int [] bands = {0, 1, 2, 3}; + return ImageTypeSpecifier.createInterleaved + (iccCS, + bands, + DataBuffer.TYPE_BYTE, + false, + false); + } + }); + } + break; case JPEG.JCS_GRAYSCALE: list.add(raw); list.add(getImageType(JPEG.JCS_RGB)); @@ -1019,6 +1052,8 @@ private void checkColorConversion(BufferedImage image, int csType = cs.getType(); convert = null; switch (outColorSpaceCode) { + case JPEG.JCS_CMYK: // Its CMYK in the file + break; case JPEG.JCS_GRAYSCALE: // Its gray in the file if (csType == ColorSpace.TYPE_RGB) { // We want RGB // IJG can do this for us more efficiently @@ -1144,6 +1179,8 @@ public BufferedImage read(int imageIndex, ImageReadParam param) private Raster readInternal(int imageIndex, ImageReadParam param, boolean wantRaster) throws IOException { + + readAsRaster = wantRaster; readHeader(imageIndex, false); WritableRaster imRas = null; @@ -1186,6 +1223,16 @@ private Raster readInternal(int imageIndex, image = null; } + // Adobe seems to have decided that the bytes in CMYK JPEGs + // should be stored inverted. So we need some extra logic to + // flip them in that case. Don't flip for the raster case + // so code that is reading these as rasters today won't + // see a change in behaviour. + invertCMYK = + (!wantRaster && + ((colorSpaceCode == JPEG.JCS_YCCK) || + (colorSpaceCode == JPEG.JCS_CMYK))); + // Create an intermediate 1-line Raster that will hold the decoded, // subsampled, clipped, band-selected image data in a single // byte-interleaved buffer. The above transformations @@ -1364,6 +1411,21 @@ private Raster readInternal(int imageIndex, * After the copy, we notify update listeners. */ private void acceptPixels(int y, boolean progressive) { + + /* + * CMYK JPEGs seems to be universally inverted at the byte level. + * Fix this here before storing. + * For "compatibility" don't do this if the target is a raster. + * Need to do this here in case the application is listening + * for line-by-line updates to the image. + */ + if (invertCMYK) { + byte[] data = ((DataBufferByte)raster.getDataBuffer()).getData(); + for (int i = 0, len = data.length; i < len; i++) { + data[i] = (byte)(0x0ff - (data[i] & 0xff)); + } + } + if (convert != null) { convert.filter(raster, raster); } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java index 720e970903f..86825a4c986 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java @@ -132,6 +132,7 @@ public class JPEGImageWriter extends ImageWriter { private int newAdobeTransform = JPEG.ADOBE_IMPOSSIBLE; // Change if needed private boolean writeDefaultJFIF = false; private boolean writeAdobe = false; + private boolean invertCMYK = false; private JPEGMetadata metadata = null; private boolean sequencePrepared = false; @@ -655,6 +656,7 @@ private void writeOnThread(IIOMetadata streamMetadata, newAdobeTransform = JPEG.ADOBE_IMPOSSIBLE; // Change if needed writeDefaultJFIF = false; writeAdobe = false; + invertCMYK = false; // By default we'll do no conversion: int inCsType = JPEG.JCS_UNKNOWN; @@ -808,6 +810,14 @@ private void writeOnThread(IIOMetadata streamMetadata, } } break; + case ColorSpace.TYPE_CMYK: + outCsType = JPEG.JCS_CMYK; + if (jfif != null) { + ignoreJFIF = true; + warningOccurred + (WARNING_IMAGE_METADATA_JFIF_MISMATCH); + } + break; } } } // else no dest, metadata, not an image. Defaults ok @@ -1014,6 +1024,11 @@ private void writeOnThread(IIOMetadata streamMetadata, System.out.println("outCsType: " + outCsType); } + invertCMYK = + (!rasterOnly && + ((outCsType == JPEG.JCS_YCCK) || + (outCsType == JPEG.JCS_CMYK))); + // Note that getData disables acceleration on buffer, but it is // just a 1-line intermediate data transfer buffer that does not // affect the acceleration of the source image. @@ -1724,6 +1739,12 @@ private void grabPixels(int y) { srcBands); } raster.setRect(sourceLine); + if (invertCMYK) { + byte[] data = ((DataBufferByte)raster.getDataBuffer()).getData(); + for (int i = 0, len = data.length; i < len; i++) { + data[i] = (byte)(0x0ff - (data[i] & 0xff)); + } + } if ((y > 7) && (y%8 == 0)) { // Every 8 scanlines cbLock.lock(); try { diff --git a/src/java.desktop/share/classes/com/sun/media/sound/AudioFileSoundbankReader.java b/src/java.desktop/share/classes/com/sun/media/sound/AudioFileSoundbankReader.java index de9d124753f..eac30372a4f 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/AudioFileSoundbankReader.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/AudioFileSoundbankReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -78,12 +78,26 @@ public Soundbank getSoundbank(InputStream stream) public Soundbank getSoundbank(AudioInputStream ais) throws InvalidMidiDataException, IOException { + int MEGABYTE = 1048576; + int DEFAULT_BUFFER_SIZE = 65536; + int MAX_FRAME_SIZE = 1024; try { byte[] buffer; - if (ais.getFrameLength() == -1) { + int frameSize = ais.getFormat().getFrameSize(); + if (frameSize <= 0 || frameSize > MAX_FRAME_SIZE) { + throw new InvalidMidiDataException("Formats with frame size " + + frameSize + " are not supported"); + } + + long totalSize = ais.getFrameLength() * frameSize; + if (totalSize >= Integer.MAX_VALUE - 2) { + throw new InvalidMidiDataException( + "Can not allocate enough memory to read audio data."); + } + + if (ais.getFrameLength() == -1 || totalSize > MEGABYTE) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] buff = new byte[1024 - - (1024 % ais.getFormat().getFrameSize())]; + byte[] buff = new byte[DEFAULT_BUFFER_SIZE - (DEFAULT_BUFFER_SIZE % frameSize)]; int ret; while ((ret = ais.read(buff)) != -1) { baos.write(buff, 0, ret); @@ -91,8 +105,7 @@ public Soundbank getSoundbank(AudioInputStream ais) ais.close(); buffer = baos.toByteArray(); } else { - buffer = new byte[(int) (ais.getFrameLength() - * ais.getFormat().getFrameSize())]; + buffer = new byte[(int) totalSize]; new DataInputStream(ais).readFully(buffer); } ModelByteBufferWavetable osc = new ModelByteBufferWavetable( diff --git a/src/java.desktop/share/classes/javax/swing/JTable.java b/src/java.desktop/share/classes/javax/swing/JTable.java index b4d3037e572..ee17b69fa80 100644 --- a/src/java.desktop/share/classes/javax/swing/JTable.java +++ b/src/java.desktop/share/classes/javax/swing/JTable.java @@ -5481,6 +5481,21 @@ public Component getTableCellRendererComponent(JTable table, Object value, return this; } + + @Override + public AccessibleContext getAccessibleContext() { + if (accessibleContext == null) { + accessibleContext = new AccessibleBooleanRenderer(); + } + return accessibleContext; + } + + class AccessibleBooleanRenderer extends JCheckBox.AccessibleJCheckBox { + @Override + public AccessibleAction getAccessibleAction() { + return null; + } + } } /** @@ -8402,7 +8417,11 @@ public void removePropertyChangeListener(PropertyChangeListener l) { * @return the AccessibleAction, or null */ public AccessibleAction getAccessibleAction() { - return getCurrentAccessibleContext().getAccessibleAction(); + AccessibleContext ac = getCurrentAccessibleContext(); + if (ac != null) { + return ac.getAccessibleAction(); + } + return null; } /** diff --git a/src/java.desktop/share/native/libawt/awt/image/cvutils/img_globals.c b/src/java.desktop/share/native/libawt/awt/image/cvutils/img_globals.c index 2b9d519b24a..5a00bff098b 100644 --- a/src/java.desktop/share/native/libawt/awt/image/cvutils/img_globals.c +++ b/src/java.desktop/share/native/libawt/awt/image/cvutils/img_globals.c @@ -77,7 +77,7 @@ make_uns_ordered_dither_array(uns_ordered_dither_array oda, * color used as an index. */ void -make_sgn_ordered_dither_array(char* oda, int minerr, int maxerr) +make_sgn_ordered_dither_array(signed char* oda, int minerr, int maxerr) { int i, j, k; diff --git a/src/java.desktop/share/native/libawt/awt/image/cvutils/img_globals.h b/src/java.desktop/share/native/libawt/awt/image/cvutils/img_globals.h index 6398e1eb7d4..e99b6912d28 100644 --- a/src/java.desktop/share/native/libawt/awt/image/cvutils/img_globals.h +++ b/src/java.desktop/share/native/libawt/awt/image/cvutils/img_globals.h @@ -137,7 +137,7 @@ typedef int ImgConvertFcn(void *colormodel, * The type of the error matrix used in the ordered dithering code. */ typedef unsigned char uns_ordered_dither_array[8][8]; -typedef char sgn_ordered_dither_array[8][8]; +typedef signed char sgn_ordered_dither_array[8][8]; /* * The function provided for constructing the ordered dithering error @@ -148,7 +148,7 @@ typedef char sgn_ordered_dither_array[8][8]; JNIEXPORT void JNICALL make_uns_ordered_dither_array(uns_ordered_dither_array oda, int quantum); -extern void make_sgn_ordered_dither_array(char* oda, int errmin, int errmax); +extern void make_sgn_ordered_dither_array(signed char* oda, int errmin, int errmax); /* * The function provided for calculating the contents of the ImgCMData diff --git a/src/java.desktop/share/native/libawt/java2d/SurfaceData.h b/src/java.desktop/share/native/libawt/java2d/SurfaceData.h index 66b637281bb..48504629703 100644 --- a/src/java.desktop/share/native/libawt/java2d/SurfaceData.h +++ b/src/java.desktop/share/native/libawt/java2d/SurfaceData.h @@ -129,9 +129,9 @@ typedef struct { * array of bytes indexed by RxGxB where each component is reduced to 5 * bits of precision before indexing. * - * char *redErrTable; - * char *grnErrTable; - * char *bluErrTable; + * signed char *redErrTable; + * signed char *grnErrTable; + * signed char *bluErrTable; * [Requires SD_LOCK_INVCOLOR] * Pointers to the beginning of the ordered dither color error tables * for the colormap. The error tables are formatted as an 8x8 array @@ -159,9 +159,9 @@ typedef struct { unsigned int lutSize; /* # colors in colormap */ jint *lutBase; /* Pointer to colormap[0] */ unsigned char *invColorTable; /* Inverse color table */ - char *redErrTable; /* Red ordered dither table */ - char *grnErrTable; /* Green ordered dither table */ - char *bluErrTable; /* Blue ordered dither table */ + signed char *redErrTable; /* Red ordered dither table */ + signed char *grnErrTable; /* Green ordered dither table */ + signed char *bluErrTable; /* Blue ordered dither table */ int *invGrayTable; /* Inverse gray table */ int representsPrimaries; /* whether cmap represents primary colors */ union { diff --git a/src/java.desktop/share/native/libawt/java2d/loops/ByteIndexed.h b/src/java.desktop/share/native/libawt/java2d/loops/ByteIndexed.h index 9e177d6e31a..59c3f4f432a 100644 --- a/src/java.desktop/share/native/libawt/java2d/loops/ByteIndexed.h +++ b/src/java.desktop/share/native/libawt/java2d/loops/ByteIndexed.h @@ -44,7 +44,7 @@ typedef jubyte ByteIndexedDataType; #define DeclareByteIndexedStoreVars(PREFIX) \ int PREFIX ## XDither, PREFIX ## YDither, PREFIX ## RepPrims; \ - char *PREFIX ## rerr, *PREFIX ## gerr, *PREFIX ## berr; \ + signed char *PREFIX ## rerr, *PREFIX ## gerr, *PREFIX ## berr; \ unsigned char *PREFIX ## InvLut; #define SetByteIndexedStoreVarsYPos(PREFIX, pRasInfo, LOC) \ diff --git a/src/java.desktop/share/native/libawt/java2d/loops/UshortIndexed.h b/src/java.desktop/share/native/libawt/java2d/loops/UshortIndexed.h index 1f404d14aa8..06e535bbf4c 100644 --- a/src/java.desktop/share/native/libawt/java2d/loops/UshortIndexed.h +++ b/src/java.desktop/share/native/libawt/java2d/loops/UshortIndexed.h @@ -51,7 +51,7 @@ typedef jushort UshortIndexedDataType; #define DeclareUshortIndexedStoreVars(PREFIX) \ int PREFIX ## XDither, PREFIX ## YDither; \ - char *PREFIX ## rerr, *PREFIX ## gerr, *PREFIX ## berr; \ + signed char *PREFIX ## rerr, *PREFIX ## gerr, *PREFIX ## berr; \ unsigned char *PREFIX ## InvLut; #define SetUshortIndexedStoreVarsYPos(PREFIX, pRasInfo, LOC) \ diff --git a/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java b/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java index 9808e46ee1f..0ea741c1ccf 100644 --- a/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java +++ b/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -294,6 +294,12 @@ private String getVersionString(File f) { return null; } + private String extractOsInfo(String s) { + if (s.startsWith("\"")) s = s.substring(1); + if (s.endsWith("\"")) s = s.substring(0, s.length()-1); + return s; + } + /** * Sets the OS name and version from environment information. */ @@ -328,6 +334,16 @@ protected void setOsNameAndVersion() { } else if ((f = new File("/etc/fedora-release")).canRead()) { osName = "Fedora"; osVersion = getVersionString(f); + } else if ((f = new File("/etc/os-release")).canRead()) { + Properties props = new Properties(); + try (FileInputStream fis = new FileInputStream(f)) { + props.load(fis); + } + osName = props.getProperty("NAME"); + osVersion = props.getProperty("VERSION_ID"); + osName = extractOsInfo(osName); + if (osName.equals("SLES")) osName = "SuSE"; + osVersion = extractOsInfo(osVersion); } } catch (Exception e) { if (FontUtilities.debugFonts()) { diff --git a/src/java.desktop/unix/classes/sun/font/MFontConfiguration.java b/src/java.desktop/unix/classes/sun/font/MFontConfiguration.java index 89cc5f6b3e3..8ba2ca7448e 100644 --- a/src/java.desktop/unix/classes/sun/font/MFontConfiguration.java +++ b/src/java.desktop/unix/classes/sun/font/MFontConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -112,6 +112,16 @@ protected void setOsNameAndVersion(){ props.load(new FileInputStream(f)); osName = props.getProperty("DISTRIB_ID"); osVersion = props.getProperty("DISTRIB_RELEASE"); + } else if ((f = new File("/etc/os-release")).canRead()) { + Properties props = new Properties(); + try (FileInputStream fis = new FileInputStream(f)) { + props.load(fis); + } + osName = props.getProperty("NAME"); + osVersion = props.getProperty("VERSION_ID"); + osName = extractOsInfo(osName); + if (osName.equals("SLES")) osName = "SuSE"; + osVersion = extractOsInfo(osVersion); } } catch (Exception e) { } @@ -132,6 +142,12 @@ private String getVersionString(File f){ return null; } + private String extractOsInfo(String s) { + if (s.startsWith("\"")) s = s.substring(1); + if (s.endsWith("\"")) s = s.substring(0, s.length()-1); + return s; + } + private static final String fontsDirPrefix = "$JRE_LIB_FONTS"; protected String mapFileName(String fileName) { diff --git a/src/java.desktop/unix/native/common/awt/colordata.h b/src/java.desktop/unix/native/common/awt/colordata.h index cfee07dffdc..1bbedbdcc55 100644 --- a/src/java.desktop/unix/native/common/awt/colordata.h +++ b/src/java.desktop/unix/native/common/awt/colordata.h @@ -39,9 +39,9 @@ typedef struct _ColorData { unsigned char *awt_icmLUT2Colors; unsigned char *img_grays; unsigned char *img_clr_tbl; - char* img_oda_red; - char* img_oda_green; - char* img_oda_blue; + signed char* img_oda_red; + signed char* img_oda_green; + signed char* img_oda_blue; int *pGrayInverseLutData; int screendata; int representsPrimaries; diff --git a/src/java.desktop/unix/native/common/awt/fontpath.c b/src/java.desktop/unix/native/common/awt/fontpath.c index c4b2fcb73c0..fd28f5c0ea6 100644 --- a/src/java.desktop/unix/native/common/awt/fontpath.c +++ b/src/java.desktop/unix/native/common/awt/fontpath.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -496,6 +496,7 @@ typedef FcResult (*FcPatternGetStringFuncType)(const FcPattern *p, FcChar8 ** s); typedef FcChar8* (*FcStrDirnameFuncType)(const FcChar8 *file); typedef void (*FcPatternDestroyFuncType)(FcPattern *p); +typedef void (*FcObjectSetDestroyFuncType)(FcObjectSet *os); typedef void (*FcFontSetDestroyFuncType)(FcFontSet *s); typedef FcPattern* (*FcNameParseFuncType)(const FcChar8 *name); typedef FcBool (*FcPatternAddStringFuncType)(FcPattern *p, @@ -542,6 +543,7 @@ static char **getFontConfigLocations() { FcPatternGetStringFuncType FcPatternGetString; FcStrDirnameFuncType FcStrDirname; FcPatternDestroyFuncType FcPatternDestroy; + FcObjectSetDestroyFuncType FcObjectSetDestroy; FcFontSetDestroyFuncType FcFontSetDestroy; FcConfig *fontconfig; @@ -571,6 +573,8 @@ static char **getFontConfigLocations() { (FcStrDirnameFuncType)dlsym(libfontconfig, "FcStrDirname"); FcPatternDestroy = (FcPatternDestroyFuncType)dlsym(libfontconfig, "FcPatternDestroy"); + FcObjectSetDestroy = + (FcObjectSetDestroyFuncType)dlsym(libfontconfig, "FcObjectSetDestroy"); FcFontSetDestroy = (FcFontSetDestroyFuncType)dlsym(libfontconfig, "FcFontSetDestroy"); @@ -580,6 +584,7 @@ static char **getFontConfigLocations() { FcFontList == NULL || FcStrDirname == NULL || FcPatternDestroy == NULL || + FcObjectSetDestroy == NULL || FcFontSetDestroy == NULL) { /* problem with the library: return. */ closeFontConfig(libfontconfig, JNI_FALSE); return NULL; @@ -636,6 +641,7 @@ static char **getFontConfigLocations() { cleanup: /* Free memory and close the ".so" */ + (*FcObjectSetDestroy)(objset); (*FcPatternDestroy)(pattern); closeFontConfig(libfontconfig, JNI_TRUE); return fontdirs; @@ -935,8 +941,10 @@ Java_sun_font_FontConfigManager_getFontConfig if (cacheDirs != NULL) { while ((cnt < max) && (cacheDir = (*FcStrListNext)(cacheDirs))) { jstr = (*env)->NewStringUTF(env, (const char*)cacheDir); - JNU_CHECK_EXCEPTION(env); - + if (IS_NULL(jstr)) { + (*FcStrListDone)(cacheDirs); + return; + } (*env)->SetObjectArrayElement(env, cacheDirArray, cnt++, jstr); (*env)->DeleteLocalRef(env, jstr); } 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 815289b7c8f..6d7d3125b94 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -579,7 +579,8 @@ getAllConfigs (JNIEnv *env, int screen, AwtScreenDataPtr screenDataPtr) { XFree (pVI8sg); if (n1sg != 0) XFree (pVI1sg); - + if (nTrue != 0) + XFree (pVITrue); AWT_UNLOCK (); } diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp index dc2f81f3423..32ead20707e 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -3917,11 +3917,11 @@ void AwtComponent::SetCandidateWindow(int iCandType, int x, int y) HIMC hIMC = ImmGetContext(hwnd); if (hIMC) { CANDIDATEFORM cf; - cf.dwStyle = CFS_POINT; + cf.dwStyle = CFS_CANDIDATEPOS; ImmGetCandidateWindow(hIMC, 0, &cf); if (x != cf.ptCurrentPos.x || y != cf.ptCurrentPos.y) { cf.dwIndex = iCandType; - cf.dwStyle = CFS_POINT; + cf.dwStyle = CFS_CANDIDATEPOS; cf.ptCurrentPos = {x, y}; cf.rcArea = {0, 0, 0, 0}; ImmSetCandidateWindow(hIMC, &cf); diff --git a/src/java.desktop/windows/native/libawt/windows/awt_DnDDS.cpp b/src/java.desktop/windows/native/libawt/windows/awt_DnDDS.cpp index 0f9fb662bbf..8146d62c4a7 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_DnDDS.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_DnDDS.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -267,13 +267,13 @@ void AwtDragSource::_DoDragDrop(void* param) { dragSource->Signal(); AwtToolkit &toolkit = AwtToolkit::GetInstance(); - toolkit.isInDoDragDropLoop = TRUE; + toolkit.isDnDSourceActive = TRUE; res = ::DoDragDrop(dragSource, dragSource, convertActionsToDROPEFFECT(dragSource->m_actions), &effects ); - toolkit.isInDoDragDropLoop = FALSE; + toolkit.isDnDSourceActive = FALSE; if (effects == DROPEFFECT_NONE && dragSource->m_dwPerformedDropEffect != DROPEFFECT_NONE) { effects = dragSource->m_dwPerformedDropEffect; diff --git a/src/java.desktop/windows/native/libawt/windows/awt_DnDDT.cpp b/src/java.desktop/windows/native/libawt/windows/awt_DnDDT.cpp index 126e7194f86..ed41af9d6bf 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_DnDDT.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_DnDDT.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -141,7 +141,7 @@ static void ScaleDown(POINT &cp, HWND m_window) { HRESULT __stdcall AwtDropTarget::DragEnter(IDataObject __RPC_FAR *pDataObj, DWORD grfKeyState, POINTL pt, DWORD __RPC_FAR *pdwEffect) { TRY; - AwtToolkit::GetInstance().isInDoDragDropLoop = TRUE; + AwtToolkit::GetInstance().isDnDTargetActive = TRUE; if (NULL != m_pIDropTargetHelper) { m_pIDropTargetHelper->DragEnter( m_window, @@ -161,7 +161,7 @@ HRESULT __stdcall AwtDropTarget::DragEnter(IDataObject __RPC_FAR *pDataObj, DWOR (IsLocalDnD() && !IsLocalDataObject(pDataObj))) { *pdwEffect = retEffect; - AwtToolkit::GetInstance().isInDoDragDropLoop = FALSE; + AwtToolkit::GetInstance().isDnDTargetActive = FALSE; return ret; } @@ -173,7 +173,7 @@ HRESULT __stdcall AwtDropTarget::DragEnter(IDataObject __RPC_FAR *pDataObj, DWOR } if (JNU_IsNull(env, m_dtcp) || !JNU_IsNull(env, safe_ExceptionOccurred(env))) { - AwtToolkit::GetInstance().isInDoDragDropLoop = FALSE; + AwtToolkit::GetInstance().isDnDTargetActive = FALSE; return ret; } @@ -200,12 +200,12 @@ HRESULT __stdcall AwtDropTarget::DragEnter(IDataObject __RPC_FAR *pDataObj, DWOR env->ExceptionDescribe(); env->ExceptionClear(); actions = java_awt_dnd_DnDConstants_ACTION_NONE; - AwtToolkit::GetInstance().isInDoDragDropLoop = FALSE; + AwtToolkit::GetInstance().isDnDTargetActive = FALSE; } } catch (std::bad_alloc&) { retEffect = ::convertActionsToDROPEFFECT(actions); *pdwEffect = retEffect; - AwtToolkit::GetInstance().isInDoDragDropLoop = FALSE; + AwtToolkit::GetInstance().isDnDTargetActive = FALSE; throw; } @@ -421,7 +421,7 @@ void AwtDropTarget::DropDone(jboolean success, jint action) { m_dropSuccess = success; m_dropActions = action; AwtToolkit::GetInstance().QuitMessageLoop(AwtToolkit::EXIT_ENCLOSING_LOOP); - AwtToolkit::GetInstance().isInDoDragDropLoop = FALSE; + AwtToolkit::GetInstance().isDnDTargetActive = FALSE; } /** @@ -1136,7 +1136,7 @@ void AwtDropTarget::UnloadCache() { void AwtDropTarget::DragCleanup(void) { UnloadCache(); - AwtToolkit::GetInstance().isInDoDragDropLoop = FALSE; + AwtToolkit::GetInstance().isDnDTargetActive = FALSE; } BOOL AwtDropTarget::IsLocalDataObject(IDataObject __RPC_FAR *pDataObject) { diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Robot.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Robot.cpp index 33457ebef32..0afce8727e0 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Robot.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Robot.cpp @@ -28,20 +28,33 @@ #include "awt_Component.h" #include -static int signum(int i) { - // special version of signum which returns 1 when value is 0 - return i >= 0 ? 1 : -1; -} - static void MouseMove(jint x, jint y) { INPUT mouseInput = {0}; mouseInput.type = INPUT_MOUSE; mouseInput.mi.time = 0; - mouseInput.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; - mouseInput.mi.dx = (x * 65536 /::GetSystemMetrics(SM_CXSCREEN)) + signum(x); - mouseInput.mi.dy = (y * 65536 /::GetSystemMetrics(SM_CYSCREEN)) + signum(y); + + // The following calculations take into account a multi-monitor setup using + // a virtual screen for all monitors combined. + // More details from Microsoft are here -- + // https://docs.microsoft.com/en-us/windows/win32/gdi/the-virtual-screen + + x -= ::GetSystemMetrics(SM_XVIRTUALSCREEN); + y -= ::GetSystemMetrics(SM_YVIRTUALSCREEN); + + mouseInput.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE | + MOUSEEVENTF_VIRTUALDESK; + + int scW = ::GetSystemMetrics(SM_CXVIRTUALSCREEN); + int scH = ::GetSystemMetrics(SM_CYVIRTUALSCREEN); + + // The following calculation to deduce mouse coordinates is based on + // empirical data + mouseInput.mi.dx = (x * 65536 + scW - 1) / scW; + mouseInput.mi.dy = (y * 65536 + scH - 1) / scH; + ::SendInput(1, &mouseInput, sizeof(mouseInput)); + } static void MousePress(jint buttonMask) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp index 355d3207273..17e69d70b15 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -344,7 +344,8 @@ AwtToolkit::AwtToolkit() { m_waitEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL); m_inputMethodWaitEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL); - isInDoDragDropLoop = FALSE; + isDnDSourceActive = FALSE; + isDnDTargetActive = FALSE; eventNumber = 0; } @@ -3012,7 +3013,7 @@ Java_sun_awt_windows_WToolkit_syncNativeQueue(JNIEnv *env, jobject self, jlong t tk.PostMessage(WM_SYNC_WAIT, 0, 0); for(long t = 2; t < timeout && WAIT_TIMEOUT == ::WaitForSingleObject(tk.m_waitEvent, 2); t+=2) { - if (tk.isInDoDragDropLoop) { + if (tk.isDnDSourceActive || tk.isDnDTargetActive) { break; } } @@ -3216,7 +3217,7 @@ LRESULT AwtToolkit::InvokeInputMethodFunction(UINT msg, WPARAM wParam, LPARAM lP * the IME completion. */ CriticalSection::Lock lock(m_inputMethodLock); - if (isInDoDragDropLoop) { + if (isDnDSourceActive || isDnDTargetActive) { SendMessage(msg, wParam, lParam); ::ResetEvent(m_inputMethodWaitEvent); return m_inputMethodData; diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h index a148001842d..ff9baf6464a 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h +++ b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -441,7 +441,8 @@ class AwtToolkit { HANDLE m_waitEvent; volatile DWORD eventNumber; - volatile BOOL isInDoDragDropLoop; + volatile BOOL isDnDSourceActive; + volatile BOOL isDnDTargetActive; private: HWND CreateToolkitWnd(LPCTSTR name); diff --git a/src/java.desktop/windows/native/libawt/windows/colordata.h b/src/java.desktop/windows/native/libawt/windows/colordata.h index f25d8979f4d..5250f2a5768 100644 --- a/src/java.desktop/windows/native/libawt/windows/colordata.h +++ b/src/java.desktop/windows/native/libawt/windows/colordata.h @@ -28,9 +28,9 @@ #include "img_globals.h" typedef struct _ColorData { - char* img_oda_red; - char* img_oda_green; - char* img_oda_blue; + signed char* img_oda_red; + signed char* img_oda_green; + signed char* img_oda_blue; unsigned char* img_clr_tbl; int *pGrayInverseLutData; int representsPrimaries; diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapURL.java b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapURL.java index 8080eb79457..f26e086d6a7 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapURL.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapURL.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -28,6 +28,10 @@ import javax.naming.*; import java.net.MalformedURLException; import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Locale; import java.util.StringTokenizer; import com.sun.jndi.toolkit.url.Uri; import com.sun.jndi.toolkit.url.UrlUtil; @@ -64,6 +68,25 @@ public final class LdapURL extends Uri { + private static final String PARSE_MODE_PROP = "com.sun.jndi.ldapURLParsing"; + private static final ParseMode DEFAULT_PARSE_MODE = ParseMode.COMPAT; + + public static final ParseMode PARSE_MODE; + static { + PrivilegedAction action = () -> + System.getProperty(PARSE_MODE_PROP, DEFAULT_PARSE_MODE.toString()); + ParseMode parseMode = DEFAULT_PARSE_MODE; + try { + @SuppressWarnings("removal") + String mode = AccessController.doPrivileged(action); + parseMode = ParseMode.valueOf(mode.toUpperCase(Locale.ROOT)); + } catch (Throwable t) { + parseMode = DEFAULT_PARSE_MODE; + } finally { + PARSE_MODE = parseMode; + } + } + private boolean useSsl = false; private String DN = null; private String attributes = null; @@ -83,7 +106,7 @@ public LdapURL(String url) throws NamingException { useSsl = scheme.equalsIgnoreCase("ldaps"); if (! (scheme.equalsIgnoreCase("ldap") || useSsl)) { - throw new MalformedURLException("Not an LDAP URL: " + url); + throw newInvalidURISchemeException(url); } parsePathAndQuery(); // DN, attributes, scope, filter, extensions @@ -99,6 +122,21 @@ public LdapURL(String url) throws NamingException { } } + @Override + protected MalformedURLException newInvalidURISchemeException(String uri) { + return new MalformedURLException("Not an LDAP URL: " + uri); + } + + @Override + protected boolean isSchemeOnly(String uri) { + return isLdapSchemeOnly(uri); + } + + @Override + protected ParseMode parseMode() { + return PARSE_MODE; + } + /** * Returns true if the URL is an LDAPS URL. */ @@ -151,13 +189,33 @@ public static String[] fromList(String urlList) throws NamingException { StringTokenizer st = new StringTokenizer(urlList, " "); while (st.hasMoreTokens()) { - urls[i++] = st.nextToken(); + // we don't accept scheme-only URLs here + urls[i++] = validateURI(st.nextToken()); } String[] trimmed = new String[i]; System.arraycopy(urls, 0, trimmed, 0, i); return trimmed; } + public static boolean isLdapSchemeOnly(String uri) { + return "ldap:".equals(uri) || "ldaps:".equals(uri); + } + + public static String validateURI(String uri) { + // no validation in legacy mode parsing + if (PARSE_MODE == ParseMode.LEGACY) { + return uri; + } + + // special case of scheme-only URIs + if (isLdapSchemeOnly(uri)) { + return uri; + } + + // use java.net.URI to validate the uri syntax + return URI.create(uri).toString(); + } + /** * Determines whether an LDAP URL has query components. */ @@ -181,7 +239,8 @@ static String toUrlString(String host, int port, String dn, boolean useSsl) String p = (port != -1) ? (":" + port) : ""; String d = (dn != null) ? ("/" + UrlUtil.encode(dn, "UTF8")) : ""; - return useSsl ? "ldaps://" + h + p + d : "ldap://" + h + p + d; + String uri = useSsl ? "ldaps://" + h + p + d : "ldap://" + h + p + d; + return validateURI(uri); } catch (UnsupportedEncodingException e) { // UTF8 should always be supported throw new IllegalStateException("UTF-8 encoding unavailable"); diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/LdapSasl.java b/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/LdapSasl.java index 9a6145dc20c..7cce83800e3 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/LdapSasl.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/LdapSasl.java @@ -42,7 +42,9 @@ import com.sun.jndi.ldap.Connection; import com.sun.jndi.ldap.LdapClient; import com.sun.jndi.ldap.LdapResult; -import com.sun.jndi.ldap.sasl.TlsChannelBinding.TlsChannelBindingType; +import sun.security.util.ChannelBindingException; +import sun.security.util.TlsChannelBinding; +import sun.security.util.TlsChannelBinding.TlsChannelBindingType; /** * Handles SASL support. @@ -62,6 +64,14 @@ public final class LdapSasl { private static final int LDAP_SUCCESS = 0; private static final int LDAP_SASL_BIND_IN_PROGRESS = 14; // LDAPv3 + // TLS channel binding type property + private static final String CHANNEL_BINDING_TYPE = + "com.sun.jndi.ldap.tls.cbtype"; + + // internal TLS channel binding property + private static final String CHANNEL_BINDING = + "jdk.internal.sasl.tlschannelbinding"; + private LdapSasl() { } @@ -113,8 +123,8 @@ public static LdapResult saslBind(LdapClient clnt, Connection conn, String[] mechs = getSaslMechanismNames(authMech); // Internal TLS Channel Binding property cannot be set explicitly - if (env.get(TlsChannelBinding.CHANNEL_BINDING) != null) { - throw new NamingException(TlsChannelBinding.CHANNEL_BINDING + + if (env.get(CHANNEL_BINDING) != null) { + throw new NamingException(CHANNEL_BINDING + " property cannot be set explicitly"); } @@ -123,17 +133,24 @@ public static LdapResult saslBind(LdapClient clnt, Connection conn, try { // Prepare TLS Channel Binding data if (conn.isTlsConnection()) { - TlsChannelBindingType cbType = - TlsChannelBinding.parseType( - (String)env.get(TlsChannelBinding.CHANNEL_BINDING_TYPE)); + TlsChannelBindingType cbType; + try { + cbType = TlsChannelBinding.parseType((String)env.get(CHANNEL_BINDING_TYPE)); + } catch (ChannelBindingException e) { + throw wrapInNamingException(e); + } if (cbType == TlsChannelBindingType.TLS_SERVER_END_POINT) { // set tls-server-end-point channel binding X509Certificate cert = conn.getTlsServerCertificate(); if (cert != null) { - TlsChannelBinding tlsCB = - TlsChannelBinding.create(cert); + TlsChannelBinding tlsCB; + try { + tlsCB = TlsChannelBinding.create(cert); + } catch (ChannelBindingException e) { + throw wrapInNamingException(e); + } envProps = (Hashtable) env.clone(); - envProps.put(TlsChannelBinding.CHANNEL_BINDING, tlsCB.getData()); + envProps.put(CHANNEL_BINDING, tlsCB.getData()); } else { throw new SaslException("No suitable certificate to generate " + "TLS Channel Binding data"); @@ -227,5 +244,11 @@ private static String[] getSaslMechanismNames(String str) { return mechNames; } + private static NamingException wrapInNamingException(Exception e) { + NamingException ne = new NamingException(); + ne.setRootCause(e); + return ne; + } + private static final byte[] NO_BYTES = new byte[0]; } diff --git a/src/java.naming/share/classes/com/sun/jndi/toolkit/url/GenericURLContext.java b/src/java.naming/share/classes/com/sun/jndi/toolkit/url/GenericURLContext.java index e7a5c2027e7..0c7e466e853 100644 --- a/src/java.naming/share/classes/com/sun/jndi/toolkit/url/GenericURLContext.java +++ b/src/java.naming/share/classes/com/sun/jndi/toolkit/url/GenericURLContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -32,6 +32,8 @@ import java.util.Hashtable; import java.net.MalformedURLException; +import com.sun.jndi.toolkit.url.Uri.ParseMode; + /** * This abstract class is a generic URL context that accepts as the * name argument either a string URL or a Name whose first component @@ -48,6 +50,7 @@ * @author Rosanna Lee */ public abstract class GenericURLContext implements Context { + protected Hashtable myEnv = null; @SuppressWarnings("unchecked") // Expect Hashtable @@ -161,8 +164,18 @@ protected String getURLPrefix(String url) throws NamingException { if (url.startsWith("//", start)) { start += 2; // skip double slash - // find last slash - int posn = url.indexOf('/', start); + // find where the authority component ends + // and the rest of the URL starts + int slash = url.indexOf('/', start); + int qmark = url.indexOf('?', start); + int fmark = url.indexOf('#', start); + if (fmark > -1 && qmark > fmark) qmark = -1; + if (fmark > -1 && slash > fmark) slash = -1; + if (qmark > -1 && slash > qmark) slash = -1; + int posn = slash > -1 ? slash + : (qmark > -1 ? qmark + : (fmark > -1 ? fmark + : url.length())); if (posn >= 0) { start = posn; } else { diff --git a/src/java.naming/share/classes/com/sun/jndi/toolkit/url/Uri.java b/src/java.naming/share/classes/com/sun/jndi/toolkit/url/Uri.java index aaeb0eab6c7..33b9621d484 100644 --- a/src/java.naming/share/classes/com/sun/jndi/toolkit/url/Uri.java +++ b/src/java.naming/share/classes/com/sun/jndi/toolkit/url/Uri.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -27,6 +27,8 @@ import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; /** @@ -36,15 +38,17 @@ * *

    The java.net.URL class cannot be used to parse URIs since it * requires the installation of URL stream handlers that may not be - * available. The hack of getting around this by temporarily - * replacing the scheme part of a URI is not appropriate here: JNDI - * service providers must work on older Java platforms, and we want - * new features and bug fixes that are not available in old versions - * of the URL class. + * available. * - *

    It may be appropriate to drop this code in favor of the - * java.net.URI class. The changes would need to be written so as to - * still run on pre-1.4 platforms not containing that class. + *

    The {@linkplain ParseMode#STRICT strict} parsing mode uses + * the java.net.URI class to syntactically validate URI strings. + * The {@linkplain ParseMode#COMPAT compat} mode validate the + * URI authority and rejects URI fragments, but doesn't perform any + * additional validation on path and query, other than that + * which may be implemented in the concrete the Uri subclasses. + * The {@linkplain ParseMode#LEGACY legacy} mode should not be + * used unless the application is capable of validating all URI + * strings before any constructors of this class is invoked. * *

    The format of an absolute URI (see the RFCs mentioned above) is: *

    {@code
    @@ -105,6 +109,28 @@
     
     public class Uri {
     
    +    // three parsing modes
    +    public enum ParseMode {
    +        /**
    +         * Strict validation mode.
    +         * Validate the URI syntactically using {@link java.net.URI}.
    +         * Rejects URI fragments unless explicitly supported by the
    +         * subclass.
    +         */
    +        STRICT,
    +        /**
    +         * Compatibility mode. The URI authority is syntactically validated.
    +         * Rejects URI fragments unless explicitly supported by the
    +         * subclass.
    +         * This is the default.
    +         */
    +        COMPAT,
    +        /**
    +         * Legacy mode. In this mode, no validation is performed.
    +         */
    +        LEGACY
    +     }
    +
         protected String uri;
         protected String scheme;
         protected String host = null;
    @@ -112,6 +138,7 @@ public class Uri {
         protected boolean hasAuthority;
         protected String path;
         protected String query = null;
    +    protected String fragment;
     
     
         /**
    @@ -128,6 +155,15 @@ public Uri(String uri) throws MalformedURLException {
         protected Uri() {
         }
     
    +    /**
    +     * The parse mode for parsing this URI.
    +     * The default is {@link ParseMode#COMPAT}.
    +     * @return the parse mode for parsing this URI.
    +     */
    +    protected ParseMode parseMode() {
    +        return ParseMode.COMPAT;
    +    }
    +
         /**
          * Initializes a Uri object given a URI string.
          * This method must be called exactly once, and before any other Uri
    @@ -135,7 +171,7 @@ protected Uri() {
          */
         protected void init(String uri) throws MalformedURLException {
             this.uri = uri;
    -        parse(uri);
    +        parse(uri, parseMode());
         }
     
         /**
    @@ -188,10 +224,229 @@ public String toString() {
             return uri;
         }
     
    +    private void parse(String uri, ParseMode mode) throws MalformedURLException {
    +        switch (mode) {
    +            case STRICT -> parseStrict(uri);
    +            case COMPAT -> parseCompat(uri);
    +            case LEGACY -> parseLegacy(uri);
    +        }
    +    }
    +
    +    /*
    +     * Parses a URI string and sets this object's fields accordingly.
    +     * Use java.net.URI to validate the uri string syntax
    +     */
    +    private void parseStrict(String uri) throws MalformedURLException {
    +        try {
    +            if (!isSchemeOnly(uri)) {
    +                URI u = new URI(uri);
    +                scheme = u.getScheme();
    +                if (scheme == null) throw new MalformedURLException("Invalid URI: " + uri);
    +                var auth = u.getRawAuthority();
    +                hasAuthority = auth != null;
    +                if (hasAuthority) {
    +                    var host = u.getHost();
    +                    var port = u.getPort();
    +                    if (host != null) this.host = host;
    +                    if (port != -1) this.port = port;
    +                    String hostport = (host == null ? "" : host)
    +                            + (port == -1 ? "" : (":" + port));
    +                    if (!hostport.equals(auth)) {
    +                        // throw if we have user info or regname
    +                        throw new MalformedURLException("unsupported authority: " + auth);
    +                    }
    +                }
    +                path = u.getRawPath();
    +                if (u.getRawQuery() != null) {
    +                    query = "?" + u.getRawQuery();
    +                }
    +                if (u.getRawFragment() != null) {
    +                    if (!acceptsFragment()) {
    +                        throw new MalformedURLException("URI fragments not supported: " + uri);
    +                    }
    +                    fragment = "#" + u.getRawFragment();
    +                }
    +            } else {
    +                // scheme-only URIs are not supported by java.net.URI
    +                // validate the URI by appending "/" to the uri string.
    +                var s = uri.substring(0, uri.indexOf(':'));
    +                URI u = new URI(uri + "/");
    +                if (!s.equals(u.getScheme())
    +                        || !checkSchemeOnly(uri, u.getScheme())) {
    +                    throw newInvalidURISchemeException(uri);
    +                }
    +                scheme = s;
    +                path = "";
    +            }
    +        } catch (URISyntaxException e) {
    +            var mue =  new MalformedURLException(e.getMessage());
    +            mue.initCause(e);
    +            throw mue;
    +        }
    +    }
    +
    +
    +    /*
    +     * Parses a URI string and sets this object's fields accordingly.
    +     * Compatibility mode. Use java.net.URI to validate the syntax of
    +     * the uri string authority.
    +     */
    +    private void parseCompat(String uri) throws MalformedURLException {
    +        int i;  // index into URI
    +
    +        i = uri.indexOf(':');                           // parse scheme
    +        int slash = uri.indexOf('/');
    +        int qmark = uri.indexOf('?');
    +        int fmark = uri.indexOf('#');
    +        if (i < 0 || slash > 0 && i > slash || qmark > 0 && i > qmark || fmark > 0 && i > fmark) {
    +            throw new MalformedURLException("Invalid URI: " + uri);
    +        }
    +        if (fmark > -1) {
    +            if (!acceptsFragment()) {
    +                throw new MalformedURLException("URI fragments not supported: " + uri);
    +            }
    +        }
    +        if (i == uri.length() - 1) {
    +            if (!isSchemeOnly(uri)) {
    +                throw newInvalidURISchemeException(uri);
    +            }
    +        }
    +        scheme = uri.substring(0, i);
    +        i++;                                            // skip past ":"
    +
    +        hasAuthority = uri.startsWith("//", i);
    +        if (fmark > -1 && qmark > fmark) qmark = -1;
    +        int endp = qmark > -1 ? qmark : fmark > -1 ? fmark : uri.length();
    +        if (hasAuthority) {                             // parse "//host:port"
    +            i += 2;                                     // skip past "//"
    +            int starta = i;
    +            // authority ends at the first appearance of /, ?, or #
    +            int enda = uri.indexOf('/', i);
    +            if (enda == -1 || qmark > -1 && qmark < enda) enda = qmark;
    +            if (enda == -1 || fmark > -1 && fmark < enda) enda = fmark;
    +            if (enda < 0) {
    +                enda = uri.length();
    +            }
    +            if (uri.startsWith(":", i)) {
    +                // LdapURL supports empty host.
    +                i++;
    +                host = "";
    +                if (enda > i) {
    +                    port = Integer.parseInt(uri.substring(i, enda));
    +                }
    +            } else {
    +                // Use URI to parse authority
    +                try {
    +                    // URI requires at least one char after authority:
    +                    // we use "/" and expect that the resulting URI path
    +                    // will be exactly "/".
    +                    URI u = new URI(uri.substring(0, enda) + "/");
    +                    String auth = uri.substring(starta, enda);
    +                    host = u.getHost();
    +                    port = u.getPort();
    +                    String p = u.getRawPath();
    +                    String q = u.getRawQuery();
    +                    String f = u.getRawFragment();
    +                    String ui = u.getRawUserInfo();
    +                    if (ui != null) {
    +                        throw new MalformedURLException("user info not supported in authority: " + ui);
    +                    }
    +                    if (!"/".equals(p)) {
    +                        throw new MalformedURLException("invalid authority: " + auth);
    +                    }
    +                    if (q != null) {
    +                        throw new MalformedURLException("invalid trailing characters in authority: ?" + q);
    +                    }
    +                    if (f != null) {
    +                        throw new MalformedURLException("invalid trailing characters in authority: #" + f);
    +                    }
    +                    String hostport = (host == null ? "" : host)
    +                            + (port == -1?"":(":" + port));
    +                    if (!auth.equals(hostport)) {
    +                        // throw if we have user info or regname
    +                        throw new MalformedURLException("unsupported authority: " + auth);
    +                    }
    +                } catch (URISyntaxException e) {
    +                    var mue = new MalformedURLException(e.getMessage());
    +                    mue.initCause(e);
    +                    throw mue;
    +                }
    +            }
    +            i = enda;
    +        }
    +        path = uri.substring(i, endp);
    +        // look for query
    +        if (qmark > -1) {
    +            if (fmark > -1) {
    +                query = uri.substring(qmark, fmark);
    +            } else {
    +                query = uri.substring(qmark);
    +            }
    +        }
    +        if (fmark > -1) {
    +            fragment = uri.substring(fmark);
    +        }
    +    }
    +
    +    /**
    +     * A subclass of {@code Uri} that supports scheme only
    +     * URIs can override this method and return true in the
    +     * case where the URI string is a scheme-only URI that
    +     * the subclass supports.
    +     * @implSpec
    +     * The default implementation of this method returns false,
    +     * always.
    +     * @param uri An URI string
    +     * @return if this is a scheme-only URI supported by the subclass
    +     */
    +    protected boolean isSchemeOnly(String uri) {
    +        return false;
    +    }
    +
    +    /**
    +     * Checks whether the given uri string should be considered
    +     * as a scheme-only URI. For some protocols - e.g. DNS, we
    +     * might accept "dns://" as a valid URL denoting default DNS.
    +     * For others - we might only accept "scheme:".
    +     * @implSpec
    +     * The default implementation of this method returns true if
    +     * the URI is of the form {@code ":"} with nothing
    +     * after the scheme delimiter.
    +     * @param uri the URI
    +     * @param scheme the scheme
    +     * @return true if the URI should be considered as a scheme-only
    +     *         URI supported by this URI scheme.
    +     */
    +    protected boolean checkSchemeOnly(String uri, String scheme) {
    +        return uri.equals(scheme + ":");
    +    }
    +
    +    /**
    +     * Creates a {@code MalformedURLException} to be thrown when the
    +     * URI scheme is not supported.
    +     *
    +     * @param uri the URI string
    +     * @return a {@link MalformedURLException}
    +     */
    +    protected MalformedURLException newInvalidURISchemeException(String uri) {
    +        return new MalformedURLException("Invalid URI scheme: " + uri);
    +    }
    +
    +    /**
    +     * Whether fragments are supported.
    +     * @implSpec
    +     * The default implementation of this method retturns false, always.
    +     * @return true if fragments are supported.
    +     */
    +    protected boolean acceptsFragment() {
    +        return parseMode() == ParseMode.LEGACY;
    +    }
    +
         /*
          * Parses a URI string and sets this object's fields accordingly.
    +     * Legacy parsing mode.
          */
    -    private void parse(String uri) throws MalformedURLException {
    +    private void parseLegacy(String uri) throws MalformedURLException {
             int i;  // index into URI
     
             i = uri.indexOf(':');                           // parse scheme
    diff --git a/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego/NegotiatorImpl.java b/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego/NegotiatorImpl.java
    index c17b54dd335..82f2391816b 100644
    --- a/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego/NegotiatorImpl.java
    +++ b/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego/NegotiatorImpl.java
    @@ -40,6 +40,9 @@
     import sun.security.jgss.GSSContextImpl;
     import sun.security.jgss.GSSUtil;
     import sun.security.jgss.HttpCaller;
    +import sun.security.jgss.krb5.internal.TlsChannelBindingImpl;
    +import sun.security.util.ChannelBindingException;
    +import sun.security.util.TlsChannelBinding;
     
     /**
      * This class encapsulates all JAAS and JGSS API calls in a separate class
    @@ -65,7 +68,7 @@ public class NegotiatorImpl extends Negotiator {
          * 
  • Creating GSSContext *
  • A first call to initSecContext */ - private void init(HttpCallerInfo hci) throws GSSException { + private void init(HttpCallerInfo hci) throws GSSException, ChannelBindingException { final Oid oid; if (hci.scheme.equalsIgnoreCase("Kerberos")) { @@ -100,6 +103,14 @@ private void init(HttpCallerInfo hci) throws GSSException { if (context instanceof GSSContextImpl) { ((GSSContextImpl)context).requestDelegPolicy(true); } + if (hci.serverCert != null) { + if (DEBUG) { + System.out.println("Negotiate: Setting CBT"); + } + // set the channel binding token + TlsChannelBinding b = TlsChannelBinding.create(hci.serverCert); + context.setChannelBinding(new TlsChannelBindingImpl(b.getData())); + } oneToken = context.initSecContext(new byte[0], 0, 0); } @@ -110,7 +121,7 @@ private void init(HttpCallerInfo hci) throws GSSException { public NegotiatorImpl(HttpCallerInfo hci) throws IOException { try { init(hci); - } catch (GSSException e) { + } catch (GSSException | ChannelBindingException e) { if (DEBUG) { System.out.println("Negotiate support not initiated, will " + "fallback to other scheme if allowed. Reason:"); diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoContext.java b/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoContext.java index 311dfadbdd7..61a5d34186d 100644 --- a/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoContext.java +++ b/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -866,6 +866,7 @@ private byte[] GSS_initSecContext(byte[] token) throws GSSException { mechContext.requestMutualAuth(mutualAuthState); mechContext.requestReplayDet(replayDetState); mechContext.requestSequenceDet(sequenceDetState); + mechContext.setChannelBinding(channelBinding); if (mechContext instanceof GSSContextImpl) { ((GSSContextImpl)mechContext).requestDelegPolicy( delegPolicyState); @@ -899,6 +900,7 @@ private byte[] GSS_acceptSecContext(byte[] token) throws GSSException { myCred.getInternalCred()); } mechContext = factory.manager.createContext(cred); + mechContext.setChannelBinding(channelBinding); } // pass token to mechanism acceptSecContext diff --git a/src/java.security.jgss/windows/native/libsspi_bridge/sspi.cpp b/src/java.security.jgss/windows/native/libsspi_bridge/sspi.cpp index 2f359a84e7b..aa673367607 100644 --- a/src/java.security.jgss/windows/native/libsspi_bridge/sspi.cpp +++ b/src/java.security.jgss/windows/native/libsspi_bridge/sspi.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -1043,6 +1043,10 @@ gss_accept_sec_context(OM_uint32 *minor_status, { PP(">>>> Calling UNIMPLEMENTED gss_accept_sec_context..."); PP("gss_accept_sec_context is not supported in this initiator-only library"); + if (output_token) { + output_token->length = 0; + output_token->value = NULL; + } return GSS_S_FAILURE; } diff --git a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java index b7412738725..e72642bbff3 100644 --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java @@ -21,7 +21,7 @@ * under the License. */ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. */ package org.jcp.xml.dsig.internal.dom; @@ -101,7 +101,9 @@ public Data dereference(URIReference uriRef, XMLCryptoContext context) if (id.startsWith("xpointer(id(")) { int i1 = id.indexOf('\''); int i2 = id.indexOf('\'', i1+1); - id = id.substring(i1+1, i2); + if (i1 >= 0 && i2 >= 0) { + id = id.substring(i1 + 1, i2); + } } // check if element is registered by Id diff --git a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Utils.java b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Utils.java index 72c34c647ba..bcf28d0afe2 100644 --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Utils.java +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Utils.java @@ -21,7 +21,7 @@ * under the License. */ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. */ package org.jcp.xml.dsig.internal.dom; @@ -94,7 +94,9 @@ public static String parseIdFromSameDocumentURI(String uri) { if (id.startsWith("xpointer(id(")) { int i1 = id.indexOf('\''); int i2 = id.indexOf('\'', i1+1); - id = id.substring(i1+1, i2); + if (i1 >= 0 && i2 >= 0) { + id = id.substring(i1 + 1, i2); + } } return id; } diff --git a/src/java.xml/share/classes/com/sun/java_cup/internal/runtime/lr_parser.java b/src/java.xml/share/classes/com/sun/java_cup/internal/runtime/lr_parser.java index e0ceedac972..dd430da6dc0 100644 --- a/src/java.xml/share/classes/com/sun/java_cup/internal/runtime/lr_parser.java +++ b/src/java.xml/share/classes/com/sun/java_cup/internal/runtime/lr_parser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -26,6 +26,8 @@ package com.sun.java_cup.internal.runtime; +import com.sun.org.apache.xalan.internal.xsltc.compiler.sym; +import java.util.Arrays; import java.util.Stack; /** This class implements a skeleton table driven LR parser. In general, @@ -134,9 +136,19 @@ * @see com.sun.java_cup.internal.runtime.Symbol * @see com.sun.java_cup.internal.runtime.virtual_parse_stack * @author Frank Flannery + * + * @LastModified: Jan 2022 */ public abstract class lr_parser { + public static final int ID_GROUP = 1; + public static final int ID_OPERATOR = 2; + public static final int ID_TOTAL_OPERATOR = 3; + + private boolean isLiteral = false; + private int grpCount = 0; + private int opCount = 0; + private int totalOpCount = 0; /*-----------------------------------------------------------*/ /*--- Constructor(s) ----------------------------------------*/ @@ -355,8 +367,29 @@ public void user_init() throws java.lang.Exception { } * the "scan with" clause. Do not recycle objects; every call to * scan() should return a fresh object. */ - public Symbol scan() throws java.lang.Exception { - return getScanner().next_token(); + public Symbol scan() throws Exception { + Symbol s = getScanner().next_token(); + + if (s.sym == sym.LPAREN) { + if (!isLiteral) { + grpCount++; + } + opCount++; // function + isLiteral = false; + } else if (contains(sym.OPERATORS, s.sym)) { + opCount++; + isLiteral = false; + } + + if (s.sym == sym.Literal || s.sym == sym.QNAME) { + isLiteral = true; + } + + return s; + } + + private boolean contains(final int[] arr, final int key) { + return Arrays.stream(arr).anyMatch(i -> i == key); } /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ @@ -552,6 +585,9 @@ public Symbol parse() throws java.lang.Exception /* do user initialization */ user_init(); + isLiteral = false; + grpCount = 0; + opCount = 0; /* get the first token */ cur_token = scan(); @@ -630,9 +666,29 @@ else if (act == 0) } } } + + totalOpCount += opCount; return lhs_sym; } + /** + * Returns the count of operators in XPath expressions. + * + * @param id the ID of the count + * @return the count associated with the ID + */ + public int getCount(int id) { + switch (id) { + case ID_GROUP: + return grpCount; + case ID_OPERATOR: + return opCount; + case ID_TOTAL_OPERATOR: + return totalOpCount; + } + return 0; + } + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Write a debugging message to System.err for the debugging version diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java index f599b4a0990..625d8f21177 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -22,7 +22,6 @@ import com.sun.java_cup.internal.runtime.Symbol; import com.sun.org.apache.xalan.internal.utils.ObjectFactory; -import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodType; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; @@ -46,6 +45,7 @@ import jdk.xml.internal.JdkXmlFeatures; import jdk.xml.internal.JdkXmlUtils; import jdk.xml.internal.SecuritySupport; +import jdk.xml.internal.XMLSecurityManager; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.InputSource; @@ -62,7 +62,7 @@ * @author G. Todd Miller * @author Morten Jorgensen * @author Erwin Bolwidt - * @LastModified: May 2021 + * @LastModified: Jan 2022 */ public class Parser implements Constants, ContentHandler { @@ -504,8 +504,10 @@ public SyntaxTreeNode parse(InputSource input) { XMLSecurityManager securityManager = (XMLSecurityManager)_xsltc.getProperty(JdkConstants.SECURITY_MANAGER); for (XMLSecurityManager.Limit limit : XMLSecurityManager.Limit.values()) { - lastProperty = limit.apiProperty(); - reader.setProperty(lastProperty, securityManager.getLimitValueAsString(limit)); + if (limit.isSupported(XMLSecurityManager.Processor.PARSER)) { + lastProperty = limit.apiProperty(); + reader.setProperty(lastProperty, securityManager.getLimitValueAsString(limit)); + } } if (securityManager.printEntityCountInfo()) { lastProperty = JdkConstants.JDK_DEBUG_LIMIT; @@ -1169,6 +1171,9 @@ private SyntaxTreeNode parseTopLevel(SyntaxTreeNode parent, String text, expression, parent)); } catch (Exception e) { + if (ErrorMsg.XPATH_LIMIT.equals(e.getMessage())) { + throw new RuntimeException(ErrorMsg.XPATH_LIMIT); + } if (_xsltc.debug()) e.printStackTrace(); reportError(ERROR, new ErrorMsg(ErrorMsg.XPATH_PARSER_ERR, expression, parent)); diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XPathParser.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XPathParser.java index ab12a274a46..bf520124eb1 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XPathParser.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XPathParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -34,14 +34,21 @@ import java.util.ArrayList; import java.util.List; import java.util.Stack; +import jdk.xml.internal.JdkConstants; +import jdk.xml.internal.XMLLimitAnalyzer; +import jdk.xml.internal.XMLSecurityManager; +import jdk.xml.internal.XMLSecurityManager.Limit; /** * CUP v0.11b generated parser. * This class was generated by CUP v0.11b on Nov 12, 2019. * - * @LastModified: Nov 2019 + * @LastModified: Jan 2022 */ public class XPathParser extends lr_parser { + private int grpLimit = 0; + private int opLimit = 0; + private int totalOpLimit = 0; /** * Default constructor. @@ -953,10 +960,19 @@ public int error_sym() { */ public SymbolTable _symbolTable; + private XMLSecurityManager _xmlSM; + private XMLLimitAnalyzer _limitAnalyzer = null; + public XPathParser(Parser parser) { _parser = parser; _xsltc = parser.getXSLTC(); _symbolTable = parser.getSymbolTable(); + _xmlSM = (XMLSecurityManager)_xsltc.getProperty(JdkConstants.SECURITY_MANAGER); + _limitAnalyzer = new XMLLimitAnalyzer(); + // no limits if _xmlSM is null + grpLimit = (_xmlSM != null) ? _xmlSM.getLimit(Limit.XPATH_GROUP_LIMIT) : 0; + opLimit = (_xmlSM != null) ? _xmlSM.getLimit(Limit.XPATH_OP_LIMIT) : 0; + totalOpLimit = (_xmlSM != null) ? _xmlSM.getLimit(Limit.XPATH_TOTALOP_LIMIT) : 0; } public int getLineNumber() { @@ -1101,7 +1117,32 @@ public Symbol parse(String expression, int lineNumber) throws Exception { try { _expression = expression; _lineNumber = lineNumber; - return super.parse(); + Symbol s = super.parse(); + int grpCount = getCount(ID_GROUP); + int opCount = getCount(ID_OPERATOR); + int totalOpCount = getCount(ID_TOTAL_OPERATOR); + + String errCode = null; + Object[] params = null; + if (grpLimit > 0 && grpCount > grpLimit) { + errCode = ErrorMsg.XPATH_GROUP_LIMIT; + params = new Object[]{grpCount, grpLimit, + _xmlSM.getStateLiteral(Limit.XPATH_GROUP_LIMIT)}; + } else if (opLimit > 0 && opCount > opLimit) { + errCode = ErrorMsg.XPATH_OPERATOR_LIMIT; + params = new Object[]{opCount, opLimit, + _xmlSM.getStateLiteral(Limit.XPATH_OP_LIMIT)}; + } else if (totalOpLimit > 0 && totalOpCount > totalOpLimit) { + errCode = ErrorMsg.XPATH_TOTAL_OPERATOR_LIMIT; + params = new Object[]{totalOpCount, totalOpLimit, + _xmlSM.getStateLiteral(Limit.XPATH_TOTALOP_LIMIT)}; + } + if (errCode != null) { + _parser.reportError(Constants.FATAL, + new ErrorMsg(errCode, lineNumber, params)); + throw new RuntimeException(ErrorMsg.XPATH_LIMIT); + } + return s; } catch (IllegalCharException e) { ErrorMsg err = new ErrorMsg(ErrorMsg.ILLEGAL_CHAR_ERR, lineNumber, e.getMessage()); diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java index 99d3681c0e7..9a256efc5a1 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -21,7 +21,6 @@ package com.sun.org.apache.xalan.internal.xsltc.compiler; import com.sun.org.apache.bcel.internal.classfile.JavaClass; -import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util; import com.sun.org.apache.xml.internal.dtm.DTM; @@ -47,8 +46,8 @@ import javax.xml.catalog.CatalogFeatures; import jdk.xml.internal.JdkConstants; import jdk.xml.internal.JdkXmlFeatures; -import jdk.xml.internal.JdkXmlUtils; import jdk.xml.internal.SecuritySupport; +import jdk.xml.internal.XMLSecurityManager; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; @@ -58,7 +57,7 @@ * @author G. Todd Miller * @author Morten Jorgensen * @author John Howard (johnh@schemasoft.com) - * @LastModified: May 2021 + * @LastModified: Jan 2022 */ public final class XSLTC { @@ -460,8 +459,11 @@ public boolean compile(InputSource input, String name) { if (name != null) { setClassName(name); } - else if (systemId != null && !systemId.equals("")) { - setClassName(Util.baseName(systemId)); + else if (systemId != null && !systemId.isEmpty()) { + String clsName = Util.baseName(systemId); + if (clsName != null && !clsName.isEmpty()) { + setClassName(clsName); + } } // Ensure we have a non-empty class name at this point @@ -505,7 +507,10 @@ else if (systemId != null && !systemId.equals("")) { } } catch (Exception e) { - /*if (_debug)*/ e.printStackTrace(); + if (_debug) e.printStackTrace(); + if (ErrorMsg.XPATH_LIMIT.equals(e.getMessage())) { + return !_parser.errorsFound(); + } _parser.reportError(Constants.FATAL, new ErrorMsg(ErrorMsg.JAXP_COMPILE_ERR, e)); } catch (Error e) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/sym.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/sym.java index 843521e419a..be41e5dcaf0 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/sym.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/sym.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -25,9 +25,13 @@ package com.sun.org.apache.xalan.internal.xsltc.compiler; +import java.util.Arrays; + /** * CUP generated class containing symbol constants. * This class was generated by CUP v0.10j on Fri Feb 27 13:01:50 PST 2004. + * + * @LastModified: Jan 2022 */ public class sym { /* terminals */ @@ -85,4 +89,12 @@ public class sym { public static final int ATTRIBUTE = 41; public static final int GT = 19; public static final int NODE = 31; + /* + AXES: count once at DCOLON, + these axes names are therefore not counted: + NAMESPACE, FOLLOWINGSIBLING, CHILD, DESCENDANTORSELF, DESCENDANT + , PRECEDINGSIBLING, SELF, ANCESTORORSELF, PRECEDING, ANCESTOROR, PARENT, FOLLOWING, ATTRIBUTE + */ + public static final int[] OPERATORS = {GE, SLASH, ATSIGN, LPAREN, DCOLON, + MINUS, STAR, LT, OR, DIV, PLUS, LE, VBAR, MOD, EQ, LBRACK, DOLLAR, NE, GT}; } diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java index 581d3cc2cb7..0c20a0ac919 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -24,6 +24,7 @@ /** * @author Morten Jorgensen + * @LastModified: Jan 2022 */ public class ErrorMessages extends ListResourceBundle { @@ -1027,12 +1028,22 @@ public Object[][] getContents() "smaller templates." }, - {ErrorMsg.DESERIALIZE_TRANSLET_ERR, "When Java security is enabled, " + - "support for deserializing TemplatesImpl is disabled." + - "This can be overridden by setting the jdk.xml.enableTemplatesImplDeserialization" + - " system property to true."} - - }; + {ErrorMsg.DESERIALIZE_TRANSLET_ERR, "When Java security is enabled, " + + "support for deserializing TemplatesImpl is disabled. This can be " + + "overridden by setting the jdk.xml.enableTemplatesImplDeserialization" + + " system property to true."}, + + {ErrorMsg.XPATH_GROUP_LIMIT, + "JAXP0801001: the compiler encountered an XPath expression containing " + + "''{0}'' groups that exceeds the ''{1}'' limit set by ''{2}''."}, + + {ErrorMsg.XPATH_OPERATOR_LIMIT, + "JAXP0801002: the compiler encountered an XPath expression containing " + + "''{0}'' operators that exceeds the ''{1}'' limit set by ''{2}''."}, + {ErrorMsg.XPATH_TOTAL_OPERATOR_LIMIT, + "JAXP0801003: the compiler encountered XPath expressions with an accumulated " + + "''{0}'' operators that exceeds the ''{1}'' limit set by ''{2}''."}, + }; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMsg.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMsg.java index e66c0905e0b..698cbad30b4 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMsg.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMsg.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -33,7 +33,7 @@ * @author G. Todd Miller * @author Erwin Bolwidt * @author Morten Jorgensen - * @LastModified: Sep 2017 + * @LastModified: Jan 2022 */ public final class ErrorMsg { @@ -171,6 +171,11 @@ public final class ErrorMsg { public static final String DESERIALIZE_TRANSLET_ERR = "DESERIALIZE_TEMPLATES_ERR"; + public static final String XPATH_LIMIT = "XPATH_LIMIT"; + public static final String XPATH_GROUP_LIMIT = "XPATH_GROUP_LIMIT"; + public static final String XPATH_OPERATOR_LIMIT = "XPATH_OPERATOR_LIMIT"; + public static final String XPATH_TOTAL_OPERATOR_LIMIT = "XPATH_TOTAL_OPERATOR_LIMIT"; + // All error messages are localized and are stored in resource bundles. // This array and the following 4 strings are read from that bundle. private static ResourceBundle _bundle; @@ -207,7 +212,11 @@ public ErrorMsg(String message, int line) { public ErrorMsg(String code, int line, Object param) { _code = code; _line = line; - _params = new Object[] { param }; + if (param instanceof Object[]) { + _params = (Object[])param; + } else { + _params = new Object[] { param }; + } } public ErrorMsg(String code, Object param) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java index 51cd76b5cd3..03fef860517 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -21,9 +21,9 @@ package com.sun.org.apache.xalan.internal.xsltc.trax; import jdk.xml.internal.JdkConstants; +import jdk.xml.internal.XMLSecurityManager; import com.sun.org.apache.xalan.internal.utils.FeaturePropertyBase; import com.sun.org.apache.xalan.internal.utils.ObjectFactory; -import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager; import com.sun.org.apache.xalan.internal.utils.XMLSecurityPropertyManager.Property; import com.sun.org.apache.xalan.internal.utils.XMLSecurityPropertyManager; import com.sun.org.apache.xalan.internal.xsltc.compiler.Constants; @@ -88,7 +88,7 @@ * @author G. Todd Miller * @author Morten Jorgensen * @author Santiago Pericas-Geertsen - * @LastModified: May 2021 + * @LastModified: Jan 2022 */ public class TransformerFactoryImpl extends SAXTransformerFactory implements SourceLoader @@ -286,7 +286,8 @@ public TransformerFactoryImpl() { _xmlSecurityManager = new XMLSecurityManager(true); //Unmodifiable hash map with loaded external extension functions _xsltcExtensionFunctions = null; - _extensionClassLoader = new JdkProperty<>(ImplPropMap.EXTCLSLOADER, null, State.DEFAULT); + _extensionClassLoader = new JdkProperty<>(ImplPropMap.EXTCLSLOADER, + ClassLoader.class, null, State.DEFAULT); } public Map> getExternalExtensionsMap() { diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java index b58eabc54d5..a7a122d07aa 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -20,7 +20,6 @@ package com.sun.org.apache.xalan.internal.xsltc.trax; -import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager; import com.sun.org.apache.xalan.internal.xsltc.DOM; import com.sun.org.apache.xalan.internal.xsltc.DOMCache; import com.sun.org.apache.xalan.internal.xsltc.StripFilter; @@ -89,6 +88,7 @@ import jdk.xml.internal.JdkXmlUtils; import jdk.xml.internal.JdkProperty.ImplPropMap; import jdk.xml.internal.JdkProperty.State; +import jdk.xml.internal.XMLSecurityManager; import jdk.xml.internal.SecuritySupport; import jdk.xml.internal.TransformErrorListener; import org.xml.sax.ContentHandler; @@ -101,7 +101,7 @@ * @author Morten Jorgensen * @author G. Todd Miller * @author Santiago Pericas-Geertsen - * @LastModified: Sept 2021 + * @LastModified: Jan 2022 */ public final class TransformerImpl extends Transformer implements DOMCache @@ -288,10 +288,8 @@ protected TransformerImpl(Translet translet, Properties outputProperties, _translet.setMessageHandler(new MessageHandler(_errorListener)); } _properties = createOutputProperties(outputProperties); - String isStandalone = SecuritySupport.getJAXPSystemProperty( - String.class, SP_XSLTC_IS_STANDALONE, "no"); _xsltcIsStandalone = new JdkProperty<>(ImplPropMap.XSLTCISSTANDALONE, - isStandalone, State.DEFAULT); + String.class, "no", State.DEFAULT); _propertiesClone = (Properties) _properties.clone(); _indentNumber = indentNumber; _tfactory = tfactory; diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/Util.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/Util.java index 1f4b02a1264..f0ff802c75b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/Util.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/Util.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -20,7 +20,6 @@ package com.sun.org.apache.xalan.internal.xsltc.trax; -import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager; import com.sun.org.apache.xalan.internal.xsltc.compiler.XSLTC; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; import java.io.InputStream; @@ -39,6 +38,7 @@ import jdk.xml.internal.JdkConstants; import jdk.xml.internal.JdkXmlFeatures; import jdk.xml.internal.JdkXmlUtils; +import jdk.xml.internal.XMLSecurityManager; import org.w3c.dom.Document; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -51,7 +51,7 @@ * * Added Catalog Support for URI resolution * - * @LastModified: May 2021 + * @LastModified: Jan 2022 */ @SuppressWarnings("deprecation") //org.xml.sax.helpers.XMLReaderFactory public final class Util { @@ -113,9 +113,11 @@ public static InputSource getInputSource(XSLTC xsltc, Source source) (XMLSecurityManager)xsltc.getProperty(JdkConstants.SECURITY_MANAGER); if (securityManager != null) { for (XMLSecurityManager.Limit limit : XMLSecurityManager.Limit.values()) { - lastProperty = limit.apiProperty(); - reader.setProperty(lastProperty, - securityManager.getLimitValueAsString(limit)); + if (limit.isSupported(XMLSecurityManager.Processor.PARSER)) { + lastProperty = limit.apiProperty(); + reader.setProperty(lastProperty, + securityManager.getLimitValueAsString(limit)); + } } if (securityManager.printEntityCountInfo()) { lastProperty = JdkConstants.JDK_DEBUG_LIMIT; diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractDOMParser.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractDOMParser.java index ac3fcfbd891..b10634943c3 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractDOMParser.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractDOMParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -56,6 +56,7 @@ import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition; import java.util.Locale; import java.util.Stack; +import jdk.xml.internal.JdkXmlUtils; import org.w3c.dom.Attr; import org.w3c.dom.CDATASection; import org.w3c.dom.Comment; @@ -84,7 +85,7 @@ * @author Andy Clark, IBM * @author Elena Litani, IBM * - * @LastModified: Jan 2019 + * @LastModified: July 2021 */ public class AbstractDOMParser extends AbstractXMLDocumentParser { @@ -2041,17 +2042,8 @@ public void externalEntityDecl (String name, XMLResourceIdentifier identifier, else { fInternalSubset.append (name); } - fInternalSubset.append (' '); - if (publicId != null) { - fInternalSubset.append ("PUBLIC '"); - fInternalSubset.append (publicId); - fInternalSubset.append ("' '"); - } - else { - fInternalSubset.append ("SYSTEM '"); - } - fInternalSubset.append (literalSystemId); - fInternalSubset.append ("'>\n"); + fInternalSubset.append (JdkXmlUtils.getDTDExternalDecl(publicId, literalSystemId)); + fInternalSubset.append (">\n"); } // NOTE: We only know how to create these nodes for the Xerces @@ -2181,20 +2173,8 @@ public void unparsedEntityDecl (String name, XMLResourceIdentifier identifier, if (fInternalSubset != null && !fInDTDExternalSubset) { fInternalSubset.append ("\n"); } @@ -2261,19 +2241,8 @@ public void notationDecl (String name, XMLResourceIdentifier identifier, if (fInternalSubset != null && !fInDTDExternalSubset) { fInternalSubset.append ("\n"); + fInternalSubset.append (JdkXmlUtils.getDTDExternalDecl(publicId, literalSystemId)); + fInternalSubset.append (">\n"); } // NOTE: We only know how to create these nodes for the Xerces diff --git a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToHTMLStream.java b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToHTMLStream.java index ff838e30fe7..58ef55e43fa 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToHTMLStream.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToHTMLStream.java @@ -31,6 +31,7 @@ import com.sun.org.apache.xml.internal.serializer.utils.MsgKey; import com.sun.org.apache.xml.internal.serializer.utils.Utils; import javax.xml.transform.ErrorListener; +import jdk.xml.internal.JdkXmlUtils; /** * This serializer takes a series of SAX or @@ -41,7 +42,7 @@ * because it is used from another package. * * @xsl.usage internal - * @LastModified: June 2021 + * @LastModified: July 2021 */ public final class ToHTMLStream extends ToStream { @@ -679,28 +680,10 @@ protected void startDocumentInternal() throws org.xml.sax.SAXException final java.io.Writer writer = m_writer; try { - writer.write("'); - outputLineSep(); + writer.write("'); + outputLineSep(); } catch(IOException e) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToStream.java b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToStream.java index 93a4dd8d301..f313e64736a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToStream.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToStream.java @@ -54,7 +54,7 @@ * serializers (xml, html, text ...) that write output to a stream. * * @xsl.usage internal - * @LastModified: June 2021 + * @LastModified: July 2021 */ abstract public class ToStream extends SerializerBase { @@ -895,16 +895,8 @@ public void externalEntityDecl( m_writer.write(""); + m_writer.write(JdkXmlUtils.getDTDExternalDecl(publicId, systemId)); + m_writer.write(">"); m_writer.write(m_lineSep, 0, m_lineSepLen); } catch (IOException e) { // TODO Auto-generated catch block @@ -1967,27 +1959,11 @@ void outputDocTypeDecl(String name, boolean closeDecl) throws SAXException final Writer writer = m_writer; writer.write(""); @@ -1995,17 +1971,6 @@ void outputDocTypeDecl(String name, boolean closeDecl) throws SAXException closeDecl = false; // done closing } } - boolean dothis = false; - if (dothis) - { - // at one point this code seemed right, - // but not anymore - Brian M. - if (closeDecl) - { - writer.write('>'); - writer.write(m_lineSep, 0, m_lineSepLen); - } - } } catch (IOException e) { @@ -3570,16 +3535,8 @@ public void notationDecl(String name, String pubID, String sysID) throws SAXExce m_writer.write(""); + m_writer.write(JdkXmlUtils.getDTDExternalDecl(pubID, sysID)); + m_writer.write(">"); m_writer.write(m_lineSep, 0, m_lineSepLen); } catch (IOException e) { // TODO Auto-generated catch block @@ -3600,16 +3557,8 @@ public void unparsedEntityDecl(String name, String pubID, String sysID, String n m_writer.write(""); m_writer.write(m_lineSep, 0, m_lineSepLen); diff --git a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/dom3/DOM3TreeWalker.java b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/dom3/DOM3TreeWalker.java index 519235d463f..2f7d41a1971 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/dom3/DOM3TreeWalker.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/dom3/DOM3TreeWalker.java @@ -63,7 +63,7 @@ * parameters and filters if any during serialization. * * @xsl.usage internal - * @LastModified: Apr 2021 + * @LastModified: July 2021 */ final class DOM3TreeWalker { @@ -506,23 +506,7 @@ protected void serializeDocType(DocumentType node, boolean bStart) dtd.append("(ImplPropMap.ISSTANDALONE, isStandalone, State.DEFAULT); + // JDK specific property isStandalone, the default value is false + fIsStandalone = new JdkProperty<>(ImplPropMap.ISSTANDALONE, Boolean.class, false, State.DEFAULT); // the system property is true only if it is "true" and false otherwise - if (isStandalone) { + if (fIsStandalone.getValue()) { fFeatures |= IS_STANDALONE; fDOMConfigProperties.setProperty(DOMConstants.NS_IS_STANDALONE, DOMConstants.DOM3_EXPLICIT_TRUE); diff --git a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java index 4dbb9472b67..a0bf61f5262 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -20,7 +20,6 @@ package com.sun.org.apache.xml.internal.utils; -import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager; import java.util.HashMap; import javax.xml.XMLConstants; import javax.xml.catalog.CatalogFeatures; @@ -28,6 +27,7 @@ import jdk.xml.internal.JdkXmlFeatures; import jdk.xml.internal.JdkXmlUtils; import jdk.xml.internal.SecuritySupport; +import jdk.xml.internal.XMLSecurityManager; import org.xml.sax.SAXException; import org.xml.sax.SAXNotRecognizedException; import org.xml.sax.SAXNotSupportedException; @@ -37,7 +37,7 @@ * Creates XMLReader objects and caches them for re-use. * This class follows the singleton pattern. * - * @LastModified: May 2021 + * @LastModified: Jan 2022 */ public class XMLReaderManager { @@ -143,9 +143,11 @@ public synchronized XMLReader getXMLReader() throws SAXException { try { if (_xmlSecurityManager != null) { for (XMLSecurityManager.Limit limit : XMLSecurityManager.Limit.values()) { - lastProperty = limit.apiProperty(); - reader.setProperty(lastProperty, - _xmlSecurityManager.getLimitValueAsString(limit)); + if (limit.isSupported(XMLSecurityManager.Processor.PARSER)) { + lastProperty = limit.apiProperty(); + reader.setProperty(lastProperty, + _xmlSecurityManager.getLimitValueAsString(limit)); + } } if (_xmlSecurityManager.printEntityCountInfo()) { lastProperty = JdkConstants.JDK_DEBUG_LIMIT; diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/XPath.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/XPath.java index f6102777054..18632eab6ab 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/XPath.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/XPath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -22,6 +22,7 @@ import com.sun.org.apache.xalan.internal.res.XSLMessages; import com.sun.org.apache.xml.internal.dtm.DTM; +import com.sun.org.apache.xml.internal.utils.DefaultErrorHandler; import com.sun.org.apache.xml.internal.utils.PrefixResolver; import com.sun.org.apache.xml.internal.utils.QName; import com.sun.org.apache.xml.internal.utils.SAXSourceLocator; @@ -35,12 +36,13 @@ import javax.xml.transform.ErrorListener; import javax.xml.transform.SourceLocator; import javax.xml.transform.TransformerException; +import jdk.xml.internal.XMLSecurityManager; /** * The XPath class wraps an expression object and provides general services * for execution of that expression. * @xsl.usage advanced - * @LastModified: May 2019 + * @LastModified: Jan 2022 */ public class XPath implements Serializable, ExpressionOwner { @@ -160,40 +162,11 @@ public String getPatternString() * * @throws javax.xml.transform.TransformerException if syntax or other error. */ - public XPath( - String exprString, SourceLocator locator, PrefixResolver prefixResolver, int type, - ErrorListener errorListener) - throws javax.xml.transform.TransformerException + public XPath(String exprString, SourceLocator locator, PrefixResolver prefixResolver, + int type, ErrorListener errorListener) + throws TransformerException { - initFunctionTable(); - if(null == errorListener) - errorListener = new com.sun.org.apache.xml.internal.utils.DefaultErrorHandler(); - - m_patternString = exprString; - - XPathParser parser = new XPathParser(errorListener, locator); - Compiler compiler = new Compiler(errorListener, locator, m_funcTable); - - if (SELECT == type) - parser.initXPath(compiler, exprString, prefixResolver); - else if (MATCH == type) - parser.initMatchPattern(compiler, exprString, prefixResolver); - else - throw new RuntimeException(XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_CANNOT_DEAL_XPATH_TYPE, - new Object[]{Integer.toString(type)})); - - // System.out.println("----------------"); - Expression expr = compiler.compileExpression(0); - - // System.out.println("expr: "+expr); - this.setExpression(expr); - - if((null != locator) && locator instanceof ExpressionNode) - { - expr.exprSetParent((ExpressionNode)locator); - } - + this(exprString, locator, prefixResolver, type, errorListener, null); } /** @@ -207,22 +180,27 @@ else if (MATCH == type) * namespace URIs. * @param type one of {@link #SELECT} or {@link #MATCH}. * @param errorListener The error listener, or null if default should be used. + * @param funcTable the function table + * @param xmlSecMgr the XML security manager * * @throws javax.xml.transform.TransformerException if syntax or other error. */ - public XPath( - String exprString, SourceLocator locator, - PrefixResolver prefixResolver, int type, - ErrorListener errorListener, FunctionTable aTable) - throws javax.xml.transform.TransformerException + public XPath(String exprString, SourceLocator locator, PrefixResolver prefixResolver, + int type, ErrorListener errorListener, FunctionTable funcTable, + XMLSecurityManager xmlSecMgr) + throws TransformerException { - m_funcTable = aTable; + if (funcTable == null) { + initFunctionTable(); + } else { + m_funcTable = funcTable; + } if(null == errorListener) - errorListener = new com.sun.org.apache.xml.internal.utils.DefaultErrorHandler(); + errorListener = new DefaultErrorHandler(); m_patternString = exprString; - XPathParser parser = new XPathParser(errorListener, locator); + XPathParser parser = new XPathParser(errorListener, locator, xmlSecMgr); Compiler compiler = new Compiler(errorListener, locator, m_funcTable); if (SELECT == type) @@ -261,13 +239,32 @@ else if (MATCH == type) * * @throws javax.xml.transform.TransformerException if syntax or other error. */ - public XPath( - String exprString, SourceLocator locator, PrefixResolver prefixResolver, int type) - throws javax.xml.transform.TransformerException + public XPath(String exprString, SourceLocator locator, PrefixResolver prefixResolver, + int type) + throws TransformerException { this(exprString, locator, prefixResolver, type, null); } + /** + * Constructs an XPath object. + * + * @param exprString The XPath expression. + * @param locator The location of the expression, may be null. + * @param prefixResolver A prefix resolver to use to resolve prefixes to + * namespace URIs. + * @param type one of {@link #SELECT} or {@link #MATCH}. + * @param errorListener The error listener, or null if default should be used. + * @param funcTable the function table + * @throws TransformerException + */ + public XPath(String exprString, SourceLocator locator, PrefixResolver prefixResolver, + int type, ErrorListener errorListener, FunctionTable funcTable) + throws TransformerException + { + this(exprString, locator, prefixResolver, type, errorListener, funcTable, null); + } + /** * Construct an XPath object. * diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/Lexer.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/Lexer.java index 44422a81ef7..41b58da8e99 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/Lexer.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/Lexer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -20,15 +20,19 @@ package com.sun.org.apache.xpath.internal.compiler; +import com.sun.org.apache.xalan.internal.res.XSLMessages; import com.sun.org.apache.xml.internal.utils.PrefixResolver; import com.sun.org.apache.xpath.internal.res.XPATHErrorResources; import java.util.List; +import javax.xml.transform.TransformerException; +import jdk.xml.internal.XMLSecurityManager; +import jdk.xml.internal.XMLSecurityManager.Limit; /** * This class is in charge of lexical processing of the XPath * expression into tokens. * - * @LastModified: Nov 2017 + * @LastModified: Jan 2022 */ class Lexer { @@ -70,6 +74,24 @@ class Lexer */ private int m_patternMapSize; + // XML security manager + XMLSecurityManager m_xmlSecMgr; + + // operator limit + private int m_opCountLimit; + + // group limit + private int m_grpCountLimit; + + // count of operators + private int m_opCount; + + // count of groups + private int m_grpCount; + + // indicate whether the current token is a literal + private boolean isLiteral = false; + /** * Create a Lexer object. * @@ -77,14 +99,22 @@ class Lexer * @param resolver The prefix resolver for mapping qualified name prefixes * to namespace URIs. * @param xpathProcessor The parser that is processing strings to opcodes. + * @param xmlSecMgr the XML security manager */ Lexer(Compiler compiler, PrefixResolver resolver, - XPathParser xpathProcessor) + XPathParser xpathProcessor, XMLSecurityManager xmlSecMgr) { - m_compiler = compiler; m_namespaceContext = resolver; m_processor = xpathProcessor; + m_xmlSecMgr = xmlSecMgr; + /** + * No limits if XML Security Manager is null. Applications using XPath through + * the public API always have a XMLSecurityManager. Applications invoking + * the internal XPath API shall consider using the public API instead. + */ + m_opCountLimit = (xmlSecMgr != null) ? xmlSecMgr.getLimit(Limit.XPATH_OP_LIMIT) : 0; + m_grpCountLimit = (xmlSecMgr != null) ? xmlSecMgr.getLimit(Limit.XPATH_GROUP_LIMIT) : 0; } /** @@ -92,7 +122,7 @@ class Lexer * elements. * @param pat XSLT Expression. * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ void tokenize(String pat) throws javax.xml.transform.TransformerException { @@ -105,13 +135,14 @@ void tokenize(String pat) throws javax.xml.transform.TransformerException * @param pat XSLT Expression. * @param targetStrings a list to hold Strings, may be null. * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ @SuppressWarnings("fallthrough") // on purpose at case '-', '(' and default void tokenize(String pat, List targetStrings) - throws javax.xml.transform.TransformerException + throws TransformerException { + boolean isGroup = false; m_compiler.m_currentPattern = pat; m_patternMapSize = 0; @@ -136,7 +167,7 @@ void tokenize(String pat, List targetStrings) switch (c) { - case '\"' : + case Token.DQ : { if (startSubstring != -1) { @@ -171,7 +202,7 @@ void tokenize(String pat, List targetStrings) } } break; - case '\'' : + case Token.SQ : if (startSubstring != -1) { isNum = false; @@ -190,9 +221,9 @@ void tokenize(String pat, List targetStrings) startSubstring = i; - for (i++; (i < nChars) && ((c = pat.charAt(i)) != '\''); i++); + for (i++; (i < nChars) && ((c = pat.charAt(i)) != Token.SQ); i++); - if (c == '\'' && i < nChars) + if (c == Token.SQ && i < nChars) { addToTokenQueue(pat.substring(startSubstring, i + 1)); @@ -220,18 +251,24 @@ void tokenize(String pat, List targetStrings) } else { - addToTokenQueue(pat.substring(startSubstring, i)); + // check operator symbol + String s = pat.substring(startSubstring, i); + if (Token.contains(s)) { + m_opCount++; + isLiteral = false; + } + addToTokenQueue(s); } startSubstring = -1; } break; - case '@' : + case Token.AT : isAttrName = true; // fall-through on purpose - case '-' : - if ('-' == c) + case Token.MINUS : + if (Token.MINUS == c) { if (!(isNum || (startSubstring == -1))) { @@ -242,22 +279,22 @@ void tokenize(String pat, List targetStrings) } // fall-through on purpose - case '(' : - case '[' : - case ')' : - case ']' : - case '|' : - case '/' : - case '*' : - case '+' : - case '=' : - case ',' : + case Token.LPAREN : + case Token.LBRACK : + case Token.RPAREN : + case Token.RBRACK : + case Token.VBAR : + case Token.SLASH : + case Token.STAR : + case Token.PLUS : + case Token.EQ : + case Token.COMMA : case '\\' : // Unused at the moment case '^' : // Unused at the moment - case '!' : // Unused at the moment - case '$' : - case '<' : - case '>' : + case Token.EM : // Unused at the moment + case Token.DOLLAR : + case Token.LT : + case Token.GT : if (startSubstring != -1) { isNum = false; @@ -275,11 +312,11 @@ void tokenize(String pat, List targetStrings) startSubstring = -1; } - else if (('/' == c) && isStartOfPat) + else if ((Token.SLASH == c) && isStartOfPat) { isStartOfPat = mapPatternElemPos(nesting, isStartOfPat, isAttrName); } - else if ('*' == c) + else if (Token.STAR == c) { isStartOfPat = mapPatternElemPos(nesting, isStartOfPat, isAttrName); isAttrName = false; @@ -287,7 +324,7 @@ else if ('*' == c) if (0 == nesting) { - if ('|' == c) + if (Token.VBAR == c) { if (null != targetStrings) { @@ -298,18 +335,32 @@ else if ('*' == c) } } - if ((')' == c) || (']' == c)) + if ((Token.RPAREN == c) || (Token.RBRACK == c)) { nesting--; } - else if (('(' == c) || ('[' == c)) + else if ((Token.LPAREN == c) || (Token.LBRACK == c)) { nesting++; + if (!isLiteral && (Token.LPAREN == c)) { + m_grpCount++; + m_opCount++; + isLiteral = false; + } + } + + if ((Token.GT == c || Token.LT == c || Token.EQ == c) && Token.EQ != peekNext(pat, i)) { + m_opCount++; + isLiteral = false; + } + else if ((Token.LPAREN != c) && (Token.RPAREN != c) && (Token.RBRACK != c)) { + m_opCount++; + isLiteral = false; } addToTokenQueue(pat.substring(i, i + 1)); break; - case ':' : + case Token.COLON_CHAR: if (i>0) { if (posOfNSSep == (i - 1)) @@ -324,7 +375,7 @@ else if (('(' == c) || ('[' == c)) isAttrName = false; startSubstring = -1; posOfNSSep = -1; - + m_opCount++; addToTokenQueue(pat.substring(i - 1, i + 1)); break; @@ -337,6 +388,7 @@ else if (('(' == c) || ('[' == c)) // fall through on purpose default : + isLiteral = true; if (-1 == startSubstring) { startSubstring = i; @@ -347,6 +399,20 @@ else if (isNum) isNum = Character.isDigit(c); } } + if (m_grpCountLimit > 0 && m_grpCount > m_grpCountLimit) { + throw new TransformerException(XSLMessages.createXPATHMessage( + XPATHErrorResources.ER_XPATH_GROUP_LIMIT, + new Object[]{Integer.toString(m_grpCount), + Integer.toString(m_grpCountLimit), + m_xmlSecMgr.getStateLiteral(Limit.XPATH_GROUP_LIMIT)})); + } + if (m_opCountLimit > 0 && m_opCount > m_opCountLimit) { + throw new TransformerException(XSLMessages.createXPATHMessage( + XPATHErrorResources.ER_XPATH_OPERATOR_LIMIT, + new Object[]{Integer.toString(m_opCount), + Integer.toString(m_opCountLimit), + m_xmlSecMgr.getStateLiteral(Limit.XPATH_OP_LIMIT)})); + } } if (startSubstring != -1) @@ -377,6 +443,19 @@ else if (null != targetStrings) m_processor.m_queueMark = 0; } + /** + * Peeks at the next character without advancing the index. + * @param s the input string + * @param index the current index + * @return the next char + */ + private char peekNext(String s, int index) { + if (index >= 0 && index < s.length() - 1) { + return s.charAt(index + 1); + } + return 0; + } + /** * Record the current position on the token queue as long as * this is a top-level element. Must be called before the @@ -499,7 +578,7 @@ private void recordTokenString(List targetStrings) resetTokenMark(tokPos + 1); - if (m_processor.lookahead('(', 1)) + if (m_processor.lookahead(Token.LPAREN, 1)) { int tok = getKeywordToken(m_processor.m_token); @@ -529,14 +608,14 @@ private void recordTokenString(List targetStrings) } else { - if (m_processor.tokenIs('@')) + if (m_processor.tokenIs(Token.AT)) { tokPos++; resetTokenMark(tokPos + 1); } - if (m_processor.lookahead(':', 1)) + if (m_processor.lookahead(Token.COLON_CHAR, 1)) { tokPos += 2; } @@ -565,13 +644,13 @@ private final void addToTokenQueue(String s) * @param posOfNSSep The position of the namespace seperator (':'). * @param posOfScan The end of the name index. * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException * * @return -1 always. */ private int mapNSTokens(String pat, int startSubstring, int posOfNSSep, int posOfScan) - throws javax.xml.transform.TransformerException + throws TransformerException { String prefix = ""; diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/Token.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/Token.java new file mode 100644 index 00000000000..7bce14e5770 --- /dev/null +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/Token.java @@ -0,0 +1,76 @@ +/* + * 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. 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.org.apache.xpath.internal.compiler; + +import java.util.Arrays; + +/** + * XPath tokens + */ +public final class Token { + static final char EM = '!'; + static final char EQ = '='; + static final char LT = '<'; + static final char GT = '>'; + static final char PLUS = '+'; + static final char MINUS = '-'; + static final char STAR = '*'; + static final char VBAR = '|'; + static final char SLASH = '/'; + static final char LBRACK = '['; + static final char RBRACK = ']'; + static final char LPAREN = '('; + static final char RPAREN = ')'; + static final char COMMA = ','; + static final char AT = '@'; + static final char US = '_'; + static final char COLON_CHAR = ':'; + static final char SQ = '\''; + static final char DQ = '"'; + static final char DOLLAR = '$'; + + static final String OR = "or"; + static final String AND = "and"; + static final String DIV = "div"; + static final String MOD = "mod"; + static final String QUO = "quo"; + static final String DOT = "."; + static final String DDOT = ".."; + static final String DCOLON = "::"; + static final String ATTR = "attribute"; + static final String CHILD = "child"; + + static final String[] OPERATORS = {OR, AND, DIV, MOD, QUO, + DDOT, DCOLON, ATTR, CHILD}; + + public static boolean contains(String str) { + return Arrays.stream(OPERATORS).anyMatch(str::equals); + } + + private Token() { + //to prevent instantiation + } +} diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/XPathParser.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/XPathParser.java index dcf044593b0..22192fd06f6 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/XPathParser.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/XPathParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -20,21 +20,22 @@ package com.sun.org.apache.xpath.internal.compiler; -import javax.xml.transform.ErrorListener; -import javax.xml.transform.TransformerException; - import com.sun.org.apache.xalan.internal.res.XSLMessages; import com.sun.org.apache.xml.internal.utils.PrefixResolver; import com.sun.org.apache.xpath.internal.XPathProcessorException; import com.sun.org.apache.xpath.internal.objects.XNumber; import com.sun.org.apache.xpath.internal.objects.XString; import com.sun.org.apache.xpath.internal.res.XPATHErrorResources; +import javax.xml.transform.ErrorListener; +import javax.xml.transform.SourceLocator; +import javax.xml.transform.TransformerException; +import jdk.xml.internal.XMLSecurityManager; /** * Tokenizes and parses XPath expressions. This should really be named * XPathParserImpl, and may be renamed in the future. * @xsl.usage general - * @LastModified: May 2019 + * @LastModified: Jan 2022 */ public class XPathParser { @@ -75,13 +76,18 @@ public class XPathParser // counts open predicates private int countPredicate; + // XML security manager + XMLSecurityManager m_xmlSecMgr; + /** * The parser constructor. */ - public XPathParser(ErrorListener errorListener, javax.xml.transform.SourceLocator sourceLocator) + public XPathParser(ErrorListener errorListener, SourceLocator sourceLocator, + XMLSecurityManager xmlSecMgr) { m_errorListener = errorListener; m_sourceLocator = sourceLocator; + m_xmlSecMgr = xmlSecMgr; } /** @@ -99,18 +105,18 @@ public XPathParser(ErrorListener errorListener, javax.xml.transform.SourceLocato * @param namespaceContext An object that is able to resolve prefixes in * the XPath to namespaces. * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ public void initXPath( Compiler compiler, String expression, PrefixResolver namespaceContext) - throws javax.xml.transform.TransformerException + throws TransformerException { m_ops = compiler; m_namespaceContext = namespaceContext; m_functionTable = compiler.getFunctionTable(); - Lexer lexer = new Lexer(compiler, namespaceContext, this); + Lexer lexer = new Lexer(compiler, namespaceContext, this, m_xmlSecMgr); lexer.tokenize(expression); @@ -178,18 +184,18 @@ public void initXPath( * @param namespaceContext An object that is able to resolve prefixes in * the XPath to namespaces. * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ public void initMatchPattern( Compiler compiler, String expression, PrefixResolver namespaceContext) - throws javax.xml.transform.TransformerException + throws TransformerException { m_ops = compiler; m_namespaceContext = namespaceContext; m_functionTable = compiler.getFunctionTable(); - Lexer lexer = new Lexer(compiler, namespaceContext, this); + Lexer lexer = new Lexer(compiler, namespaceContext, this, m_xmlSecMgr); lexer.tokenize(expression); @@ -382,9 +388,9 @@ private final boolean lookbehindHasToken(int n) if ((m_queueMark - n) > 0) { String lookbehind = (String) m_ops.m_tokenQueue.elementAt(m_queueMark - (n - 1)); - char c0 = (lookbehind == null) ? '|' : lookbehind.charAt(0); + char c0 = (lookbehind == null) ? Token.VBAR : lookbehind.charAt(0); - hasToken = (c0 == '|') ? false : true; + hasToken = (c0 == Token.VBAR) ? false : true; } else { @@ -496,10 +502,10 @@ private final void prevToken() * * @param expected The string to be expected. * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ private final void consumeExpected(String expected) - throws javax.xml.transform.TransformerException + throws TransformerException { if (tokenIs(expected)) @@ -524,10 +530,10 @@ private final void consumeExpected(String expected) * * @param expected the character to be expected. * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ private final void consumeExpected(char expected) - throws javax.xml.transform.TransformerException + throws TransformerException { if (tokenIs(expected)) @@ -749,9 +755,9 @@ void appendOp(int length, int op) * Expr ::= OrExpr * * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected void Expr() throws javax.xml.transform.TransformerException + protected void Expr() throws TransformerException { OrExpr(); } @@ -763,16 +769,16 @@ protected void Expr() throws javax.xml.transform.TransformerException * | OrExpr 'or' AndExpr * * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected void OrExpr() throws javax.xml.transform.TransformerException + protected void OrExpr() throws TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); AndExpr(); - if ((null != m_token) && tokenIs("or")) + if ((null != m_token) && tokenIs(Token.OR)) { nextToken(); insertOp(opPos, 2, OpCodes.OP_OR); @@ -790,16 +796,16 @@ protected void OrExpr() throws javax.xml.transform.TransformerException * | AndExpr 'and' EqualityExpr * * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected void AndExpr() throws javax.xml.transform.TransformerException + protected void AndExpr() throws TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); EqualityExpr(-1); - if ((null != m_token) && tokenIs("and")) + if ((null != m_token) && tokenIs(Token.AND)) { nextToken(); insertOp(opPos, 2, OpCodes.OP_AND); @@ -823,9 +829,9 @@ protected void AndExpr() throws javax.xml.transform.TransformerException * * @return the position at the end of the equality expression. * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected int EqualityExpr(int addPos) throws javax.xml.transform.TransformerException + protected int EqualityExpr(int addPos) throws TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); @@ -837,7 +843,7 @@ protected int EqualityExpr(int addPos) throws javax.xml.transform.TransformerExc if (null != m_token) { - if (tokenIs('!') && lookahead('=', 1)) + if (tokenIs(Token.EM) && lookahead(Token.EQ, 1)) { nextToken(); nextToken(); @@ -850,7 +856,7 @@ protected int EqualityExpr(int addPos) throws javax.xml.transform.TransformerExc m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen); addPos += 2; } - else if (tokenIs('=')) + else if (tokenIs(Token.EQ)) { nextToken(); insertOp(addPos, 2, OpCodes.OP_EQUALS); @@ -883,9 +889,9 @@ else if (tokenIs('=')) * * @return the position at the end of the relational expression. * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected int RelationalExpr(int addPos) throws javax.xml.transform.TransformerException + protected int RelationalExpr(int addPos) throws TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); @@ -897,11 +903,11 @@ protected int RelationalExpr(int addPos) throws javax.xml.transform.TransformerE if (null != m_token) { - if (tokenIs('<')) + if (tokenIs(Token.LT)) { nextToken(); - if (tokenIs('=')) + if (tokenIs(Token.EQ)) { nextToken(); insertOp(addPos, 2, OpCodes.OP_LTE); @@ -918,11 +924,11 @@ protected int RelationalExpr(int addPos) throws javax.xml.transform.TransformerE m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen); addPos += 2; } - else if (tokenIs('>')) + else if (tokenIs(Token.GT)) { nextToken(); - if (tokenIs('=')) + if (tokenIs(Token.EQ)) { nextToken(); insertOp(addPos, 2, OpCodes.OP_GTE); @@ -958,9 +964,9 @@ else if (tokenIs('>')) * * @return the position at the end of the equality expression. * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected int AdditiveExpr(int addPos) throws javax.xml.transform.TransformerException + protected int AdditiveExpr(int addPos) throws TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); @@ -972,7 +978,7 @@ protected int AdditiveExpr(int addPos) throws javax.xml.transform.TransformerExc if (null != m_token) { - if (tokenIs('+')) + if (tokenIs(Token.PLUS)) { nextToken(); insertOp(addPos, 2, OpCodes.OP_PLUS); @@ -984,7 +990,7 @@ protected int AdditiveExpr(int addPos) throws javax.xml.transform.TransformerExc m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen); addPos += 2; } - else if (tokenIs('-')) + else if (tokenIs(Token.MINUS)) { nextToken(); insertOp(addPos, 2, OpCodes.OP_MINUS); @@ -1016,9 +1022,9 @@ else if (tokenIs('-')) * * @return the position at the end of the equality expression. * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected int MultiplicativeExpr(int addPos) throws javax.xml.transform.TransformerException + protected int MultiplicativeExpr(int addPos) throws TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); @@ -1030,7 +1036,7 @@ protected int MultiplicativeExpr(int addPos) throws javax.xml.transform.Transfor if (null != m_token) { - if (tokenIs('*')) + if (tokenIs(Token.STAR)) { nextToken(); insertOp(addPos, 2, OpCodes.OP_MULT); @@ -1042,7 +1048,7 @@ protected int MultiplicativeExpr(int addPos) throws javax.xml.transform.Transfor m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen); addPos += 2; } - else if (tokenIs("div")) + else if (tokenIs(Token.DIV)) { nextToken(); insertOp(addPos, 2, OpCodes.OP_DIV); @@ -1054,7 +1060,7 @@ else if (tokenIs("div")) m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen); addPos += 2; } - else if (tokenIs("mod")) + else if (tokenIs(Token.MOD)) { nextToken(); insertOp(addPos, 2, OpCodes.OP_MOD); @@ -1066,7 +1072,7 @@ else if (tokenIs("mod")) m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen); addPos += 2; } - else if (tokenIs("quo")) + else if (tokenIs(Token.QUO)) { nextToken(); insertOp(addPos, 2, OpCodes.OP_QUO); @@ -1089,15 +1095,15 @@ else if (tokenIs("quo")) * | '-' UnaryExpr * * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected void UnaryExpr() throws javax.xml.transform.TransformerException + protected void UnaryExpr() throws TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); boolean isNeg = false; - if (m_tokenChar == '-') + if (m_tokenChar == Token.MINUS) { nextToken(); appendOp(2, OpCodes.OP_NEG); @@ -1117,9 +1123,9 @@ protected void UnaryExpr() throws javax.xml.transform.TransformerException * StringExpr ::= Expr * * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected void StringExpr() throws javax.xml.transform.TransformerException + protected void StringExpr() throws TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); @@ -1137,9 +1143,9 @@ protected void StringExpr() throws javax.xml.transform.TransformerException * StringExpr ::= Expr * * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected void BooleanExpr() throws javax.xml.transform.TransformerException + protected void BooleanExpr() throws TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); @@ -1163,9 +1169,9 @@ protected void BooleanExpr() throws javax.xml.transform.TransformerException * NumberExpr ::= Expr * * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected void NumberExpr() throws javax.xml.transform.TransformerException + protected void NumberExpr() throws TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); @@ -1188,9 +1194,9 @@ protected void NumberExpr() throws javax.xml.transform.TransformerException * | UnionExpr '|' PathExpr * * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected void UnionExpr() throws javax.xml.transform.TransformerException + protected void UnionExpr() throws TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); @@ -1201,7 +1207,7 @@ protected void UnionExpr() throws javax.xml.transform.TransformerException { PathExpr(); - if (tokenIs('|')) + if (tokenIs(Token.VBAR)) { if (false == foundUnion) { @@ -1234,9 +1240,9 @@ protected void UnionExpr() throws javax.xml.transform.TransformerException * @throws XSLProcessorException thrown if the active ProblemListener and XPathContext decide * the error condition is severe enough to halt processing. * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected void PathExpr() throws javax.xml.transform.TransformerException + protected void PathExpr() throws TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); @@ -1249,7 +1255,7 @@ protected void PathExpr() throws javax.xml.transform.TransformerException // have been inserted. boolean locationPathStarted = (filterExprMatch==FILTER_MATCH_PREDICATES); - if (tokenIs('/')) + if (tokenIs(Token.SLASH)) { nextToken(); @@ -1299,9 +1305,9 @@ protected void PathExpr() throws javax.xml.transform.TransformerException * FilterExpr that was just a PrimaryExpr; or * FILTER_MATCH_FAILED, if this method did not match a FilterExpr * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected int FilterExpr() throws javax.xml.transform.TransformerException + protected int FilterExpr() throws TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); @@ -1310,13 +1316,13 @@ protected int FilterExpr() throws javax.xml.transform.TransformerException if (PrimaryExpr()) { - if (tokenIs('[')) + if (tokenIs(Token.LBRACK)) { // int locationPathOpPos = opPos; insertOp(opPos, 2, OpCodes.OP_LOCATIONPATH); - while (tokenIs('[')) + while (tokenIs(Token.LBRACK)) { Predicate(); } @@ -1354,16 +1360,16 @@ protected int FilterExpr() throws javax.xml.transform.TransformerException * * @return true if this method successfully matched a PrimaryExpr * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException * */ - protected boolean PrimaryExpr() throws javax.xml.transform.TransformerException + protected boolean PrimaryExpr() throws TransformerException { boolean matchFound; int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); - if ((m_tokenChar == '\'') || (m_tokenChar == '"')) + if ((m_tokenChar == Token.SQ) || (m_tokenChar == Token.DQ)) { appendOp(2, OpCodes.OP_LITERAL); Literal(); @@ -1373,7 +1379,7 @@ protected boolean PrimaryExpr() throws javax.xml.transform.TransformerException matchFound = true; } - else if (m_tokenChar == '$') + else if (m_tokenChar == Token.DOLLAR) { nextToken(); // consume '$' appendOp(2, OpCodes.OP_VARIABLE); @@ -1384,12 +1390,12 @@ else if (m_tokenChar == '$') matchFound = true; } - else if (m_tokenChar == '(') + else if (m_tokenChar == Token.LPAREN) { nextToken(); appendOp(2, OpCodes.OP_GROUP); Expr(); - consumeExpected(')'); + consumeExpected(Token.RPAREN); m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); @@ -1407,7 +1413,7 @@ else if ((null != m_token) && ((('.' == m_tokenChar) && (m_token.length() > 1) & matchFound = true; } - else if (lookahead('(', 1) || (lookahead(':', 1) && lookahead('(', 3))) + else if (lookahead(Token.LPAREN, 1) || (lookahead(Token.COLON_CHAR, 1) && lookahead(Token.LPAREN, 3))) { matchFound = FunctionCall(); } @@ -1424,9 +1430,9 @@ else if (lookahead('(', 1) || (lookahead(':', 1) && lookahead('(', 3))) * Argument ::= Expr * * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected void Argument() throws javax.xml.transform.TransformerException + protected void Argument() throws TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); @@ -1444,14 +1450,14 @@ protected void Argument() throws javax.xml.transform.TransformerException * * @return true if, and only if, a FunctionCall was matched * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected boolean FunctionCall() throws javax.xml.transform.TransformerException + protected boolean FunctionCall() throws TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); - if (lookahead(':', 1)) + if (lookahead(Token.COLON_CHAR, 1)) { appendOp(4, OpCodes.OP_EXTFUNCTION); @@ -1491,22 +1497,23 @@ protected boolean FunctionCall() throws javax.xml.transform.TransformerException nextToken(); } - consumeExpected('('); + consumeExpected(Token.LPAREN); - while (!tokenIs(')') && m_token != null) + while (!tokenIs(Token.RPAREN) && m_token != null) { - if (tokenIs(',')) + if (tokenIs(Token.COMMA)) { - error(XPATHErrorResources.ER_FOUND_COMMA_BUT_NO_PRECEDING_ARG, null); //"Found ',' but no preceding argument!"); + //"Found ',' but no preceding argument!"); + error(XPATHErrorResources.ER_FOUND_COMMA_BUT_NO_PRECEDING_ARG, null); } Argument(); - if (!tokenIs(')')) + if (!tokenIs(Token.RPAREN)) { - consumeExpected(','); + consumeExpected(Token.COMMA); - if (tokenIs(')')) + if (tokenIs(Token.RPAREN)) { error(XPATHErrorResources.ER_FOUND_COMMA_BUT_NO_FOLLOWING_ARG, null); //"Found ',' but no following argument!"); @@ -1514,7 +1521,7 @@ protected boolean FunctionCall() throws javax.xml.transform.TransformerException } } - consumeExpected(')'); + consumeExpected(Token.RPAREN); // Terminate for safety. m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ENDOP); @@ -1533,9 +1540,9 @@ protected boolean FunctionCall() throws javax.xml.transform.TransformerException * | AbsoluteLocationPath * * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected void LocationPath() throws javax.xml.transform.TransformerException + protected void LocationPath() throws TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); @@ -1543,7 +1550,7 @@ protected void LocationPath() throws javax.xml.transform.TransformerException // int locationPathOpPos = opPos; appendOp(2, OpCodes.OP_LOCATIONPATH); - boolean seenSlash = tokenIs('/'); + boolean seenSlash = tokenIs(Token.SLASH); if (seenSlash) { @@ -1584,17 +1591,17 @@ protected void LocationPath() throws javax.xml.transform.TransformerException * * @returns true if, and only if, a RelativeLocationPath was matched * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ protected boolean RelativeLocationPath() - throws javax.xml.transform.TransformerException + throws TransformerException { if (!Step()) { return false; } - while (tokenIs('/')) + while (tokenIs(Token.SLASH)) { nextToken(); @@ -1616,13 +1623,13 @@ protected boolean RelativeLocationPath() * * @returns false if step was empty (or only a '/'); true, otherwise * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected boolean Step() throws javax.xml.transform.TransformerException + protected boolean Step() throws TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); - boolean doubleSlash = tokenIs('/'); + boolean doubleSlash = tokenIs(Token.SLASH); // At most a single '/' before each Step is consumed by caller; if the // first thing is a '/', that means we had '//' and the Step must not @@ -1654,11 +1661,11 @@ protected boolean Step() throws javax.xml.transform.TransformerException opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); } - if (tokenIs(".")) + if (tokenIs(Token.DOT)) { nextToken(); - if (tokenIs('[')) + if (tokenIs(Token.LBRACK)) { error(XPATHErrorResources.ER_PREDICATE_ILLEGAL_SYNTAX, null); //"'..[predicate]' or '.[predicate]' is illegal syntax. Use 'self::node()[predicate]' instead."); } @@ -1669,7 +1676,7 @@ protected boolean Step() throws javax.xml.transform.TransformerException m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 2,4); m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 1, OpCodes.NODETYPE_NODE); } - else if (tokenIs("..")) + else if (tokenIs(Token.DDOT)) { nextToken(); appendOp(4, OpCodes.FROM_PARENT); @@ -1682,12 +1689,12 @@ else if (tokenIs("..")) // There is probably a better way to test for this // transition... but it gets real hairy if you try // to do it in basis(). - else if (tokenIs('*') || tokenIs('@') || tokenIs('_') + else if (tokenIs(Token.STAR) || tokenIs(Token.AT) || tokenIs(Token.US) || (m_token!= null && Character.isLetter(m_token.charAt(0)))) { Basis(); - while (tokenIs('[')) + while (tokenIs(Token.LBRACK)) { Predicate(); } @@ -1716,23 +1723,23 @@ else if (tokenIs('*') || tokenIs('@') || tokenIs('_') * Basis ::= AxisName '::' NodeTest * | AbbreviatedBasis * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected void Basis() throws javax.xml.transform.TransformerException + protected void Basis() throws TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); int axesType; // The next blocks guarantee that a FROM_XXX will be added. - if (lookahead("::", 1)) + if (lookahead(Token.DCOLON, 1)) { axesType = AxisName(); nextToken(); nextToken(); } - else if (tokenIs('@')) + else if (tokenIs(Token.AT)) { axesType = OpCodes.FROM_ATTRIBUTES; @@ -1763,9 +1770,9 @@ else if (tokenIs('@')) * * @return FROM_XXX axes type, found in {@link com.sun.org.apache.xpath.internal.compiler.Keywords}. * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected int AxisName() throws javax.xml.transform.TransformerException + protected int AxisName() throws TransformerException { Object val = Keywords.getAxisName(m_token); @@ -1791,12 +1798,12 @@ protected int AxisName() throws javax.xml.transform.TransformerException * * @param axesType FROM_XXX axes type, found in {@link com.sun.org.apache.xpath.internal.compiler.Keywords}. * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected void NodeTest(int axesType) throws javax.xml.transform.TransformerException + protected void NodeTest(int axesType) throws TransformerException { - if (lookahead('(', 1)) + if (lookahead(Token.LPAREN, 1)) { Object nodeTestOp = Keywords.getNodeType(m_token); @@ -1814,17 +1821,17 @@ protected void NodeTest(int axesType) throws javax.xml.transform.TransformerExce m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), nt); m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); - consumeExpected('('); + consumeExpected(Token.LPAREN); if (OpCodes.NODETYPE_PI == nt) { - if (!tokenIs(')')) + if (!tokenIs(Token.RPAREN)) { Literal(); } } - consumeExpected(')'); + consumeExpected(Token.RPAREN); } } else @@ -1834,9 +1841,9 @@ protected void NodeTest(int axesType) throws javax.xml.transform.TransformerExce m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.NODENAME); m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); - if (lookahead(':', 1)) + if (lookahead(Token.COLON_CHAR, 1)) { - if (tokenIs('*')) + if (tokenIs(Token.STAR)) { m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ELEMWILDCARD); } @@ -1846,7 +1853,7 @@ protected void NodeTest(int axesType) throws javax.xml.transform.TransformerExce // Minimalist check for an NCName - just check first character // to distinguish from other possible tokens - if (!Character.isLetter(m_tokenChar) && !tokenIs('_')) + if (!Character.isLetter(m_tokenChar) && !tokenIs(Token.US)) { // "Node test that matches either NCName:* or QName was expected." error(XPATHErrorResources.ER_EXPECTED_NODE_TEST, null); @@ -1863,7 +1870,7 @@ protected void NodeTest(int axesType) throws javax.xml.transform.TransformerExce m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); - if (tokenIs('*')) + if (tokenIs(Token.STAR)) { m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ELEMWILDCARD); } @@ -1873,7 +1880,7 @@ protected void NodeTest(int axesType) throws javax.xml.transform.TransformerExce // Minimalist check for an NCName - just check first character // to distinguish from other possible tokens - if (!Character.isLetter(m_tokenChar) && !tokenIs('_')) + if (!Character.isLetter(m_tokenChar) && !tokenIs(Token.US)) { // "Node test that matches either NCName:* or QName was expected." error(XPATHErrorResources.ER_EXPECTED_NODE_TEST, null); @@ -1891,11 +1898,11 @@ protected void NodeTest(int axesType) throws javax.xml.transform.TransformerExce * Predicate ::= '[' PredicateExpr ']' * * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected void Predicate() throws javax.xml.transform.TransformerException + protected void Predicate() throws TransformerException { - if (tokenIs('[')) + if (tokenIs(Token.LBRACK)) { countPredicate++; nextToken(); @@ -1910,9 +1917,9 @@ protected void Predicate() throws javax.xml.transform.TransformerException * PredicateExpr ::= Expr * * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected void PredicateExpr() throws javax.xml.transform.TransformerException + protected void PredicateExpr() throws TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); @@ -1932,12 +1939,12 @@ protected void PredicateExpr() throws javax.xml.transform.TransformerException * Prefix ::= NCName * LocalPart ::= NCName * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected void QName() throws javax.xml.transform.TransformerException + protected void QName() throws TransformerException { // Namespace - if(lookahead(':', 1)) + if(lookahead(Token.COLON_CHAR, 1)) { m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), m_queueMark - 1); m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); @@ -1979,16 +1986,16 @@ protected void NCName() * | "'" [^']* "'" * * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected void Literal() throws javax.xml.transform.TransformerException + protected void Literal() throws TransformerException { int last = m_token.length() - 1; char c0 = m_tokenChar; char cX = m_token.charAt(last); - if (((c0 == '\"') && (cX == '\"')) || ((c0 == '\'') && (cX == '\''))) + if (((c0 == Token.DQ) && (cX == Token.DQ)) || ((c0 == Token.SQ) && (cX == Token.SQ))) { // Mutate the token to remove the quotes and have the XString object @@ -2019,9 +2026,9 @@ protected void Literal() throws javax.xml.transform.TransformerException * Number ::= [0-9]+('.'[0-9]+)? | '.'[0-9]+ * * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected void Number() throws javax.xml.transform.TransformerException + protected void Number() throws TransformerException { if (null != m_token) @@ -2062,16 +2069,16 @@ protected void Number() throws javax.xml.transform.TransformerException * | Pattern '|' LocationPathPattern * * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected void Pattern() throws javax.xml.transform.TransformerException + protected void Pattern() throws TransformerException { while (true) { LocationPathPattern(); - if (tokenIs('|')) + if (tokenIs(Token.VBAR)) { nextToken(); } @@ -2090,9 +2097,9 @@ protected void Pattern() throws javax.xml.transform.TransformerException * | '//'? RelativePathPattern * * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected void LocationPathPattern() throws javax.xml.transform.TransformerException + protected void LocationPathPattern() throws TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); @@ -2105,17 +2112,17 @@ protected void LocationPathPattern() throws javax.xml.transform.TransformerExcep appendOp(2, OpCodes.OP_LOCATIONPATHPATTERN); - if (lookahead('(', 1) + if (lookahead(Token.LPAREN, 1) && (tokenIs(Keywords.FUNC_ID_STRING) || tokenIs(Keywords.FUNC_KEY_STRING))) { IdKeyPattern(); - if (tokenIs('/')) + if (tokenIs(Token.SLASH)) { nextToken(); - if (tokenIs('/')) + if (tokenIs(Token.SLASH)) { appendOp(4, OpCodes.MATCH_ANY_ANCESTOR); @@ -2133,9 +2140,9 @@ protected void LocationPathPattern() throws javax.xml.transform.TransformerExcep relativePathStatus = RELATIVE_PATH_REQUIRED; } } - else if (tokenIs('/')) + else if (tokenIs(Token.SLASH)) { - if (lookahead('/', 1)) + if (lookahead(Token.SLASH, 1)) { appendOp(4, OpCodes.MATCH_ANY_ANCESTOR); @@ -2168,7 +2175,7 @@ else if (tokenIs('/')) if (relativePathStatus != RELATIVE_PATH_NOT_PERMITTED) { - if (!tokenIs('|') && (null != m_token)) + if (!tokenIs(Token.VBAR) && (null != m_token)) { RelativePathPattern(); } @@ -2193,9 +2200,9 @@ else if (relativePathStatus == RELATIVE_PATH_REQUIRED) * (Also handle doc()) * * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ - protected void IdKeyPattern() throws javax.xml.transform.TransformerException + protected void IdKeyPattern() throws TransformerException { FunctionCall(); } @@ -2206,17 +2213,17 @@ protected void IdKeyPattern() throws javax.xml.transform.TransformerException * | RelativePathPattern '/' StepPattern * | RelativePathPattern '//' StepPattern * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ protected void RelativePathPattern() - throws javax.xml.transform.TransformerException + throws TransformerException { // Caller will have consumed any '/' or '//' preceding the // RelativePathPattern, so let StepPattern know it can't begin with a '/' boolean trailingSlashConsumed = StepPattern(false); - while (tokenIs('/')) + while (tokenIs(Token.SLASH)) { nextToken(); @@ -2236,10 +2243,10 @@ protected void RelativePathPattern() * * @return boolean indicating whether a slash following the step was consumed * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ protected boolean StepPattern(boolean isLeadingSlashPermitted) - throws javax.xml.transform.TransformerException + throws TransformerException { return AbbreviatedNodeTestStep(isLeadingSlashPermitted); } @@ -2253,10 +2260,10 @@ protected boolean StepPattern(boolean isLeadingSlashPermitted) * * @return boolean indicating whether a slash following the step was consumed * - * @throws javax.xml.transform.TransformerException + * @throws TransformerException */ protected boolean AbbreviatedNodeTestStep(boolean isLeadingSlashPermitted) - throws javax.xml.transform.TransformerException + throws TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); @@ -2265,22 +2272,22 @@ protected boolean AbbreviatedNodeTestStep(boolean isLeadingSlashPermitted) // The next blocks guarantee that a MATCH_XXX will be added. int matchTypePos = -1; - if (tokenIs('@')) + if (tokenIs(Token.AT)) { axesType = OpCodes.MATCH_ATTRIBUTE; appendOp(2, axesType); nextToken(); } - else if (this.lookahead("::", 1)) + else if (this.lookahead(Token.DCOLON, 1)) { - if (tokenIs("attribute")) + if (tokenIs(Token.ATTR)) { axesType = OpCodes.MATCH_ATTRIBUTE; appendOp(2, axesType); } - else if (tokenIs("child")) + else if (tokenIs(Token.CHILD)) { matchTypePos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); axesType = OpCodes.MATCH_IMMEDIATE_ANCESTOR; @@ -2298,7 +2305,7 @@ else if (tokenIs("child")) nextToken(); nextToken(); } - else if (tokenIs('/')) + else if (tokenIs(Token.SLASH)) { if (!isLeadingSlashPermitted) { @@ -2327,7 +2334,7 @@ else if (tokenIs('/')) m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH + 1, m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); - while (tokenIs('[')) + while (tokenIs(Token.LBRACK)) { Predicate(); } @@ -2346,7 +2353,7 @@ else if (tokenIs('/')) // If current step is on the attribute axis (e.g., "@x//b"), we won't // change the current step, and let following step be marked as // MATCH_ANY_ANCESTOR on next call instead. - if ((matchTypePos > -1) && tokenIs('/') && lookahead('/', 1)) + if ((matchTypePos > -1) && tokenIs(Token.SLASH) && lookahead(Token.SLASH, 1)) { m_ops.setOp(matchTypePos, OpCodes.MATCH_ANY_ANCESTOR); 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 f0914cfb4fa..c99b4917cd0 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -30,13 +30,14 @@ import jdk.xml.internal.JdkConstants; import jdk.xml.internal.JdkProperty; import jdk.xml.internal.JdkXmlFeatures; +import jdk.xml.internal.XMLSecurityManager; /** * The XPathFactory builds XPaths. * * @author Ramesh Mandava * - * @LastModified: Nov 2021 + * @LastModified: Jan 2022 */ public class XPathFactoryImpl extends XPathFactory { @@ -69,6 +70,11 @@ public class XPathFactoryImpl extends XPathFactory { */ private final JdkXmlFeatures _featureManager; + /** + * The XML security manager + */ + private XMLSecurityManager _xmlSecMgr; + /** * javax.xml.xpath.XPathFactory implementation. */ @@ -79,7 +85,9 @@ public XPathFactoryImpl() { _isNotSecureProcessing = false; } _featureManager = new JdkXmlFeatures(!_isNotSecureProcessing); + _xmlSecMgr = new XMLSecurityManager(true); } + /** *

    Is specified object model supported by this * XPathFactory?

    @@ -126,9 +134,8 @@ public boolean isObjectModelSupported(String objectModel) { * @return New XPath */ public javax.xml.xpath.XPath newXPath() { - return new com.sun.org.apache.xpath.internal.jaxp.XPathImpl( - xPathVariableResolver, xPathFunctionResolver, - !_isNotSecureProcessing, _featureManager ); + return new XPathImpl(xPathVariableResolver, xPathFunctionResolver, + !_isNotSecureProcessing, _featureManager, _xmlSecMgr); } /** @@ -310,36 +317,4 @@ public void setXPathVariableResolver(XPathVariableResolver resolver) { xPathVariableResolver = resolver; } - - public void setProperty(String name, String value) { - // property name cannot be null - if (name == null) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_PROPERTY_NAME_NULL, - new Object[] {CLASS_NAME, value} ); - throw new NullPointerException(fmsg); - } - - // property name not recognized - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_PROPERTY_UNKNOWN, - new Object[] {name, CLASS_NAME, value} ); - throw new IllegalArgumentException(fmsg); - } - - public String getProperty(String name) { - // property name cannot be null - if (name == null) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_GETTING_NULL_PROPERTY, - new Object[] {CLASS_NAME} ); - throw new NullPointerException(fmsg); - } - - // unknown property - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_GETTING_UNKNOWN_PROPERTY, - new Object[] {name, CLASS_NAME} ); - throw new IllegalArgumentException(fmsg); - } } 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 87965873684..bddc73811ee 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -32,6 +32,7 @@ import javax.xml.xpath.XPathFunctionResolver; import javax.xml.xpath.XPathVariableResolver; import jdk.xml.internal.JdkXmlFeatures; +import jdk.xml.internal.XMLSecurityManager; import org.w3c.dom.Document; import org.xml.sax.InputSource; @@ -45,6 +46,8 @@ * Updated 12/04/2014: * New methods: evaluateExpression * Refactored to share code with XPathExpressionImpl. + * + * @LastModified: Jan 2022 */ public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath { @@ -54,18 +57,19 @@ public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath { private NamespaceContext namespaceContext=null; XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr) { - this(vr, fr, false, new JdkXmlFeatures(false)); + this(vr, fr, false, new JdkXmlFeatures(false), new XMLSecurityManager(true)); } XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr, - boolean featureSecureProcessing, JdkXmlFeatures featureManager) { + boolean featureSecureProcessing, JdkXmlFeatures featureManager, + XMLSecurityManager xmlSecMgr) { this.origVariableResolver = this.variableResolver = vr; this.origFunctionResolver = this.functionResolver = fr; this.featureSecureProcessing = featureSecureProcessing; this.featureManager = featureManager; overrideDefaultParser = featureManager.getFeature( JdkXmlFeatures.XmlFeature.JDK_OVERRIDE_PARSER); - + this.xmlSecMgr = xmlSecMgr; } @@ -113,8 +117,8 @@ public NamespaceContext getNamespaceContext() { private XObject eval(String expression, Object contextItem) throws TransformerException { requireNonNull(expression, "XPath expression"); - com.sun.org.apache.xpath.internal.XPath xpath = new com.sun.org.apache.xpath.internal.XPath(expression, - null, prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT); + XPath xpath = new XPath(expression, null, prefixResolver, XPath.SELECT, + null, null, xmlSecMgr); return eval(contextItem, xpath); } @@ -159,8 +163,8 @@ public XPathExpression compile(String expression) throws XPathExpressionException { requireNonNull(expression, "XPath expression"); try { - com.sun.org.apache.xpath.internal.XPath xpath = new XPath (expression, null, - prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT); + XPath xpath = new XPath(expression, null, prefixResolver, XPath.SELECT, + null, null, xmlSecMgr); // Can have errorListener XPathExpressionImpl ximpl = new XPathExpressionImpl (xpath, prefixResolver, functionResolver, variableResolver, 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 099a98b511f..14b47fd5dae 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -43,6 +43,7 @@ import javax.xml.xpath.XPathVariableResolver; import jdk.xml.internal.JdkXmlFeatures; import jdk.xml.internal.JdkXmlUtils; +import jdk.xml.internal.XMLSecurityManager; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.traversal.NodeIterator; @@ -52,6 +53,8 @@ /** * This class contains several utility methods used by XPathImpl and * XPathExpressionImpl + * + * @LastModified: Jan 2022 */ class XPathImplUtil { XPathFunctionResolver functionResolver; @@ -63,6 +66,7 @@ class XPathImplUtil { // extensions function need to throw XPathFunctionException boolean featureSecureProcessing = false; JdkXmlFeatures featureManager; + XMLSecurityManager xmlSecMgr; /** * Evaluate an XPath context using the internal XPath engine diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathResultImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathResultImpl.java index 4953702f4ba..b30a27cd9dd 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathResultImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathResultImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -171,7 +171,11 @@ static T getValue(XObject resultObject, Class type) throws TransformerExc case XObject.CLASS_RTREEFRAG: //NODE NodeIterator ni = resultObject.nodeset(); //Return the first node, or null - return type.cast(ni.nextNode()); + try { + return type.cast(ni.nextNode()); + } catch (RuntimeException e) { + throw new TransformerException(e.getMessage(), e.getCause()); + } } return null; diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources.java index 2e5f86ee30e..1fa2cac9fac 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -31,7 +31,7 @@ * Also you need to update the count of messages(MAX_CODE)or * the count of warnings(MAX_WARNING) [ Information purpose only] * @xsl.usage advanced - * @LastModified: Nov 2021 + * @LastModified: Jan 2022 */ public class XPATHErrorResources extends ListResourceBundle { @@ -322,10 +322,9 @@ public class XPATHErrorResources extends ListResourceBundle public static final String ER_SECUREPROCESSING_FEATURE = "ER_SECUREPROCESSING_FEATURE"; public static final String ER_NULL_XPATH_FUNCTION_RESOLVER = "ER_NULL_XPATH_FUNCTION_RESOLVER"; public static final String ER_NULL_XPATH_VARIABLE_RESOLVER = "ER_NULL_XPATH_VARIABLE_RESOLVER"; - public static final String ER_PROPERTY_NAME_NULL = "ER_PROPERTY_NAME_NULL"; - public static final String ER_PROPERTY_UNKNOWN = "ER_PROPERTY_UNKNOWN"; - public static final String ER_GETTING_NULL_PROPERTY = "ER_GETTING_NULL_PROPERTY"; - public static final String ER_GETTING_UNKNOWN_PROPERTY = "ER_GETTING_UNKNOWN_PROPERTY"; + public static final String ER_XPATH_GROUP_LIMIT = "XPATH_GROUP_LIMIT"; + public static final String ER_XPATH_OPERATOR_LIMIT = "XPATH_OPERATOR_LIMIT"; + //END: Keys needed for exception messages of JAXP 1.3 XPath API implementation public static final String WG_LOCALE_NAME_NOT_HANDLED = @@ -840,25 +839,13 @@ public class XPATHErrorResources extends ListResourceBundle { ER_NULL_XPATH_VARIABLE_RESOLVER, "Attempting to set a null XPathVariableResolver:{0}#setXPathVariableResolver(null)"}, - /** Field ER_PROPERTY_NAME_NULL */ - - { ER_PROPERTY_NAME_NULL, - "Trying to set a property with a null name: {0}#setProperty( null, {1})"}, - - /** Field ER_PROPERTY_UNKNOWN */ - - { ER_PROPERTY_UNKNOWN, - "Trying to set the unknown property \"{0}\":{1}#setProperty({0},{2})"}, - - /** Field ER_GETTING_NULL_PROPERTY */ - - { ER_GETTING_NULL_PROPERTY, - "Trying to get a property with a null name: {0}#getProperty(null)"}, - - /** Field ER_GETTING_NULL_PROPERTY */ + { ER_XPATH_GROUP_LIMIT, + "JAXP0801001: the compiler encountered an XPath expression containing " + + "''{0}'' groups that exceeds the ''{1}'' limit set by ''{2}''."}, - { ER_GETTING_UNKNOWN_PROPERTY, - "Trying to get the unknown property \"{0}\":{1}#getProperty({0})"}, + { ER_XPATH_OPERATOR_LIMIT, + "JAXP0801002: the compiler encountered an XPath expression containing " + + "''{0}'' operators that exceeds the ''{1}'' limit set by ''{2}''."}, //END: Definitions of error keys used in exception messages of JAXP 1.3 XPath API implementation diff --git a/src/java.xml/share/classes/com/sun/xml/internal/stream/events/EntityDeclarationImpl.java b/src/java.xml/share/classes/com/sun/xml/internal/stream/events/EntityDeclarationImpl.java index e4b36ece592..638063283de 100644 --- a/src/java.xml/share/classes/com/sun/xml/internal/stream/events/EntityDeclarationImpl.java +++ b/src/java.xml/share/classes/com/sun/xml/internal/stream/events/EntityDeclarationImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -28,6 +28,7 @@ import javax.xml.stream.events.EntityDeclaration; import javax.xml.stream.events.XMLEvent; import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; +import jdk.xml.internal.JdkXmlUtils; /** * @@ -129,18 +130,12 @@ protected void writeAsEncodedUnicodeEx(java.io.Writer writer) //escape quotes, lt and amps writer.write(" \""); charEncode(writer, fReplacementText); + writer.write("\""); } else { //external entity - String pubId = getPublicId(); - if (pubId != null) { - writer.write(" PUBLIC \""); - writer.write(pubId); - } else { - writer.write(" SYSTEM \""); - writer.write(getSystemId()); - } + writer.write(JdkXmlUtils.getDTDExternalDecl(getPublicId(), getSystemId())); } - writer.write("\""); + if (fNotationName != null) { writer.write(" NDATA "); writer.write(fNotationName); diff --git a/src/java.xml/share/classes/com/sun/xml/internal/stream/events/NotationDeclarationImpl.java b/src/java.xml/share/classes/com/sun/xml/internal/stream/events/NotationDeclarationImpl.java index b8a22d9c192..2f980ccd62e 100644 --- a/src/java.xml/share/classes/com/sun/xml/internal/stream/events/NotationDeclarationImpl.java +++ b/src/java.xml/share/classes/com/sun/xml/internal/stream/events/NotationDeclarationImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -28,6 +28,7 @@ import javax.xml.stream.events.NotationDeclaration; import javax.xml.stream.events.XMLEvent; import com.sun.xml.internal.stream.dtd.nonvalidating.XMLNotationDecl; +import jdk.xml.internal.JdkXmlUtils; /** * Implementation of NotationDeclaration event. @@ -88,16 +89,7 @@ protected void writeAsEncodedUnicodeEx(java.io.Writer writer) { writer.write("'); } } diff --git a/src/java.xml/share/classes/jdk/xml/internal/JdkConstants.java b/src/java.xml/share/classes/jdk/xml/internal/JdkConstants.java index c4c54a65d63..d01b799e57a 100644 --- a/src/java.xml/share/classes/jdk/xml/internal/JdkConstants.java +++ b/src/java.xml/share/classes/jdk/xml/internal/JdkConstants.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -205,6 +205,21 @@ public final class JdkConstants { */ public static final String SP_MAX_ELEMENT_DEPTH = "jdk.xml.maxElementDepth"; + /** + * JDK XPath Expression group limit + */ + public static final String XPATH_GROUP_LIMIT = "jdk.xml.xpathExprGrpLimit"; + + /** + * JDK XPath Expression operators limit + */ + public static final String XPATH_OP_LIMIT = "jdk.xml.xpathExprOpLimit"; + + /** + * JDK XSL XPath limit or Total Number of Operators Permitted in an XSL Stylesheet + */ + public static final String XPATH_TOTALOP_LIMIT = "jdk.xml.xpathTotalOpLimit"; + /** * JDK TransformerFactory and Transformer attribute that specifies a class * loader that will be used for extension functions class loading diff --git a/src/java.xml/share/classes/jdk/xml/internal/JdkProperty.java b/src/java.xml/share/classes/jdk/xml/internal/JdkProperty.java index 2294659f9c7..1a555cf1473 100644 --- a/src/java.xml/share/classes/jdk/xml/internal/JdkProperty.java +++ b/src/java.xml/share/classes/jdk/xml/internal/JdkProperty.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. 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. * * This code is free software; you can redistribute it and/or modify it @@ -51,20 +51,43 @@ */ public final class JdkProperty { - private ImplPropMap pName; + private final ImplPropMap pName; + private final Class pType; private T pValue; private State pState = State.DEFAULT; /** * Constructs a JDkProperty. * @param name the name of the property + * @param type the type of the value * @param value the initial value * @param state the state of the property */ - public JdkProperty(ImplPropMap name, T value, State state) { + public JdkProperty(ImplPropMap name, Class type, T value, State state) { this.pName = name; + this.pType = type; this.pValue = value; this.pState = state; + readSystemProperty(); + } + + /** + * Read from system properties, or those in jaxp.properties + */ + private void readSystemProperty() { + if (pState == State.DEFAULT) { + T value = null; + if (pName.systemProperty() != null) { + value = SecuritySupport.getJAXPSystemProperty(pType, pName.systemProperty(), null); + } + if (value == null && pName.systemPropertyOld() != null) { + value = SecuritySupport.getJAXPSystemProperty(pType, pName.systemPropertyOld(), null); + } + if (value != null) { + pValue = value; + pState = State.SYSTEMPROPERTY; + } + } } /** 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 6e0975356cb..3cb0cb32143 100644 --- a/src/java.xml/share/classes/jdk/xml/internal/JdkXmlUtils.java +++ b/src/java.xml/share/classes/jdk/xml/internal/JdkXmlUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -24,7 +24,6 @@ */ package jdk.xml.internal; -import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager; import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl; @@ -367,19 +366,40 @@ public static SAXTransformerFactory getSAXTransformFactory(boolean overrideDefau } /** - * Returns the character to be used to quote the input content. Between - * single and double quotes, this method returns the one that is not found - * in the input. Returns double quote by default. + * Returns the external declaration for a DTD construct. * - * @param s the input string - * @return returns the quote not found in the input + * @param publicId the public identifier + * @param systemId the system identifier + * @return a DTD external declaration */ - public static char getQuoteChar(String s) { - if (s != null && s.indexOf('"') > -1) { - return '\''; - } else { - return '"'; + public static String getDTDExternalDecl(String publicId, String systemId) { + StringBuilder sb = new StringBuilder(); + if (null != publicId) { + sb.append(" PUBLIC "); + sb.append(quoteString(publicId)); + } + + if (null != systemId) { + if (null == publicId) { + sb.append(" SYSTEM "); + } else { + sb.append(" "); + } + + sb.append(quoteString(systemId)); } + return sb.toString(); + } + + /** + * Returns the input string quoted with double quotes or single ones if + * there is a double quote in the string. + * @param s the input string, can not be null + * @return the quoted string + */ + private static String quoteString(String s) { + char c = (s.indexOf('"') > -1) ? '\'' : '"'; + return c + s + c; } private static XMLReader getXMLReaderWSAXFactory(boolean overrideDefaultParser) { diff --git a/src/java.xml/share/classes/jdk/xml/internal/XMLLimitAnalyzer.java b/src/java.xml/share/classes/jdk/xml/internal/XMLLimitAnalyzer.java new file mode 100644 index 00000000000..4b9f8dc8682 --- /dev/null +++ b/src/java.xml/share/classes/jdk/xml/internal/XMLLimitAnalyzer.java @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2013, 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. 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 jdk.xml.internal; + +import java.util.Formatter; +import java.util.HashMap; +import java.util.Map; +import jdk.xml.internal.XMLSecurityManager.Limit; + + +/** + * A helper for analyzing entity expansion limits + * + */ +public final class XMLLimitAnalyzer { + + /** + * Map old property names with the new ones + */ + public static enum NameMap { + ENTITY_EXPANSION_LIMIT(JdkConstants.SP_ENTITY_EXPANSION_LIMIT, JdkConstants.ENTITY_EXPANSION_LIMIT), + MAX_OCCUR_NODE_LIMIT(JdkConstants.SP_MAX_OCCUR_LIMIT, JdkConstants.MAX_OCCUR_LIMIT), + ELEMENT_ATTRIBUTE_LIMIT(JdkConstants.SP_ELEMENT_ATTRIBUTE_LIMIT, JdkConstants.ELEMENT_ATTRIBUTE_LIMIT); + + final String newName; + final String oldName; + + NameMap(String newName, String oldName) { + this.newName = newName; + this.oldName = oldName; + } + + String getOldName(String newName) { + if (newName.equals(this.newName)) { + return oldName; + } + return null; + } + } + + /** + * Max value accumulated for each property + */ + private final int[] values; + /** + * Names of the entities corresponding to their max values + */ + private final String[] names; + /** + * Total value of accumulated entities + */ + private final int[] totalValue; + + /** + * Maintain values of the top 10 elements in the process of parsing + */ + private final Map[] caches; + + private String entityStart, entityEnd; + /** + * Default constructor. Establishes default values for known security + * vulnerabilities. + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + public XMLLimitAnalyzer() { + values = new int[Limit.values().length]; + totalValue = new int[Limit.values().length]; + names = new String[Limit.values().length]; + caches = new Map[Limit.values().length]; + } + + /** + * Add the value to the current max count for the specified property + * To find the max value of all entities, set no limit + * + * @param limit the type of the property + * @param entityName the name of the entity + * @param value the value of the entity + */ + public void addValue(Limit limit, String entityName, int value) { + addValue(limit.ordinal(), entityName, value); + } + + /** + * Add the value to the current count by the index of the property + * @param index the index of the property + * @param entityName the name of the entity + * @param value the value of the entity + */ + public void addValue(int index, String entityName, int value) { + if (index == Limit.ENTITY_EXPANSION_LIMIT.ordinal() || + index == Limit.MAX_OCCUR_NODE_LIMIT.ordinal() || + index == Limit.ELEMENT_ATTRIBUTE_LIMIT.ordinal() || + index == Limit.TOTAL_ENTITY_SIZE_LIMIT.ordinal() || + index == Limit.ENTITY_REPLACEMENT_LIMIT.ordinal() + ) { + totalValue[index] += value; + return; + } + if (index == Limit.MAX_ELEMENT_DEPTH_LIMIT.ordinal() || + index == Limit.MAX_NAME_LIMIT.ordinal()) { + values[index] = value; + totalValue[index] = value; + return; + } + + Map cache; + if (caches[index] == null) { + cache = new HashMap<>(10); + caches[index] = cache; + } else { + cache = caches[index]; + } + + int accumulatedValue = value; + if (cache.containsKey(entityName)) { + accumulatedValue += cache.get(entityName); + cache.put(entityName, accumulatedValue); + } else { + cache.put(entityName, value); + } + + if (accumulatedValue > values[index]) { + values[index] = accumulatedValue; + names[index] = entityName; + } + + + if (index == Limit.GENERAL_ENTITY_SIZE_LIMIT.ordinal() || + index == Limit.PARAMETER_ENTITY_SIZE_LIMIT.ordinal()) { + totalValue[Limit.TOTAL_ENTITY_SIZE_LIMIT.ordinal()] += value; + } + } + + /** + * Return the value of the current max count for the specified property + * + * @param limit the property + * @return the value of the property + */ + public int getValue(Limit limit) { + return getValue(limit.ordinal()); + } + + public int getValue(int index) { + if (index == Limit.ENTITY_REPLACEMENT_LIMIT.ordinal()) { + return totalValue[index]; + } + return values[index]; + } + /** + * Return the total value accumulated so far + * + * @param limit the property + * @return the accumulated value of the property + */ + public int getTotalValue(Limit limit) { + return totalValue[limit.ordinal()]; + } + + public int getTotalValue(int index) { + return totalValue[index]; + } + /** + * Return the current max value (count or length) by the index of a property + * @param index the index of a property + * @return count of a property + */ + public int getValueByIndex(int index) { + return values[index]; + } + + public void startEntity(String name) { + entityStart = name; + } + + public boolean isTracking(String name) { + if (entityStart == null) { + return false; + } + return entityStart.equals(name); + } + /** + * Stop tracking the entity + * @param limit the limit property + * @param name the name of an entity + */ + public void endEntity(Limit limit, String name) { + entityStart = ""; + Map cache = caches[limit.ordinal()]; + if (cache != null) { + cache.remove(name); + } + } + + /** + * Resets the current value of the specified limit. + * @param limit The limit to be reset. + */ + public void reset(Limit limit) { + if (limit.ordinal() == Limit.TOTAL_ENTITY_SIZE_LIMIT.ordinal()) { + totalValue[limit.ordinal()] = 0; + } else if (limit.ordinal() == Limit.GENERAL_ENTITY_SIZE_LIMIT.ordinal()) { + names[limit.ordinal()] = null; + values[limit.ordinal()] = 0; + caches[limit.ordinal()] = null; + totalValue[limit.ordinal()] = 0; + } + } + + public void debugPrint(XMLSecurityManager securityManager) { + Formatter formatter = new Formatter(); + System.out.println(formatter.format("%30s %15s %15s %15s %30s", + "Property","Limit","Total size","Size","Entity Name")); + + for (Limit limit : Limit.values()) { + formatter = new Formatter(); + System.out.println(formatter.format("%30s %15d %15d %15d %30s", + limit.name(), + securityManager.getLimit(limit), + totalValue[limit.ordinal()], + values[limit.ordinal()], + names[limit.ordinal()])); + } + } +} diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/utils/XMLSecurityManager.java b/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java similarity index 66% rename from src/java.xml/share/classes/com/sun/org/apache/xalan/internal/utils/XMLSecurityManager.java rename to src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java index 910d8636888..cf803eca3d4 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/utils/XMLSecurityManager.java +++ b/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -22,23 +22,17 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +package jdk.xml.internal; -package com.sun.org.apache.xalan.internal.utils; +import com.sun.org.apache.xerces.internal.util.SecurityManager; import java.util.concurrent.CopyOnWriteArrayList; -import jdk.xml.internal.JdkConstants; -import jdk.xml.internal.JdkProperty.ImplPropMap; import jdk.xml.internal.JdkProperty.State; -import jdk.xml.internal.SecuritySupport; +import jdk.xml.internal.JdkProperty.ImplPropMap; import org.xml.sax.SAXException; - /** - * This class is not the same as that in Xerces. It is used to manage the - * state of corresponding Xerces properties and pass the values over to - * the Xerces Security Manager. - * - * @author Joe Wang Oracle Corp. + * This class manages standard and implementation-specific limitations. * */ public final class XMLSecurityManager { @@ -48,38 +42,47 @@ public final class XMLSecurityManager { */ @SuppressWarnings("deprecation") public static enum Limit { - ENTITY_EXPANSION_LIMIT("EntityExpansionLimit", JdkConstants.JDK_ENTITY_EXPANSION_LIMIT, - JdkConstants.SP_ENTITY_EXPANSION_LIMIT, 0, 64000), + JdkConstants.SP_ENTITY_EXPANSION_LIMIT, 0, 64000, Processor.PARSER), MAX_OCCUR_NODE_LIMIT("MaxOccurLimit", JdkConstants.JDK_MAX_OCCUR_LIMIT, - JdkConstants.SP_MAX_OCCUR_LIMIT, 0, 5000), + JdkConstants.SP_MAX_OCCUR_LIMIT, 0, 5000, Processor.PARSER), ELEMENT_ATTRIBUTE_LIMIT("ElementAttributeLimit", JdkConstants.JDK_ELEMENT_ATTRIBUTE_LIMIT, - JdkConstants.SP_ELEMENT_ATTRIBUTE_LIMIT, 0, 10000), + JdkConstants.SP_ELEMENT_ATTRIBUTE_LIMIT, 0, 10000, Processor.PARSER), TOTAL_ENTITY_SIZE_LIMIT("TotalEntitySizeLimit", JdkConstants.JDK_TOTAL_ENTITY_SIZE_LIMIT, - JdkConstants.SP_TOTAL_ENTITY_SIZE_LIMIT, 0, 50000000), + JdkConstants.SP_TOTAL_ENTITY_SIZE_LIMIT, 0, 50000000, Processor.PARSER), GENERAL_ENTITY_SIZE_LIMIT("MaxEntitySizeLimit", JdkConstants.JDK_GENERAL_ENTITY_SIZE_LIMIT, - JdkConstants.SP_GENERAL_ENTITY_SIZE_LIMIT, 0, 0), + JdkConstants.SP_GENERAL_ENTITY_SIZE_LIMIT, 0, 0, Processor.PARSER), PARAMETER_ENTITY_SIZE_LIMIT("MaxEntitySizeLimit", JdkConstants.JDK_PARAMETER_ENTITY_SIZE_LIMIT, - JdkConstants.SP_PARAMETER_ENTITY_SIZE_LIMIT, 0, 1000000), + JdkConstants.SP_PARAMETER_ENTITY_SIZE_LIMIT, 0, 1000000, Processor.PARSER), MAX_ELEMENT_DEPTH_LIMIT("MaxElementDepthLimit", JdkConstants.JDK_MAX_ELEMENT_DEPTH, - JdkConstants.SP_MAX_ELEMENT_DEPTH, 0, 0), + JdkConstants.SP_MAX_ELEMENT_DEPTH, 0, 0, Processor.PARSER), MAX_NAME_LIMIT("MaxXMLNameLimit", JdkConstants.JDK_XML_NAME_LIMIT, - JdkConstants.SP_XML_NAME_LIMIT, 1000, 1000), + JdkConstants.SP_XML_NAME_LIMIT, 1000, 1000, Processor.PARSER), ENTITY_REPLACEMENT_LIMIT("EntityReplacementLimit", JdkConstants.JDK_ENTITY_REPLACEMENT_LIMIT, - JdkConstants.SP_ENTITY_REPLACEMENT_LIMIT, 0, 3000000); + JdkConstants.SP_ENTITY_REPLACEMENT_LIMIT, 0, 3000000, Processor.PARSER), + XPATH_GROUP_LIMIT("XPathGroupLimit", JdkConstants.XPATH_GROUP_LIMIT, + JdkConstants.XPATH_GROUP_LIMIT, 10, 10, Processor.XPATH), + XPATH_OP_LIMIT("XPathExprOpLimit", JdkConstants.XPATH_OP_LIMIT, + JdkConstants.XPATH_OP_LIMIT, 100, 100, Processor.XPATH), + XPATH_TOTALOP_LIMIT("XPathTotalOpLimit", JdkConstants.XPATH_TOTALOP_LIMIT, + JdkConstants.XPATH_TOTALOP_LIMIT, 10000, 10000, Processor.XPATH) + ; final String key; final String apiProperty; final String systemProperty; final int defaultValue; final int secureValue; + final Processor processor; - Limit(String key, String apiProperty, String systemProperty, int value, int secureValue) { + Limit(String key, String apiProperty, String systemProperty, int value, + int secureValue, Processor processor) { this.key = key; this.apiProperty = apiProperty; this.systemProperty = systemProperty; this.defaultValue = value; this.secureValue = secureValue; + this.processor = processor; } /** @@ -130,6 +133,10 @@ public int defaultValue() { return defaultValue; } + public boolean isSupported(Processor p) { + return processor == p; + } + int secureValue() { return secureValue; } @@ -140,12 +147,9 @@ int secureValue() { */ public static enum NameMap { - ENTITY_EXPANSION_LIMIT(JdkConstants.SP_ENTITY_EXPANSION_LIMIT, - JdkConstants.ENTITY_EXPANSION_LIMIT), - MAX_OCCUR_NODE_LIMIT(JdkConstants.SP_MAX_OCCUR_LIMIT, - JdkConstants.MAX_OCCUR_LIMIT), - ELEMENT_ATTRIBUTE_LIMIT(JdkConstants.SP_ELEMENT_ATTRIBUTE_LIMIT, - JdkConstants.ELEMENT_ATTRIBUTE_LIMIT); + ENTITY_EXPANSION_LIMIT(JdkConstants.SP_ENTITY_EXPANSION_LIMIT, JdkConstants.ENTITY_EXPANSION_LIMIT), + MAX_OCCUR_NODE_LIMIT(JdkConstants.SP_MAX_OCCUR_LIMIT, JdkConstants.MAX_OCCUR_LIMIT), + ELEMENT_ATTRIBUTE_LIMIT(JdkConstants.SP_ELEMENT_ATTRIBUTE_LIMIT, JdkConstants.ELEMENT_ATTRIBUTE_LIMIT); final String newName; final String oldName; @@ -161,14 +165,32 @@ String getOldName(String newName) { return null; } } + + /** + * Supported processors + */ + public static enum Processor { + PARSER, + XPATH, + } + + private static final int NO_LIMIT = 0; + /** * Values of the properties */ private final int[] values; + /** * States of the settings for each property */ private State[] states; + + /** + * Flag indicating if secure processing is set + */ + boolean secureProcessing; + /** * States that determine if properties are set explicitly */ @@ -198,9 +220,10 @@ public XMLSecurityManager(boolean secureProcessing) { values = new int[Limit.values().length]; states = new State[Limit.values().length]; isSet = new boolean[Limit.values().length]; + this.secureProcessing = secureProcessing; for (Limit limit : Limit.values()) { if (secureProcessing) { - values[limit.ordinal()] = limit.secureValue(); + values[limit.ordinal()] = limit.secureValue; states[limit.ordinal()] = State.FSP; } else { values[limit.ordinal()] = limit.defaultValue(); @@ -215,6 +238,7 @@ public XMLSecurityManager(boolean secureProcessing) { * Setting FEATURE_SECURE_PROCESSING explicitly */ public void setSecureProcessing(boolean secure) { + secureProcessing = secure; for (Limit limit : Limit.values()) { if (secure) { setLimit(limit.ordinal(), State.FSP, limit.secureValue()); @@ -224,6 +248,33 @@ public void setSecureProcessing(boolean secure) { } } + /** + * Return the state of secure processing + * @return the state of secure processing + */ + public boolean isSecureProcessing() { + return secureProcessing; + } + + /** + * Finds a limit's new name with the given property name. + * @param propertyName the property name specified + * @return the limit's new name if found, null otherwise + */ + public String find(String propertyName) { + for (Limit limit : Limit.values()) { + if (limit.is(propertyName)) { + // current spec: new property name == systemProperty + return limit.systemProperty(); + } + } + //ENTITYCOUNT's new name is qName + if (ImplPropMap.ENTITYCOUNT.is(propertyName)) { + return ImplPropMap.ENTITYCOUNT.qName(); + } + return null; + } + /** * Set limit by property name and state * @param propertyName property name @@ -265,7 +316,6 @@ public void setLimit(Limit limit, State state, int value) { */ public void setLimit(int index, State state, Object value) { if (index == indexEntityCountInfo) { - //if it's explicitly set, it's treated as yes no matter the value printEntityCountInfo = (String)value; } else { int temp; @@ -302,9 +352,8 @@ public void setLimit(int index, State state, int value) { } } - /** - * Return the value of the specified property. + * Return the value of the specified property * * @param propertyName the property name * @return the value of the property as a string. If a property is managed @@ -318,17 +367,6 @@ public String getLimitAsString(String propertyName) { return null; } - - /** - * Return the value of a property by its ordinal - * - * @param limit the property - * @return value of a property - */ - public String getLimitValueAsString(Limit limit) { - return Integer.toString(values[limit.ordinal()]); - } - /** * Return the value of the specified property * @@ -342,14 +380,15 @@ public int getLimit(Limit limit) { /** * Return the value of a property by its ordinal * - * @param index the index of a property + * @param limit the property * @return value of a property */ - public int getLimitByIndex(int index) { - return values[index]; + public String getLimitValueAsString(Limit limit) { + return Integer.toString(values[limit.ordinal()]); } + /** - * Return the value of a property by its index + * Return the value of a property by its ordinal * * @param index the index of a property * @return limit of a property as a string @@ -361,6 +400,7 @@ public String getLimitValueByIndex(int index) { return Integer.toString(values[index]); } + /** * Return the state of the limit property * @@ -402,6 +442,85 @@ public int getIndex(String propertyName) { return -1; } + /** + * Check if there's no limit defined by the Security Manager + * @param limit + * @return + */ + public boolean isNoLimit(int limit) { + return limit == NO_LIMIT; + } + /** + * Check if the size (length or count) of the specified limit property is + * over the limit + * + * @param limit the type of the limit property + * @param entityName the name of the entity + * @param size the size (count or length) of the entity + * @return true if the size is over the limit, false otherwise + */ + public boolean isOverLimit(Limit limit, String entityName, int size, + XMLLimitAnalyzer limitAnalyzer) { + return isOverLimit(limit.ordinal(), entityName, size, limitAnalyzer); + } + + /** + * Check if the value (length or count) of the specified limit property is + * over the limit + * + * @param index the index of the limit property + * @param entityName the name of the entity + * @param size the size (count or length) of the entity + * @return true if the size is over the limit, false otherwise + */ + public boolean isOverLimit(int index, String entityName, int size, + XMLLimitAnalyzer limitAnalyzer) { + if (values[index] == NO_LIMIT) { + return false; + } + if (size > values[index]) { + limitAnalyzer.addValue(index, entityName, size); + return true; + } + return false; + } + + /** + * Check against cumulated value + * + * @param limit the type of the limit property + * @param size the size (count or length) of the entity + * @return true if the size is over the limit, false otherwise + */ + public boolean isOverLimit(Limit limit, XMLLimitAnalyzer limitAnalyzer) { + return isOverLimit(limit.ordinal(), limitAnalyzer); + } + + public boolean isOverLimit(int index, XMLLimitAnalyzer limitAnalyzer) { + if (values[index] == NO_LIMIT) { + return false; + } + + if (index == Limit.ELEMENT_ATTRIBUTE_LIMIT.ordinal() || + index == Limit.ENTITY_EXPANSION_LIMIT.ordinal() || + index == Limit.TOTAL_ENTITY_SIZE_LIMIT.ordinal() || + index == Limit.ENTITY_REPLACEMENT_LIMIT.ordinal() || + index == Limit.MAX_ELEMENT_DEPTH_LIMIT.ordinal() || + index == Limit.MAX_NAME_LIMIT.ordinal() + ) { + return (limitAnalyzer.getTotalValue(index) > values[index]); + } else { + return (limitAnalyzer.getValue(index) > values[index]); + } + } + + public void debugPrint(XMLLimitAnalyzer limitAnalyzer) { + if (printEntityCountInfo.equals(JdkConstants.JDK_YES)) { + limitAnalyzer.debugPrint(this); + } + } + + /** * Indicate if a property is set explicitly * @param index @@ -414,6 +533,7 @@ public boolean isSet(int index) { public boolean printEntityCountInfo() { return printEntityCountInfo.equals(JdkConstants.JDK_YES); } + /** * Read from system properties, or those in jaxp.properties */ @@ -477,4 +597,37 @@ private boolean getSystemProperty(Limit limit, String sysPropertyName) { } return false; } + + + /** + * Convert a value set through setProperty to XMLSecurityManager. + * If the value is an instance of XMLSecurityManager, use it to override the default; + * If the value is an old SecurityManager, convert to the new XMLSecurityManager. + * + * @param value user specified security manager + * @param securityManager an instance of XMLSecurityManager + * @return an instance of the new security manager XMLSecurityManager + */ + public static XMLSecurityManager convert(Object value, XMLSecurityManager securityManager) { + if (value == null) { + if (securityManager == null) { + securityManager = new XMLSecurityManager(true); + } + return securityManager; + } + if (value instanceof XMLSecurityManager) { + return (XMLSecurityManager)value; + } else { + if (securityManager == null) { + securityManager = new XMLSecurityManager(true); + } + if (value instanceof SecurityManager) { + SecurityManager origSM = (SecurityManager)value; + securityManager.setLimit(Limit.MAX_OCCUR_NODE_LIMIT, State.APIPROPERTY, origSM.getMaxOccurNodeLimit()); + securityManager.setLimit(Limit.ENTITY_EXPANSION_LIMIT, State.APIPROPERTY, origSM.getEntityExpansionLimit()); + securityManager.setLimit(Limit.ELEMENT_ATTRIBUTE_LIMIT, State.APIPROPERTY, origSM.getElementAttrLimit()); + } + return securityManager; + } + } } diff --git a/src/java.xml/share/classes/module-info.java b/src/java.xml/share/classes/module-info.java index 253ea709f45..4045a480cd6 100644 --- a/src/java.xml/share/classes/module-info.java +++ b/src/java.xml/share/classes/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -407,7 +407,7 @@ * * XPath * XPath - * + * N/A * * * {@code XPathFactory factory = XPathFactory.newInstance();}
    @@ -432,12 +432,13 @@ * Full Name (prefix + name) * [1] * Description - * System Property [2] - * jaxp.properties [2] - * Value [3] - * Security [4] - * Supported Processor [5] - * Since [6] + * API Property [2] + * System Property [3] + * jaxp.properties [3] + * Value [4] + * Security [5] + * Supported Processor [6] + * Since [7] * * * Type @@ -455,6 +456,7 @@ * * yes * yes + * yes * Integer * * A positive integer. A value less than or equal to 0 indicates no limit. @@ -544,6 +546,7 @@ * * yes * yes + * yes * boolean * true/false * false @@ -567,6 +570,7 @@ * * yes * yes + * yes * String * yes/no * no @@ -584,6 +588,7 @@ * * yes * yes + * yes * Integer * A positive integer. A value less than * or equal to 0 indicates that the property is not specified. If the value is not @@ -599,6 +604,7 @@ * Sets a non-null ClassLoader instance to be used for loading XSLTC java * extension functions. * + * yes * no * no * Object @@ -609,6 +615,46 @@ * Transform * 9 * + * + * jdk.xml.xpathExprGrpLimit + * Limits the number of groups an XPath expression can contain. + * + * + * Transform:yes
    + * XPath:no + * + * yes + * yes + * Integer + * A positive integer. A value less than or equal to 0 indicates no limit. + * If the value is not an integer, a NumberFormatException is thrown. + * 10 + * 10 + * Yes + * + * Transform
    + * XPath + * + * 19 + * + * + * jdk.xml.xpathExprOpLimit + * Limits the number of operators an XPath expression can contain. + * + * 100 + * 100 + * + * + * jdk.xml.xpathTotalOpLimit + * Limits the total number of XPath operators in an XSL Stylesheet. + * + * yes + * 10000 + * 10000 + * + * Transform
    + * + * * * *

    @@ -622,12 +668,13 @@ * Full Name (prefix + name) * [1] * Description - * System Property [2] - * jaxp.properties [2] - * Value [3] - * Security [4] - * Supported Processor [5] - * Since [6] + * API Property [2] + * System Property [3] + * jaxp.properties [3] + * Value [4] + * Security [5] + * Supported Processor [6] + * Since [7] * * * Type @@ -643,6 +690,7 @@ * * yes * yes + * yes * Boolean * * true or false. True indicates that extension functions are allowed; False otherwise. @@ -700,11 +748,14 @@ *

    * [1] The full name of a property should be used to set the property. *

    - * [2] A value "yes" indicates there is a corresponding System Property + * [2] A value "yes" indicates that the property can be set through the + * processor or its factory, "no" otherwise. + *

    + * [3] A value "yes" indicates there is a corresponding System Property * for the property, "no" otherwise. * - *

    - * [3] The value must be exactly as listed in this table, case-sensitive. + *

    + * [4] The value must be exactly as listed in this table, case-sensitive. * The value of the corresponding System Property is the String representation of * the property value. If the type is boolean, the system property is true only * if it is "true"; If the type is String, the system property is true only if @@ -713,15 +764,15 @@ * is Integer, the value of the System Property is the String representation of * the value (e.g. "64000" for {@code entityExpansionLimit}). * - *

    - * [4] A value "yes" indicates the property is a Security Property. Refer + *

    + * [5] A value "yes" indicates the property is a Security Property. Refer * to the Scope and Order on how secure processing * may affect the value of a Security Property. - *

    - * [5] One or more processors that support the property. The values of the - * field are IDs described in table Processors. *

    - * [6] Indicates the initial release the property is introduced. + * [6] One or more processors that support the property. The values of the + * field are IDs described in table Processors. + *

    + * [7] Indicates the initial release the property is introduced. * *

    Legacy Property Names (deprecated)

    * JDK releases prior to JDK 17 support the use of URI style prefix for properties. diff --git a/src/java.xml/share/legal/bcel.md b/src/java.xml/share/legal/bcel.md index aca04ab4a8d..6dffd077c81 100644 --- a/src/java.xml/share/legal/bcel.md +++ b/src/java.xml/share/legal/bcel.md @@ -3,14 +3,11 @@ ### Apache Commons BCEL Notice
     
    -    =========================================================================
    -    ==  NOTICE file corresponding to the section 4 d of                    ==
    -    ==  the Apache License, Version 2.0,                                   ==
    -    ==  in this case for the Apache Commons BCEL distribution.             ==
    -    =========================================================================
    -
    -   This product includes software developed by
    -   The Apache Software Foundation (http://www.apache.org/).
    +    Apache Commons BCEL
    +    Copyright 2004-2020 The Apache Software Foundation
    +
    +    This product includes software developed at
    +    The Apache Software Foundation (https://www.apache.org/).
     
     
    diff --git a/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java b/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java index 072a7ad89af..6818a89b7bd 100644 --- a/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java +++ b/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java @@ -27,6 +27,7 @@ import java.awt.*; import java.awt.event.*; +import java.awt.geom.AffineTransform; import java.util.*; import java.lang.*; import java.lang.reflect.*; @@ -478,6 +479,9 @@ private AccessibleContext getAccessibleContextAt(int x, int y, if (parent == null) { return null; } + Point userSpaceXY = AccessibilityGraphicsEnvironment.toUserSpace(x, y); + x = userSpaceXY.x; + y = userSpaceXY.y; if (windowHandleToContextMap != null && windowHandleToContextMap.containsValue(getRootAccessibleContext(parent))) { // Path for applications that register their top-level @@ -1593,6 +1597,8 @@ public Rectangle call() throws Exception { if (p != null) { r.x = p.x; r.y = p.y; + + r = AccessibilityGraphicsEnvironment.toDeviceSpaceAbs(r); return r; } } catch (Exception e) { @@ -2257,6 +2263,7 @@ public Rectangle call() throws Exception { if (s != null && s.equals("\n")) { rect.width = 0; } + rect = AccessibilityGraphicsEnvironment.toDeviceSpaceAbs(rect); return rect; } } @@ -7338,4 +7345,182 @@ T getResult() throws Exception { } } } + + /** + * A helper class to handle coordinate conversion between screen and user spaces. + * See {@link sun.java2d.SunGraphicsEnvironment} + */ + private static abstract class AccessibilityGraphicsEnvironment extends GraphicsEnvironment { + /** + * Returns the graphics configuration which bounds contain the given point in the user's space. + * + * See {@link sun.java2d.SunGraphicsEnvironment#getGraphicsConfigurationAtPoint(GraphicsConfiguration, double, double)} + * + * @param x the x coordinate of the given point in the user's space + * @param y the y coordinate of the given point in the user's space + * @return the graphics configuration + */ + public static GraphicsConfiguration getGraphicsConfigurationAtPoint(double x, double y) { + GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice().getDefaultConfiguration(); + return getGraphicsConfigurationAtPoint(gc, x, y); + } + + /** + * Returns the graphics configuration which bounds contain the given point in the user's space. + * + * See {@link sun.java2d.SunGraphicsEnvironment#getGraphicsConfigurationAtPoint(GraphicsConfiguration, double, double)} + * + * @param current the default configuration which is checked in the first + * place + * @param x the x coordinate of the given point in the user's space + * @param y the y coordinate of the given point in the user's space + * @return the graphics configuration + */ + public static GraphicsConfiguration getGraphicsConfigurationAtPoint( + GraphicsConfiguration current, double x, double y) { + if (containsUserSpacePoint(current, x, y)) { + return current; + } + GraphicsEnvironment env = getLocalGraphicsEnvironment(); + for (GraphicsDevice device : env.getScreenDevices()) { + GraphicsConfiguration config = device.getDefaultConfiguration(); + if (containsUserSpacePoint(config, x, y)) { + return config; + } + } + return current; + } + + /** + * Returns the graphics configuration which bounds contain the given point in the device space. + * + * @param x the x coordinate of the given point in the device space + * @param y the y coordinate of the given point in the device space + * @return the graphics configuration + */ + public static GraphicsConfiguration getGraphicsConfigurationAtDevicePoint(double x, double y) { + GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice().getDefaultConfiguration(); + return getGraphicsConfigurationAtDevicePoint(gc, x, y); + } + + /** + * Returns the graphics configuration which bounds contain the given point in the device space. + * + * @param current the default configuration which is checked in the first + * place + * @param x the x coordinate of the given point in the device space + * @param y the y coordinate of the given point in the device space + * @return the graphics configuration + */ + public static GraphicsConfiguration getGraphicsConfigurationAtDevicePoint( + GraphicsConfiguration current, double x, double y) { + if (containsDeviceSpacePoint(current, x, y)) { + return current; + } + GraphicsEnvironment env = getLocalGraphicsEnvironment(); + for (GraphicsDevice device : env.getScreenDevices()) { + GraphicsConfiguration config = device.getDefaultConfiguration(); + if (containsDeviceSpacePoint(config, x, y)) { + return config; + } + } + return current; + } + + private static boolean containsDeviceSpacePoint(GraphicsConfiguration config, double x, double y) { + Rectangle bounds = config.getBounds(); + bounds = toDeviceSpaceAbs(config, bounds.x, bounds.y, bounds.width, bounds.height); + return bounds.contains(x, y); + } + + private static boolean containsUserSpacePoint(GraphicsConfiguration config, double x, double y) { + Rectangle bounds = config.getBounds(); + return bounds.contains(x, y); + } + + /** + * Converts absolute coordinates from the device + * space to the user's space space using appropriate device transformation. + * + * @param x absolute x coordinate in the device's space + * @param y absolute y coordinate in the device's space + * @return the corresponding coordinates in user's space + */ + public static Point toUserSpace(int x, int y) { + GraphicsConfiguration gc = getGraphicsConfigurationAtDevicePoint(x, y); + return toUserSpace(gc, x, y); + } + + /** + * Converts absolute coordinates from the device + * space to the user's space using passed graphics configuration. + * + * @param gc the graphics configuration to be used for transformation + * @param x absolute x coordinate in the device's space + * @param y absolute y coordinate in the device's space + * @return the corresponding coordinates in user's space + */ + public static Point toUserSpace(GraphicsConfiguration gc, int x, int y) { + AffineTransform tx = gc.getDefaultTransform(); + Rectangle screen = gc.getBounds(); + int userX = screen.x + clipRound((x - screen.x) / tx.getScaleX()); + int userY = screen.y + clipRound((y - screen.y) / tx.getScaleY()); + return new Point(userX, userY); + } + + /** + * Converts the rectangle from the user's space to the device space using + * appropriate device transformation. + * + * See {@link sun.java2d.SunGraphicsEnvironment#toDeviceSpaceAbs(Rectangle)} + * + * @param rect the rectangle in the user's space + * @return the rectangle which uses device space (pixels) + */ + public static Rectangle toDeviceSpaceAbs(Rectangle rect) { + GraphicsConfiguration gc = getGraphicsConfigurationAtPoint(rect.x, rect.y); + return toDeviceSpaceAbs(gc, rect.x, rect.y, rect.width, rect.height); + } + + /** + * Converts absolute coordinates (x, y) and the size (w, h) from the user's + * space to the device space using passed graphics configuration. + * + * See {@link sun.java2d.SunGraphicsEnvironment#toDeviceSpaceAbs(GraphicsConfiguration, int, int, int, int)} + * + * @param gc the graphics configuration to be used for transformation + * @param x absolute coordinate in the user's space + * @param y absolute coordinate in the user's space + * @param w the width in the user's space + * @param h the height in the user's space + * @return the rectangle which uses device space (pixels) + */ + public static Rectangle toDeviceSpaceAbs(GraphicsConfiguration gc, + int x, int y, int w, int h) { + AffineTransform tx = gc.getDefaultTransform(); + Rectangle screen = gc.getBounds(); + return new Rectangle( + screen.x + clipRound((x - screen.x) * tx.getScaleX()), + screen.y + clipRound((y - screen.y) * tx.getScaleY()), + clipRound(w * tx.getScaleX()), + clipRound(h * tx.getScaleY()) + ); + } + + /** + * See {@link sun.java2d.pipe.Region#clipRound} + */ + private static int clipRound(final double coordinate) { + final double newv = coordinate - 0.5; + if (newv < Integer.MIN_VALUE) { + return Integer.MIN_VALUE; + } + if (newv > Integer.MAX_VALUE) { + return Integer.MAX_VALUE; + } + return (int) Math.ceil(newv); + } + } } diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSAOperations.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSAOperations.java index 00010d28d1b..af6b1e160ca 100644 --- a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSAOperations.java +++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSAOperations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -30,6 +30,7 @@ import sun.security.util.math.*; import static sun.security.ec.ECOperations.IntermediateValueException; +import java.math.BigInteger; import java.security.ProviderException; import java.security.spec.*; import java.util.Arrays; @@ -200,7 +201,8 @@ public boolean verifySignedDigest(byte[] digest, byte[] sig, ECPoint pp) { IntegerFieldModuloP field = ecOps.getField(); IntegerFieldModuloP orderField = ecOps.getOrderField(); - int length = (orderField.getSize().bitLength() + 7) / 8; + BigInteger mod = orderField.getSize(); + int length = (mod.bitLength() + 7) / 8; byte[] r; byte[] s; @@ -218,6 +220,13 @@ public boolean verifySignedDigest(byte[] digest, byte[] sig, ECPoint pp) { System.arraycopy(sig, encodeLength, s, length - encodeLength, encodeLength); } + BigInteger rb = new BigInteger(1, r); + BigInteger sb = new BigInteger(1, s); + if (rb.signum() == 0 || sb.signum() == 0 + || rb.compareTo(mod) >= 0 || sb.compareTo(mod) >= 0) { + return false; + } + ArrayUtil.reverse(r); ArrayUtil.reverse(s); IntegerModuloP ri = orderField.getElement(r); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java index c7613b2ff14..0e8f5bd5564 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java @@ -4029,12 +4029,12 @@ public final VectorMask maskAll(boolean bit) { */ static ByteSpecies species(VectorShape s) { Objects.requireNonNull(s); - switch (s) { - case S_64_BIT: return (ByteSpecies) SPECIES_64; - case S_128_BIT: return (ByteSpecies) SPECIES_128; - case S_256_BIT: return (ByteSpecies) SPECIES_256; - case S_512_BIT: return (ByteSpecies) SPECIES_512; - case S_Max_BIT: return (ByteSpecies) SPECIES_MAX; + switch (s.switchKey) { + case VectorShape.SK_64_BIT: return (ByteSpecies) SPECIES_64; + case VectorShape.SK_128_BIT: return (ByteSpecies) SPECIES_128; + case VectorShape.SK_256_BIT: return (ByteSpecies) SPECIES_256; + case VectorShape.SK_512_BIT: return (ByteSpecies) SPECIES_512; + case VectorShape.SK_Max_BIT: return (ByteSpecies) SPECIES_MAX; default: throw new IllegalArgumentException("Bad shape: " + s); } } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java index 9dadb3f7b03..ac19b64f809 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java @@ -3631,12 +3631,12 @@ public final VectorMask maskAll(boolean bit) { */ static DoubleSpecies species(VectorShape s) { Objects.requireNonNull(s); - switch (s) { - case S_64_BIT: return (DoubleSpecies) SPECIES_64; - case S_128_BIT: return (DoubleSpecies) SPECIES_128; - case S_256_BIT: return (DoubleSpecies) SPECIES_256; - case S_512_BIT: return (DoubleSpecies) SPECIES_512; - case S_Max_BIT: return (DoubleSpecies) SPECIES_MAX; + switch (s.switchKey) { + case VectorShape.SK_64_BIT: return (DoubleSpecies) SPECIES_64; + case VectorShape.SK_128_BIT: return (DoubleSpecies) SPECIES_128; + case VectorShape.SK_256_BIT: return (DoubleSpecies) SPECIES_256; + case VectorShape.SK_512_BIT: return (DoubleSpecies) SPECIES_512; + case VectorShape.SK_Max_BIT: return (DoubleSpecies) SPECIES_MAX; default: throw new IllegalArgumentException("Bad shape: " + s); } } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java index 1841b3e0dec..4fdfbb80a20 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java @@ -3618,12 +3618,12 @@ public final VectorMask maskAll(boolean bit) { */ static FloatSpecies species(VectorShape s) { Objects.requireNonNull(s); - switch (s) { - case S_64_BIT: return (FloatSpecies) SPECIES_64; - case S_128_BIT: return (FloatSpecies) SPECIES_128; - case S_256_BIT: return (FloatSpecies) SPECIES_256; - case S_512_BIT: return (FloatSpecies) SPECIES_512; - case S_Max_BIT: return (FloatSpecies) SPECIES_MAX; + switch (s.switchKey) { + case VectorShape.SK_64_BIT: return (FloatSpecies) SPECIES_64; + case VectorShape.SK_128_BIT: return (FloatSpecies) SPECIES_128; + case VectorShape.SK_256_BIT: return (FloatSpecies) SPECIES_256; + case VectorShape.SK_512_BIT: return (FloatSpecies) SPECIES_512; + case VectorShape.SK_Max_BIT: return (FloatSpecies) SPECIES_MAX; default: throw new IllegalArgumentException("Bad shape: " + s); } } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java index f23cdfa1149..7bd0da683cb 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java @@ -3727,12 +3727,12 @@ public final VectorMask maskAll(boolean bit) { */ static IntSpecies species(VectorShape s) { Objects.requireNonNull(s); - switch (s) { - case S_64_BIT: return (IntSpecies) SPECIES_64; - case S_128_BIT: return (IntSpecies) SPECIES_128; - case S_256_BIT: return (IntSpecies) SPECIES_256; - case S_512_BIT: return (IntSpecies) SPECIES_512; - case S_Max_BIT: return (IntSpecies) SPECIES_MAX; + switch (s.switchKey) { + case VectorShape.SK_64_BIT: return (IntSpecies) SPECIES_64; + case VectorShape.SK_128_BIT: return (IntSpecies) SPECIES_128; + case VectorShape.SK_256_BIT: return (IntSpecies) SPECIES_256; + case VectorShape.SK_512_BIT: return (IntSpecies) SPECIES_512; + case VectorShape.SK_Max_BIT: return (IntSpecies) SPECIES_MAX; default: throw new IllegalArgumentException("Bad shape: " + s); } } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java index c1c1aea390a..da6657bc217 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java @@ -3621,12 +3621,12 @@ public final VectorMask maskAll(boolean bit) { */ static LongSpecies species(VectorShape s) { Objects.requireNonNull(s); - switch (s) { - case S_64_BIT: return (LongSpecies) SPECIES_64; - case S_128_BIT: return (LongSpecies) SPECIES_128; - case S_256_BIT: return (LongSpecies) SPECIES_256; - case S_512_BIT: return (LongSpecies) SPECIES_512; - case S_Max_BIT: return (LongSpecies) SPECIES_MAX; + switch (s.switchKey) { + case VectorShape.SK_64_BIT: return (LongSpecies) SPECIES_64; + case VectorShape.SK_128_BIT: return (LongSpecies) SPECIES_128; + case VectorShape.SK_256_BIT: return (LongSpecies) SPECIES_256; + case VectorShape.SK_512_BIT: return (LongSpecies) SPECIES_512; + case VectorShape.SK_Max_BIT: return (LongSpecies) SPECIES_MAX; default: throw new IllegalArgumentException("Bad shape: " + s); } } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java index a2ee13e6319..6284208535e 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java @@ -4024,12 +4024,12 @@ public final VectorMask maskAll(boolean bit) { */ static ShortSpecies species(VectorShape s) { Objects.requireNonNull(s); - switch (s) { - case S_64_BIT: return (ShortSpecies) SPECIES_64; - case S_128_BIT: return (ShortSpecies) SPECIES_128; - case S_256_BIT: return (ShortSpecies) SPECIES_256; - case S_512_BIT: return (ShortSpecies) SPECIES_512; - case S_Max_BIT: return (ShortSpecies) SPECIES_MAX; + switch (s.switchKey) { + case VectorShape.SK_64_BIT: return (ShortSpecies) SPECIES_64; + case VectorShape.SK_128_BIT: return (ShortSpecies) SPECIES_128; + case VectorShape.SK_256_BIT: return (ShortSpecies) SPECIES_256; + case VectorShape.SK_512_BIT: return (ShortSpecies) SPECIES_512; + case VectorShape.SK_Max_BIT: return (ShortSpecies) SPECIES_MAX; default: throw new IllegalArgumentException("Bad shape: " + s); } } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template index 2fb3ae856cf..355645a2f6e 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template @@ -5033,12 +5033,12 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { */ static $Type$Species species(VectorShape s) { Objects.requireNonNull(s); - switch (s) { - case S_64_BIT: return ($Type$Species) SPECIES_64; - case S_128_BIT: return ($Type$Species) SPECIES_128; - case S_256_BIT: return ($Type$Species) SPECIES_256; - case S_512_BIT: return ($Type$Species) SPECIES_512; - case S_Max_BIT: return ($Type$Species) SPECIES_MAX; + switch (s.switchKey) { + case VectorShape.SK_64_BIT: return ($Type$Species) SPECIES_64; + case VectorShape.SK_128_BIT: return ($Type$Species) SPECIES_128; + case VectorShape.SK_256_BIT: return ($Type$Species) SPECIES_256; + case VectorShape.SK_512_BIT: return ($Type$Species) SPECIES_512; + case VectorShape.SK_Max_BIT: return ($Type$Species) SPECIES_MAX; default: throw new IllegalArgumentException("Bad shape: " + s); } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java index 528bb34e059..3ec0b603a87 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -27,6 +27,11 @@ */ public class MetaUtil { + public static final char PACKAGE_SEPARATOR_INTERNAL = '/'; + public static final char HIDDEN_SEPARATOR_INTERNAL = '.'; + public static final char PACKAGE_SEPARATOR_JAVA = HIDDEN_SEPARATOR_INTERNAL; + public static final char HIDDEN_SEPARATOR_JAVA = PACKAGE_SEPARATOR_INTERNAL; + /** * Extends the functionality of {@link Class#getSimpleName()} to include a non-empty string for * anonymous and local classes. @@ -87,25 +92,27 @@ private static String safeSimpleName(Class clazz) { } /** - * Classes for lambdas can have {@code /} characters that are not package separators. These are - * distinguished by being followed by a character that is not a + * Hidden classes have {@code /} characters in their internal names and {@code .} characters in their names returned + * by {@link Class#getName()} that are not package separators. + * These are distinguished by being followed by a character that is not a * {@link Character#isJavaIdentifierStart(char)} (e.g., * "jdk.vm.ci.runtime.test.TypeUniverse$$Lambda$1/869601985"). + * + * @param name the name to perform the replacements on + * @param packageSeparator the {@link Character} used as the package separator, e.g. {@code /} in internal form + * @param hiddenSeparator the {@link Character} used as the hidden class separator, e.g. {@code .} in internal form */ - private static String replacePackageSeparatorsWithDot(String name) { + private static String replacePackageAndHiddenSeparators(String name, Character packageSeparator, Character hiddenSeparator) { + int index = name.indexOf(hiddenSeparator); // check if it's a hidden class int length = name.length(); - int i = 0; StringBuilder buf = new StringBuilder(length); - while (i < length - 1) { - char ch = name.charAt(i); - if (ch == '/' && Character.isJavaIdentifierStart(name.charAt(i + 1))) { - buf.append('.'); - } else { - buf.append(ch); - } - i++; + if (index < 0) { + buf.append(name.replace(packageSeparator, hiddenSeparator)); + } else { + buf.append(name.substring(0, index).replace(packageSeparator, hiddenSeparator)); + buf.append(packageSeparator); + buf.append(name.substring(index + 1)); } - buf.append(name.charAt(length - 1)); return buf.toString(); } @@ -122,9 +129,10 @@ private static String replacePackageSeparatorsWithDot(String name) { public static String internalNameToJava(String name, boolean qualified, boolean classForNameCompatible) { switch (name.charAt(0)) { case 'L': { - String result = replacePackageSeparatorsWithDot(name.substring(1, name.length() - 1)); + String type = name.substring(1, name.length() - 1); + String result = replacePackageAndHiddenSeparators(type, PACKAGE_SEPARATOR_INTERNAL, HIDDEN_SEPARATOR_INTERNAL); if (!qualified) { - final int lastDot = result.lastIndexOf('.'); + final int lastDot = result.lastIndexOf(HIDDEN_SEPARATOR_INTERNAL); if (lastDot != -1) { result = result.substring(lastDot + 1); } @@ -132,7 +140,11 @@ public static String internalNameToJava(String name, boolean qualified, boolean return result; } case '[': - return classForNameCompatible ? replacePackageSeparatorsWithDot(name) : internalNameToJava(name.substring(1), qualified, classForNameCompatible) + "[]"; + if (classForNameCompatible) { + return replacePackageAndHiddenSeparators(name, PACKAGE_SEPARATOR_INTERNAL, HIDDEN_SEPARATOR_INTERNAL); + } else { + return internalNameToJava(name.substring(1), qualified, false) + "[]"; + } default: if (name.length() != 1) { throw new IllegalArgumentException("Illegal internal name: " + name); @@ -213,7 +225,7 @@ static void appendProfile(StringBuilder buf, AbstractJavaProfile profile, public static String toInternalName(String className) { if (className.startsWith("[")) { /* Already in the correct array style. */ - return className.replace('.', '/'); + return replacePackageAndHiddenSeparators(className, PACKAGE_SEPARATOR_JAVA, HIDDEN_SEPARATOR_JAVA); } StringBuilder result = new StringBuilder(); @@ -252,7 +264,7 @@ public static String toInternalName(String className) { result.append("V"); break; default: - result.append("L").append(base.replace('.', '/')).append(";"); + result.append("L").append(replacePackageAndHiddenSeparators(base, PACKAGE_SEPARATOR_JAVA, HIDDEN_SEPARATOR_JAVA)).append(";"); break; } return result.toString(); diff --git a/src/jdk.jcmd/share/man/jcmd.1 b/src/jdk.jcmd/share/man/jcmd.1 index c742db0e486..9641bc15f5b 100644 --- a/src/jdk.jcmd/share/man/jcmd.1 +++ b/src/jdk.jcmd/share/man/jcmd.1 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. +.\" Copyright (c) 2012, 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 @@ -764,6 +764,56 @@ The following \f[I]options\f[R] must be specified using either (BOOLEAN, false) .RE .TP +.B \f[CB]VM.cds\f[R] [\f[I]arguments\f[R]] +Dumps a static or dynamic shared archive that includes all currently +loaded classes. +.RS +.PP +Impact: Medium \-\-\- pause time depends on number of loaded classes +.PP +Permission: \f[CB]java.lang.management.ManagementPermission(monitor)\f[R] +.PP +\f[I]arguments\f[R]: +.IP \[bu] 2 +\f[CB]subcmd\f[R]: must be either \f[CB]static_dump\f[R] or +.IP \[bu] 2 +\f[CB]filename\f[R]: (Optional) Name of the shared archive to be dumped +(STRING, no default value) +.PP +If \f[CB]filename\f[R] is not specified, a default file name is chosen +using the pid of the target JVM process. +For example, java_pid1234_static.jsa, java_pid5678_dynamic.jsa, etc. +.PP +If \f[CB]filename\f[R] is not specified as an absolute path, the archive +file is created in a directory relative to the current directory of the +target JVM process. +.RE +.TP +.B \f[CB]VM.classloaders\f[R] [\f[I]options\f[R]] +Prints classloader hierarchy. +.RS +.PP +Impact: Medium \-\-\- Depends on number of class loaders and classes +loaded. +.PP +Permission: \f[CB]java.lang.management.ManagementPermission(monitor)\f[R] +.PP +The following \f[I]options\f[R] must be specified using either +\f[I]key\f[R] or \f[I]key\f[R]\f[CB]=\f[R]\f[I]value\f[R] syntax. +.PP +\f[I]options\f[R]: +.IP \[bu] 2 +\f[CB]show\-classes\f[R]: (Optional) Print loaded classes. +(BOOLEAN, false) +.IP \[bu] 2 +\f[CB]verbose\f[R]: (Optional) Print detailed information. +(BOOLEAN, false) +.IP \[bu] 2 +\f[CB]fold\f[R]: (Optional) Show loaders of the same name and class as +one. +(BOOLEAN, true) +.RE +.TP .B \f[CB]VM.classloader_stats\f[R] Prints statistics about all ClassLoaders. .RS diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java index 1c4df796279..b03c175da24 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java @@ -356,7 +356,8 @@ public ClassFile getClassFile(String name) throws IOException { protected ClassFile readClassFile(JarFile jarfile, JarEntry e) throws IOException { try (InputStream is = jarfile.getInputStream(e)) { ClassFile cf = ClassFile.read(is); - if (jarfile.isMultiRelease()) { + // exclude module-info.class since this jarFile is on classpath + if (jarfile.isMultiRelease() && !cf.getName().equals("module-info")) { VersionHelper.add(jarfile, e, cf); } return cf; @@ -437,5 +438,4 @@ public void remove() { throw new UnsupportedOperationException("Not supported yet."); } } - private static final String MODULE_INFO = "module-info.class"; } diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java index 514e2ef607a..d9a07700134 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java @@ -268,7 +268,14 @@ private Set waitForTasksCompleted() { } return targets; } catch (InterruptedException|ExecutionException e) { - throw new Error(e); + Throwable cause = e.getCause(); + if (cause instanceof RuntimeException x) { + throw x; + } else if (cause instanceof Error x) { + throw x; + } else { + throw new Error(e); + } } } diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/MultiReleaseException.java b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/MultiReleaseException.java index 65fce011a58..5289c565ed3 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/MultiReleaseException.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/MultiReleaseException.java @@ -46,7 +46,7 @@ class MultiReleaseException extends RuntimeException { * The detail message array */ public MultiReleaseException(String key, Object... params) { - super(); + super(JdepsTask.getMessage(key, params)); this.key = key; this.params = params; } diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/VersionHelper.java b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/VersionHelper.java index 9ff358a63d3..227c9ccd264 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/VersionHelper.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/VersionHelper.java @@ -55,15 +55,10 @@ public static void add(JarFile jarfile, JarEntry e, ClassFile cf) String version = realName.substring(len, n); assert (Integer.parseInt(version) > 8); String name = cf.getName().replace('/', '.'); - if (nameToVersion.containsKey(name)) { - if (!version.equals(nameToVersion.get(name))) { - throw new MultiReleaseException( - "err.multirelease.version.associated", - name, nameToVersion.get(name), version - ); - } - } else { - nameToVersion.put(name, version); + String v = nameToVersion.computeIfAbsent(name, _n -> version); + if (!version.equals(v)) { + throw new MultiReleaseException("err.multirelease.version.associated", + name, nameToVersion.get(name), version); } } else { throw new MultiReleaseException("err.multirelease.jar.malformed", diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/classTrack.c b/src/jdk.jdwp.agent/share/native/libjdwp/classTrack.c index 62513115234..de9918780bf 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/classTrack.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/classTrack.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -81,14 +81,22 @@ cbTrackingObjectFree(jvmtiEnv* jvmti_env, jlong tag) struct bag * classTrack_processUnloads(JNIEnv *env) { - debugMonitorEnter(classTrackLock); if (deletedSignatures == NULL) { - // Class tracking not initialized, nobody's interested. - debugMonitorExit(classTrackLock); - return NULL; + return NULL; } + + /* Allocate new bag outside classTrackLock lock to avoid deadlock. + * + * Note: jvmtiAllocate/jvmtiDeallocate() may be blocked by ongoing safepoints. + * It is dangerous to call them (via bagCreateBag/bagDestroyBag()) while holding monitor(s), + * because jvmti may post events, e.g. JVMTI_EVENT_OBJECT_FREE at safepoints and event processing + * code may acquire the same monitor(s), e.g. classTrackLock in cbTrackingObjectFree(), + * which can lead to deadlock. + */ + struct bag* new_bag = bagCreateBag(sizeof(char*), 10); + debugMonitorEnter(classTrackLock); struct bag* deleted = deletedSignatures; - deletedSignatures = bagCreateBag(sizeof(char*), 10); + deletedSignatures = new_bag; debugMonitorExit(classTrackLock); return deleted; } @@ -194,8 +202,11 @@ classTrack_initialize(JNIEnv *env) void classTrack_activate(JNIEnv *env) { + // Allocate bag outside classTrackLock lock to avoid deadlock. + // See comments in classTrack_processUnloads() for details. + struct bag* new_bag = bagCreateBag(sizeof(char*), 1000); debugMonitorEnter(classTrackLock); - deletedSignatures = bagCreateBag(sizeof(char*), 1000); + deletedSignatures = new_bag; debugMonitorExit(classTrackLock); } @@ -214,12 +225,14 @@ void classTrack_reset(void) { debugMonitorEnter(classTrackLock); + struct bag* to_delete = deletedSignatures; + deletedSignatures = NULL; + debugMonitorExit(classTrackLock); - if (deletedSignatures != NULL) { - bagEnumerateOver(deletedSignatures, cleanDeleted, NULL); - bagDestroyBag(deletedSignatures); - deletedSignatures = NULL; + // Deallocate bag outside classTrackLock to avoid deadlock. + // See comments in classTrack_processUnloads() for details. + if (to_delete != NULL) { + bagEnumerateOver(to_delete, cleanDeleted, NULL); + bagDestroyBag(to_delete); } - - debugMonitorExit(classTrackLock); } diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c b/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c index fdc7a0bc613..a5b94fdd796 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c @@ -232,6 +232,7 @@ fillInvokeRequest(JNIEnv *env, InvokeRequest *request, /* * Squirrel away the method signature */ + JDI_ASSERT_MSG(request->methodSignature == NULL, "Request methodSignature not null"); error = methodSignature(method, NULL, &request->methodSignature, NULL); if (error != JVMTI_ERROR_NONE) { return error; @@ -773,6 +774,10 @@ invoker_completeInvokeRequest(jthread thread) */ deleteGlobalArgumentRefs(env, request); + JDI_ASSERT_MSG(request->methodSignature != NULL, "methodSignature is NULL"); + jvmtiDeallocate(request->methodSignature); + request->methodSignature = NULL; + /* From now on, do not access the request structure anymore * for this request id, because once we give up the invokerLock it may * be immediately reused by a new invoke request. diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java index dc877b52efd..0f35c33a3f0 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java @@ -154,6 +154,8 @@ public static EventStream openRepository() throws IOException { *

    * By default, the stream starts with the next event flushed by Flight * Recorder. + *

    + * Only trusted disk repositories should be opened. * * @param directory location of the disk repository, not {@code null} * @@ -184,6 +186,8 @@ public static EventStream openRepository(Path directory) throws IOException { * Creates an event stream from a file. *

    * By default, the stream starts with the first event in the file. + *

    + * Only recording files from trusted sources should be opened. * * @param file location of the file, not {@code null} * diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java index 5ebe57bcce4..8650d3aaaf9 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -70,6 +70,8 @@ public final class RecordingFile implements Closeable { /** * Creates a recording file. + *

    + * Only recording files from trusted sources should be used. * * @param file the path of the file to open, not {@code null} * @throws IOException if it's not a valid recording file, or an I/O error @@ -209,6 +211,8 @@ public void close() throws IOException { *

    * This method is intended for simple cases where it's convenient to read all * events in a single operation. It isn't intended for reading large files. + *

    + * Only recording files from trusted sources should be used. * * @param path the path to the file, not {@code null} * diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataReader.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataReader.java index ca5c5c31ecd..b835ceb55cc 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataReader.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataReader.java @@ -66,6 +66,7 @@ final class MetadataReader { public MetadataReader(RecordingInput input) throws IOException { this.input = input; int size = input.readInt(); + input.require(size, "Metadata string pool size %d exceeds available data" ); this.pool = new ArrayList<>(size); StringParser p = new StringParser(null, false); for (int i = 0; i < size; i++) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java index 4027f447cf4..d99809aa2ee 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -114,7 +114,7 @@ public void refresh() throws IOException { byte fileState1; input.positionPhysical(absoluteChunkStart + FILE_STATE_POSITION); while ((fileState1 = input.readPhysicalByte()) == UPDATING_CHUNK_HEADER) { - Utils.takeNap(1); + input.pollWait(); input.positionPhysical(absoluteChunkStart + FILE_STATE_POSITION); } input.positionPhysical(absoluteChunkStart + CHUNK_SIZE_POSITION); @@ -184,7 +184,7 @@ public void awaitFinished() throws IOException { finished = true; return; } - Utils.takeNap(1); + input.pollWait(); } } finally { input.position(pos); 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 28db3b68f3f..0bad40f7e52 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 @@ -148,6 +148,7 @@ protected void processRecursionSafe() throws IOException { } currentChunkStartNanos = repositoryFiles.getTimestamp(path); try (RecordingInput input = new RecordingInput(path.toFile(), fileAccess)) { + input.setStreamed(); currentParser = new ChunkParser(input, disp.parserConfiguration); long segmentStart = currentParser.getStartNanos() + currentParser.getChunkDuration(); long filterStart = validStartTime ? disp.startNanos : segmentStart; 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 c4595ab639d..faeb7d89023 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 @@ -50,6 +50,7 @@ public EventFileStream(@SuppressWarnings("removal") AccessControlContext acc, Pa super(acc, null, Collections.emptyList()); Objects.requireNonNull(path); this.input = new RecordingInput(path.toFile(), FileAccess.UNPRIVILEGED); + this.input.setStreamed(); } @Override diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/OngoingStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/OngoingStream.java index 91d725c1e48..1816d00f345 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/OngoingStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/OngoingStream.java @@ -214,6 +214,7 @@ private boolean ensureInput() throws IOException { return false; } input = new RecordingInput(path.toFile(), SecuritySupport.PRIVILEGED); + input.setStreamed(); header = new ChunkHeader(input); } return true; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ParserFactory.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ParserFactory.java index c04b80bd37a..b44416d601a 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ParserFactory.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ParserFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -296,6 +296,7 @@ public ArrayParser(Parser elementParser) { @Override public Object parse(RecordingInput input) throws IOException { final int size = input.readInt(); + input.require(size, "Array size %d exceeds available data" ); final Object[] array = new Object[size]; for (int i = 0; i < size; i++) { array[i] = elementParser.parse(input); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInput.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInput.java index b07e9c82631..35abaaba1b1 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInput.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInput.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -31,6 +31,7 @@ import java.io.IOException; import java.io.RandomAccessFile; import java.nio.file.Path; +import jdk.jfr.internal.Utils; public final class RecordingInput implements DataInput, AutoCloseable { @@ -66,6 +67,7 @@ public void reset() { } private final int blockSize; private final FileAccess fileAccess; + private long pollCount = 1000; private RandomAccessFile file; private String filename; private Block currentBlock = new Block(); @@ -418,6 +420,15 @@ public String getFilename() { return filename; } + // Purpose of this method is to prevent OOM by sanity check + // the minimum required number of bytes against what is available in + // segment/chunk/file + public void require(int minimumBytes, String errorMessage) throws IOException { + if (position + minimumBytes > size) { + throw new IOException(String.format(errorMessage, minimumBytes)); + } + } + // Purpose of this method is to reuse block cache from a // previous RecordingInput public void setFile(Path path) throws IOException { @@ -430,4 +441,18 @@ public void setFile(Path path) throws IOException { initialize(path.toFile()); } + // Marks that it is OK to poll indefinitely for file update + // By default, only 1000 polls are allowed + public void setStreamed() { + this.pollCount = Long.MAX_VALUE; + } + + // Wait for file to be updated + public void pollWait() throws IOException { + pollCount--; + if (pollCount < 0) { + throw new IOException("Recording file is stuck in locked stream state."); + } + Utils.takeNap(1); + } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/StringParser.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/StringParser.java index 2766da889a2..79227544a41 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/StringParser.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/StringParser.java @@ -69,6 +69,7 @@ private static final class CharsetParser extends Parser { @Override public Object parse(RecordingInput input) throws IOException { int size = input.readInt(); + input.require(size, "String size %d exceeds available data"); ensureSize(size); if (lastSize == size) { boolean equalsLastString = true; @@ -114,6 +115,7 @@ private static final class CharArrayParser extends Parser { @Override public Object parse(RecordingInput input) throws IOException { int size = input.readInt(); + input.require(size, "String size %d exceeds available data"); ensureSize(size); if (lastSize == size) { boolean equalsLastString = true; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/JSONWriter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/JSONWriter.java index cbf508306d5..f395f702e7c 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/JSONWriter.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/JSONWriter.java @@ -185,7 +185,7 @@ private void printNull() { private void printDataStructureName(String text) { printIndent(); print("\""); - print(text); + printEscaped(text); print("\": "); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/XMLWriter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/XMLWriter.java index 2db1688239b..056642eb4aa 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/XMLWriter.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/XMLWriter.java @@ -83,7 +83,11 @@ private void printEvent(RecordedEvent event) { } private void printAttribute(String name, String value) { - print(" ", name, "=\"", value, "\""); + print(" "); + print(name); // Only known strings + print("=\""); + printEscaped(value); + print("\""); } public void printObject(RecordedObject struct) { diff --git a/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/DnsUrl.java b/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/DnsUrl.java index f77e3d4f57b..5d5703c85eb 100644 --- a/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/DnsUrl.java +++ b/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/DnsUrl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -27,7 +27,11 @@ import java.net.MalformedURLException; -import java.util.Hashtable; +import java.net.URI; +import java.net.URISyntaxException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Locale; import java.util.StringTokenizer; import com.sun.jndi.toolkit.url.Uri; @@ -56,6 +60,24 @@ public class DnsUrl extends Uri { + private static final String PARSE_MODE_PROP = "com.sun.jndi.dnsURLParsing"; + private static final ParseMode DEFAULT_PARSE_MODE = ParseMode.COMPAT; + + public static final ParseMode PARSE_MODE; + static { + PrivilegedAction action = () -> + System.getProperty(PARSE_MODE_PROP, DEFAULT_PARSE_MODE.toString()); + ParseMode parseMode = DEFAULT_PARSE_MODE; + try { + @SuppressWarnings("removal") + String mode = AccessController.doPrivileged(action); + parseMode = ParseMode.valueOf(mode.toUpperCase(Locale.ROOT)); + } catch (Throwable t) { + parseMode = DEFAULT_PARSE_MODE; + } finally { + PARSE_MODE = parseMode; + } + } private String domain; // domain name of the context @@ -71,19 +93,58 @@ public static DnsUrl[] fromList(String urlList) StringTokenizer st = new StringTokenizer(urlList, " "); while (st.hasMoreTokens()) { - urls[i++] = new DnsUrl(st.nextToken()); + try { + urls[i++] = new DnsUrl(validateURI(st.nextToken())); + } catch (URISyntaxException e) { + MalformedURLException mue = new MalformedURLException(e.getMessage()); + mue.initCause(e); + throw mue; + } } DnsUrl[] trimmed = new DnsUrl[i]; System.arraycopy(urls, 0, trimmed, 0, i); return trimmed; } + @Override + protected ParseMode parseMode() { + return PARSE_MODE; + } + + @Override + protected final boolean isSchemeOnly(String uri) { + return isDnsSchemeOnly(uri); + } + + @Override + protected boolean checkSchemeOnly(String uri, String scheme) { + return uri.equals(scheme + ":") || uri.equals(scheme + "://"); + } + + @Override + protected final MalformedURLException newInvalidURISchemeException(String uri) { + return new MalformedURLException( + uri + " is not a valid DNS pseudo-URL"); + } + + private static boolean isDnsSchemeOnly(String uri) { + return "dns:".equals(uri) || "dns://".equals(uri); + } + + private static String validateURI(String uri) throws URISyntaxException { + // no validation in legacy parsing mode + if (PARSE_MODE == ParseMode.LEGACY) return uri; + // special case of scheme-only URIs + if (isDnsSchemeOnly(uri)) return uri; + // use java.net.URI to validate the uri syntax + return new URI(uri).toString(); + } + public DnsUrl(String url) throws MalformedURLException { super(url); if (!scheme.equals("dns")) { - throw new MalformedURLException( - url + " is not a valid DNS pseudo-URL"); + throw newInvalidURISchemeException(url); } domain = path.startsWith("/") diff --git a/src/jdk.naming.rmi/share/classes/com/sun/jndi/url/rmi/rmiURLContext.java b/src/jdk.naming.rmi/share/classes/com/sun/jndi/url/rmi/rmiURLContext.java index 4c6c78110fb..cfa66ed9174 100644 --- a/src/jdk.naming.rmi/share/classes/com/sun/jndi/url/rmi/rmiURLContext.java +++ b/src/jdk.naming.rmi/share/classes/com/sun/jndi/url/rmi/rmiURLContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -25,12 +25,17 @@ package com.sun.jndi.url.rmi; +import java.net.URI; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.Hashtable; +import java.util.Locale; import javax.naming.*; import javax.naming.spi.ResolveResult; import com.sun.jndi.toolkit.url.GenericURLContext; import com.sun.jndi.rmi.registry.RegistryContext; +import com.sun.jndi.toolkit.url.Uri.ParseMode; /** @@ -47,75 +52,263 @@ */ public class rmiURLContext extends GenericURLContext { - public rmiURLContext(Hashtable env) { - super(env); - } + private static final String PARSE_MODE_PROP = "com.sun.jndi.rmiURLParsing"; + private static final ParseMode DEFAULT_PARSE_MODE = ParseMode.COMPAT; - /** - * Resolves the registry portion of "url" to the corresponding - * RMI registry, and returns the atomic object name as the - * remaining name. - */ - protected ResolveResult getRootURLContext(String url, Hashtable env) - throws NamingException - { - if (!url.startsWith("rmi:")) { - throw (new IllegalArgumentException( - "rmiURLContext: name is not an RMI URL: " + url)); + public static final ParseMode PARSE_MODE; + static { + PrivilegedAction action = () -> + System.getProperty(PARSE_MODE_PROP, DEFAULT_PARSE_MODE.toString()); + ParseMode parseMode = DEFAULT_PARSE_MODE; + try { + @SuppressWarnings("removal") + String mode = AccessController.doPrivileged(action); + parseMode = ParseMode.valueOf(mode.toUpperCase(Locale.ROOT)); + } catch (Throwable t) { + parseMode = DEFAULT_PARSE_MODE; + } finally { + PARSE_MODE = parseMode; } + } - // Parse the URL. + public rmiURLContext(Hashtable env) { + super(env); + } + public static class Parser { + final String url; + final ParseMode mode; String host = null; int port = -1; String objName = null; + public Parser(String url) { + this(url, PARSE_MODE); + } + public Parser(String url, ParseMode mode) { + this.url = url; + this.mode = mode; + } - int i = 4; // index into url, following the "rmi:" + public String url() {return url;} + public String host() {return host;} + public int port() {return port;} + public String objName() {return objName;} + public ParseMode mode() {return mode;} - if (url.startsWith("//", i)) { // parse "//host:port" - i += 2; // skip past "//" - int slash = url.indexOf('/', i); - if (slash < 0) { - slash = url.length(); - } - if (url.startsWith("[", i)) { // at IPv6 literal - int brac = url.indexOf(']', i + 1); - if (brac < 0 || brac > slash) { - throw new IllegalArgumentException( - "rmiURLContext: name is an Invalid URL: " + url); + public void parse() throws NamingException { + if (!url.startsWith("rmi:")) { + throw (new IllegalArgumentException( + "rmiURLContext: name is not an RMI URL: " + url)); + } + + switch (mode) { + case STRICT -> parseStrict(); + case COMPAT -> parseCompat(); + case LEGACY -> parseLegacy(); + } + + } + + private void parseStrict() throws NamingException { + assert url.startsWith("rmi:"); + + if (url.equals("rmi:") || url.equals("rmi://")) return; + + // index into url, following the "rmi:" + int i = 4; + + if (url.startsWith("//", i)) { + i += 2; + try { + URI uri = URI.create(url); + host = uri.getHost(); + port = uri.getPort(); + String auth = uri.getRawAuthority(); + String hostport = (host == null ? "" : host) + + (port == -1 ? "" : ":" + port); + if (!hostport.equals(auth)) { + boolean failed = true; + if (hostport.equals("") && auth.startsWith(":")) { + // supports missing host + try { + port = Integer.parseInt(auth.substring(1)); + failed = false; + } catch (NumberFormatException x) { + failed = true; + } + } + if (failed) { + throw newNamingException(new IllegalArgumentException("invalid authority: " + + auth)); + } + } + i += auth.length(); + } catch (IllegalArgumentException iae) { + throw newNamingException(iae); + } + } + int fmark = url.indexOf('#', i); + if (fmark > -1) { + if (!acceptsFragment()) { + throw newNamingException(new IllegalArgumentException("URI fragments not supported: " + url)); } - host = url.substring(i, brac + 1); // include brackets - i = brac + 1; // skip past "[...]" - } else { // at host name or IPv4 - int colon = url.indexOf(':', i); - int hostEnd = (colon < 0 || colon > slash) - ? slash - : colon; - if (i < hostEnd) { - host = url.substring(i, hostEnd); + } + + if ("".equals(host)) { + host = null; + } + if (url.startsWith("/", i)) { // skip "/" before object name + i++; + } + if (i < url.length()) { + objName = url.substring(i); + } + } + + private void parseCompat() throws NamingException { + assert url.startsWith("rmi:"); + + int i = 4; // index into url, following the "rmi:" + boolean hasAuthority = url.startsWith("//", i); + if (hasAuthority) i += 2; // skip past "//" + int slash = url.indexOf('/', i); + int qmark = url.indexOf('?', i); + int fmark = url.indexOf('#', i); + if (fmark > -1 && qmark > fmark) qmark = -1; + if (fmark > -1 && slash > fmark) slash = -1; + if (qmark > -1 && slash > qmark) slash = -1; + + // The end of the authority component is either the + // slash (slash will be -1 if it doesn't come before + // query or fragment), or the question mark (qmark will + // be -1 if it doesn't come before the fragment), or + // the fragment separator, or the end of the URI + // string if there is no path, no query, and no fragment. + int enda = slash > -1 ? slash + : (qmark > -1 ? qmark + : (fmark > -1 ? fmark + : url.length())); + if (fmark > -1) { + if (!acceptsFragment()) { + throw newNamingException(new IllegalArgumentException("URI fragments not supported: " + url)); } - i = hostEnd; // skip past host } - if ((i + 1 < slash)) { - if ( url.startsWith(":", i)) { // parse port - i++; // skip past ":" - port = Integer.parseInt(url.substring(i, slash)); + + if (hasAuthority && enda > i) { // parse "//host:port" + if (url.startsWith(":", i)) { + // LdapURL supports empty host. + i++; + host = ""; + if (enda > i) { + port = Integer.parseInt(url.substring(i, enda)); + } } else { - throw new IllegalArgumentException( - "rmiURLContext: name is an Invalid URL: " + url); + try { + URI uri = URI.create(url.substring(0, enda)); + host = uri.getHost(); + port = uri.getPort(); + String hostport = (host == null ? "" : host) + + (port == -1 ? "" : ":" + port); + if (!hostport.equals(uri.getRawAuthority())) { + throw newNamingException(new IllegalArgumentException("invalid authority: " + + uri.getRawAuthority())); + } + } catch (IllegalArgumentException iae) { + throw newNamingException(iae); + } } + i = enda; + } + if ("".equals(host)) { + host = null; + } + if (url.startsWith("/", i)) { // skip "/" before object name + i++; } - i = slash; + if (i < url.length()) { + objName = url.substring(i); + } + } - if ("".equals(host)) { - host = null; + + // The legacy parsing used to only throw IllegalArgumentException + // and continues to do so + private void parseLegacy() { + assert url.startsWith("rmi:"); + + // Parse the URL. + int i = 4; // index into url, following the "rmi:" + + if (url.startsWith("//", i)) { // parse "//host:port" + i += 2; // skip past "//" + int slash = url.indexOf('/', i); + if (slash < 0) { + slash = url.length(); + } + if (url.startsWith("[", i)) { // at IPv6 literal + int brac = url.indexOf(']', i + 1); + if (brac < 0 || brac > slash) { + throw new IllegalArgumentException( + "rmiURLContext: name is an Invalid URL: " + url); + } + host = url.substring(i, brac + 1); // include brackets + i = brac + 1; // skip past "[...]" + } else { // at host name or IPv4 + int colon = url.indexOf(':', i); + int hostEnd = (colon < 0 || colon > slash) + ? slash + : colon; + if (i < hostEnd) { + host = url.substring(i, hostEnd); + } + i = hostEnd; // skip past host + } + if ((i + 1 < slash)) { + if ( url.startsWith(":", i)) { // parse port + i++; // skip past ":" + port = Integer.parseInt(url.substring(i, slash)); + } else { + throw new IllegalArgumentException( + "rmiURLContext: name is an Invalid URL: " + url); + } + } + i = slash; + } + if ("".equals(host)) { + host = null; + } + if (url.startsWith("/", i)) { // skip "/" before object name + i++; + } + if (i < url.length()) { + objName = url.substring(i); + } } - if (url.startsWith("/", i)) { // skip "/" before object name - i++; + + NamingException newNamingException(Throwable cause) { + NamingException ne = new InvalidNameException(cause.getMessage()); + ne.initCause(cause); + return ne; } - if (i < url.length()) { - objName = url.substring(i); + + protected boolean acceptsFragment() { + return true; } + } + + /** + * Resolves the registry portion of "url" to the corresponding + * RMI registry, and returns the atomic object name as the + * remaining name. + */ + protected ResolveResult getRootURLContext(String url, Hashtable env) + throws NamingException + { + Parser parser = new Parser(url); + parser.parse(); + String host = parser.host; + int port = parser.port; + String objName = parser.objName; // Represent object name as empty or single-component composite name. CompositeName remaining = new CompositeName(); diff --git a/src/jdk.random/share/classes/jdk/random/L32X64MixRandom.java b/src/jdk.random/share/classes/jdk/random/L32X64MixRandom.java index 1cb222e9cca..1b64a4b28cd 100644 --- a/src/jdk.random/share/classes/jdk/random/L32X64MixRandom.java +++ b/src/jdk.random/share/classes/jdk/random/L32X64MixRandom.java @@ -155,6 +155,8 @@ public L32X64MixRandom(int a, int s, int x0, int x1) { // Force a to be odd. this.a = a | 1; this.s = s; + this.x0 = x0; + this.x1 = x1; // If x0 and x1 are both zero, we must choose nonzero values. if ((x0 | x1) == 0) { int v = s; diff --git a/test/hotspot/gtest/logging/test_logConfiguration.cpp b/test/hotspot/gtest/logging/test_logConfiguration.cpp index d0e8441afb2..38b66488115 100644 --- a/test/hotspot/gtest/logging/test_logConfiguration.cpp +++ b/test/hotspot/gtest/logging/test_logConfiguration.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -359,6 +359,29 @@ TEST_VM_F(LogConfigurationTest, parse_command_line_arguments) { ret = jio_snprintf(buf, sizeof(buf), ":%s", TestLogFileName); ASSERT_NE(-1, ret); EXPECT_TRUE(LogConfiguration::parse_command_line_arguments(buf)); + +#ifdef _WINDOWS + // We need to test the special-case parsing for drive letters in + // log file paths e.g. c:\log.txt and c:/log.txt. Our temp directory + // based TestLogFileName should already be the \ format (we print it + // below to visually verify) so we only need to convert to /. + printf("Checked: %s\n", buf); + // First disable logging so the current log file will be closed and we + // can delete it, so that UL won't try to perform log file rotation. + // The rotated file would not be auto-deleted. + set_log_config(TestLogFileName, "all=off"); + delete_file(TestLogFileName); + + // now convert \ to / + char* current_pos = strchr(buf,'\\'); + while (current_pos != nullptr) { + *current_pos = '/'; + current_pos = strchr(current_pos + 1, '\\'); + } + printf("Checking: %s\n", buf); + EXPECT_TRUE(LogConfiguration::parse_command_line_arguments(buf)); +#endif + } // Test split up log configuration arguments diff --git a/test/hotspot/gtest/runtime/test_os.cpp b/test/hotspot/gtest/runtime/test_os.cpp index 79bfcf06550..0c3359798f2 100644 --- a/test/hotspot/gtest/runtime/test_os.cpp +++ b/test/hotspot/gtest/runtime/test_os.cpp @@ -26,6 +26,7 @@ #include "memory/resourceArea.hpp" #include "runtime/os.hpp" #include "runtime/thread.hpp" +#include "services/memTracker.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" #include "utilities/ostream.hpp" @@ -417,9 +418,33 @@ struct NUMASwitcher { #else TEST_VM(os, release_multi_mappings) { #endif + + // With NMT enabled, this will trigger JDK-8263464. For now disable the test if NMT=on. + if (MemTracker::tracking_level() > NMT_off) { + return; + } + // Test that we can release an area created with multiple reservation calls - const size_t stripe_len = 4 * M; - const int num_stripes = 4; + // What we do: + // A) we reserve 6 small segments (stripes) adjacent to each other. We commit + // them with alternating permissions to prevent the kernel from folding them into + // a single segment. + // -stripe-stripe-stripe-stripe-stripe-stripe- + // B) we release the middle four stripes with a single os::release_memory call. This + // tests that os::release_memory indeed works across multiple segments created with + // multiple os::reserve calls. + // -stripe-___________________________-stripe- + // C) Into the now vacated address range between the first and the last stripe, we + // re-reserve a new memory range. We expect this to work as a proof that the address + // range was really released by the single release call (B). + // + // Note that this is inherently racy. Between (B) and (C), some other thread may have + // reserved something into the hole in the meantime. Therefore we keep that range small and + // entrenched between the first and last stripe, which reduces the chance of some concurrent + // thread grabbing that memory. + + const size_t stripe_len = os::vm_allocation_granularity(); + const int num_stripes = 6; const size_t total_range_len = stripe_len * num_stripes; // reserve address space... @@ -427,22 +452,27 @@ struct NUMASwitcher { ASSERT_NE(p, (address)NULL); PRINT_MAPPINGS("A"); - // .. release it... + // .. release the middle stripes... + address p_middle_stripes = p + stripe_len; + const size_t middle_stripe_len = (num_stripes - 2) * stripe_len; { - // On Windows, use UseNUMAInterleaving=1 which makes - // os::release_memory accept multi-map-ranges. - // Otherwise we would assert (see below for death test). + // On Windows, temporarily switch on UseNUMAInterleaving to allow release_memory to release + // multiple mappings in one go (otherwise we assert, which we test too, see death test below). WINDOWS_ONLY(NUMASwitcher b(true);) - ASSERT_TRUE(os::release_memory((char*)p, total_range_len)); + ASSERT_TRUE(os::release_memory((char*)p_middle_stripes, middle_stripe_len)); } PRINT_MAPPINGS("B"); - // re-reserve it. This should work unless release failed. - address p2 = (address)os::attempt_reserve_memory_at((char*)p, total_range_len); - ASSERT_EQ(p2, p); + // ...re-reserve the middle stripes. This should work unless release silently failed. + address p2 = (address)os::attempt_reserve_memory_at((char*)p_middle_stripes, middle_stripe_len); + ASSERT_EQ(p2, p_middle_stripes); PRINT_MAPPINGS("C"); - ASSERT_TRUE(os::release_memory((char*)p, total_range_len)); + // Clean up. Release all mappings. + { + WINDOWS_ONLY(NUMASwitcher b(true);) // allow release_memory to release multiple regions + ASSERT_TRUE(os::release_memory((char*)p, total_range_len)); + } } #endif // !AIX diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 32b371dcc4c..90e17533166 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -154,7 +154,6 @@ vmTestbase/nsk/jvmti/AttachOnDemand/attach045/TestDescription.java 8202971 gener vmTestbase/nsk/jvmti/scenarios/jni_interception/JI05/ji05t001/TestDescription.java 8219652 aix-ppc64 vmTestbase/nsk/jvmti/scenarios/jni_interception/JI06/ji06t001/TestDescription.java 8219652 aix-ppc64 vmTestbase/nsk/jvmti/SetJNIFunctionTable/setjniftab001/TestDescription.java 8219652 aix-ppc64 -vmTestbase/nsk/jvmti/SuspendThread/suspendthrd003/TestDescription.java 8264605 generic-all vmTestbase/nsk/jvmti/PopFrame/popframe011/TestDescription.java 8266593 generic-all vmTestbase/gc/lock/jni/jnilock002/TestDescription.java 8192647 generic-all diff --git a/test/hotspot/jtreg/TEST.ROOT b/test/hotspot/jtreg/TEST.ROOT index cb10a02899f..80b7f894d91 100644 --- a/test/hotspot/jtreg/TEST.ROOT +++ b/test/hotspot/jtreg/TEST.ROOT @@ -63,6 +63,7 @@ requires.properties= \ vm.debug \ vm.hasSA \ vm.hasJFR \ + vm.hasDTrace \ vm.rtm.cpu \ vm.rtm.compiler \ vm.cds \ diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index d5345551c1c..60961b0a942 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -1,5 +1,5 @@ # -# Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 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 @@ -94,6 +94,9 @@ hotspot_vector_2 = \ compiler/vectorapi/VectorRebracket128Test.java \ -compiler/intrinsics/string/TestStringLatin1IndexOfChar.java +hotspot_compiler_arraycopy = \ + compiler/arraycopy/stress + tier1_common = \ sanity/BasicVMTest.java \ gtest/GTestWrapper.java \ @@ -114,7 +117,9 @@ hotspot_not_fast_compiler = \ hotspot_slow_compiler = \ compiler/codegen/aes \ compiler/codecache/stress \ - compiler/gcbarriers/PreserveFPRegistersTest.java + compiler/gcbarriers/PreserveFPRegistersTest.java \ + resourcehogs/compiler \ + :hotspot_compiler_arraycopy tier1_compiler_1 = \ compiler/arraycopy/ \ @@ -131,6 +136,7 @@ tier1_compiler_1 = \ -compiler/c2/Test6792161.java \ -compiler/c2/Test6603011.java \ -compiler/c2/Test6912517.java \ + -:hotspot_slow_compiler tier1_compiler_2 = \ compiler/classUnloading/ \ diff --git a/test/hotspot/jtreg/compiler/allocation/TestAllocArrayAfterAllocNoUse.java b/test/hotspot/jtreg/compiler/allocation/TestAllocArrayAfterAllocNoUse.java new file mode 100644 index 00000000000..e2bc9bfdd16 --- /dev/null +++ b/test/hotspot/jtreg/compiler/allocation/TestAllocArrayAfterAllocNoUse.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8279125 + * @summary fatal error: no reachable node should have no use + * @requires vm.flavor == "server" + * + * @run main/othervm -XX:-BackgroundCompilation -XX:-DoEscapeAnalysis TestAllocArrayAfterAllocNoUse + * + */ + +public class TestAllocArrayAfterAllocNoUse { + private static Object field; + + public static void main(String[] args) { + for (int i = 0; i < 20_000; i++) { + test(); + } + } + + private static void test() { + try { + final TestAllocArrayAfterAllocNoUse o = new TestAllocArrayAfterAllocNoUse(); + } catch (Exception e) { + final int[] array = new int[100]; + field = array; + } + + } +} diff --git a/test/hotspot/jtreg/compiler/allocation/TestCCPAllocateArray.java b/test/hotspot/jtreg/compiler/allocation/TestCCPAllocateArray.java new file mode 100644 index 00000000000..9e312a79530 --- /dev/null +++ b/test/hotspot/jtreg/compiler/allocation/TestCCPAllocateArray.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8279062 + * @summary C2: assert(t->meet(t0) == t) failed: Not monotonic after JDK-8278413 + * + * @run main/othervm -XX:-BackgroundCompilation TestCCPAllocateArray + * + */ + +public class TestCCPAllocateArray { + public static void main(String[] args) { + for (int i = 0; i < 20_000; i++) { + try { + test(); + } catch (OutOfMemoryError e) { + } + length(42); + } + } + + private static int[] test() { + int i = 2; + for (; i < 4; i *= 2); + return new int[length(i)]; + } + + private static int length(int i) { + return i == 4 ? Integer.MAX_VALUE : 0; + } +} diff --git a/test/hotspot/jtreg/compiler/allocation/TestFailedAllocationBadGraph.java b/test/hotspot/jtreg/compiler/allocation/TestFailedAllocationBadGraph.java new file mode 100644 index 00000000000..9d5c2a193b7 --- /dev/null +++ b/test/hotspot/jtreg/compiler/allocation/TestFailedAllocationBadGraph.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2022, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8279219 + * @summary C2 crash when allocating array of size too large + * @requires vm.compiler2.enabled + * @library /test/lib / + * @build sun.hotspot.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -ea -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-BackgroundCompilation TestFailedAllocationBadGraph + */ + +import sun.hotspot.WhiteBox; +import java.lang.reflect.Method; +import compiler.whitebox.CompilerWhiteBoxTest; + +public class TestFailedAllocationBadGraph { + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + + private static long[] array; + private static int field; + private static volatile int barrier; + + public static void main(String[] args) throws Exception { + run("test1"); + run("test2"); + } + + private static void run(String method) throws Exception { + Method m = TestFailedAllocationBadGraph.class.getDeclaredMethod(method); + WHITE_BOX.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION); + if (!WHITE_BOX.isMethodCompiled(m) || WHITE_BOX.getMethodCompilationLevel(m) != CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION) { + throw new RuntimeException("should still be compiled"); + } + } + + private static int test1() { + int length = Integer.MAX_VALUE; + try { + array = new long[length]; + } catch (OutOfMemoryError outOfMemoryError) { + barrier = 0x42; + length = field; + } + return length; + } + + private static int test2() { + int length = -1; + try { + array = new long[length]; + } catch (OutOfMemoryError outOfMemoryError) { + barrier = 0x42; + length = field; + } + return length; + } +} diff --git a/test/hotspot/jtreg/compiler/arraycopy/TestArrayCopyAsLoadsStores.java b/test/hotspot/jtreg/compiler/arraycopy/TestArrayCopyAsLoadsStores.java index 4c4c38848d8..103e99fefef 100644 --- a/test/hotspot/jtreg/compiler/arraycopy/TestArrayCopyAsLoadsStores.java +++ b/test/hotspot/jtreg/compiler/arraycopy/TestArrayCopyAsLoadsStores.java @@ -38,6 +38,19 @@ * compiler.arraycopy.TestArrayCopyAsLoadsStores */ +/* + * @test + * @bug 8282590 + * @library / + * + * @run main/othervm -ea -XX:-BackgroundCompilation -XX:-UseOnStackReplacement + * -XX:CompileCommand=dontinline,compiler.arraycopy.TestArrayCopyAsLoadsStores::m* + * -XX:TypeProfileLevel=200 + * -XX:+IgnoreUnrecognizedVMOptions -XX:+StressArrayCopyMacroNode + * -XX:-TieredCompilation -XX:+StressReflectiveCode -XX:-ReduceInitialCardMarks + * compiler.arraycopy.TestArrayCopyAsLoadsStores + */ + package compiler.arraycopy; import java.util.Arrays; diff --git a/test/hotspot/jtreg/compiler/arraycopy/TestCloneAccess.java b/test/hotspot/jtreg/compiler/arraycopy/TestCloneAccess.java index efe22f9228b..a0da0741cad 100644 --- a/test/hotspot/jtreg/compiler/arraycopy/TestCloneAccess.java +++ b/test/hotspot/jtreg/compiler/arraycopy/TestCloneAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -25,6 +25,8 @@ * @test * @bug 8248791 * @summary Test cloning with more than 8 (=ArrayCopyLoadStoreMaxElem) where loads are wrongly replaced by zero. + * @requires vm.compiler2.enabled | vm.graal.enabled + * * @run main/othervm -XX:-ReduceBulkZeroing * -XX:CompileCommand=dontinline,compiler.arraycopy.TestCloneAccess::* * compiler.arraycopy.TestCloneAccess diff --git a/test/hotspot/jtreg/compiler/arraycopy/TestCloneAccessStressGCM.java b/test/hotspot/jtreg/compiler/arraycopy/TestCloneAccessStressGCM.java index 0b259681ac4..5c910a4d293 100644 --- a/test/hotspot/jtreg/compiler/arraycopy/TestCloneAccessStressGCM.java +++ b/test/hotspot/jtreg/compiler/arraycopy/TestCloneAccessStressGCM.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -27,6 +27,7 @@ * @bug 8235332 8248226 * @summary Test cloning with more than 8 (=ArrayCopyLoadStoreMaxElem) fields with StressGCM * @library / + * @requires vm.compiler2.enabled | vm.graal.enabled * * @run main/othervm -Xbatch * -XX:CompileCommand=dontinline,compiler.arraycopy.TestCloneAccessStressGCM::test diff --git a/test/hotspot/jtreg/compiler/arraycopy/stress/AbstractStressArrayCopy.java b/test/hotspot/jtreg/compiler/arraycopy/stress/AbstractStressArrayCopy.java new file mode 100644 index 00000000000..f74c9b9cfcc --- /dev/null +++ b/test/hotspot/jtreg/compiler/arraycopy/stress/AbstractStressArrayCopy.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2021, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.arraycopy.stress; + +import java.util.Random; + +public abstract class AbstractStressArrayCopy { + /** + * Max array size to test. This should be reasonably high to test + * massive vectorized copies, plus cases that cross the cache lines and + * (small) page boundaries. But it should also be reasonably low to + * keep the test costs down. + * + * A rough guideline: + * - AVX-512: 64-byte copies over 32 registers copies roughly 2K per step. + * - AArch64: small pages can be about 64K large + */ + static final int MAX_SIZE = 128*1024 + 1; + + /** + * Arrays up to this size would be tested exhaustively: with all combinations + * of source/destination starts and copy lengths. Exercise restraint when bumping + * this value, as the test costs are proportional to N^3 of this setting. + */ + static final int EXHAUSTIVE_SIZES = Integer.getInteger("exhaustiveSizes", 192); + + /* + * Larger arrays would fuzzed with this many attempts. + */ + static final int FUZZ_COUNT = Integer.getInteger("fuzzCount", 300); + + public static void throwSeedError(int len, int pos) { + throw new RuntimeException("Error after seed: " + + len + " elements, at pos " + pos); + } + + public static void throwContentsError(int l, int r, int len, int pos) { + throwError("in contents", l, r, len, pos); + } + + public static void throwHeadError(int l, int r, int len, int pos) { + throwError("in head", l, r, len, pos); + } + + public static void throwTailError(int l, int r, int len, int pos) { + throwError("in tail", l, r, len, pos); + } + + private static void throwError(String phase, int l, int r, int len, int pos) { + throw new RuntimeException("Error " + phase + ": " + + len + " elements, " + + "[" + l + ", " + (l+len) + ") -> " + + "[" + r + ", " + (r+len) + "), " + + "at pos " + pos); + } + + protected abstract void testWith(int size, int l, int r, int len); + + private void checkBounds(int size, int l, int r, int len) { + if (l >= size) throw new IllegalStateException("l is out of bounds"); + if (l + len > size) throw new IllegalStateException("l+len is out of bounds"); + if (r >= size) throw new IllegalStateException("r is out of bounds"); + if (r + len > size) throw new IllegalStateException("r+len is out of bounds: " + l + " " + r + " " + len + " " + size); + } + + private void checkDisjoint(int size, int l, int r, int len) { + if (l == r) throw new IllegalStateException("Not disjoint: l == r"); + if (l < r && l + len > r) throw new IllegalStateException("Not disjoint"); + if (l > r && r + len > l) throw new IllegalStateException("Not disjoint"); + } + + private void checkConjoint(int size, int l, int r, int len) { + if (l == r) return; // Definitely conjoint, even with zero len + if (l < r && l + len < r) throw new IllegalStateException("Not conjoint"); + if (l > r && r + len < l) throw new IllegalStateException("Not conjoint"); + } + + public void exhaustiveWith(int size) { + for (int l = 0; l < size; l++) { + for (int r = 0; r < size; r++) { + int maxLen = Math.min(size - l, size - r); + for (int len = 0; len <= maxLen; len++) { + checkBounds(size, l, r, len); + testWith(size, l, r, len); + } + } + } + } + + public void fuzzWith(Random rand, int size) { + // Some basic checks first + testWith(size, 0, 1, 1); + testWith(size, 0, 1, size-1); + + // Test disjoint: + for (int c = 0; c < FUZZ_COUNT; c++) { + int l = rand.nextInt(size / 2); + int len = rand.nextInt((size - l) / 2); + int r = (l + len + 1) + rand.nextInt(size - 2*len - l - 1); + + checkBounds(size, l, r, len); + checkDisjoint(size, l, r, len); + + testWith(size, l, r, len); + testWith(size, r, l, len); + } + + // Test conjoint: + for (int c = 0; c < FUZZ_COUNT; c++) { + int l = rand.nextInt(size); + int len = rand.nextInt(size - l); + int r = Math.min(l + (len > 0 ? rand.nextInt(len) : 0), size - len); + + checkBounds(size, l, r, len); + checkConjoint(size, l, r, len); + + testWith(size, l, r, len); + testWith(size, r, l, len); + } + } + + public void run(Random rand) { + // Exhaustive on all small arrays + for (int size = 1; size <= EXHAUSTIVE_SIZES; size++) { + exhaustiveWith(size); + } + + // Fuzz powers of ten + for (int size = 10; size < MAX_SIZE; size *= 10) { + if (size <= EXHAUSTIVE_SIZES) continue; + fuzzWith(rand, size - 1); + fuzzWith(rand, size); + fuzzWith(rand, size + 1); + } + + // Fuzz powers of two + for (int size = 2; size < MAX_SIZE; size *= 2) { + if (size <= EXHAUSTIVE_SIZES) continue; + fuzzWith(rand, size - 1); + fuzzWith(rand, size); + fuzzWith(rand, size + 1); + } + } + +} diff --git a/test/hotspot/jtreg/compiler/arraycopy/stress/StressBooleanArrayCopy.java b/test/hotspot/jtreg/compiler/arraycopy/stress/StressBooleanArrayCopy.java new file mode 100644 index 00000000000..bd424c393d8 --- /dev/null +++ b/test/hotspot/jtreg/compiler/arraycopy/stress/StressBooleanArrayCopy.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.arraycopy.stress; + +import java.util.Arrays; +import java.util.Random; +import jdk.test.lib.Utils; + +public class StressBooleanArrayCopy extends AbstractStressArrayCopy { + + private static final boolean[] orig = new boolean[MAX_SIZE]; + private static final boolean[] test = new boolean[MAX_SIZE]; + + protected void testWith(int size, int l, int r, int len) { + // Seed the test from the original + System.arraycopy(orig, 0, test, 0, size); + + // Check the seed is correct + { + int m = Arrays.mismatch(test, 0, size, + orig, 0, size); + if (m != -1) { + throwSeedError(size, m); + } + } + + // Perform the tested copy + System.arraycopy(test, l, test, r, len); + + // Check the copy has proper contents + { + int m = Arrays.mismatch(test, r, r+len, + orig, l, l+len); + if (m != -1) { + throwContentsError(l, r, len, r+m); + } + } + + // Check anything else was not affected: head and tail + { + int m = Arrays.mismatch(test, 0, r, + orig, 0, r); + if (m != -1) { + throwHeadError(l, r, len, m); + } + } + { + int m = Arrays.mismatch(test, r + len, size, + orig, r + len, size); + if (m != -1) { + throwTailError(l, r, len, m); + } + } + } + + public static void main(String... args) { + Random rand = Utils.getRandomInstance(); + for (int c = 0; c < orig.length; c++) { + orig[c] = rand.nextBoolean(); + } + new StressBooleanArrayCopy().run(rand); + } + +} diff --git a/test/hotspot/jtreg/compiler/arraycopy/stress/StressByteArrayCopy.java b/test/hotspot/jtreg/compiler/arraycopy/stress/StressByteArrayCopy.java new file mode 100644 index 00000000000..86d957bf2cb --- /dev/null +++ b/test/hotspot/jtreg/compiler/arraycopy/stress/StressByteArrayCopy.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.arraycopy.stress; + +import java.util.Arrays; +import java.util.Random; +import jdk.test.lib.Utils; + +public class StressByteArrayCopy extends AbstractStressArrayCopy { + + private static final byte[] orig = new byte[MAX_SIZE]; + private static final byte[] test = new byte[MAX_SIZE]; + + protected void testWith(int size, int l, int r, int len) { + // Seed the test from the original + System.arraycopy(orig, 0, test, 0, size); + + // Check the seed is correct + { + int m = Arrays.mismatch(test, 0, size, + orig, 0, size); + if (m != -1) { + throwSeedError(size, m); + } + } + + // Perform the tested copy + System.arraycopy(test, l, test, r, len); + + // Check the copy has proper contents + { + int m = Arrays.mismatch(test, r, r+len, + orig, l, l+len); + if (m != -1) { + throwContentsError(l, r, len, r+m); + } + } + + // Check anything else was not affected: head and tail + { + int m = Arrays.mismatch(test, 0, r, + orig, 0, r); + if (m != -1) { + throwHeadError(l, r, len, m); + } + } + { + int m = Arrays.mismatch(test, r + len, size, + orig, r + len, size); + if (m != -1) { + throwTailError(l, r, len, m); + } + } + } + + public static void main(String... args) { + Random rand = Utils.getRandomInstance(); + for (int c = 0; c < orig.length; c++) { + orig[c] = (byte)rand.nextInt(); + } + new StressByteArrayCopy().run(rand); + } + +} diff --git a/test/hotspot/jtreg/compiler/arraycopy/stress/StressCharArrayCopy.java b/test/hotspot/jtreg/compiler/arraycopy/stress/StressCharArrayCopy.java new file mode 100644 index 00000000000..0770f4aa488 --- /dev/null +++ b/test/hotspot/jtreg/compiler/arraycopy/stress/StressCharArrayCopy.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.arraycopy.stress; + +import java.util.Arrays; +import java.util.Random; +import jdk.test.lib.Utils; + +public class StressCharArrayCopy extends AbstractStressArrayCopy { + + private static final char[] orig = new char[MAX_SIZE]; + private static final char[] test = new char[MAX_SIZE]; + + protected void testWith(int size, int l, int r, int len) { + // Seed the test from the original + System.arraycopy(orig, 0, test, 0, size); + + // Check the seed is correct + { + int m = Arrays.mismatch(test, 0, size, + orig, 0, size); + if (m != -1) { + throwSeedError(size, m); + } + } + + // Perform the tested copy + System.arraycopy(test, l, test, r, len); + + // Check the copy has proper contents + { + int m = Arrays.mismatch(test, r, r+len, + orig, l, l+len); + if (m != -1) { + throwContentsError(l, r, len, r+m); + } + } + + // Check anything else was not affected: head and tail + { + int m = Arrays.mismatch(test, 0, r, + orig, 0, r); + if (m != -1) { + throwHeadError(l, r, len, m); + } + } + { + int m = Arrays.mismatch(test, r + len, size, + orig, r + len, size); + if (m != -1) { + throwTailError(l, r, len, m); + } + } + } + + public static void main(String... args) { + Random rand = Utils.getRandomInstance(); + for (int c = 0; c < orig.length; c++) { + orig[c] = (char)rand.nextInt(); + } + new StressCharArrayCopy().run(rand); + } + +} diff --git a/test/hotspot/jtreg/compiler/arraycopy/stress/StressDoubleArrayCopy.java b/test/hotspot/jtreg/compiler/arraycopy/stress/StressDoubleArrayCopy.java new file mode 100644 index 00000000000..c0cb54ca969 --- /dev/null +++ b/test/hotspot/jtreg/compiler/arraycopy/stress/StressDoubleArrayCopy.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.arraycopy.stress; + +import java.util.Arrays; +import java.util.Random; +import jdk.test.lib.Utils; + +public class StressDoubleArrayCopy extends AbstractStressArrayCopy { + + private static final double[] orig = new double[MAX_SIZE]; + private static final double[] test = new double[MAX_SIZE]; + + protected void testWith(int size, int l, int r, int len) { + // Seed the test from the original + System.arraycopy(orig, 0, test, 0, size); + + // Check the seed is correct + { + int m = Arrays.mismatch(test, 0, size, + orig, 0, size); + if (m != -1) { + throwSeedError(size, m); + } + } + + // Perform the tested copy + System.arraycopy(test, l, test, r, len); + + // Check the copy has proper contents + { + int m = Arrays.mismatch(test, r, r+len, + orig, l, l+len); + if (m != -1) { + throwContentsError(l, r, len, r+m); + } + } + + // Check anything else was not affected: head and tail + { + int m = Arrays.mismatch(test, 0, r, + orig, 0, r); + if (m != -1) { + throwHeadError(l, r, len, m); + } + } + { + int m = Arrays.mismatch(test, r + len, size, + orig, r + len, size); + if (m != -1) { + throwTailError(l, r, len, m); + } + } + } + + public static void main(String... args) { + Random rand = Utils.getRandomInstance(); + for (int c = 0; c < orig.length; c++) { + orig[c] = rand.nextDouble(); + } + new StressDoubleArrayCopy().run(rand); + } + +} diff --git a/test/hotspot/jtreg/compiler/arraycopy/stress/StressFloatArrayCopy.java b/test/hotspot/jtreg/compiler/arraycopy/stress/StressFloatArrayCopy.java new file mode 100644 index 00000000000..d5c10570f37 --- /dev/null +++ b/test/hotspot/jtreg/compiler/arraycopy/stress/StressFloatArrayCopy.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.arraycopy.stress; + +import java.util.Arrays; +import java.util.Random; +import jdk.test.lib.Utils; + +public class StressFloatArrayCopy extends AbstractStressArrayCopy { + + private static final float[] orig = new float[MAX_SIZE]; + private static final float[] test = new float[MAX_SIZE]; + + protected void testWith(int size, int l, int r, int len) { + // Seed the test from the original + System.arraycopy(orig, 0, test, 0, size); + + // Check the seed is correct + { + int m = Arrays.mismatch(test, 0, size, + orig, 0, size); + if (m != -1) { + throwSeedError(size, m); + } + } + + // Perform the tested copy + System.arraycopy(test, l, test, r, len); + + // Check the copy has proper contents + { + int m = Arrays.mismatch(test, r, r+len, + orig, l, l+len); + if (m != -1) { + throwContentsError(l, r, len, r+m); + } + } + + // Check anything else was not affected: head and tail + { + int m = Arrays.mismatch(test, 0, r, + orig, 0, r); + if (m != -1) { + throwHeadError(l, r, len, m); + } + } + { + int m = Arrays.mismatch(test, r + len, size, + orig, r + len, size); + if (m != -1) { + throwTailError(l, r, len, m); + } + } + } + + public static void main(String... args) { + Random rand = Utils.getRandomInstance(); + for (int c = 0; c < orig.length; c++) { + orig[c] = rand.nextFloat(); + } + new StressFloatArrayCopy().run(rand); + } + +} diff --git a/test/hotspot/jtreg/compiler/arraycopy/stress/StressIntArrayCopy.java b/test/hotspot/jtreg/compiler/arraycopy/stress/StressIntArrayCopy.java new file mode 100644 index 00000000000..3cad6ce8793 --- /dev/null +++ b/test/hotspot/jtreg/compiler/arraycopy/stress/StressIntArrayCopy.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.arraycopy.stress; + +import java.util.Arrays; +import java.util.Random; +import jdk.test.lib.Utils; + +public class StressIntArrayCopy extends AbstractStressArrayCopy { + + private static final int[] orig = new int[MAX_SIZE]; + private static final int[] test = new int[MAX_SIZE]; + + protected void testWith(int size, int l, int r, int len) { + // Seed the test from the original + System.arraycopy(orig, 0, test, 0, size); + + // Check the seed is correct + { + int m = Arrays.mismatch(test, 0, size, + orig, 0, size); + if (m != -1) { + throwSeedError(size, m); + } + } + + // Perform the tested copy + System.arraycopy(test, l, test, r, len); + + // Check the copy has proper contents + { + int m = Arrays.mismatch(test, r, r+len, + orig, l, l+len); + if (m != -1) { + throwContentsError(l, r, len, r+m); + } + } + + // Check anything else was not affected: head and tail + { + int m = Arrays.mismatch(test, 0, r, + orig, 0, r); + if (m != -1) { + throwHeadError(l, r, len, m); + } + } + { + int m = Arrays.mismatch(test, r + len, size, + orig, r + len, size); + if (m != -1) { + throwTailError(l, r, len, m); + } + } + } + + public static void main(String... args) { + Random rand = Utils.getRandomInstance(); + for (int c = 0; c < orig.length; c++) { + orig[c] = rand.nextInt(); + } + new StressIntArrayCopy().run(rand); + } + +} diff --git a/test/hotspot/jtreg/compiler/arraycopy/stress/StressLongArrayCopy.java b/test/hotspot/jtreg/compiler/arraycopy/stress/StressLongArrayCopy.java new file mode 100644 index 00000000000..988e8ad56f9 --- /dev/null +++ b/test/hotspot/jtreg/compiler/arraycopy/stress/StressLongArrayCopy.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.arraycopy.stress; + +import java.util.Arrays; +import java.util.Random; +import jdk.test.lib.Utils; + +public class StressLongArrayCopy extends AbstractStressArrayCopy { + + private static final long[] orig = new long[MAX_SIZE]; + private static final long[] test = new long[MAX_SIZE]; + + protected void testWith(int size, int l, int r, int len) { + // Seed the test from the original + System.arraycopy(orig, 0, test, 0, size); + + // Check the seed is correct + { + int m = Arrays.mismatch(test, 0, size, + orig, 0, size); + if (m != -1) { + throwSeedError(size, m); + } + } + + // Perform the tested copy + System.arraycopy(test, l, test, r, len); + + // Check the copy has proper contents + { + int m = Arrays.mismatch(test, r, r+len, + orig, l, l+len); + if (m != -1) { + throwContentsError(l, r, len, r+m); + } + } + + // Check anything else was not affected: head and tail + { + int m = Arrays.mismatch(test, 0, r, + orig, 0, r); + if (m != -1) { + throwHeadError(l, r, len, m); + } + } + { + int m = Arrays.mismatch(test, r + len, size, + orig, r + len, size); + if (m != -1) { + throwTailError(l, r, len, m); + } + } + } + + public static void main(String... args) { + Random rand = Utils.getRandomInstance(); + for (int c = 0; c < orig.length; c++) { + orig[c] = rand.nextLong(); + } + new StressLongArrayCopy().run(rand); + } + +} diff --git a/test/hotspot/jtreg/compiler/arraycopy/stress/StressObjectArrayCopy.java b/test/hotspot/jtreg/compiler/arraycopy/stress/StressObjectArrayCopy.java new file mode 100644 index 00000000000..562daa4a820 --- /dev/null +++ b/test/hotspot/jtreg/compiler/arraycopy/stress/StressObjectArrayCopy.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.arraycopy.stress; + +import java.util.Arrays; +import java.util.Random; +import jdk.test.lib.Utils; + +public class StressObjectArrayCopy extends AbstractStressArrayCopy { + + private static final Object[] orig = new Object[MAX_SIZE]; + private static final Object[] test = new Object[MAX_SIZE]; + + protected void testWith(int size, int l, int r, int len) { + // Seed the test from the original + System.arraycopy(orig, 0, test, 0, size); + + // Check the seed is correct + { + int m = Arrays.mismatch(test, 0, size, + orig, 0, size); + if (m != -1) { + throwSeedError(size, m); + } + } + + // Perform the tested copy + System.arraycopy(test, l, test, r, len); + + // Check the copy has proper contents + { + int m = Arrays.mismatch(test, r, r+len, + orig, l, l+len); + if (m != -1) { + throwContentsError(l, r, len, r+m); + } + } + + // Check anything else was not affected: head and tail + { + int m = Arrays.mismatch(test, 0, r, + orig, 0, r); + if (m != -1) { + throwHeadError(l, r, len, m); + } + } + { + int m = Arrays.mismatch(test, r + len, size, + orig, r + len, size); + if (m != -1) { + throwTailError(l, r, len, m); + } + } + } + + public static void main(String... args) { + Random rand = Utils.getRandomInstance(); + for (int c = 0; c < orig.length; c++) { + orig[c] = new Object(); + } + new StressObjectArrayCopy().run(rand); + } + +} diff --git a/test/hotspot/jtreg/compiler/arraycopy/stress/StressShortArrayCopy.java b/test/hotspot/jtreg/compiler/arraycopy/stress/StressShortArrayCopy.java new file mode 100644 index 00000000000..1594d54ca36 --- /dev/null +++ b/test/hotspot/jtreg/compiler/arraycopy/stress/StressShortArrayCopy.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.arraycopy.stress; + +import java.util.Arrays; +import java.util.Random; +import jdk.test.lib.Utils; + +public class StressShortArrayCopy extends AbstractStressArrayCopy { + + private static final short[] orig = new short[MAX_SIZE]; + private static final short[] test = new short[MAX_SIZE]; + + protected void testWith(int size, int l, int r, int len) { + // Seed the test from the original + System.arraycopy(orig, 0, test, 0, size); + + // Check the seed is correct + { + int m = Arrays.mismatch(test, 0, size, + orig, 0, size); + if (m != -1) { + throwSeedError(size, m); + } + } + + // Perform the tested copy + System.arraycopy(test, l, test, r, len); + + // Check the copy has proper contents + { + int m = Arrays.mismatch(test, r, r+len, + orig, l, l+len); + if (m != -1) { + throwContentsError(l, r, len, r+m); + } + } + + // Check anything else was not affected: head and tail + { + int m = Arrays.mismatch(test, 0, r, + orig, 0, r); + if (m != -1) { + throwHeadError(l, r, len, m); + } + } + { + int m = Arrays.mismatch(test, r + len, size, + orig, r + len, size); + if (m != -1) { + throwTailError(l, r, len, m); + } + } + } + + public static void main(String... args) { + Random rand = Utils.getRandomInstance(); + for (int c = 0; c < orig.length; c++) { + orig[c] = (short)rand.nextInt(); + } + new StressShortArrayCopy().run(rand); + } + +} diff --git a/test/hotspot/jtreg/compiler/arraycopy/stress/TestStressArrayCopy.java b/test/hotspot/jtreg/compiler/arraycopy/stress/TestStressArrayCopy.java new file mode 100644 index 00000000000..5153f85c9d7 --- /dev/null +++ b/test/hotspot/jtreg/compiler/arraycopy/stress/TestStressArrayCopy.java @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2021, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.arraycopy.stress; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import jdk.test.lib.Platform; +import jdk.test.lib.Utils; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +import jdk.test.whitebox.cpuinfo.CPUInfo; + +/** + * @test + * @key stress randomness + * @library /test/lib + * @build compiler.arraycopy.stress.AbstractStressArrayCopy + * compiler.arraycopy.stress.StressBooleanArrayCopy + * compiler.arraycopy.stress.StressByteArrayCopy + * compiler.arraycopy.stress.StressCharArrayCopy + * compiler.arraycopy.stress.StressShortArrayCopy + * compiler.arraycopy.stress.StressIntArrayCopy + * compiler.arraycopy.stress.StressFloatArrayCopy + * compiler.arraycopy.stress.StressLongArrayCopy + * compiler.arraycopy.stress.StressDoubleArrayCopy + * compiler.arraycopy.stress.StressObjectArrayCopy + * jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * + * @run main/othervm/timeout=7200 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * compiler.arraycopy.stress.TestStressArrayCopy + */ +public class TestStressArrayCopy { + + // These tests are remarkably memory bandwidth hungry. Running multiple + // configs in parallel makes sense only when running a single test in + // isolation, and only on machines with many memory channels. In common + // testing, or even running all arraycopy stress tests at once, overloading + // the system with many configs become counter-productive very quickly. + // + // Default to 1/4 of the CPUs, and allow users to override. + static final int MAX_PARALLELISM = Integer.getInteger("maxParallelism", + Math.max(1, Runtime.getRuntime().availableProcessors() / 4)); + + private static List mix(List o, String... mix) { + List n = new ArrayList<>(o); + for (String m : mix) { + n.add(m); + } + return n; + } + + private static List> product(List> list, String... mix) { + List> newList = new ArrayList<>(); + for (List c : list) { + for (String m : mix) { + newList.add(mix(c, m)); + } + } + return newList; + } + + private static List> alternate(List> list, String opt) { + return product(list, "-XX:+" + opt, "-XX:-" + opt); + } + + private static boolean containsFuzzy(List list, String sub) { + for (String s : list) { + if (s.contains(sub)) return true; + } + return false; + } + + public static void main(String... args) throws Exception { + List> configs = new ArrayList<>(); + List cpuFeatures = CPUInfo.getFeatures(); + + if (Platform.isX64() || Platform.isX86()) { + // If CPU features were not found, provide a default config. + if (cpuFeatures.isEmpty()) { + configs.add(new ArrayList()); + } + + // Otherwise, select the tests that make sense on current platform. + if (containsFuzzy(cpuFeatures, "avx512")) { + configs.add(List.of("-XX:UseAVX=3")); + } + if (containsFuzzy(cpuFeatures, "avx2")) { + configs.add(List.of("-XX:UseAVX=2")); + } + if (containsFuzzy(cpuFeatures, "avx")) { + configs.add(List.of("-XX:UseAVX=1")); + } + if (containsFuzzy(cpuFeatures, "sse4")) { + configs.add(List.of("-XX:UseAVX=0", "-XX:UseSSE=4")); + } + if (containsFuzzy(cpuFeatures, "sse3")) { + configs.add(List.of("-XX:UseAVX=0", "-XX:UseSSE=3")); + } + if (containsFuzzy(cpuFeatures, "sse2")) { + configs.add(List.of("-XX:UseAVX=0", "-XX:UseSSE=2")); + } + + // x86_64 always has UseSSE >= 2. These lower configurations only + // make sense for x86_32. + if (Platform.isX86()) { + if (containsFuzzy(cpuFeatures, "sse")) { + configs.add(List.of("-XX:UseAVX=0", "-XX:UseSSE=1")); + } + + configs.add(List.of("-XX:UseAVX=0", "-XX:UseSSE=0")); + } + + // Alternate configs with other flags + if (Platform.isX64()) { + configs = alternate(configs, "UseCompressedOops"); + } + configs = alternate(configs, "UseUnalignedLoadStores"); + + } else if (Platform.isAArch64()) { + // AArch64. + configs.add(new ArrayList()); + + // Alternate configs with other flags + configs = alternate(configs, "UseCompressedOops"); + configs = alternate(configs, "UseSIMDForMemoryOps"); + } else { + // Generic config. + configs.add(new ArrayList()); + } + + String[] classNames = { + "compiler.arraycopy.stress.StressBooleanArrayCopy", + "compiler.arraycopy.stress.StressByteArrayCopy", + "compiler.arraycopy.stress.StressCharArrayCopy", + "compiler.arraycopy.stress.StressShortArrayCopy", + "compiler.arraycopy.stress.StressIntArrayCopy", + "compiler.arraycopy.stress.StressFloatArrayCopy", + "compiler.arraycopy.stress.StressLongArrayCopy", + "compiler.arraycopy.stress.StressDoubleArrayCopy", + "compiler.arraycopy.stress.StressObjectArrayCopy", + }; + + ArrayList forks = new ArrayList<>(); + int jobs = 0; + + for (List c : configs) { + for (String className : classNames) { + // Start a new job + { + ProcessBuilder pb = ProcessTools.createTestJvm(mix(c, "-Xmx256m", className)); + Process p = pb.start(); + OutputAnalyzer oa = new OutputAnalyzer(p); + forks.add(new Fork(p, oa)); + jobs++; + } + + // Wait for the completion of other jobs + while (jobs >= MAX_PARALLELISM) { + Fork f = findDone(forks); + if (f != null) { + OutputAnalyzer oa = f.oa(); + oa.shouldHaveExitValue(0); + forks.remove(f); + jobs--; + } else { + // Nothing is done, wait a little. + Thread.sleep(200); + } + } + } + } + + // Drain the rest + for (Fork f : forks) { + OutputAnalyzer oa = f.oa(); + oa.shouldHaveExitValue(0); + } + } + + private static Fork findDone(List forks) { + for (Fork f : forks) { + if (!f.p().isAlive()) { + return f; + } + } + return null; + } + + private static record Fork(Process p, OutputAnalyzer oa) {}; + +} diff --git a/test/hotspot/jtreg/compiler/c1/Test8275337.java b/test/hotspot/jtreg/compiler/c1/Test8275337.java new file mode 100644 index 00000000000..5e7ab912e20 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c1/Test8275337.java @@ -0,0 +1,65 @@ +/* + * 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 8275337 + * @run main/othervm -Xcomp -XX:TieredStopAtLevel=1 compiler.c1.Test8275337 + */ + + +package compiler.c1; + +public class Test8275337 { + public static final int N = 400; + + public static void mainTest() { + int iArr1[] = new int[N]; + float fArr1[][] = new float[N][N]; + + for (int i = 9; i < 171; i++) { + int z; + try { + z = i % i; + } catch (ArithmeticException a_e) {} + for (int j = 1; j < 155; ++j) { + fArr1[j - 1][i] -= 1; + iArr1[i - 1] = 1; + } + for (int j = 4; j < 155; j++) { + for (int k = 1; k < 2; ++k) { + iArr1[i - 1] += 1; + fArr1[k - 1][j] -= 2; + } + } + } + } + public static void main(String[] strArr) { + + try { + for (int i = 0; i < 10; i++) { + mainTest(); + } + } catch (Exception ex) { + } + } +} diff --git a/test/hotspot/jtreg/compiler/c1/TestRangeCheckEliminated.java b/test/hotspot/jtreg/compiler/c1/TestRangeCheckEliminated.java index 328d8a92b06..7d4dd350e03 100644 --- a/test/hotspot/jtreg/compiler/c1/TestRangeCheckEliminated.java +++ b/test/hotspot/jtreg/compiler/c1/TestRangeCheckEliminated.java @@ -50,6 +50,7 @@ public static void main(String[] args) throws Throwable { "-XX:TieredStopAtLevel=1", "-XX:+TraceRangeCheckElimination", "-XX:-BackgroundCompilation", + "-XX:CompileThreshold=500", test_constant_array.class.getName() }; @@ -69,6 +70,7 @@ public static void main(String[] args) throws Throwable { "-XX:TieredStopAtLevel=1", "-XX:+TraceRangeCheckElimination", "-XX:-BackgroundCompilation", + "-XX:CompileThreshold=500", test_multi_constant_array.class.getName() }; @@ -88,6 +90,7 @@ public static void main(String[] args) throws Throwable { "-XX:TieredStopAtLevel=1", "-XX:+TraceRangeCheckElimination", "-XX:-BackgroundCompilation", + "-XX:CompileThreshold=500", test_multi_new_array.class.getName() }; diff --git a/test/hotspot/jtreg/compiler/c2/TestCMoveInfiniteGVN.java b/test/hotspot/jtreg/compiler/c2/TestCMoveInfiniteGVN.java new file mode 100644 index 00000000000..50d9d02dea6 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestCMoveInfiniteGVN.java @@ -0,0 +1,68 @@ +/* + * 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 + * @key stress randomness + * @bug 8280123 + * @run main/othervm -Xcomp -XX:-TieredCompilation + * -XX:CompileCommand=compileonly,compiler.c2.TestCMoveInfiniteGVN::test + * -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN -XX:StressSeed=43739875 + * compiler.c2.TestCMoveInfiniteGVN + * @run main/othervm -Xcomp -XX:-TieredCompilation + * -XX:CompileCommand=compileonly,compiler.c2.TestCMoveInfiniteGVN::test + * -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN + * compiler.c2.TestCMoveInfiniteGVN + */ + +package compiler.c2; + +public class TestCMoveInfiniteGVN { + + static int test(boolean b, int i) { + int iArr[] = new int[2]; + + double d = Math.max(i, i); + for (int i1 = 1; i1 < 2; i1++) { + if (i1 != 0) { + return (b ? 1 : 0); // CMoveI + } + for (int i2 = 1; i2 < 2; i2++) { + switch (i2) { + case 1: d -= Math.max(i1, i2); break; + } + d -= iArr[i1 - 1]; + } + } + return 0; + } + + static void test() { + test(true, 234); + } + + public static void main(String[] strArr) { + test(); // compilation, then nmethod invalidation during execution + test(); // trigger crashing recompilation + } +} diff --git a/test/hotspot/jtreg/compiler/c2/TestJumpTable.java b/test/hotspot/jtreg/compiler/c2/TestJumpTable.java index a7d1a803452..f624855eaa9 100644 --- a/test/hotspot/jtreg/compiler/c2/TestJumpTable.java +++ b/test/hotspot/jtreg/compiler/c2/TestJumpTable.java @@ -25,6 +25,8 @@ * @test * @bug 8229855 8238812 * @summary Test jump table with key value that gets out of bounds after loop unrolling. + * @requires vm.compiler2.enabled + * * @run main/othervm -XX:CompileCommand=dontinline,compiler.c2.TestJumpTable::test* * -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -XX:-UseSwitchProfiling * compiler.c2.TestJumpTable diff --git a/test/hotspot/jtreg/compiler/c2/TestModDivTopInput.java b/test/hotspot/jtreg/compiler/c2/TestModDivTopInput.java new file mode 100644 index 00000000000..9e4ba1dd6f0 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestModDivTopInput.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2022, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8283451 + * @summary C2: assert(_base == Long) failed: Not a Long + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+StressLCM -XX:+StressGCM -XX:+StressCCP -XX:+StressIGVN + * -Xcomp -XX:CompileOnly=TestModDivTopInput -XX:-TieredCompilation -XX:StressSeed=87628618 TestModDivTopInput + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+StressLCM -XX:+StressGCM -XX:+StressCCP -XX:+StressIGVN + * -Xcomp -XX:CompileOnly=TestModDivTopInput -XX:-TieredCompilation TestModDivTopInput + */ + +public class TestModDivTopInput { + + public static final int N = 400; + + public static float fFld=-2.447F; + public long lFld=-189L; + + public void mainTest(String[] strArr1) { + + int i18, i20=-14, i21, iArr2[]=new int[N]; + boolean b2=true; + double d2; + long l; + + init(iArr2, -13265); + + for (i18 = 13; i18 < 315; ++i18) { + if (b2) continue; + for (d2 = 5; d2 < 83; d2++) { + } + for (i21 = 4; i21 < 83; i21++) { + for (l = 1; 2 > l; l++) { + } + b2 = b2; + lFld %= (i20 | 1); + i20 = (int)fFld; + i20 += (int)d2; + } + } + } + + public static void main(String[] strArr) { + TestModDivTopInput _instance = new TestModDivTopInput(); + for (int i = 0; i < 10; i++ ) { + _instance.mainTest(strArr); + } + } + + static void init(int[] arr, int v) { + for (int i = 0; i < arr.length; i++) { + arr[i] = v; + } + } + +} diff --git a/test/hotspot/jtreg/compiler/c2/TestReplaceEquivPhis.java b/test/hotspot/jtreg/compiler/c2/TestReplaceEquivPhis.java index 229df93e5c4..1fc767f8dfc 100644 --- a/test/hotspot/jtreg/compiler/c2/TestReplaceEquivPhis.java +++ b/test/hotspot/jtreg/compiler/c2/TestReplaceEquivPhis.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. * 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 8243670 * @summary Unexpected test result caused by C2 MergeMemNode::Ideal + * @requires vm.compiler2.enabled * * @run main/othervm -Xcomp -XX:-SplitIfBlocks * -XX:CompileOnly=compiler.c2.TestReplaceEquivPhis::test diff --git a/test/hotspot/jtreg/compiler/c2/TestShiftRightAndAccumulate.java b/test/hotspot/jtreg/compiler/c2/TestShiftRightAndAccumulate.java index 517bed22b14..7b083cb79a8 100644 --- a/test/hotspot/jtreg/compiler/c2/TestShiftRightAndAccumulate.java +++ b/test/hotspot/jtreg/compiler/c2/TestShiftRightAndAccumulate.java @@ -25,8 +25,17 @@ * @test * @bug 8260585 * @summary AArch64: Wrong code generated for shifting right and accumulating four unsigned short integers. + * * @run main/othervm compiler.c2.TestShiftRightAndAccumulate * @run main/othervm -Xcomp compiler.c2.TestShiftRightAndAccumulate + */ + +/** + * @test + * @bug 8260585 + * @summary AArch64: Wrong code generated for shifting right and accumulating four unsigned short integers. + * @requires vm.compiler2.enabled + * * @run main/othervm -XX:-SuperWordLoopUnrollAnalysis compiler.c2.TestShiftRightAndAccumulate */ diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestSkeletonPredicates.java b/test/hotspot/jtreg/compiler/c2/irTests/TestSkeletonPredicates.java new file mode 100644 index 00000000000..79bcd16cfb2 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestSkeletonPredicates.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2022, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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; + +import compiler.lib.ir_framework.*; +import jdk.test.lib.Utils; +import java.util.Random; + +/* + * @test + * @bug 8278228 + * @summary C2: Improve identical back-to-back if elimination + * @library /test/lib / + * @run driver compiler.c2.irTests.TestSkeletonPredicates + */ + +public class TestSkeletonPredicates { + public static void main(String[] args) { + TestFramework.runWithFlags("-XX:-UseLoopPredicate", "-XX:LoopUnrollLimit=240", "-XX:+StressIGVN", "-XX:StressSeed=255527877"); + TestFramework.runWithFlags("-XX:-UseLoopPredicate", "-XX:LoopUnrollLimit=240", "-XX:+StressIGVN"); + } + + static volatile int barrier; + + @ForceInline + static boolean test1_helper(int start, int stop, double[] array1, double[] array2) { + for (int i = start; i < stop; i++) { + if ((i % 2) == 0) { + array1[i] = 42.42; + } else { + barrier = 0x42; + } + } + return false; + } + + @Test + @IR(counts = { IRNode.COUNTEDLOOP, "3" }) + static double[] test1(int stop, double[] array2) { + double[] array1 = null; + array1 = new double[10]; + for (int j = 0; j < stop; j++) { + if (test1_helper(8, j, array1, array2)) { + return null; + } + } + return array1; + } + + @Run(test = "test1") + void test1_runner() { + double[] array2 = new double[10]; + double[] array3 = new double[1000]; + test1_helper(1, 1000, array3, array3); + test1(11, array3); + } +} diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestStripMiningDropsSafepoint.java b/test/hotspot/jtreg/compiler/c2/irTests/TestStripMiningDropsSafepoint.java new file mode 100644 index 00000000000..951b94ed1a7 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestStripMiningDropsSafepoint.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2022, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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; + +import compiler.lib.ir_framework.*; + +/* + * @test + * @bug 8282045 + * @summary When loop strip mining fails, safepoints are removed from loop anyway + * @library /test/lib / + * @run driver compiler.c2.irTests.TestStripMiningDropsSafepoint + */ + +public class TestStripMiningDropsSafepoint { + public static void main(String[] args) { + TestFramework.runWithFlags("-XX:+UseCountedLoopSafepoints", "-XX:LoopStripMiningIter=1000", "-XX:LoopMaxUnroll=1", "-XX:-RangeCheckElimination"); + TestFramework.runWithFlags("-XX:+UseCountedLoopSafepoints", "-XX:LoopStripMiningIter=1000", "-XX:LoopMaxUnroll=1", "-XX:-RangeCheckElimination", "-XX:-PartialPeelLoop"); + } + + @Test + @IR(applyIf = { "PartialPeelLoop", "true" }, counts = { IRNode.COUNTEDLOOP, "1", IRNode.OUTERSTRIPMINEDLOOP, "1", IRNode.SAFEPOINT, "1" }) + private static void test1(int[] dst, int[] src) { + // Partial peel is applied. No side effect between exit and + // safepoint. + for (int i = 0; ; ) { + // prevent ciTypeFlow from cloning head + synchronized (new Object()) {} + i++; + if (i >= src.length) { + break; + } + dst[i] = src[i]; + if (i / 2 >= 2000) { + break; + } + } + } + + @Run(test = "test1") + private static void test1_runner() { + int[] array1 = new int[1000]; + int[] array2 = new int[10000]; + test1(array1, array1); + test1(array2, array2); + } + + @Test + @IR(applyIf = { "PartialPeelLoop", "true" }, counts = { IRNode.COUNTEDLOOP, "1", IRNode.SAFEPOINT, "1" }) + @IR(applyIf = { "PartialPeelLoop", "true" }, failOn = { IRNode.OUTERSTRIPMINEDLOOP }) + private static void test2(int[] dst, int[] src) { + // Partial peel is applied. Some side effect between exit and + // safepoint. + int v = src[0]; + for (int i = 0; ; ) { + synchronized (new Object()) {} + dst[i] = v; + i++; + if (i >= src.length) { + break; + } + v = src[i]; + if (i / 2 >= 2000) { + break; + } + } + } + + @Run(test = "test2") + private static void test2_runner() { + int[] array1 = new int[1000]; + int[] array2 = new int[10000]; + test2(array1, array1); + test2(array2, array2); + } + + @Test + @IR(applyIf = { "PartialPeelLoop", "false" }, counts = { IRNode.COUNTEDLOOP, "1", IRNode.OUTERSTRIPMINEDLOOP, "1", IRNode.SAFEPOINT, "1" }) + private static void test3(int[] dst, int[] src) { + int v = src[0]; + for (int i = 0; ; ) { + synchronized (new Object()) {} + dst[i] = v; + int inc = test3_helper(2); + v = src[i]; + i += (inc / 2); + if (i >= src.length) { + break; + } + for (int j = 0; j < 10; j++) { + } + // safepoint on backedge + } + } + + private static int test3_helper(int stop) { + int i = 1; + do { + synchronized (new Object()) {} + i *= 2; + } while (i < stop); + return i; + } + + @Run(test = "test3") + private static void test3_runner() { + int[] array1 = new int[1000]; + test3(array1, array1); + test3_helper(10); + } +} diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestSuperwordFailsUnrolling.java b/test/hotspot/jtreg/compiler/c2/irTests/TestSuperwordFailsUnrolling.java new file mode 100644 index 00000000000..2ba5e4e7340 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestSuperwordFailsUnrolling.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2022, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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; + +import compiler.lib.ir_framework.*; +import sun.hotspot.WhiteBox; + +/* + * @test + * @bug 8283187 + * @summary C2: loop candidate for superword not always unrolled fully if superword fails + * @library /test/lib / + * @build sun.hotspot.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -DSkipWhiteBoxInstall=true -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI compiler.c2.irTests.TestSuperwordFailsUnrolling + */ + +public class TestSuperwordFailsUnrolling { + private static int v = 0; + private final static WhiteBox wb = WhiteBox.getWhiteBox(); + + public static void main(String[] args) { + Object avx = wb.getVMFlag("UseAVX"); + if (avx != null && ((Long)avx) > 2) { + TestFramework.runWithFlags("-XX:UseAVX=2", "-XX:LoopMaxUnroll=8"); + } + TestFramework.runWithFlags("-XX:LoopMaxUnroll=8"); + } + + @Test + @IR(applyIf = { "UsePopCountInstruction", "true" }, counts = { IRNode.POPCOUNT_L, "10" }) + private static int test(long[] array1, long[] array2) { + v = 0; + for (int i = 0; i < array1.length; i++) { + v += Long.bitCount(array1[i]); + } + return v; + } + + @Run(test = "test") + void test_runner() { + long[] array = new long[1000]; + test(array, array); + } +} diff --git a/test/hotspot/jtreg/compiler/cha/AbstractRootMethod.java b/test/hotspot/jtreg/compiler/cha/AbstractRootMethod.java index a450b1e02e1..01787593412 100644 --- a/test/hotspot/jtreg/compiler/cha/AbstractRootMethod.java +++ b/test/hotspot/jtreg/compiler/cha/AbstractRootMethod.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. 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. * * This code is free software; you can redistribute it and/or modify it @@ -50,12 +50,23 @@ */ package compiler.cha; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; + import static compiler.cha.Utils.*; public class AbstractRootMethod { public static void main(String[] args) { run(AbstractClass.class); run(AbstractInterface.class); + + // Implementation limitation: CHA is not performed by C1 during inlining through MH linkers. + if (!sun.hotspot.code.Compiler.isC1Enabled()) { + run(AbstractClass.TestMH.class, AbstractClass.class); + run(AbstractInterface.TestMH.class, AbstractInterface.class); + } + + System.out.println("TEST PASSED"); } public static class AbstractClass extends ATest { @@ -124,7 +135,21 @@ public void test() { call(new G() { public Object m() { return CORRECT; } }); // Gn <: G.m <: C.m ABSTRACT assertCompiled(); } + + public static class TestMH extends AbstractClass { + static final MethodHandle TEST_MH = findVirtualHelper(C.class, "m", Object.class, MethodHandles.lookup()); + + @Override + public Object test(C obj) { + try { + return TEST_MH.invokeExact(obj); // invokevirtual C.m() + } catch (Throwable e) { + throw new InternalError(e); + } + } + } } + public static class AbstractInterface extends ATest { public AbstractInterface() { super(C.class, D.class); @@ -193,5 +218,18 @@ public void test() { call(new G() { public Object m() { return CORRECT; } }); // Gn <: G.m <: C <: I.m ABSTRACT assertCompiled(); } + + public static class TestMH extends AbstractInterface { + static final MethodHandle TEST_MH = findVirtualHelper(C.class, "m", Object.class, MethodHandles.lookup()); + + @Override + public Object test(C obj) { + try { + return TEST_MH.invokeExact(obj); // invokevirtual C.m() + } catch (Throwable e) { + throw new InternalError(e); + } + } + } } } diff --git a/test/hotspot/jtreg/compiler/cha/DefaultRootMethod.java b/test/hotspot/jtreg/compiler/cha/DefaultRootMethod.java index 354412d7748..a13a9cfdd26 100644 --- a/test/hotspot/jtreg/compiler/cha/DefaultRootMethod.java +++ b/test/hotspot/jtreg/compiler/cha/DefaultRootMethod.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. 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. * * This code is free software; you can redistribute it and/or modify it @@ -50,12 +50,22 @@ */ package compiler.cha; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; + import static compiler.cha.Utils.*; public class DefaultRootMethod { public static void main(String[] args) { run(DefaultRoot.class); run(InheritedDefault.class); + + // Implementation limitation: CHA is not performed by C1 during inlining through MH linkers. + if (!sun.hotspot.code.Compiler.isC1Enabled()) { + run(DefaultRoot.TestMH.class, DefaultRoot.class); + run(InheritedDefault.TestMH.class, InheritedDefault.class); + } + System.out.println("TEST PASSED"); } @@ -83,7 +93,7 @@ static abstract class F2 extends C implements I2 { } static class G extends C { public Object m() { return CORRECT; } } @Override - public Object test(C obj) { + public Object test(C obj) throws Throwable { return obj.m(); // invokevirtual C.m() } @@ -122,6 +132,15 @@ public void test() { call(new G() { public Object m() { return CORRECT; } }); // Gn <: G.m <: C <: I.m DEFAULT assertCompiled(); } + + public static class TestMH extends DefaultRoot { + static final MethodHandle TEST_MH = findVirtualHelper(C.class, "m", Object.class, MethodHandles.lookup()); + + @Override + public Object test(C obj) throws Throwable { + return TEST_MH.invokeExact(obj); // invokevirtual C.m() + } + } } public static class InheritedDefault extends ATest { @@ -151,7 +170,7 @@ interface K extends I { default Object m() { return CORRECT; } } static class G extends C implements K { /* inherits K.m DEFAULT */ } @Override - public Object test(C obj) { + public Object test(C obj) throws Throwable { return obj.m(); // invokevirtual C.m() } @@ -190,5 +209,14 @@ public void test() { call(new G() { public Object m() { return CORRECT; } }); // Gn <: G.m <: C <: I.m DEFAULT assertCompiled(); } + + public static class TestMH extends InheritedDefault { + static final MethodHandle TEST_MH = findVirtualHelper(C.class, "m", Object.class, MethodHandles.lookup()); + + @Override + public Object test(C obj) throws Throwable { + return TEST_MH.invokeExact(obj); // invokevirtual C.m() + } + } } } diff --git a/test/hotspot/jtreg/compiler/cha/Utils.java b/test/hotspot/jtreg/compiler/cha/Utils.java index cad185b1110..f45ab256fbb 100644 --- a/test/hotspot/jtreg/compiler/cha/Utils.java +++ b/test/hotspot/jtreg/compiler/cha/Utils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. 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. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.lang.reflect.Method; import java.util.HashMap; import java.util.concurrent.Callable; @@ -45,6 +46,7 @@ public class Utils { public static final Unsafe U = Unsafe.getUnsafe(); + public static final WhiteBox WB = WhiteBox.getWhiteBox(); interface Test { void call(T o); @@ -99,8 +101,6 @@ default void repeat(int cnt, Runnable r) { } public static abstract class ATest implements Test { - public static final WhiteBox WB = WhiteBox.getWhiteBox(); - public static final Object CORRECT = new Object(); public static final Object WRONG = new Object(); @@ -117,7 +117,7 @@ public ATest(Class declared, Class receiver) { } @DontInline - public abstract Object test(T i); + public abstract Object test(T i) throws Throwable; public abstract void checkInvalidReceiver(); @@ -133,7 +133,6 @@ public T receiver(int id) { })); } - public void compile(Runnable r) { while (!WB.isMethodCompiled(TEST)) { for (int i = 0; i < 100; i++) { @@ -161,19 +160,35 @@ public void assertCompiled() { @Override public void call(T i) { - assertTrue(test(i) != WRONG); + try { + assertTrue(test(i) != WRONG); + } catch (Throwable e) { + throw new InternalError(e); + } + } + + public static T compute(Callable c) { + try { + return c.call(); + } catch (Exception e) { + throw new Error(e); + } + } + + public static MethodHandle findVirtualHelper(Class refc, String name, Class returnType, MethodHandles.Lookup lookup) { + return compute(() -> lookup.findVirtual(refc, name, MethodType.methodType(returnType))); } } @Retention(value = RetentionPolicy.RUNTIME) public @interface TestCase {} - static void run(Class test) { + static void run(Class test, Class enclosed) { try { - for (Method m : test.getDeclaredMethods()) { + for (Method m : test.getMethods()) { if (m.isAnnotationPresent(TestCase.class)) { System.out.println(m.toString()); - ClassLoader cl = new MyClassLoader(test); + ClassLoader cl = new MyClassLoader(enclosed); Class c = cl.loadClass(test.getName()); c.getMethod(m.getName()).invoke(c.getDeclaredConstructor().newInstance()); } @@ -183,6 +198,10 @@ static void run(Class test) { } } + static void run(Class test) { + run(test, test); + } + static class ObjectToStringHelper { static Object testHelper(Object o) { throw new Error("not used"); @@ -303,7 +322,7 @@ public static void shouldThrow(Class expectedException, Run try { r.run(); throw new AssertionError("Exception not thrown: " + expectedException.getName()); - } catch(Throwable e) { + } catch (Throwable e) { if (expectedException == e.getClass()) { // success: proper exception is thrown } else { @@ -320,12 +339,4 @@ public static MethodHandle unsafeCastMH(Class cls) { throw new Error(e); } } - - static T compute(Callable c) { - try { - return c.call(); - } catch (Exception e) { - throw new Error(e); - } - } } diff --git a/test/hotspot/jtreg/compiler/codecache/OverflowCodeCacheTest.java b/test/hotspot/jtreg/compiler/codecache/OverflowCodeCacheTest.java index 1dc02e25312..cd69d0a31da 100644 --- a/test/hotspot/jtreg/compiler/codecache/OverflowCodeCacheTest.java +++ b/test/hotspot/jtreg/compiler/codecache/OverflowCodeCacheTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -23,7 +23,7 @@ /* * @test OverflowCodeCacheTest - * @bug 8059550 + * @bug 8059550 8279356 * @summary testing of code cache segments overflow * @library /test/lib * @modules java.base/jdk.internal.misc @@ -33,11 +33,14 @@ * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,null::* - * -XX:-SegmentedCodeCache - * compiler.codecache.OverflowCodeCacheTest + * -XX:-SegmentedCodeCache -Xmixed + * compiler.codecache.OverflowCodeCacheTest CompilationDisabled * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,null::* - * -XX:+SegmentedCodeCache + * -XX:+SegmentedCodeCache -Xmixed + * compiler.codecache.OverflowCodeCacheTest CompilationDisabled + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:-SegmentedCodeCache -Xmixed * compiler.codecache.OverflowCodeCacheTest */ @@ -49,13 +52,21 @@ import sun.hotspot.code.CodeBlob; import java.lang.management.MemoryPoolMXBean; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.EnumSet; +class Helper { + // Uncommon signature to prevent sharing and force creation of a new adapter + public void method(float a, float b, float c, Object o) { } +} + public class OverflowCodeCacheTest { private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + private static boolean COMPILATION_DISABLED = false; public static void main(String[] args) { + COMPILATION_DISABLED = args.length > 0; EnumSet blobTypes = BlobType.getAvailable(); for (BlobType type : blobTypes) { new OverflowCodeCacheTest(type).test(); @@ -74,6 +85,8 @@ private void test() { System.out.println("allocating till possible..."); ArrayList blobs = new ArrayList<>(); int compilationActivityMode = -1; + // Lock compilation to be able to better control code cache space + WHITE_BOX.lockCompilation(); try { long addr; int size = (int) (getHeapSize() >> 7); @@ -88,15 +101,43 @@ private void test() { } } /* now, remember compilationActivityMode to check it later, after freeing, since we - possibly have no free cache for futher work */ + possibly have no free cache for further work */ compilationActivityMode = WHITE_BOX.getCompilationActivityMode(); + + // Use smallest allocation size to make sure all of the available space + // is filled up. Don't free these below to put some pressure on the sweeper. + while ((addr = WHITE_BOX.allocateCodeBlob(1, type.id)) != 0) { } } finally { + try { + // Trigger creation of a new adapter for Helper::method + // which will fail because we are out of code cache space. + Helper helper = new Helper(); + } catch (VirtualMachineError e) { + // Expected + } + // Free code cache space for (Long blob : blobs) { WHITE_BOX.freeCodeBlob(blob); } + + // Convert some nmethods to zombie and then free them to re-enable compilation + WHITE_BOX.unlockCompilation(); + WHITE_BOX.forceNMethodSweep(); + WHITE_BOX.forceNMethodSweep(); + + // Trigger compilation of Helper::method which will hit an assert because + // adapter creation failed above due to a lack of code cache space. + Helper helper = new Helper(); + for (int i = 0; i < 100_000; i++) { + helper.method(0, 0, 0, null); + } + } + // Only check this if compilation is disabled, otherwise the sweeper might have + // freed enough nmethods to allow for re-enabling compilation. + if (COMPILATION_DISABLED) { + Asserts.assertNotEquals(compilationActivityMode, 1 /* run_compilation*/, + "Compilation must be disabled when CodeCache(CodeHeap) overflows"); } - Asserts.assertNotEquals(compilationActivityMode, 1 /* run_compilation*/, - "Compilation must be disabled when CodeCache(CodeHeap) overflows"); } private long getHeapSize() { diff --git a/test/hotspot/jtreg/compiler/codecache/stress/ReturnBlobToWrongHeapTest.java b/test/hotspot/jtreg/compiler/codecache/stress/ReturnBlobToWrongHeapTest.java index 37d570e460f..1ef65182a0e 100644 --- a/test/hotspot/jtreg/compiler/codecache/stress/ReturnBlobToWrongHeapTest.java +++ b/test/hotspot/jtreg/compiler/codecache/stress/ReturnBlobToWrongHeapTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -37,6 +37,7 @@ * -XX:+SegmentedCodeCache * -XX:ReservedCodeCacheSize=16M * -XX:CodeCacheMinBlockLength=1 + * -XX:CICompilerCount=2 * compiler.codecache.stress.ReturnBlobToWrongHeapTest */ diff --git a/test/hotspot/jtreg/compiler/codegen/ClearArrayTest.java b/test/hotspot/jtreg/compiler/codegen/ClearArrayTest.java index d1deb90e5bf..90f57ef3de6 100644 --- a/test/hotspot/jtreg/compiler/codegen/ClearArrayTest.java +++ b/test/hotspot/jtreg/compiler/codegen/ClearArrayTest.java @@ -25,7 +25,10 @@ * @test * @bug 8260716 * @summary Test for correct code generation by the JIT - * @run main/othervm -Xbatch -XX:CompileCommand=compileonly,*ClearArrayTest.test -XX:+UnlockDiagnosticVMOptions -XX:-IdealizeClearArrayNode compiler.codegen.ClearArrayTest + * @run main/othervm -Xbatch -XX:CompileCommand=compileonly,*ClearArrayTest.test + * -XX:+IgnoreUnrecognizedVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:-IdealizeClearArrayNode + * compiler.codegen.ClearArrayTest */ package compiler.codegen; diff --git a/test/hotspot/jtreg/compiler/exceptions/TestLateMHInlineExceptions.java b/test/hotspot/jtreg/compiler/exceptions/TestLateMHInlineExceptions.java new file mode 100644 index 00000000000..6949c9948df --- /dev/null +++ b/test/hotspot/jtreg/compiler/exceptions/TestLateMHInlineExceptions.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2021, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8275638 8278966 + * @summary GraphKit::combine_exception_states fails with "matching stack sizes" assert + * + * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:CompileCommand=dontinline,TestLateMHInlineExceptions::m + * -XX:+IgnoreUnrecognizedVMOptions -XX:+AlwaysIncrementalInline TestLateMHInlineExceptions + * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacements -XX:+IgnoreUnrecognizedVMOptions -XX:+AlwaysIncrementalInline + * TestLateMHInlineExceptions + * + */ + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +public class TestLateMHInlineExceptions { + public static void main(String[] args) throws Throwable { + TestLateMHInlineExceptions test = new TestLateMHInlineExceptions(); + for (int i = 0; i < 20_000; i++) { + test1(test); + try { + test1(null); + } catch (NullPointerException npe) { + } + test2(test); + test2(null); + test3(test); + try { + test3(null); + } catch (NullPointerException npe) { + } + test4(test); + test4(null); + test5(test); + try { + test5(null); + } catch (NullPointerException npe) { + } + test6(test); + try { + test6(null); + } catch (NullPointerException npe) { + } + } + } + + void m() { + } + + static void nothing(Throwable t) { + } + + static final MethodHandle mh; + static final MethodHandle mh_nothing; + static final MethodHandle mh2; + static final MethodHandle mh3; + + static { + MethodHandles.Lookup lookup = MethodHandles.lookup(); + try { + mh = lookup.findVirtual(TestLateMHInlineExceptions.class, "m", MethodType.methodType(void.class)); + mh_nothing = lookup.findStatic(TestLateMHInlineExceptions.class, "nothing", MethodType.methodType(void.class, Throwable.class)); + mh2 = MethodHandles.tryFinally(mh, mh_nothing); + mh3 = MethodHandles.catchException(mh, Throwable.class, mh_nothing); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + throw new RuntimeException("Method handle lookup failed"); + } catch (IllegalAccessException e) { + e.printStackTrace(); + throw new RuntimeException("Method handle lookup failed"); + } + } + + private static void test1(TestLateMHInlineExceptions test) throws Throwable { + mh.invokeExact(test); + } + + private static void test2(TestLateMHInlineExceptions test) throws Throwable { + try { + mh.invokeExact(test); + } catch (NullPointerException npe) { + } + } + + private static void inlined(TestLateMHInlineExceptions test) throws Throwable { + mh.invokeExact(test); + } + + + private static void test3(TestLateMHInlineExceptions test) throws Throwable { + inlined(test); + } + + private static void test4(TestLateMHInlineExceptions test) throws Throwable { + try { + inlined(test); + } catch (NullPointerException npe) { + } + } + + private static void test5(TestLateMHInlineExceptions test) throws Throwable { + mh2.invokeExact(test); + } + + private static void test6(TestLateMHInlineExceptions test) throws Throwable { + mh3.invokeExact(test); + } +} diff --git a/test/hotspot/jtreg/compiler/inlining/ResolvedClassTest.java b/test/hotspot/jtreg/compiler/inlining/ResolvedClassTest.java new file mode 100644 index 00000000000..92263bf10cf --- /dev/null +++ b/test/hotspot/jtreg/compiler/inlining/ResolvedClassTest.java @@ -0,0 +1,158 @@ +/* + * 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 8279515 + * + * @requires vm.flagless & vm.compiler1.enabled & vm.compiler2.enabled + * @modules java.base/jdk.internal.misc + * @library /test/lib / + * + * @run driver compiler.jsr292.ResolvedClassTest + */ + +package compiler.jsr292; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +import java.io.IOException; + +public class ResolvedClassTest { + /* ======================================================================== */ + static void testStatic() throws IOException { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+IgnoreUnrecognizedVMOptions", "-showversion", + "-XX:+PrintCompilation", "-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintInlining", + "-Xbatch", "-XX:CompileCommand=quiet", "-XX:CompileCommand=compileonly," + TestStatic.class.getName() + "::test", + TestStatic.class.getName()); + + OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + + analyzer.shouldHaveExitValue(0); + + analyzer.shouldNotContain("TestStatic$A::m (1 bytes) not inlineable"); + analyzer.shouldNotContain("TestStatic$A::m (1 bytes) no static binding"); + + analyzer.shouldContain("TestStatic$A::m (1 bytes) inline"); + } + + static class TestStatic { + static class A { + static void m() {} + } + static class B extends A {} + + // @DontInline + static void test() { + B.m(); // invokestatic B "m" => A::m + } + + public static void main(String[] args) { + for (int i = 0; i < 20_000; i++) { + test(); + } + } + } + + /* ======================================================================== */ + static void testStaticInit() throws IOException { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+IgnoreUnrecognizedVMOptions", "-showversion", + "-XX:+PrintCompilation", "-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintInlining", + "-Xbatch", "-XX:CompileCommand=quiet", "-XX:CompileCommand=compileonly," + TestStaticInit.class.getName() + "::test", + TestStaticInit.class.getName()); + + OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + + analyzer.shouldHaveExitValue(0); + + analyzer.shouldContain("TestStaticInit$A::m (1 bytes) no static binding"); + } + + static class TestStaticInit { + static class A { + static { + for (int i = 0; i < 20_000; i++) { + TestStaticInit.test(); + } + } + + static void m() {} + } + static class B extends A {} + + // @DontInline + static void test() { + B.m(); // A:: => test() => A::m() + } + + public static void main(String[] args) { + A.m(); // trigger initialization of A + } + } + + /* ======================================================================== */ + static void testIndy() throws IOException { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+IgnoreUnrecognizedVMOptions", "-showversion", + "-XX:+PrintCompilation", "-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintInlining", + "-Xbatch", "-XX:CompileCommand=quiet", "-XX:CompileCommand=compileonly," + TestIndy.class.getName() + "::test", + TestIndy.class.getName()); + + OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + + analyzer.shouldHaveExitValue(0); + + analyzer.shouldNotMatch("java\\.lang\\.invoke\\..+::linkToTargetMethod \\(9 bytes\\) not inlineable"); + + analyzer.shouldMatch("java\\.lang\\.invoke\\..+::linkToTargetMethod \\(9 bytes\\) force inline by annotation"); + analyzer.shouldContain("java/lang/invoke/MethodHandle::invokeBasic (not loaded) not inlineable"); + } + + static class TestIndy { + static String str = ""; + + // @DontInline + static void test() { + String s1 = "" + str; // indy (linked) + + for (int i = 0; i < 200_000; i++) {} // trigger OSR compilation + + String s2 = "" + str; // indy (not linked) + } + + public static void main(String[] args) { + test(); + } + } + + /* ======================================================================== */ + + public static void main(String[] args) throws IOException { + testStatic(); + testStaticInit(); + testIndy(); + } +} diff --git a/test/hotspot/jtreg/compiler/interpreter/Custom.jasm b/test/hotspot/jtreg/compiler/interpreter/Custom.jasm new file mode 100644 index 00000000000..e52d513d2fa --- /dev/null +++ b/test/hotspot/jtreg/compiler/interpreter/Custom.jasm @@ -0,0 +1,63 @@ +/* + * 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. + */ + +package compiler/interpreter; + +/* JASM simplified from the following Java pattern: + * + * public class Custom { + * + * static void test(int v) { + * int i8 = 1; + * try { + * v += 1; + * } catch (ArithmeticException exc1) { + * } finally { + * for (; i8 < 100; i8++) { + * } + * } + * } + * + */ + +super public class Custom { + + public static Method test:"(I)V" stack 2 locals 3 { + iconst_1; + istore_1; + try t0; + iinc 0, 1; + endtry t0; +Loop: + iload_1; + bipush 100; + if_icmpge Lexit; + iinc 1, 1; + goto Loop; // deoptimize here on backwards branch + catch t0 java/lang/ArithmeticException; // unreachable block + astore_2; +Lexit: + return + } + +} diff --git a/test/hotspot/jtreg/compiler/interpreter/VerifyStackWithUnreachableBlock.java b/test/hotspot/jtreg/compiler/interpreter/VerifyStackWithUnreachableBlock.java new file mode 100644 index 00000000000..f8aace2b31b --- /dev/null +++ b/test/hotspot/jtreg/compiler/interpreter/VerifyStackWithUnreachableBlock.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Alibaba Group Holding Limited. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 VerifyStackWithUnreachableBlock + * @bug 8271055 + * @compile Custom.jasm VerifyStackWithUnreachableBlock.java + * @summary Using VerifyStack for method that contains unreachable basic blocks + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+VerifyStack compiler.interpreter.VerifyStackWithUnreachableBlock + */ + +package compiler.interpreter; + +public class VerifyStackWithUnreachableBlock { + public static void main(String[] strArr) { + for (int i = 0; i < 10000; i++) { + Custom.test(i); + } + } +} diff --git a/test/hotspot/jtreg/compiler/intrinsics/string/TestStringIntrinsics2.java b/test/hotspot/jtreg/compiler/intrinsics/string/TestStringIntrinsics2.java index e6b3f89155a..91daadb72ec 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/string/TestStringIntrinsics2.java +++ b/test/hotspot/jtreg/compiler/intrinsics/string/TestStringIntrinsics2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -706,4 +706,18 @@ public static void test_asmStringEquals() { } } + static String longLatin1 = "0123456789A".repeat(100); + static String longUTF = "0123456789\ubeef".repeat(100); + + @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "0123456789", "1" }) + public static boolean indexOf_use_result_immediately(String a, String b) { + char ch = b.charAt(0); + return ch == a.charAt(a.indexOf(ch)); + } + + @Test(role = Role.TEST_ENTRY) + public static void test_indexOf_use_result_immediately() { + assertTrue(indexOf_use_result_immediately(longLatin1, "A")); + assertTrue(indexOf_use_result_immediately(longUTF, "\ubeef")); + } } diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java index 5383168d3c7..2fccb9e6b2f 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java @@ -42,6 +42,8 @@ import static java.lang.reflect.Modifier.isProtected; import static java.lang.reflect.Modifier.isPublic; import static java.lang.reflect.Modifier.isStatic; +import static jdk.vm.ci.meta.MetaUtil.internalNameToJava; +import static jdk.vm.ci.meta.MetaUtil.toInternalName; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -165,16 +167,15 @@ public void isArrayTest() { } @Test - public void internalNameTest() { - // Verify that the last slash in lambda types are not replaced with a '.' as they - // are part of the type name. + public void lambdaInternalNameTest() { + // Verify that the last dot in lambda types is properly handled when transitioning from internal name to java + // name and vice versa. Supplier lambda = () -> () -> System.out.println("run"); ResolvedJavaType lambdaType = metaAccess.lookupJavaType(lambda.getClass()); String typeName = lambdaType.getName(); - int typeNameLen = TestResolvedJavaType.class.getSimpleName().length(); - int index = typeName.indexOf(TestResolvedJavaType.class.getSimpleName()); - String suffix = typeName.substring(index + typeNameLen, typeName.length() - 1); - assertEquals(TestResolvedJavaType.class.getName() + suffix, lambdaType.toJavaName()); + String javaName = lambda.getClass().getName(); + assertEquals(typeName, toInternalName(javaName)); + assertEquals(javaName, internalNameToJava(typeName, true, true)); } @Test diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index b8cd6583a8f..0cae420a667 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -113,6 +113,7 @@ public class IRNode { public static final String LOOP = START + "Loop" + MID + END; public static final String COUNTEDLOOP = START + "CountedLoop\\b" + MID + END; public static final String COUNTEDLOOP_MAIN = START + "CountedLoop\\b" + MID + "main" + END; + public static final String OUTERSTRIPMINEDLOOP = START + "OuterStripMinedLoop\\b" + MID + END; public static final String CALL = START + "Call.*Java" + MID + END; public static final String CALL_OF_METHOD = COMPOSITE_PREFIX + START + "Call.*Java" + MID + IS_REPLACED + " " + END; @@ -132,6 +133,8 @@ public class IRNode { public static final String SCOPE_OBJECT = "(.*# ScObj.*" + END; public static final String MEMBAR = START + "MemBar" + MID + END; + public static final String SAFEPOINT = START + "SafePoint" + MID + END; + public static final String POPCOUNT_L = START + "PopCountL" + MID + END; /** * Called by {@link IRMatcher} to merge special composite nodes together with additional user-defined input. diff --git a/test/hotspot/jtreg/compiler/longcountedloops/TestIVPhiTypeIncorrectAfterCCP.java b/test/hotspot/jtreg/compiler/longcountedloops/TestIVPhiTypeIncorrectAfterCCP.java new file mode 100644 index 00000000000..0c22c12f06f --- /dev/null +++ b/test/hotspot/jtreg/compiler/longcountedloops/TestIVPhiTypeIncorrectAfterCCP.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8277906 + * @summary Incorrect type for IV phi of long counted loops after CCP + * + * @run main/othervm -XX:-TieredCompilation -XX:CompileCommand=compileonly,TestIVPhiTypeIncorrectAfterCCP::test -XX:-BackgroundCompilation TestIVPhiTypeIncorrectAfterCCP + * + */ + +public class TestIVPhiTypeIncorrectAfterCCP { + + static int test() { + int array[] = new int[50]; + + float f = 0; + for (int i = 3; i < 49; i++) { + for (long l = 1; l < i; l++) { + array[(int)l] = i; + f += l; + } + } + int sum = 0; + for (int i = 0; i < array.length; i++) { + sum += array[i]; + } + return sum; + } + + public static void main(String[] args) { + long expected = test(); + for (int i = 0; i < 10_000; i++) { + int res = test(); + if (res != expected) { + throw new RuntimeException("Unexpected result: " + res + " != " + expected); + } + } + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/FillArrayWithUnsafe.java b/test/hotspot/jtreg/compiler/loopopts/FillArrayWithUnsafe.java new file mode 100644 index 00000000000..6e3b840987a --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/FillArrayWithUnsafe.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8283408 + * @summary Fill a byte array with Java Unsafe API + * @run main/othervm -XX:+OptimizeFill compiler.loopopts.FillArrayWithUnsafe + */ + +package compiler.loopopts; + +import java.lang.reflect.Field; + +import sun.misc.Unsafe; + +public class FillArrayWithUnsafe { + + private static Unsafe unsafe; + + public static void main(String[] args) throws Exception { + Class klass = Unsafe.class; + Field field = klass.getDeclaredField("theUnsafe"); + field.setAccessible(true); + unsafe = (Unsafe) field.get(null); + + byte[] buffer; + // Make sure method newByteArray is compiled by C2 + for (int i = 0; i < 50000; i++) { + buffer = newByteArray(100, (byte) 0x80); + } + } + + public static byte[] newByteArray(int size, byte val) { + byte[] arr = new byte[size]; + int offset = unsafe.arrayBaseOffset(byte[].class); + for (int i = offset; i < offset + size; i++) { + unsafe.putByte(arr, i, val); + } + return arr; + } +} + diff --git a/test/hotspot/jtreg/compiler/loopopts/TestCastIIMakesMainLoopPhiDead.java b/test/hotspot/jtreg/compiler/loopopts/TestCastIIMakesMainLoopPhiDead.java new file mode 100644 index 00000000000..3c40761a77d --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestCastIIMakesMainLoopPhiDead.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8280600 + * @summary C2: assert(!had_error) failed: bad dominance + * @run main/othervm -Xcomp -XX:CompileOnly=TestCastIIMakesMainLoopPhiDead TestCastIIMakesMainLoopPhiDead + */ + +public class TestCastIIMakesMainLoopPhiDead { + int iArr[] = new int[0]; + + void test() { + int x = 8; + try { + for (int i = 0; i < 8; i++) { + iArr[1] = 9; + for (int j = -400; 1 > j; j++) { + iArr[j] = 4; + x -= 2; + } + } + } catch (ArrayIndexOutOfBoundsException e) { + } + } + public static void main(String[] k) { + TestCastIIMakesMainLoopPhiDead t = new TestCastIIMakesMainLoopPhiDead(); + for (int i = 0; i < 3; i++) { + t.test(); + } + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/TestIterationSplitWithRegionHead.java b/test/hotspot/jtreg/compiler/loopopts/TestIterationSplitWithRegionHead.java new file mode 100644 index 00000000000..7a29be60908 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestIterationSplitWithRegionHead.java @@ -0,0 +1,82 @@ +/* + * 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 + * @requires vm.compiler2.enabled + * @bug 8279837 + * @summary Tests infinite loop with region head in iteration split. + * @run main/othervm -Xcomp -XX:-TieredCompilation + * -XX:CompileCommand=compileonly,compiler.loopopts.TestIterationSplitWithRegionHead::test + * -XX:CompileCommand=dontinline,compiler.loopopts.TestIterationSplitWithRegionHead::* + * compiler.loopopts.TestIterationSplitWithRegionHead + */ + +package compiler.loopopts; + +public class TestIterationSplitWithRegionHead { + + static boolean flagFalse = false; + + public static void main(String[] args) { + test(); + } + + public static void test() { + // 1) The loop tree is built. We find that nested loop N2 is an infinite loop and add a NeverBranch + // to the inner loop to make it reachable. But the current loop tree does not have N2, yet. The + // resulting loop tree is: + // + // Loop: N0/N0 has_call has_sfpt + // Loop: N77/N121 has_call // N1 outer + // Loop: N77/N111 has_call sfpts={ 111 97 } // N1 inner + // + // 2) beautify_loops() finds that the outer loop head of N1 is shared and thus adds a new region + // in merge_many_backedges(). As a result, the loop tree is built again. This time, the NeverBranch + // in the inner loop of N2 allows that a loop tree can be built for it: + // + // Loop: N0/N0 has_call has_sfpt + // Loop: N216/N213 limit_check profile_predicated predicated has_call sfpts={ 111 97 } // N1 shared loop head + // Loop: N196/N201 sfpts={ 201 } // N2 inner loop now discovered with the new NeverBranch + // + // However, a LoopNode is only added by beautify_loops() which won't be called until the next iteration of loop opts. + // This means that we have a Region node (N196) as head in the loop tree which cannot be handled by iteration_split_impl() + // resulting in an assertion failure. + + // Nested loop N1 + while (flagFalse) { + while (dontInlineFalse()) { + } + } + dontInlineFalse(); + + // Nested loop N2 + while (flagFalse) { + while (true) ; // Detected as infinite inner loop by C2 -> NeverBranch added + } + } + + public static boolean dontInlineFalse() { + return false; + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/TestLoopEndNodeEliminate.java b/test/hotspot/jtreg/compiler/loopopts/TestLoopEndNodeEliminate.java new file mode 100644 index 00000000000..a4683db4f70 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestLoopEndNodeEliminate.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8275854 + * @summary Crashes in PhaseIdealLoop::transform_long_counted_loop + * @requires vm.compiler2.enabled + * + * @run main/othervm -Xbatch -XX:CompileCommand=compileonly,TestLoopEndNodeEliminate::lMeth TestLoopEndNodeEliminate + * + */ + +public class TestLoopEndNodeEliminate { + public volatile boolean bFld=true; + public volatile byte byFld=0; + public volatile short sArrFld[]=new short[N]; + public int iArrFld[]=new int[N]; + public boolean bArrFld[]=new boolean[N]; + + public static int iFld=10; + public static final int N = 400; + public static long instanceCount=0L; + public static long lMeth_check_sum = 0; + + public long lMeth() { + long l1=-33582180L; + int i14=-5, i15=-14, i16=0, i17=25699, i18=97, i19=-3, i20=0, i21=0, i22=42, i23=0, i24=25699, i25=97; + + for (l1 = 286; l1 > 16; l1 -= 3) { + for (i15 = 17; i15 > l1; --i15) { + switch (((iArrFld[i15] >>> 1) % 7) + 101) { + case 101: + case 102: + case 103: + case 104: + for (i17 = (int)(l1); i17 < 1; i17++) { + bArrFld[i17] = bFld; + } + break; + case 105: + case 106: + case 107: + } + } + for (i19 = 1; i19 < 270; ++i19) { + TestLoopEndNodeEliminate.iFld += byFld; + i21 = 1; + while (++i21 < 2) { + bFld = true; + } + for (i22 = 1; 2 > i22; ++i22) { + bFld = true; + } + for (i24 = 1; 2 > i24; ++i24) { + bFld = true; + } + bArrFld[(int)(l1) % N] = bFld; + sArrFld[i19 - 1] ^= (short)(++TestLoopEndNodeEliminate.instanceCount); + } + } + long meth_res = l1 + i14 + i15 + i16 + i17 + i18 + i19 + i20 + i21 + i22 + i23 + i24 + i25; + lMeth_check_sum += meth_res; + return (long)meth_res; + } + + public static void main(String[] strArr) { + TestLoopEndNodeEliminate _instance = new TestLoopEndNodeEliminate(); + for (int i = 0; i < 10000; i++ ) { + _instance.lMeth(); + } + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/TestPredicateInputBelowLoopPredicate.java b/test/hotspot/jtreg/compiler/loopopts/TestPredicateInputBelowLoopPredicate.java new file mode 100644 index 00000000000..3b0cc314074 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestPredicateInputBelowLoopPredicate.java @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2022, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8280799 + * @summary C2: assert(false) failed: cyclic dependency prevents range check elimination + * @run main/othervm -XX:-BackgroundCompilation -XX:-UseCountedLoopSafepoints TestPredicateInputBelowLoopPredicate + */ + +public class TestPredicateInputBelowLoopPredicate { + private static final Object object = new Object(); + private static int fieldStop = 100; + private static int[] array = new int[200]; + private static int[] array2 = new int[200]; + private static int fieldStart = 0; + + public static void main(String[] args) { + for (int i = 0; i < 20_000; i++) { + test(true); + test(false); + } + } + + private static void test(boolean flag) { + if (array == null) { + } + int start = fieldStart; + int i = start; + for(;;) { + int j; + for (j = -10; j < 0; j++) { + } + int stop = fieldStop; + // bound check becomes candidate for predication once + // loop above is optimized out + array[stop - i + j] = 0; + + // A bunch of stuff to grow loop body size and prevent peeling: + array2[0] = 0; + array2[1] = 0; + array2[2] = 0; + array2[3] = 0; + array2[4] = 0; + array2[5] = 0; + array2[6] = 0; + array2[7] = 0; + array2[8] = 0; + array2[9] = 0; + array2[10] = 0; + array2[11] = 0; + array2[12] = 0; + array2[13] = 0; + array2[14] = 0; + array2[15] = 0; + array2[16] = 0; + array2[17] = 0; + array2[18] = 0; + array2[19] = 0; + array2[20] = 0; + array2[21] = 0; + array2[22] = 0; + array2[23] = 0; + array2[24] = 0; + array2[25] = 0; + array2[26] = 0; + array2[27] = 0; + array2[28] = 0; + array2[29] = 0; + array2[30] = 0; + array2[31] = 0; + array2[32] = 0; + array2[33] = 0; + array2[34] = 0; + array2[35] = 0; + array2[36] = 0; + array2[37] = 0; + array2[38] = 0; + array2[39] = 0; + array2[40] = 0; + array2[41] = 0; + array2[42] = 0; + array2[43] = 0; + array2[44] = 0; + array2[45] = 0; + array2[46] = 0; + array2[47] = 0; + array2[48] = 0; + array2[49] = 0; + array2[50] = 0; + array2[51] = 0; + array2[52] = 0; + array2[53] = 0; + array2[54] = 0; + array2[55] = 0; + array2[56] = 0; + array2[57] = 0; + array2[58] = 0; + array2[59] = 0; + array2[60] = 0; + array2[61] = 0; + array2[62] = 0; + array2[63] = 0; + array2[64] = 0; + array2[65] = 0; + array2[66] = 0; + array2[67] = 0; + array2[68] = 0; + array2[69] = 0; + array2[70] = 0; + array2[71] = 0; + array2[72] = 0; + array2[73] = 0; + array2[74] = 0; + array2[75] = 0; + array2[76] = 0; + array2[77] = 0; + array2[78] = 0; + array2[79] = 0; + array2[80] = 0; + array2[81] = 0; + array2[82] = 0; + array2[83] = 0; + array2[84] = 0; + array2[85] = 0; + array2[86] = 0; + array2[87] = 0; + array2[88] = 0; + array2[89] = 0; + array2[90] = 0; + array2[91] = 0; + array2[92] = 0; + array2[93] = 0; + array2[94] = 0; + array2[95] = 0; + array2[96] = 0; + array2[97] = 0; + array2[98] = 0; + array2[99] = 0; + + array2[100] = 0; + array2[101] = 0; + array2[102] = 0; + array2[103] = 0; + array2[104] = 0; + array2[105] = 0; + array2[106] = 0; + array2[107] = 0; + array2[108] = 0; + array2[109] = 0; + array2[110] = 0; + array2[111] = 0; + array2[112] = 0; + array2[113] = 0; + array2[114] = 0; + array2[115] = 0; + array2[116] = 0; + array2[117] = 0; + array2[118] = 0; + array2[119] = 0; + array2[120] = 0; + array2[121] = 0; + array2[122] = 0; + array2[123] = 0; + array2[124] = 0; + array2[125] = 0; + array2[126] = 0; + array2[127] = 0; + array2[128] = 0; + array2[129] = 0; + array2[130] = 0; + array2[131] = 0; + array2[132] = 0; + array2[133] = 0; + array2[134] = 0; + array2[135] = 0; + array2[136] = 0; + array2[137] = 0; + array2[138] = 0; + array2[139] = 0; + array2[140] = 0; + array2[141] = 0; + array2[142] = 0; + array2[143] = 0; + array2[144] = 0; + array2[145] = 0; + array2[146] = 0; + array2[147] = 0; + array2[148] = 0; + array2[149] = 0; + array2[150] = 0; + array2[151] = 0; + array2[152] = 0; + array2[153] = 0; + array2[154] = 0; + array2[155] = 0; + array2[156] = 0; + array2[157] = 0; + array2[158] = 0; + array2[159] = 0; + array2[160] = 0; + array2[161] = 0; + array2[162] = 0; + array2[163] = 0; + array2[164] = 0; + array2[165] = 0; + array2[166] = 0; + array2[167] = 0; + array2[168] = 0; + array2[169] = 0; + array2[170] = 0; + array2[171] = 0; + array2[172] = 0; + array2[173] = 0; + array2[174] = 0; + array2[175] = 0; + array2[176] = 0; + array2[177] = 0; + array2[178] = 0; + array2[179] = 0; + array2[180] = 0; + array2[181] = 0; + array2[182] = 0; + array2[183] = 0; + array2[184] = 0; + array2[185] = 0; + array2[186] = 0; + array2[187] = 0; + array2[188] = 0; + array2[189] = 0; + array2[190] = 0; + array2[191] = 0; + array2[192] = 0; + array2[193] = 0; + array2[194] = 0; + array2[195] = 0; + array2[196] = 0; + array2[197] = 0; + array2[198] = 0; + array2[199] = 0; + i++; + + if (i == stop) { // requires a loop limit predicate + break; + } + } + } +} diff --git a/test/hotspot/jtreg/compiler/print/PrintInlining.java b/test/hotspot/jtreg/compiler/print/PrintInlining.java index deb1ae0aae0..4b45a32949f 100644 --- a/test/hotspot/jtreg/compiler/print/PrintInlining.java +++ b/test/hotspot/jtreg/compiler/print/PrintInlining.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -23,11 +23,14 @@ /* * @test - * @bug 8022585 + * @bug 8022585 8277055 * @summary VM crashes when ran with -XX:+PrintInlining * @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining * compiler.print.PrintInlining - * + * @run main/othervm -Xcomp -XX:-TieredCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining + * compiler.print.PrintInlining + * @run main/othervm -Xcomp -XX:-TieredCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintIntrinsics + * compiler.print.PrintInlining */ package compiler.print; diff --git a/test/hotspot/jtreg/compiler/runtime/Test8168712.java b/test/hotspot/jtreg/compiler/runtime/Test8168712.java index 00cffa3e757..e411dc21479 100644 --- a/test/hotspot/jtreg/compiler/runtime/Test8168712.java +++ b/test/hotspot/jtreg/compiler/runtime/Test8168712.java @@ -22,11 +22,29 @@ */ /** - * @test + * @test id=with-dtrace * @requires vm.debug + * @requires vm.hasDTrace * @bug 8168712 * - * @run main/othervm -XX:CompileCommand=compileonly,Test8168712.* -XX:CompileCommand=compileonly,*Object.* -XX:+DTraceMethodProbes -XX:-UseOnStackReplacement -XX:+DeoptimizeRandom compiler.runtime.Test8168712 + * @run main/othervm -XX:CompileCommand=compileonly,Test8168712.* + * -XX:CompileCommand=compileonly,*Object.* + * -XX:+DTraceMethodProbes + * -XX:-UseOnStackReplacement + * -XX:+DeoptimizeRandom + * compiler.runtime.Test8168712 + */ + +/** + * @test id=without-dtrace + * @requires vm.debug + * @bug 8168712 + * + * @run main/othervm -XX:CompileCommand=compileonly,Test8168712.* + * -XX:CompileCommand=compileonly,*Object.* + * -XX:-UseOnStackReplacement + * -XX:+DeoptimizeRandom + * compiler.runtime.Test8168712 */ package compiler.runtime; diff --git a/test/hotspot/jtreg/compiler/runtime/TestConstantsInError.java b/test/hotspot/jtreg/compiler/runtime/TestConstantsInError.java new file mode 100644 index 00000000000..2f9189cd9bc --- /dev/null +++ b/test/hotspot/jtreg/compiler/runtime/TestConstantsInError.java @@ -0,0 +1,283 @@ +/* + * 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 8279822 + * @requires vm.flagless + * @library /test/lib + * @modules java.base/jdk.internal.org.objectweb.asm + * + * @run main compiler.runtime.TestConstantsInError + */ +package compiler.runtime; + +import jdk.internal.org.objectweb.asm.*; +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandleProxies; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.ArrayList; +import java.util.List; + +import static jdk.internal.org.objectweb.asm.ClassWriter.*; +import static jdk.internal.org.objectweb.asm.Opcodes.*; + +interface OutputProcessor { + default void process(OutputAnalyzer output, boolean isC1) {} +} + +public abstract class TestConstantsInError implements OutputProcessor { + static final String TEST_PREFIX = class2desc(TestConstantsInError.class) + "$Test"; + + public interface Test extends Runnable {} + + + interface Generator { + void generate(MethodVisitor mv); + } + + static String class2desc(Class cls) { + return cls.getName().replace('.', '/'); + } + + public static final String PATH = System.getProperty("test.classes", ".") + java.io.File.separator; + + static byte[] generateClassFile(String suffix, Generator g) throws IOException { + var cw = new ClassWriter(COMPUTE_MAXS | COMPUTE_FRAMES); + String name = TEST_PREFIX + "_" + suffix; + cw.visit(V17, ACC_PUBLIC | ACC_SUPER, name, null, "java/lang/Object", null); + + { + var mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "test", "()V", null, null); + mv.visitCode(); + g.generate(mv); + mv.visitInsn(RETURN); + mv.visitMaxs(0, 0); + } + byte[] classFile = cw.toByteArray(); + + try (FileOutputStream fos = new FileOutputStream(PATH + name + ".class")) { + fos.write(classFile); + } + + return classFile; + } + + static Test generate(String suffix, Class expectedError, Generator g) { + try { + byte[] classFile = generateClassFile(suffix, g); + MethodHandles.Lookup testLookup = MethodHandles.lookup().defineHiddenClass(classFile, true); + MethodHandle testMH = testLookup.findStatic(testLookup.lookupClass(), "test", MethodType.methodType(void.class)); + + testMH = MethodHandles.filterReturnValue(testMH, + MethodHandles.insertArguments( + MethodHandles.throwException(void.class, AssertionError.class), + 0, new AssertionError("no exception thrown"))); + + // Install empty handler for linkage exceptions. + testMH = MethodHandles.catchException(testMH, expectedError, + MethodHandles.empty(MethodType.methodType(void.class, expectedError))); + + return MethodHandleProxies.asInterfaceInstance(Test.class, testMH); + } catch (Throwable e) { + throw new InternalError(e); + } + } + + static void run(String name, Class expectedError, Generator g) { + Test test = generate(name, expectedError, g); + for (int i = 0; i < 1000; i++) { + test.run(); + } + } + + static class TestConstantClass extends TestConstantsInError { + public static void main(String[] args) { + run("C1", NoClassDefFoundError.class, mv -> mv.visitLdcInsn(Type.getType("LUnknownClass;"))); // non-existent class + run("C2", IllegalAccessError.class, mv -> mv.visitLdcInsn(Type.getType("Ljava/lang/invoke/LambdaForm;"))); // inaccessible + + // class loader constraints? + } + + public void process(OutputAnalyzer results, boolean isC1) { + results.shouldMatch("Test_C1/.*::test \\(3 bytes\\)$") + .shouldMatch("Test_C2/.*::test \\(3 bytes\\)$"); + + if (isC1 && Platform.isAArch64()) { // no code patching + results.shouldMatch("Test_C1/.*::test \\(3 bytes\\) made not entrant") + .shouldMatch("Test_C2/.*::test \\(3 bytes\\) made not entrant"); + } else { + results.shouldNotContain("made not entrant"); + } + } + + public void processC2(OutputAnalyzer results) { + results.shouldNotContain("made not entrant"); + } + } + + static class TestConstantMethodHandle extends TestConstantsInError { + public static void main(String[] args) { + // Non-existent holder class + run("MH1", NoClassDefFoundError.class, + mv -> mv.visitLdcInsn(new Handle(H_INVOKESTATIC, "UnknownClass", "ignored", "()V", false))); + + // Inaccessible holder class + run("MH2", IllegalAccessError.class, + mv -> mv.visitLdcInsn(new Handle(H_INVOKESTATIC, "java/lang/invoke/LambdaForm", "ignored", "()V", false))); + + // Method vs InterfaceMethod mismatch + run("MH3", IncompatibleClassChangeError.class, + mv -> mv.visitLdcInsn(new Handle(H_INVOKESTATIC, "java/lang/Object", "ignored", "()V", true))); + + // Non-existent method + run("MH4", NoSuchMethodError.class, + mv -> mv.visitLdcInsn(new Handle(H_INVOKESTATIC, "java/lang/Object", "cast", "()V", false))); + } + + public void process(OutputAnalyzer results, boolean isC1) { + results.shouldMatch("Test_MH1/.*::test \\(3 bytes\\)$") + .shouldMatch("Test_MH2/.*::test \\(3 bytes\\)$") + .shouldMatch("Test_MH3/.*::test \\(3 bytes\\)$") + .shouldMatch("Test_MH4/.*::test \\(3 bytes\\)$"); + + if (isC1 && Platform.isAArch64()) { // no code patching + results.shouldMatch("Test_MH1/.*::test \\(3 bytes\\) made not entrant") + .shouldMatch("Test_MH2/.*::test \\(3 bytes\\) made not entrant") + .shouldMatch("Test_MH3/.*::test \\(3 bytes\\) made not entrant") + .shouldMatch("Test_MH4/.*::test \\(3 bytes\\) made not entrant"); + } else { + results.shouldNotContain("made not entrant"); + } + } + } + + static class TestConstantMethodType extends TestConstantsInError { + public static void main(String[] args) { + run("MT1", NoClassDefFoundError.class, + mv -> mv.visitLdcInsn(Type.getMethodType("(LUnknownClass;)V"))); + run("MT2", NoClassDefFoundError.class, + mv -> mv.visitLdcInsn(Type.getMethodType("()LUnknownClass;"))); + } + + public void process(OutputAnalyzer results, boolean isC1) { + results.shouldMatch("Test_MT1/.*::test \\(3 bytes\\)$") + .shouldMatch("Test_MT2/.*::test \\(3 bytes\\)$"); + + if (isC1 && Platform.isAArch64()) { // no code patching + results.shouldMatch("Test_MT1/.*::test \\(3 bytes\\) made not entrant") + .shouldMatch("Test_MT2/.*::test \\(3 bytes\\) made not entrant"); + } else { + results.shouldNotContain("made not entrant"); + } + } + } + + static class TestConstantDynamic extends TestConstantsInError { + static int bsm1() throws Exception { + throw new AssertionError("should not be invoked"); + } + + static int bsm2(MethodHandles.Lookup lookup, String name, Class c) throws Exception { + throw new Exception("expected"); + } + + static final Handle BSM1 = new Handle(H_INVOKESTATIC, class2desc(TestConstantDynamic.class), "bsm1", "()I", false); + static final Handle BSM2 = new Handle(H_INVOKESTATIC, class2desc(TestConstantDynamic.class), "bsm2", + "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)I", + false); + + public static void main(String[] args) { + run("CD1", NoClassDefFoundError.class, + mv -> { + Handle bsm = new Handle(H_INVOKESTATIC, "UnknownClass", "unknown", "()LUnknownClass;", false); + mv.visitLdcInsn(new ConstantDynamic("tmp", "LUnknownClass;", bsm)); + }); + run("CD2", NoSuchMethodError.class, + mv -> { + Handle bsm = new Handle(H_INVOKESTATIC, class2desc(TestConstantDynamic.class), "unknown", "()I", false); + mv.visitLdcInsn(new ConstantDynamic("tmp", "LUnknownClass;", bsm)); + }); + run("CD3", BootstrapMethodError.class, mv -> mv.visitLdcInsn(new ConstantDynamic("tmp", "I", BSM1))); + run("CD4", BootstrapMethodError.class, mv -> mv.visitLdcInsn(new ConstantDynamic("tmp", "I", BSM2))); + } + + public void process(OutputAnalyzer results, boolean isC1) { + if (isC1) { + results.shouldMatch("Test_CD1.*::test \\(3 bytes\\) COMPILE SKIPPED: could not resolve a constant") + .shouldMatch("Test_CD2.*::test \\(3 bytes\\) COMPILE SKIPPED: could not resolve a constant") + .shouldMatch("Test_CD3.*::test \\(3 bytes\\) COMPILE SKIPPED: could not resolve a constant") + .shouldMatch("Test_CD4.*::test \\(3 bytes\\) COMPILE SKIPPED: could not resolve a constant"); + } else { + results.shouldMatch("Test_CD1.*::test \\(3 bytes\\)$") + .shouldMatch("Test_CD2.*::test \\(3 bytes\\)$") + .shouldMatch("Test_CD3.*::test \\(3 bytes\\)$") + .shouldMatch("Test_CD4.*::test \\(3 bytes\\)$"); + } + } + } + + static void run(TestConstantsInError test) throws Exception { + List commonArgs = List.of( + "--add-exports", "java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED", + "-Xbatch", "-XX:CompileThreshold=100", + "-XX:CompileCommand=quiet", "-XX:CompileCommand=compileonly,*::test", + "-XX:+PrintCompilation", + "-XX:CompileCommand=print,*::test", + "-Dtest.classes=" + System.getProperty("test.classes", "."), + "-XX:+IgnoreUnrecognizedVMOptions", + test.getClass().getName()); + + ArrayList c1Args = new ArrayList<>(); + c1Args.addAll(List.of("-XX:+TieredCompilation", "-XX:TieredStopAtLevel=1", "-XX:+TracePatching")); + c1Args.addAll(commonArgs); + + OutputAnalyzer outputC1 = ProcessTools.executeTestJvm(c1Args) + .shouldHaveExitValue(0); + + test.process(outputC1, true); + + ArrayList c2Args = new ArrayList<>(); + c2Args.add("-XX:-TieredCompilation"); + c2Args.addAll(commonArgs); + + OutputAnalyzer outputC2 = ProcessTools.executeTestJvm(c2Args) + .shouldHaveExitValue(0); + + test.process(outputC2, false); + } + + public static void main(String[] args) throws Exception { + run(new TestConstantClass()); + run(new TestConstantMethodType()); + run(new TestConstantMethodHandle()); + run(new TestConstantDynamic()); + } +} diff --git a/test/hotspot/jtreg/compiler/vectorapi/Test8278948.java b/test/hotspot/jtreg/compiler/vectorapi/Test8278948.java new file mode 100644 index 00000000000..5218e10c4af --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/Test8278948.java @@ -0,0 +1,82 @@ +/* + * 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. + */ + +package compiler.vectorapi; + +import java.util.Random; +import jdk.incubator.vector.ByteVector; +import jdk.incubator.vector.DoubleVector; +import jdk.incubator.vector.ShortVector; +import jdk.test.lib.Asserts; +import jdk.test.lib.Utils; + +/* + * @test + * @bug 8278948 + * @summary Intermediate integer promotion vector length encoding is calculated incorrectly on x86 + * @modules jdk.incubator.vector + * @library /test/lib + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:CompileThreshold=100 -XX:UseAVX=1 + * compiler.vectorapi.Test8278948 + */ +public class Test8278948 { + static final int INVOCATIONS = 10000; + + static final Random random = Utils.getRandomInstance(); + static final byte[] BYTES = new byte[8]; + static final short[] SHORTS = new short[4]; + static final double[] DOUBLES = new double[4]; + + + public static void main(String[] args) { + for (int i = 0; i < INVOCATIONS; i++) { + for (int j = 0; j < DOUBLES.length; j++) { + BYTES[j] = (byte)random.nextInt(); + } + bytesToDoubles(); + for (int j = 0; j < DOUBLES.length; j++) { + Asserts.assertEquals((double)BYTES[j], DOUBLES[j]); + } + + for (int j = 0; j < DOUBLES.length; j++) { + SHORTS[j] = (short)random.nextInt(); + } + shortsToDoubles(); + for (int j = 0; j < DOUBLES.length; j++) { + Asserts.assertEquals((double)SHORTS[j], DOUBLES[j]); + } + } + } + + static void bytesToDoubles() { + ((DoubleVector)ByteVector.fromArray(ByteVector.SPECIES_64, BYTES, 0) + .castShape(DoubleVector.SPECIES_256, 0)) + .intoArray(DOUBLES, 0); + } + + static void shortsToDoubles() { + ((DoubleVector)ShortVector.fromArray(ShortVector.SPECIES_64, SHORTS, 0) + .castShape(DoubleVector.SPECIES_256, 0)) + .intoArray(DOUBLES, 0); + } +} diff --git a/test/hotspot/jtreg/containers/docker/TestMisc.java b/test/hotspot/jtreg/containers/docker/TestMisc.java index e242bdf6632..5625fe828bb 100644 --- a/test/hotspot/jtreg/containers/docker/TestMisc.java +++ b/test/hotspot/jtreg/containers/docker/TestMisc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -56,6 +56,7 @@ public static void main(String[] args) throws Exception { testMinusContainerSupport(); testIsContainerized(); testPrintContainerInfo(); + testPrintContainerInfoActiveProcessorCount(); } finally { DockerTestUtils.removeDockerImage(imageName); } @@ -92,6 +93,15 @@ private static void testPrintContainerInfo() throws Exception { checkContainerInfo(Common.run(opts)); } + private static void testPrintContainerInfoActiveProcessorCount() throws Exception { + Common.logNewTestCase("Test print_container_info()"); + + DockerRunOptions opts = Common.newOpts(imageName, "PrintContainerInfo").addJavaOpts("-XX:ActiveProcessorCount=2"); + Common.addWhiteBoxOpts(opts); + + OutputAnalyzer out = Common.run(opts); + out.shouldContain("but overridden by -XX:ActiveProcessorCount 2"); + } private static void checkContainerInfo(OutputAnalyzer out) throws Exception { String[] expectedToContain = new String[] { diff --git a/test/hotspot/jtreg/gc/TestSystemGC.java b/test/hotspot/jtreg/gc/TestSystemGC.java index bbe17f2b4bc..9cef6bbdb01 100644 --- a/test/hotspot/jtreg/gc/TestSystemGC.java +++ b/test/hotspot/jtreg/gc/TestSystemGC.java @@ -24,35 +24,48 @@ package gc; /* - * @test TestSystemGCSerial + * @test id=Serial * @requires vm.gc.Serial * @summary Runs System.gc() with different flags. * @run main/othervm -XX:+UseSerialGC gc.TestSystemGC + * @run main/othervm -XX:+UseSerialGC -XX:+UseLargePages gc.TestSystemGC */ /* - * @test TestSystemGCParallel + * @test id=Parallel * @requires vm.gc.Parallel * @summary Runs System.gc() with different flags. * @run main/othervm -XX:+UseParallelGC gc.TestSystemGC + * @run main/othervm -XX:+UseParallelGC -XX:+UseLargePages gc.TestSystemGC */ /* - * @test TestSystemGCG1 + * @test id=G1 * @requires vm.gc.G1 * @summary Runs System.gc() with different flags. * @run main/othervm -XX:+UseG1GC gc.TestSystemGC * @run main/othervm -XX:+UseG1GC -XX:+ExplicitGCInvokesConcurrent gc.TestSystemGC - * @run main/othervm -XX:+UseLargePages gc.TestSystemGC - */ + * @run main/othervm -XX:+UseG1GC -XX:+UseLargePages gc.TestSystemGC + */ /* - * @test TestSystemGCShenandoah + * @test id=Shenandoah * @requires vm.gc.Shenandoah * @summary Runs System.gc() with different flags. - * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC gc.TestSystemGC - * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+ExplicitGCInvokesConcurrent gc.TestSystemGC + * @run main/othervm -XX:+UseShenandoahGC gc.TestSystemGC + * @run main/othervm -XX:+UseShenandoahGC -XX:+ExplicitGCInvokesConcurrent gc.TestSystemGC + * @run main/othervm -XX:+UseShenandoahGC -XX:+UseLargePages gc.TestSystemGC + */ + +/* + * @test id=Z + * @requires vm.gc.Z + * @comment ZGC will not start when LargePages cannot be allocated, therefore + * we do not run such configuration. + * @summary Runs System.gc() with different flags. + * @run main/othervm -XX:+UseZGC gc.TestSystemGC */ + public class TestSystemGC { public static void main(String args[]) throws Exception { System.gc(); diff --git a/test/hotspot/jtreg/gc/g1/mixedgc/TestOldGenCollectionUsage.java b/test/hotspot/jtreg/gc/g1/mixedgc/TestOldGenCollectionUsage.java index 916e1b85722..49ecf89f726 100644 --- a/test/hotspot/jtreg/gc/g1/mixedgc/TestOldGenCollectionUsage.java +++ b/test/hotspot/jtreg/gc/g1/mixedgc/TestOldGenCollectionUsage.java @@ -139,8 +139,8 @@ public void run() { if (newCollectionCount <= collectionCount) { throw new RuntimeException("No new collection"); } - if (newCollectionTime <= collectionTime) { - throw new RuntimeException("Collector has not run some more"); + if (newCollectionTime < collectionTime) { + throw new RuntimeException("Collection time ran backwards"); } System.out.println("Test passed."); diff --git a/test/hotspot/jtreg/gc/g1/plab/TestPLABEvacuationFailure.java b/test/hotspot/jtreg/gc/g1/plab/TestPLABEvacuationFailure.java index 35e6339fe6c..0cebc725261 100644 --- a/test/hotspot/jtreg/gc/g1/plab/TestPLABEvacuationFailure.java +++ b/test/hotspot/jtreg/gc/g1/plab/TestPLABEvacuationFailure.java @@ -68,7 +68,7 @@ public class TestPLABEvacuationFailure { "failure wasted")); private static final String[] COMMON_OPTIONS = { - "-Xlog:gc=debug,gc+phases=trace", + "-Xlog:gc,gc+plab=debug", "-XX:+UseG1GC", "-XX:InitiatingHeapOccupancyPercent=100", "-XX:-G1UseAdaptiveIHOP", diff --git a/test/hotspot/jtreg/gc/g1/plab/lib/LogParser.java b/test/hotspot/jtreg/gc/g1/plab/lib/LogParser.java index e23fb9c65da..d8096d1aab8 100644 --- a/test/hotspot/jtreg/gc/g1/plab/lib/LogParser.java +++ b/test/hotspot/jtreg/gc/g1/plab/lib/LogParser.java @@ -190,13 +190,17 @@ public Map getExcludedSpecifiedStats(List specifiedGcIdFor } private Map getSpecifiedStats(List gcIds, LogParser.ReportType type, List fieldNames, boolean extractId) { - return new HashMap<>( - getEntries().entryStream() - .filter(gcLogItem -> extractId == gcIds.contains(gcLogItem.getKey())) - .collect(Collectors.toMap(gcLogItem -> gcLogItem.getKey(), - gcLogItem -> gcLogItem.getValue().get(type).filter(fieldNames) + var map = new HashMap<>( + getEntries().entryStream() + .filter(gcLogItem -> extractId == gcIds.contains(gcLogItem.getKey())) + .collect(Collectors.toMap(gcLogItem -> gcLogItem.getKey(), + gcLogItem -> gcLogItem.getValue().get(type).filter(fieldNames) + ) ) - ) - ); + ); + if (map.isEmpty()) { + throw new RuntimeException("Cannot find relevant PLAB statistics in the log"); + } + return map; } } diff --git a/test/hotspot/jtreg/gc/shenandoah/compiler/TestBarrierAboveProj.java b/test/hotspot/jtreg/gc/shenandoah/compiler/TestBarrierAboveProj.java new file mode 100644 index 00000000000..560b6f34617 --- /dev/null +++ b/test/hotspot/jtreg/gc/shenandoah/compiler/TestBarrierAboveProj.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8281811 + * @summary assert(_base == Tuple) failed: Not a Tuple after JDK-8280799 + * @requires vm.gc.Shenandoah + * @run main/othervm -XX:+UseShenandoahGC -XX:-BackgroundCompilation -XX:LoopMaxUnroll=1 TestBarrierAboveProj + */ + + +public class TestBarrierAboveProj { + private static C objField = new C(); + private static final Object[] arrayField = new Object[1000]; + private static volatile int volatileField; + + public static void main(String[] args) { + for (int i = 0; i < 20_000; i++) { + test1(); + test2(); + } + } + + private static float test1() { + float v = 1; + for (int i = 1; i < 1000; i++) { + if (objField == arrayField[i]) { + return v; + } + v *= 2; + } + return v; + } + + private static float test2() { + float v = 1; + volatileField = 0x42; + for (int i = 1; i < 1000; i++) { + if (objField == arrayField[i]) { + return v; + } + v *= 2; + } + return v; + } + + private static class C { + public float floatField; + } +} diff --git a/test/hotspot/jtreg/resourcehogs/compiler/intrinsics/string/TestStringIntrinsics2LargeArray.java b/test/hotspot/jtreg/resourcehogs/compiler/intrinsics/string/TestStringIntrinsics2LargeArray.java new file mode 100644 index 00000000000..7a224abab14 --- /dev/null +++ b/test/hotspot/jtreg/resourcehogs/compiler/intrinsics/string/TestStringIntrinsics2LargeArray.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016 SAP SE. 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8254790 + * @requires vm.bits == "64" & os.maxMemory > 8G + * @modules java.base/jdk.internal.misc + * @library /test/lib /test/hotspot/jtreg + * + * @build compiler.intrinsics.string.TestStringIntrinsics2 + * @build sun.hotspot.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox + * + * @run main/othervm + * -mx8G + * -Xbootclasspath/a:. + * -Xmixed + * -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions + * -XX:MaxInlineSize=70 + * -XX:MinInlineFrequencyRatio=0 + * resourcehogs.compiler.intrinsics.string.TestStringIntrinsics2LargeArray + */ + +package resourcehogs.compiler.intrinsics.string; + +import java.lang.ref.Reference; + +import compiler.intrinsics.string.TestStringIntrinsics2; + +public final class TestStringIntrinsics2LargeArray { + public static void main(String[] args) throws Exception { + int[] hugeArray = new int[Integer.MAX_VALUE / 2]; + TestStringIntrinsics2.main(args); + Reference.reachabilityFence(hugeArray); + } +} diff --git a/test/hotspot/jtreg/runtime/8176717/TestInheritFD.java b/test/hotspot/jtreg/runtime/8176717/TestInheritFD.java index 04a739079f9..37c5280d236 100644 --- a/test/hotspot/jtreg/runtime/8176717/TestInheritFD.java +++ b/test/hotspot/jtreg/runtime/8176717/TestInheritFD.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -79,6 +79,7 @@ public class TestInheritFD { public static final String RETAINS_FD = "VM RESULT => RETAINS FD"; public static final String EXIT = "VM RESULT => VM EXIT"; public static final String LOG_SUFFIX = ".strangelogsuffixthatcanbecheckedfor"; + public static final String USER_DIR = System.getProperty("user.dir"); // first VM public static void main(String[] args) throws Exception { @@ -187,10 +188,10 @@ static Optional lsofCommand() { static Collection outputContainingFilenames() { long pid = ProcessHandle.current().pid(); - String[] command = lsofCommand().orElseThrow(() -> new RuntimeException("lsof like command not found")); - System.out.println("using command: " + command[0] + " " + command[1]); - return run(command[0], command[1], "" + pid).collect(toList()); + // Only search the directory in which the VM is running (user.dir property). + System.out.println("using command: " + command[0] + " -a +d " + USER_DIR + " " + command[1] + " " + pid); + return run(command[0], "-a", "+d", USER_DIR, command[1], "" + pid).collect(toList()); } static boolean findOpenLogFile(Collection fileNames) { diff --git a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java index 23471904a3e..d4ba080c6f8 100644 --- a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java +++ b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java @@ -223,8 +223,8 @@ public static void smallHeapTestWith1GNoCoop() throws Exception { "-XX:+VerifyBeforeGC", "-version"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("Narrow klass base: 0x0000000000000000"); - if (!Platform.isAArch64()) { - // Currently relax this test for Aarch64. + if (!Platform.isAArch64() && !Platform.isPPC()) { + // Currently relax this test for Aarch64 and ppc. output.shouldContain("Narrow klass shift: 0"); } output.shouldHaveExitValue(0); @@ -243,8 +243,8 @@ public static void largeHeapTestNoCoop() throws Exception { "-XX:+VerifyBeforeGC", "-version"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("Narrow klass base: 0x0000000000000000"); - if (!Platform.isAArch64()) { - // Currently relax this test for Aarch64. + if (!Platform.isAArch64() && !Platform.isPPC()) { + // Currently relax this test for Aarch64 and ppc. output.shouldContain("Narrow klass shift: 0"); } output.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/runtime/EnclosingMethodAttr/EnclMethodAttr.java b/test/hotspot/jtreg/runtime/EnclosingMethodAttr/EnclMethodAttr.java index 605a8a9a700..db6b924078b 100644 --- a/test/hotspot/jtreg/runtime/EnclosingMethodAttr/EnclMethodAttr.java +++ b/test/hotspot/jtreg/runtime/EnclosingMethodAttr/EnclMethodAttr.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -44,6 +44,7 @@ public static void main(String args[]) throws Throwable { System.out.println("Regression test for bug 8044738"); ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("EnclMethTest"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotHaveExitValue(0); output.shouldContain("java.lang.ClassFormatError: Wrong EnclosingMethod"); } } diff --git a/test/hotspot/jtreg/runtime/Monitor/MonitorUsedDeflationThresholdTest.java b/test/hotspot/jtreg/runtime/Monitor/MonitorUsedDeflationThresholdTest.java index 1260234f164..0a6b602faf8 100644 --- a/test/hotspot/jtreg/runtime/Monitor/MonitorUsedDeflationThresholdTest.java +++ b/test/hotspot/jtreg/runtime/Monitor/MonitorUsedDeflationThresholdTest.java @@ -80,6 +80,11 @@ public static void main(String[] args) throws Exception { // of monitors for threads that call Object.wait(). "-XX:+UnlockDiagnosticVMOptions", "-XX:AvgMonitorsPerThreadEstimate=1", + // MonitorUsedDeflationThreshold == 10 means we'll request + // deflations when 10% of monitors are used rather than the + // default 90%. This should allow the test to tolerate a burst + // of used monitors by threads not under this test's control. + "-XX:MonitorUsedDeflationThreshold=10", // Enable monitorinflation logging so we can see that // MonitorUsedDeflationThreshold and // NoAsyncDeflationProgressMaxoption are working. @@ -88,8 +93,9 @@ public static void main(String[] args) throws Exception { "-Xlog:safepoint+cleanup=info", "-Xlog:safepoint+stats=debug", // Run the test with inflate_count == 33 since that - // reproduced the bug with JDK13. Anything above the - // in_use_list_ceiling will do the trick. + // reproduced the bug with JDK13. With inflate_count == 33, an + // initial ceiling == 12 and MonitorUsedDeflationThreshold == 10, + // we should hit NoAsyncDeflationProgressMax at least 3 times. "MonitorUsedDeflationThresholdTest", "33"); OutputAnalyzer output_detail = new OutputAnalyzer(pb.start()); @@ -110,6 +116,8 @@ public static void main(String[] args) throws Exception { throw new RuntimeException("Did not find too_many string in output.\n"); } System.out.println("too_many='" + too_many + "'"); + // Uncomment the following line for dumping test output in passing runs: + // output_detail.reportDiagnosticSummary(); System.out.println("PASSED."); return; diff --git a/test/hotspot/jtreg/runtime/Nestmates/protectionDomain/TestDifferentProtectionDomains.java b/test/hotspot/jtreg/runtime/Nestmates/protectionDomain/TestDifferentProtectionDomains.java index 83c4d260c1b..cbf4dbdc6d8 100644 --- a/test/hotspot/jtreg/runtime/Nestmates/protectionDomain/TestDifferentProtectionDomains.java +++ b/test/hotspot/jtreg/runtime/Nestmates/protectionDomain/TestDifferentProtectionDomains.java @@ -29,7 +29,8 @@ * perform a nestmate access check. * @comment We use WB to force-compile a constructor to recreate the original * failure scenario, so only run when we have "normal" compiler flags. - * @requires vm.compMode=="Xmixed" & + * @requires vm.compMode == "Xmixed" & + * vm.compiler2.enabled & * (vm.opt.TieredStopAtLevel == null | vm.opt.TieredStopAtLevel == 4) * @library /test/lib / * @build sun.hotspot.WhiteBox @@ -110,7 +111,9 @@ public static void main(String[] args) throws Throwable { // Force the constructor to compile, which then triggers the nestmate // access check in the compiler thread, which leads to the original bug. - wb.enqueueMethodForCompilation(cons, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION); + if (!wb.enqueueMethodForCompilation(cons, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION)) { + throw new RuntimeException("Failed to queue constructor for compilation"); + } while (!wb.isMethodCompiled(cons)) { Thread.sleep(100); } diff --git a/test/hotspot/jtreg/runtime/SelectionResolution/classes/selectionresolution/ClassBuilder.java b/test/hotspot/jtreg/runtime/SelectionResolution/classes/selectionresolution/ClassBuilder.java index 445a137e0f4..b453c64de12 100644 --- a/test/hotspot/jtreg/runtime/SelectionResolution/classes/selectionresolution/ClassBuilder.java +++ b/test/hotspot/jtreg/runtime/SelectionResolution/classes/selectionresolution/ClassBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -112,7 +112,7 @@ private void addHelperMethod(int classId) { int packageId = classdata.get(classId).packageId.ordinal(); Clazz C = helpers[packageId]; if (C == null) { - C = new Clazz(getPackageName(packageId) + "Helper", -1, ACC_PUBLIC); + C = new Clazz(getPackageName(packageId) + "Helper", ACC_PUBLIC, -1); helpers[packageId] = C; classes.add(C); } diff --git a/test/hotspot/jtreg/runtime/SelectionResolution/classes/selectionresolution/Clazz.java b/test/hotspot/jtreg/runtime/SelectionResolution/classes/selectionresolution/Clazz.java index 45c2d6d1b92..141e5743595 100644 --- a/test/hotspot/jtreg/runtime/SelectionResolution/classes/selectionresolution/Clazz.java +++ b/test/hotspot/jtreg/runtime/SelectionResolution/classes/selectionresolution/Clazz.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -69,7 +69,7 @@ public Clazz(String name, String extending, int access, int index, String... imp * @param implementing Interfaces implemented */ public Clazz(String name, String extending, int access, int classFileVersion, int index, String... implementing) { - super(name, extending == null ? "java/lang/Object" : extending, access + ACC_SUPER, classFileVersion, index, implementing); + super(name, extending == null ? "java/lang/Object" : extending, access | ACC_SUPER, classFileVersion, index, implementing); // Add the default constructor addMethod("", "()V", ACC_PUBLIC).makeConstructor(extending, false); } diff --git a/test/hotspot/jtreg/runtime/SelectionResolution/classes/selectionresolution/TestBuilder.java b/test/hotspot/jtreg/runtime/SelectionResolution/classes/selectionresolution/TestBuilder.java index 8fdf98bfe45..47eea703f76 100644 --- a/test/hotspot/jtreg/runtime/SelectionResolution/classes/selectionresolution/TestBuilder.java +++ b/test/hotspot/jtreg/runtime/SelectionResolution/classes/selectionresolution/TestBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -36,7 +36,7 @@ public TestBuilder(int classId, SelectionResolutionTestCase testcase) { super(testcase); // Make a public class Test that contains all our test methods - testClass = new Clazz("Test", null, -1, ACC_PUBLIC); + testClass = new Clazz("Test", null, ACC_PUBLIC, -1); // Add a main method mainMethod = testClass.addMethod("main", "([Ljava/lang/String;)V", ACC_PUBLIC + ACC_STATIC); diff --git a/test/hotspot/jtreg/runtime/Thread/Fibonacci.java b/test/hotspot/jtreg/runtime/Thread/Fibonacci.java index 271295a73cc..a7ff3f76879 100644 --- a/test/hotspot/jtreg/runtime/Thread/Fibonacci.java +++ b/test/hotspot/jtreg/runtime/Thread/Fibonacci.java @@ -28,6 +28,7 @@ * This test is skipped on 32-bit Windows: limited virtual space on Win-32 * make this test inherently unstable on Windows with 32-bit VM data model. * @requires !(os.family == "windows" & sun.arch.data.model == "32") + * @requires !(os.family == "linux" & os.maxMemory < 512M) * @modules java.base/jdk.internal.misc * @library /test/lib * @run main/othervm Fibonacci 15 diff --git a/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java b/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java index d23c80c9c42..1a6523d9c0e 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java @@ -31,7 +31,8 @@ * @build sun.hotspot.WhiteBox * @compile test-classes/Hello.java * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SharedArchiveConsistency + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SharedArchiveConsistency on + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SharedArchiveConsistency auto */ import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.Utils; @@ -69,6 +70,9 @@ public class SharedArchiveConsistency { public static int int_size; // size of int public static long alignment; // MetaspaceShared::core_region_alignment + public static boolean shareAuto; // true == -Xshare:auto + // false == -Xshare:on + // The following should be consistent with the enum in the C++ MetaspaceShared class public static String[] shared_region_name = { "rw", // ReadWrite @@ -80,6 +84,8 @@ public class SharedArchiveConsistency { "last_open_archive" }; + public static final String HELLO_WORLD = "Hello World"; + public static int num_regions = shared_region_name.length; public static String[] matchMessages = { "Unable to use shared archive", @@ -339,7 +345,7 @@ public static void setReadWritePermission(File file) throws Exception { } public static void testAndCheck(String[] execArgs) throws Exception { - OutputAnalyzer output = TestCommon.execCommon(execArgs); + OutputAnalyzer output = shareAuto ? TestCommon.execAuto(execArgs) : TestCommon.execCommon(execArgs); String stdtxt = output.getOutput(); System.out.println("Note: this test may fail in very rare occasions due to CRC32 checksum collision"); for (String message : matchMessages) { @@ -361,6 +367,14 @@ public static void testAndCheck(String[] execArgs) throws Exception { // 6) insert bytes in data begining // 7) randomly corrupt data in each region specified by shared_region_name[] public static void main(String... args) throws Exception { + if (args.length != 1) { + throw new RuntimeException("One arg of 'on' or 'auto' to run the test"); + } + if (!args[0].equals("on") && !args[0].equals("auto")) { + throw new RuntimeException("Arg must be 'on' or 'auto'"); + } + shareAuto = args[0].equals("auto"); + // must call to get offset info first!!! getFileOffsetInfo(); Path currentRelativePath = Paths.get(""); @@ -380,10 +394,10 @@ public static void main(String... args) throws Exception { // VerifySharedSpaces enabled to detect inconsistencies String[] verifyExecArgs = {"-Xlog:cds", "-XX:+VerifySharedSpaces", "-cp", jarFile, "Hello"}; - OutputAnalyzer output = TestCommon.execCommon(execArgs); + OutputAnalyzer output = shareAuto ? TestCommon.execAuto(execArgs) : TestCommon.execCommon(execArgs); try { - TestCommon.checkExecReturn(output, 0, true, "Hello World"); + TestCommon.checkExecReturn(output, 0, true, HELLO_WORLD); } catch (Exception e) { TestCommon.checkExecReturn(output, 1, true, matchMessages[0]); } @@ -397,36 +411,42 @@ public static void main(String... args) throws Exception { // modify jsa header, test should fail System.out.println("\n2. Corrupt header, should fail\n"); modifyJsaHeader(copyFile(orgJsaFile, "corrupt-header")); - output = TestCommon.execCommon(execArgs); + output = shareAuto ? TestCommon.execAuto(execArgs) : TestCommon.execCommon(execArgs); output.shouldContain("The shared archive file has a bad magic number"); output.shouldNotContain("Checksum verification failed"); + if (shareAuto) { + output.shouldContain(HELLO_WORLD); + } // modify _jvm_ident, test should fail System.out.println("\n2a. Corrupt _jvm_ident, should fail\n"); modifyJvmIdent(copyFile(orgJsaFile, "modify-jvm-ident")); - output = TestCommon.execCommon(execArgs); + output = shareAuto ? TestCommon.execAuto(execArgs) : TestCommon.execCommon(execArgs); output.shouldContain("The shared archive file was created by a different version or build of HotSpot"); output.shouldNotContain("Checksum verification failed"); - - // use the same archive as above, but run with -Xshare:auto - System.out.println("\n2b. Corrupt _jvm_ident run with -Xshare:auto\n"); - output = TestCommon.execAuto(execArgs); - output.shouldContain("The shared archive file was created by a different version or build of HotSpot"); - output.shouldContain("Hello World"); + if (shareAuto) { + output.shouldContain(HELLO_WORLD); + } // modify _magic, test should fail System.out.println("\n2c. Corrupt _magic, should fail\n"); modifyHeaderIntField(copyFile(orgJsaFile, "modify-magic"), offset_magic, 0x00000000); - output = TestCommon.execCommon(execArgs); + output = shareAuto ? TestCommon.execAuto(execArgs) : TestCommon.execCommon(execArgs); output.shouldContain("The shared archive file has a bad magic number"); output.shouldNotContain("Checksum verification failed"); + if (shareAuto) { + output.shouldContain(HELLO_WORLD); + } // modify _version, test should fail System.out.println("\n2d. Corrupt _version, should fail\n"); modifyHeaderIntField(copyFile(orgJsaFile, "modify-version"), offset_version, 0x00000000); - output = TestCommon.execCommon(execArgs); + output = shareAuto ? TestCommon.execAuto(execArgs) : TestCommon.execCommon(execArgs); output.shouldContain("The shared archive file has the wrong version"); output.shouldNotContain("Checksum verification failed"); + if (shareAuto) { + output.shouldContain(HELLO_WORLD); + } // modify content inside regions System.out.println("\n3. Corrupt Content, should fail\n"); @@ -442,9 +462,12 @@ public static void main(String... args) throws Exception { File newJsaFile = copyFile(orgJsaFile, "header-and-content"); modifyJsaHeader(newJsaFile); modifyJsaContent(0, newJsaFile); // this will not be reached since failed on header change first - output = TestCommon.execCommon(execArgs); + output = shareAuto ? TestCommon.execAuto(execArgs) : TestCommon.execCommon(execArgs); output.shouldContain("The shared archive file has a bad magic number"); output.shouldNotContain("Checksum verification failed"); + if (shareAuto) { + output.shouldContain(HELLO_WORLD); + } // delete bytes in data section System.out.println("\n5. Delete bytes at beginning of data section, should fail\n"); diff --git a/test/hotspot/jtreg/runtime/logging/ClassInitializationTest.java b/test/hotspot/jtreg/runtime/logging/ClassInitializationTest.java index cb9b03f77bb..b88d3620f47 100644 --- a/test/hotspot/jtreg/runtime/logging/ClassInitializationTest.java +++ b/test/hotspot/jtreg/runtime/logging/ClassInitializationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -45,6 +45,7 @@ public static void main(String... args) throws Exception { "-Xmx128m", "BadMap50"); OutputAnalyzer out = new OutputAnalyzer(pb.start()); + out.shouldNotHaveExitValue(0); out.shouldContain("Start class verification for:"); out.shouldContain("End class verification for:"); out.shouldContain("Initializing"); @@ -69,6 +70,7 @@ public static void main(String... args) throws Exception { "-Xmx128m", "BadMap50"); out = new OutputAnalyzer(pb.start()); + out.shouldNotHaveExitValue(0); out.shouldNotContain("[class,init]"); out.shouldNotContain("Fail over class verification to old verifier for: BadMap50"); diff --git a/test/hotspot/jtreg/runtime/logging/ClassResolutionTest.java b/test/hotspot/jtreg/runtime/logging/ClassResolutionTest.java index 18b74e26353..770515bd12d 100644 --- a/test/hotspot/jtreg/runtime/logging/ClassResolutionTest.java +++ b/test/hotspot/jtreg/runtime/logging/ClassResolutionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -62,6 +62,7 @@ public static void main(String... args) throws Exception { ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:class+resolve=debug", ClassResolutionTestMain.class.getName()); OutputAnalyzer o = new OutputAnalyzer(pb.start()); + o.shouldHaveExitValue(0); o.shouldContain("[class,resolve] ClassResolutionTest$ClassResolutionTestMain$Thing1Handler ClassResolutionTest$ClassResolutionTestMain$Thing1"); o.shouldContain("[class,resolve] resolve JVM_CONSTANT_MethodHandle"); @@ -70,6 +71,7 @@ public static void main(String... args) throws Exception { "-Xlog:class+resolve=off", ClassResolutionTestMain.class.getName()); o = new OutputAnalyzer(pb.start()); + o.shouldHaveExitValue(0); o.shouldNotContain("[class,resolve]"); }; diff --git a/test/hotspot/jtreg/runtime/logging/CondyIndyTest.java b/test/hotspot/jtreg/runtime/logging/CondyIndyTest.java index 61c0996b079..f04fcfa9cba 100644 --- a/test/hotspot/jtreg/runtime/logging/CondyIndyTest.java +++ b/test/hotspot/jtreg/runtime/logging/CondyIndyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -42,6 +42,7 @@ public static void main(String... args) throws Exception { ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:methodhandles", "CondyIndy"); OutputAnalyzer o = new OutputAnalyzer(pb.start()); + o.shouldHaveExitValue(0); o.shouldContain("[info][methodhandles"); o.shouldNotContain("[debug][methodhandles,indy"); o.shouldNotContain("[debug][methodhandles,condy"); @@ -50,6 +51,7 @@ public static void main(String... args) throws Exception { pb = ProcessTools.createJavaProcessBuilder("-Xlog:methodhandles+condy=debug", "CondyIndy"); o = new OutputAnalyzer(pb.start()); + o.shouldHaveExitValue(0); o.shouldNotContain("[info ][methodhandles"); o.shouldNotContain("[debug][methodhandles,indy"); o.shouldContain("[debug][methodhandles,condy"); @@ -58,6 +60,7 @@ public static void main(String... args) throws Exception { pb = ProcessTools.createJavaProcessBuilder("-Xlog:methodhandles+indy=debug", "CondyIndy"); o = new OutputAnalyzer(pb.start()); + o.shouldHaveExitValue(0); o.shouldNotContain("[info ][methodhandles"); o.shouldContain("[debug][methodhandles,indy"); o.shouldNotContain("[debug][methodhandles,condy"); @@ -68,6 +71,7 @@ public static void main(String... args) throws Exception { "-Xlog:methodhandles+indy=debug", "CondyIndy"); o = new OutputAnalyzer(pb.start()); + o.shouldHaveExitValue(0); o.shouldContain("[info ][methodhandles"); o.shouldContain("[debug][methodhandles,indy"); o.shouldContain("[debug][methodhandles,condy"); diff --git a/test/hotspot/jtreg/runtime/logging/LoaderConstraintsTest.java b/test/hotspot/jtreg/runtime/logging/LoaderConstraintsTest.java index cfe7bc54956..1de943cce1b 100644 --- a/test/hotspot/jtreg/runtime/logging/LoaderConstraintsTest.java +++ b/test/hotspot/jtreg/runtime/logging/LoaderConstraintsTest.java @@ -27,6 +27,7 @@ * @bug 8149996 * @modules java.base/jdk.internal.misc * @library /test/lib classes + * @build test.Empty * @run driver LoaderConstraintsTest */ @@ -68,11 +69,13 @@ public static void main(String... args) throws Exception { // -Xlog:class+loader+constraints=info pb = exec("-Xlog:class+loader+constraints=info"); out = new OutputAnalyzer(pb.start()); + out.shouldHaveExitValue(0); out.shouldContain("[class,loader,constraints] adding new constraint for name: java/lang/Class, loader[0]: 'app', loader[1]: 'bootstrap'"); // -Xlog:class+loader+constraints=off pb = exec("-Xlog:class+loader+constraints=off"); out = new OutputAnalyzer(pb.start()); + out.shouldHaveExitValue(0); out.shouldNotContain("[class,loader,constraints]"); } diff --git a/test/hotspot/jtreg/runtime/logging/MonitorMismatchTest.java b/test/hotspot/jtreg/runtime/logging/MonitorMismatchTest.java index f0550841657..cf44ffdaa77 100644 --- a/test/hotspot/jtreg/runtime/logging/MonitorMismatchTest.java +++ b/test/hotspot/jtreg/runtime/logging/MonitorMismatchTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -44,6 +44,7 @@ public static void main(String... args) throws Exception { "-Xlog:monitormismatch=info", "MonitorMismatchHelper"); OutputAnalyzer o = new OutputAnalyzer(pb.start()); + o.shouldHaveExitValue(0); o.shouldContain("[monitormismatch] Monitor mismatch in method"); // monitormismatch should turn off. @@ -52,6 +53,7 @@ public static void main(String... args) throws Exception { "-Xlog:monitormismatch=off", "MonitorMismatchHelper"); o = new OutputAnalyzer(pb.start()); + o.shouldHaveExitValue(0); o.shouldNotContain("[monitormismatch]"); }; diff --git a/test/hotspot/jtreg/runtime/verifier/TestSigParse.java b/test/hotspot/jtreg/runtime/verifier/TestSigParse.java index df710162637..dfaed215a71 100644 --- a/test/hotspot/jtreg/runtime/verifier/TestSigParse.java +++ b/test/hotspot/jtreg/runtime/verifier/TestSigParse.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8129579 + * @bug 8219579 * @summary Test that signatures are properly parsed when verification of local * classes is requested but verification of remote classes is not. * @compile BadSignatures.jcod @@ -33,7 +33,7 @@ public class TestSigParse { public static void main(String args[]) throws Throwable { - System.out.println("Regression test for bug 819579"); + System.out.println("Regression test for bug 8219579"); // Test a FieldRef with a bad signature. try { diff --git a/test/hotspot/jtreg/serviceability/7170638/SDTProbesGNULinuxTest.java b/test/hotspot/jtreg/serviceability/7170638/SDTProbesGNULinuxTest.java index 9ad10282d1b..d4a49247909 100644 --- a/test/hotspot/jtreg/serviceability/7170638/SDTProbesGNULinuxTest.java +++ b/test/hotspot/jtreg/serviceability/7170638/SDTProbesGNULinuxTest.java @@ -28,6 +28,7 @@ * @summary Test SDT probes available on GNU/Linux when DTRACE_ENABLED * @requires os.family == "linux" * @requires vm.flagless + * @requires vm.hasDTrace * * @library /test/lib * @run driver SDTProbesGNULinuxTest @@ -36,7 +37,6 @@ import jdk.test.lib.Utils; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; -import jtreg.SkippedException; import java.nio.file.Files; import java.nio.file.Path; @@ -44,17 +44,7 @@ public class SDTProbesGNULinuxTest { public static void main(String[] args) throws Throwable { - { - var pb = ProcessTools.createJavaProcessBuilder( - "-XX:+ExtendedDTraceProbes", - "-version"); - var oa = new OutputAnalyzer(pb.start()); - // This test only matters when build with DTRACE_ENABLED. - if (oa.getExitValue() != 0) { - throw new SkippedException("Not build using DTRACE_ENABLED"); - } - } - + // This test only matters when build with DTRACE_ENABLED. try (var libjvms = Files.walk(Paths.get(Utils.TEST_JDK))) { libjvms.filter(p -> "libjvm.so".equals(p.getFileName().toString())) .map(Path::toAbsolutePath) diff --git a/test/hotspot/jtreg/serviceability/dtrace/DTraceOptionsTest.java b/test/hotspot/jtreg/serviceability/dtrace/DTraceOptionsTest.java new file mode 100644 index 00000000000..8822a9ed378 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/dtrace/DTraceOptionsTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2022, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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=enabled + * @bug 8281822 + * @summary Test DTrace options are accepted on suitable builds + * @requires vm.flagless + * @requires vm.hasDTrace + * + * @library /test/lib + * @run driver DTraceOptionsTest true + */ + +/* + * @test id=disabled + * @bug 8281822 + * @summary Test DTrace options are rejected on unsuitable builds + * @requires vm.flagless + * @requires !vm.hasDTrace + * + * @library /test/lib + * @run driver DTraceOptionsTest disabled + */ + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class DTraceOptionsTest { + public static void main(String[] args) throws Throwable { + boolean dtraceEnabled; + if (args.length > 0) { + dtraceEnabled = Boolean.parseBoolean(args[0]); + } else { + throw new IllegalArgumentException("Should provide the argument"); + } + + String[] options = { + "ExtendedDTraceProbes", + "DTraceMethodProbes", + "DTraceAllocProbes", + "DTraceMonitorProbes", + }; + + for (String opt : options) { + var pb = ProcessTools.createJavaProcessBuilder("-XX:+" + opt, "-version"); + var oa = new OutputAnalyzer(pb.start()); + if (dtraceEnabled) { + oa.shouldHaveExitValue(0); + } else { + oa.shouldNotHaveExitValue(0); + oa.shouldContain(opt + " flag is not applicable for this configuration"); + } + } + } + +} diff --git a/test/hotspot/jtreg/serviceability/jvmti/FieldAccessWatch/FieldAccessWatch.java b/test/hotspot/jtreg/serviceability/jvmti/FieldAccessWatch/FieldAccessWatch.java index c3be30a0148..d4345af2586 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/FieldAccessWatch/FieldAccessWatch.java +++ b/test/hotspot/jtreg/serviceability/jvmti/FieldAccessWatch/FieldAccessWatch.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -57,7 +57,7 @@ public static void main(String[] args) throws Exception { throw ex; } - if (!initWatchers(MyList.class, MyList.class.getDeclaredField("items"))) { + if (!initWatchers(MyList.class, MyList.class.getDeclaredField("items"), Thread.currentThread())) { throw new RuntimeException("Watchers initializations error"); } @@ -131,7 +131,7 @@ private static void test(String descr, TestAction action) throws Exception { log(descr + ": OK"); } - private static native boolean initWatchers(Class cls, Field field); + private static native boolean initWatchers(Class cls, Field field, Thread testThread); private static native boolean startTest(TestResult results); private static native void stopTest(); diff --git a/test/hotspot/jtreg/serviceability/jvmti/FieldAccessWatch/libFieldAccessWatch.c b/test/hotspot/jtreg/serviceability/jvmti/FieldAccessWatch/libFieldAccessWatch.c index fdc28961e89..9973f5eef75 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/FieldAccessWatch/libFieldAccessWatch.c +++ b/test/hotspot/jtreg/serviceability/jvmti/FieldAccessWatch/libFieldAccessWatch.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -37,6 +37,7 @@ static jvmtiEnv *jvmti = NULL; // valid while a test is executed static jobject testResultObject = NULL; static jclass testResultClass = NULL; +static jthread testThread = NULL; static void reportError(const char *msg, int err) { @@ -46,6 +47,7 @@ static void reportError(const char *msg, int err) { // logs the notification and updates currentTestResult static void handleNotification(JNIEnv *jni_env, + jthread thread, jmethodID method, jfieldID field, jclass field_klass, @@ -64,6 +66,10 @@ static void handleNotification(JNIEnv *jni_env, return; } + if (!(*jni_env)->IsSameObject(jni_env, thread, testThread)) { + return; // skip events from unexpected threads + } + err = (*jvmti)->GetFieldName(jvmti, field_klass, field, &name, NULL, NULL); if (err != JVMTI_ERROR_NONE) { reportError("GetFieldName failed", err); @@ -179,7 +185,7 @@ onFieldAccess(jvmtiEnv *jvmti_env, jobject object, jfieldID field) { - handleNotification(jni_env, method, field, field_klass, 0, location); + handleNotification(jni_env, thread, method, field, field_klass, 0, location); } @@ -195,7 +201,7 @@ onFieldModification(jvmtiEnv *jvmti_env, char signature_type, jvalue new_value) { - handleNotification(jni_env, method, field, field_klass, 1, location); + handleNotification(jni_env, thread, method, field, field_klass, 1, location); if (signature_type == 'L') { jobject newObject = new_value.l; @@ -251,7 +257,7 @@ Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) JNIEXPORT jboolean JNICALL -Java_FieldAccessWatch_initWatchers(JNIEnv *env, jclass thisClass, jclass cls, jobject field) +Java_FieldAccessWatch_initWatchers(JNIEnv *env, jclass thisClass, jclass cls, jobject field, jthread thread) { jfieldID fieldId; jvmtiError err; @@ -275,6 +281,8 @@ Java_FieldAccessWatch_initWatchers(JNIEnv *env, jclass thisClass, jclass cls, jo return JNI_FALSE; } + testThread = (jthread)(*env)->NewGlobalRef(env, thread); + return JNI_TRUE; } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/NonbranchyTree.java b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/NonbranchyTree.java index 41ce6126f43..55e136d1f41 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/NonbranchyTree.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/NonbranchyTree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -23,12 +23,11 @@ package nsk.share.gc; -import java.io.*; -import java.util.*; - import nsk.share.test.ExecutionController; import nsk.share.test.LocalRandom; +import java.io.PrintStream; + /** * NonbranchyTree defines a tree structure. Each node of the tree * always has one son. A node may have the second son with probability @@ -38,11 +37,9 @@ public class NonbranchyTree { /** Minimal size of each node (in bytes) */ public final static int MIN_NODE_SIZE = 20; - private Node root; - private int numberOfNodes; - private float branchiness; - private int size; - private ExecutionController controller; + private final Node root; + private final float branchiness; + private final ExecutionController controller; /** * Creates a new tree with number of nodes not more than @@ -62,36 +59,26 @@ public class NonbranchyTree { */ public NonbranchyTree(int numberOfNodes, float branchiness, int size) { this(numberOfNodes, branchiness, size, null); - initTree(); } public NonbranchyTree(int numberOfNodes, float branchiness, int size, ExecutionController controller) { - this.numberOfNodes = numberOfNodes; - this.branchiness = branchiness; - this.size = size; - this.controller = controller; - initTree(); - } - - private void initTree() { if (numberOfNodes < 1) { throw new IllegalArgumentException("Illegal number of nodes: " - + numberOfNodes + ", must be at " - + "least 1."); + + numberOfNodes + ", must be at least 1."); } - if ( (branchiness >= 1) || (branchiness <= 0) ) { + if ((branchiness >= 1) || (branchiness <= 0)) { throw new IllegalArgumentException("Illegal value of branchiness: " - + numberOfNodes + ", must be at " - + "greater than 0 and less than " - + " 1."); + + branchiness + ", must be greater than 0 and less than 1."); } if (size < 1) { throw new IllegalArgumentException("Illegal size of nodes: " - + size + ", must be at least 1."); + + size + ", must be at least 1."); } // ensure that LocalRandom is loaded and has enough memory LocalRandom.nextBoolean(); - root = createTree(numberOfNodes, size); + this.branchiness = branchiness; + this.controller = controller; + this.root = createTree(numberOfNodes, size); } // Create a new tree with specified number of nodes and size of each node diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/agent_tools.cpp b/test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/agent_tools.cpp index 660e2fc54e5..2412bd63040 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/agent_tools.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/agent_tools.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -138,34 +138,25 @@ jvmtiEnv* nsk_jvmti_getAgentJVMTIEnv() { return jvmti_env; } -/* ============================================================================= */ -static void set_agent_thread_state(thread_state_t value) { - rawMonitorEnter(jvmti_env, agent_data.monitor); - agent_data.thread_state = value; - rawMonitorNotify(jvmti_env, agent_data.monitor); - rawMonitorExit(jvmti_env, agent_data.monitor); -} - /** Wrapper for user agent thread. */ static void JNICALL agentThreadWrapper(jvmtiEnv* jvmti_env, JNIEnv* agentJNI, void* arg) { jni_env = agentJNI; - /* run user agent proc */ - { - set_agent_thread_state(RUNNABLE); + rawMonitorEnter(jvmti_env, agent_data.monitor); + agent_data.thread_state = RUNNABLE; + rawMonitorNotify(jvmti_env, agent_data.monitor); + rawMonitorExit(jvmti_env, agent_data.monitor); - NSK_TRACE((*agentThreadProc)(jvmti_env, agentJNI, agentThreadArg)); + NSK_TRACE((*agentThreadProc)(jvmti_env, agentJNI, agentThreadArg)); - set_agent_thread_state(TERMINATED); - } + rawMonitorEnter(jvmti_env, agent_data.monitor); + agent_data.thread_state = TERMINATED; + agentJNI->DeleteGlobalRef(agentThread); + agentThread = NULL; + rawMonitorNotify(jvmti_env, agent_data.monitor); + rawMonitorExit(jvmti_env, agent_data.monitor); - /* finalize agent thread */ - { - /* gelete global ref for agent thread */ - agentJNI->DeleteGlobalRef(agentThread); - agentThread = NULL; - } } /** Start wrapper for user agent thread. */ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/sysdict/share/BTreeTest.java b/test/hotspot/jtreg/vmTestbase/nsk/sysdict/share/BTreeTest.java index d14f3091495..e041f90b71d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/sysdict/share/BTreeTest.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/sysdict/share/BTreeTest.java @@ -59,7 +59,7 @@ protected void parseArgs(String args[]) { } try { // Load FatsInfo with URLClassLoader btree.jar & fats.jar should not - // present in classpath + // be present in classpath Class info; if (useFats) { info = createJarLoader().loadClass(PACKAGE_PREFIX + "FatsInfo"); @@ -76,7 +76,7 @@ protected void parseArgs(String args[]) { } if (level >= height) { - throw new Failure("Icorrect level : " + level + " .Should be less then " + height); + throw new Failure("Incorrect level : " + level + " should be less than " + height); } // generate names for all nodes at the given level: diff --git a/test/hotspot/jtreg/vmTestbase/nsk/sysdict/share/GenClassesBuilder.java b/test/hotspot/jtreg/vmTestbase/nsk/sysdict/share/GenClassesBuilder.java index e48ff567aac..6f3a2084083 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/sysdict/share/GenClassesBuilder.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/sysdict/share/GenClassesBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -71,6 +71,7 @@ private static void build(String name, String prefix, Runnable generator) { moveJavaFiles(genSrcDir, prefix); JDKToolLauncher javac = JDKToolLauncher.create("javac") + .addToolArg("-J-Xmx1G") .addToolArg("-d") .addToolArg(classesDir.toString()) .addToolArg("-cp") diff --git a/test/hotspot/jtreg/vmTestbase/nsk/sysdict/share/SysDictTest.java b/test/hotspot/jtreg/vmTestbase/nsk/sysdict/share/SysDictTest.java index f7ce05fc918..2b217a368c2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/sysdict/share/SysDictTest.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/sysdict/share/SysDictTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -62,7 +62,7 @@ protected void parseArgs(String args[]) { if (args[i].equals("-useSingleLoader")) { this.useSingleLoader = false; } - // jar path is in useal classpath format + // jar path is in usual classpath format if (args[i].equals("-jarpath")) { String[] files = args[i + 1].split(File.pathSeparator); jars = new URL[files.length]; @@ -148,11 +148,8 @@ public void run() { // set name into public variable just to be sure // that class is loaded tmp = clz.getName(); - } catch (ClassNotFoundException cnfe) { - throw new TestFailure(cnfe); - } catch (OutOfMemoryError oome) { - // just ignore - // we do not check memory leaks in PermGen in this tests + } catch (OutOfMemoryError | ClassNotFoundException | NoClassDefFoundError e) { + // just ignore, note that CNFE and NCDFE can be caused by OOM exceptions. } catch (StackOverflowError soe) { // just ignore, chains could be too large // StackOverflowError could be in some sparcs @@ -164,6 +161,7 @@ public void run() { } } + @Override protected Runnable createRunnable(int i) { currentClassLoaders = createClassLoadersInternal(); diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/func/findByName/Test.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/func/findByName/Test.java similarity index 89% rename from test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/func/findByName/Test.java rename to test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/func/findByName/Test.java index c327000dcdb..f891b980f82 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/func/findByName/Test.java +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/func/findByName/Test.java @@ -37,23 +37,23 @@ * /test/lib * * @comment build test class and indify classes - * @build vm.mlvm.anonloader.func.findByName.Test + * @build vm.mlvm.hiddenloader.func.findByName.Test * @run driver vm.mlvm.share.IndifiedClassesBuilder * - * @run main/othervm vm.mlvm.anonloader.func.findByName.Test + * @run main/othervm vm.mlvm.hiddenloader.func.findByName.Test */ -package vm.mlvm.anonloader.func.findByName; +package vm.mlvm.hiddenloader.func.findByName; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; -import vm.mlvm.anonloader.share.AnonkTestee01; +import vm.mlvm.hiddenloader.share.HiddenkTestee01; import vm.mlvm.share.MlvmTest; import vm.share.FileUtils; public class Test extends MlvmTest { - private static final Class PARENT = AnonkTestee01.class; + private static final Class PARENT = HiddenkTestee01.class; public boolean run() throws Exception { try { diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/share/AnonkTestee01.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/share/HiddenkTestee01.java similarity index 97% rename from test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/share/AnonkTestee01.java rename to test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/share/HiddenkTestee01.java index 0594e8c523c..15b81f3c5a5 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/share/AnonkTestee01.java +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/share/HiddenkTestee01.java @@ -21,11 +21,11 @@ * questions. */ -package vm.mlvm.anonloader.share; +package vm.mlvm.hiddenloader.share; import vm.mlvm.share.Env; -public class AnonkTestee01 { +public class HiddenkTestee01 { public final static String muzzy = "BIG \uFFFF\u0000\uFFFE\uFEFF MUZZY"; public final static String theDrumIsTheDrumIsTheDrumIsTheDrumIsTheDrumIsTheDrumIsTheDrumIsTheDrumIsTheDrumIsTheDrumIsTheDrumIsTheDrumIsTheDrumIsTheDrumIsTheDrumIsTheDrumIsTheDrumIsTheDrumIsTheDrumIsTheDrumIsTheDrumIsTheDrumIsTheDrumIsTheDrumIsTheDrum diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/share/AnonkTestee02.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/share/HiddenkTestee02.java similarity index 89% rename from test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/share/AnonkTestee02.java rename to test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/share/HiddenkTestee02.java index 89f526e02e6..95d5372c762 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/share/AnonkTestee02.java +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/share/HiddenkTestee02.java @@ -21,8 +21,8 @@ * questions. */ -package vm.mlvm.anonloader.share; +package vm.mlvm.hiddenloader.share; -public class AnonkTestee02 extends AnonkTestee01 { - public AnonkTestee02() {} +public class HiddenkTestee02 extends HiddenkTestee01 { + public HiddenkTestee02() {} } diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/share/StressClassLoadingTest.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/share/StressClassLoadingTest.java similarity index 97% rename from test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/share/StressClassLoadingTest.java rename to test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/share/StressClassLoadingTest.java index 2c9d96aac76..edb91743c44 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/share/StressClassLoadingTest.java +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/share/StressClassLoadingTest.java @@ -21,7 +21,7 @@ * questions. */ -package vm.mlvm.anonloader.share; +package vm.mlvm.hiddenloader.share; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; @@ -65,14 +65,14 @@ *

    The test fails, if there were hangups. * *

    By default, before loading class, the bytes are - * saved to {@code _AnonkTestee01.class} file in the current directory. + * saved to {@code _HiddenkTestee01.class} file in the current directory. * If JVM crashes, the bytecodes can be analysed. * Class saving is controlled by -saveClassFile option. * A prefix can be added to the file name using {@link #setFileNamePrefix} * function. */ public abstract class StressClassLoadingTest extends MlvmTest { - private static final String RESCUE_FILE_NAME = "_AnonkTestee01.class"; + private static final String RESCUE_FILE_NAME = "_HiddenkTestee01.class"; private static final String HUNG_CLASS_FILE_NAME = "hang.class"; @Option(name = "iterations", default_value = "100000", @@ -100,7 +100,7 @@ public abstract class StressClassLoadingTest extends MlvmTest { /** * Sets prefix for names of the files, created by test: - * _AnonkTestee01.class and hangXX.class. + * _HiddenkTestee01.class and hangXX.class. * * @param p a prefix to add before file name. * @throws java.lang.NullPointerException if p is null diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/byteMutation/TEST.properties b/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/byteMutation/TEST.properties similarity index 100% rename from test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/byteMutation/TEST.properties rename to test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/byteMutation/TEST.properties diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/byteMutation/Test.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/byteMutation/Test.java similarity index 77% rename from test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/byteMutation/Test.java rename to test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/byteMutation/Test.java index 305eb6cc408..e6a3e8a890d 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/byteMutation/Test.java +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/byteMutation/Test.java @@ -27,23 +27,23 @@ * @key randomness * @modules java.base/jdk.internal.misc * - * @summary converted from VM Testbase vm/mlvm/anonloader/stress/byteMutation. + * @summary converted from VM Testbase vm/mlvm/hiddenloader/stress/byteMutation. * VM Testbase keywords: [feature_mlvm, nonconcurrent] * * @library /vmTestbase * /test/lib * * @comment build test class and indify classes - * @build vm.mlvm.anonloader.stress.byteMutation.Test + * @build vm.mlvm.hiddenloader.stress.byteMutation.Test * @run driver vm.mlvm.share.IndifiedClassesBuilder * - * @run main/othervm vm.mlvm.anonloader.stress.byteMutation.Test -stressIterationsFactor 100000 + * @run main/othervm vm.mlvm.hiddenloader.stress.byteMutation.Test -stressIterationsFactor 100000 */ -package vm.mlvm.anonloader.stress.byteMutation; +package vm.mlvm.hiddenloader.stress.byteMutation; -import vm.mlvm.anonloader.share.AnonkTestee01; -import vm.mlvm.anonloader.share.StressClassLoadingTest; +import vm.mlvm.hiddenloader.share.HiddenkTestee01; +import vm.mlvm.hiddenloader.share.StressClassLoadingTest; import vm.share.FileUtils; import vm.share.options.Option; @@ -67,7 +67,7 @@ * */ public class Test extends StressClassLoadingTest { - private final static Class HOST_CLASS = AnonkTestee01.class; + private final static Class HOST_CLASS = HiddenkTestee01.class; private final byte[] testeeBytes; @Option(name = "mutationCount", default_value = "3", description = "How many bytes to mutate in a class") @@ -76,16 +76,16 @@ public class Test extends StressClassLoadingTest { /** * Constructs the test. * @throws Exception if there are any errors when - * reading {@link vm.mlvm.anonloader.share.AnonkTestee01} class bytecodes. + * reading {@link vm.mlvm.hiddenloader.share.HiddenkTestee01} class bytecodes. */ public Test() throws Exception { - this.testeeBytes = FileUtils.readClass(AnonkTestee01.class.getName()); + this.testeeBytes = FileUtils.readClass(HiddenkTestee01.class.getName()); } /** - * Returns {@link vm.mlvm.anonloader.share.AnonkTestee01} class to the + * Returns {@link vm.mlvm.hiddenloader.share.HiddenkTestee01} class to the * parent. - * @return {@link vm.mlvm.anonloader.share.AnonkTestee01} class. + * @return {@link vm.mlvm.hiddenloader.share.HiddenkTestee01} class. */ @Override protected Class getHostClass() { @@ -93,9 +93,9 @@ protected Class getHostClass() { } /** - * Takes {@link vm.mlvm.anonloader.share.AnonkTestee01} class bytecodes + * Takes {@link vm.mlvm.hiddenloader.share.HiddenkTestee01} class bytecodes * and modifies mutationCount bytes setting them to random values. - * @return {@link vm.mlvm.anonloader.share.AnonkTestee01} class bytecodes with modified bytes. + * @return {@link vm.mlvm.hiddenloader.share.HiddenkTestee01} class bytecodes with modified bytes. */ @Override protected byte[] generateClassBytes() { diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/oome/heap/TEST.properties b/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/oome/heap/TEST.properties similarity index 100% rename from test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/oome/heap/TEST.properties rename to test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/oome/heap/TEST.properties diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/oome/heap/Test.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/oome/heap/Test.java similarity index 87% rename from test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/oome/heap/Test.java rename to test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/oome/heap/Test.java index 723c63d02fb..ea59685dfd3 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/oome/heap/Test.java +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/oome/heap/Test.java @@ -34,20 +34,20 @@ * /test/lib * * @comment build test class and indify classes - * @build vm.mlvm.anonloader.stress.oome.heap.Test + * @build vm.mlvm.hiddenloader.stress.oome.heap.Test * @run driver vm.mlvm.share.IndifiedClassesBuilder * - * @run main/othervm -XX:-UseGCOverheadLimit -Xmx128m vm.mlvm.anonloader.stress.oome.heap.Test + * @run main/othervm -XX:-UseGCOverheadLimit -Xmx128m vm.mlvm.hiddenloader.stress.oome.heap.Test */ -package vm.mlvm.anonloader.stress.oome.heap; +package vm.mlvm.hiddenloader.stress.oome.heap; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; import java.util.List; import java.io.IOException; -import vm.mlvm.anonloader.share.AnonkTestee01; +import vm.mlvm.hiddenloader.share.HiddenkTestee01; import vm.mlvm.share.MlvmOOMTest; import vm.mlvm.share.MlvmTestExecutor; import vm.mlvm.share.Env; @@ -63,7 +63,7 @@ public class Test extends MlvmOOMTest { @Override protected void checkOOME(OutOfMemoryError oome) { String message = oome.getMessage(); - if (!"Java heap space".equals(message)) { + if (!message.startsWith("Java heap space")) { throw new RuntimeException("TEST FAIL : wrong OOME", oome); } } @@ -71,14 +71,14 @@ protected void checkOOME(OutOfMemoryError oome) { protected void eatMemory(List list) { byte[] classBytes = null; try { - classBytes = FileUtils.readClass(AnonkTestee01.class.getName()); + classBytes = FileUtils.readClass(HiddenkTestee01.class.getName()); } catch (IOException e) { Env.throwAsUncheckedException(e); } try { while (true) { Lookup lookup = MethodHandles.lookup(); - Lookup ank_lookup = MethodHandles.privateLookupIn(AnonkTestee01.class, lookup); + Lookup ank_lookup = MethodHandles.privateLookupIn(HiddenkTestee01.class, lookup); Class c = ank_lookup.defineHiddenClass(classBytes, true).lookupClass(); list.add(c.newInstance()); } diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/oome/metaspace/TEST.properties b/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/oome/metaspace/TEST.properties similarity index 100% rename from test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/oome/metaspace/TEST.properties rename to test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/oome/metaspace/TEST.properties diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/oome/metaspace/Test.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/oome/metaspace/Test.java similarity index 88% rename from test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/oome/metaspace/Test.java rename to test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/oome/metaspace/Test.java index 1984555708e..85bb7c6167f 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/oome/metaspace/Test.java +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/oome/metaspace/Test.java @@ -33,21 +33,21 @@ * /test/lib * * @comment build test class and indify classes - * @build vm.mlvm.anonloader.stress.oome.metaspace.Test + * @build vm.mlvm.hiddenloader.stress.oome.metaspace.Test * @run driver vm.mlvm.share.IndifiedClassesBuilder * * @run main/othervm -XX:MaxRAMPercentage=25 -XX:-UseGCOverheadLimit -XX:MetaspaceSize=10m - * -XX:MaxMetaspaceSize=20m vm.mlvm.anonloader.stress.oome.metaspace.Test + * -XX:MaxMetaspaceSize=20m vm.mlvm.hiddenloader.stress.oome.metaspace.Test */ -package vm.mlvm.anonloader.stress.oome.metaspace; +package vm.mlvm.hiddenloader.stress.oome.metaspace; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; import java.util.List; import java.io.IOException; -import vm.mlvm.anonloader.share.AnonkTestee01; +import vm.mlvm.hiddenloader.share.HiddenkTestee01; import vm.mlvm.share.MlvmOOMTest; import vm.mlvm.share.MlvmTestExecutor; import vm.mlvm.share.Env; @@ -71,14 +71,14 @@ protected void checkOOME(OutOfMemoryError oome) { protected void eatMemory(List list) { byte[] classBytes = null; try { - classBytes = FileUtils.readClass(AnonkTestee01.class.getName()); + classBytes = FileUtils.readClass(HiddenkTestee01.class.getName()); } catch (IOException e) { Env.throwAsUncheckedException(e); } try { while (true) { Lookup lookup = MethodHandles.lookup(); - Lookup ank_lookup = MethodHandles.privateLookupIn(AnonkTestee01.class, lookup); + Lookup ank_lookup = MethodHandles.privateLookupIn(HiddenkTestee01.class, lookup); Class c = ank_lookup.defineHiddenClass(classBytes, true).lookupClass(); list.add(c.newInstance()); } diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/parallelLoad/TEST.properties b/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/parallelLoad/TEST.properties similarity index 100% rename from test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/parallelLoad/TEST.properties rename to test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/parallelLoad/TEST.properties diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/parallelLoad/Test.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/parallelLoad/Test.java similarity index 88% rename from test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/parallelLoad/Test.java rename to test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/parallelLoad/Test.java index 4ba9a037ead..fa4dbf3f4eb 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/parallelLoad/Test.java +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/parallelLoad/Test.java @@ -33,22 +33,22 @@ * /test/lib * * @comment build test class and indify classes - * @build vm.mlvm.anonloader.stress.parallelLoad.Test + * @build vm.mlvm.hiddenloader.stress.parallelLoad.Test * @run driver vm.mlvm.share.IndifiedClassesBuilder * * @run main/othervm * -Xverify:all - * vm.mlvm.anonloader.stress.parallelLoad.Test + * vm.mlvm.hiddenloader.stress.parallelLoad.Test * -threadsPerCpu 4 * -threadsExtra 20 * -parseTimeout 0 * -hiddenLoad true */ -package vm.mlvm.anonloader.stress.parallelLoad; +package vm.mlvm.hiddenloader.stress.parallelLoad; -import vm.mlvm.anonloader.share.StressClassLoadingTest; -import vm.mlvm.anonloader.share.AnonkTestee01; +import vm.mlvm.hiddenloader.share.StressClassLoadingTest; +import vm.mlvm.hiddenloader.share.HiddenkTestee01; import vm.mlvm.share.MlvmTestExecutor; import vm.mlvm.share.MultiThreadedTest; import vm.share.FileUtils; @@ -60,7 +60,7 @@ * */ public class Test extends MultiThreadedTest { - private static final Class HOST_CLASS = AnonkTestee01.class; + private static final Class HOST_CLASS = HiddenkTestee01.class; private static final String NAME_PREFIX = "thread%03d"; private final byte[] classBytes; @@ -89,7 +89,7 @@ public Test() throws Exception { /** * Constructs a sub-test class and runs it. The sub-test class loads - * {@link vm.mlvm.anonloader.share.AnonkTestee01} class bytecodes + * {@link vm.mlvm.hiddenloader.share.HiddenkTestee01} class bytecodes * using {@link java.lang.invoke.MethodHandles.Lookup#defineHiddenClass} * @param numThread Number of the thread * @throws Exception if there any exceptions thrown in the sub-test diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/randomBytecodes/TEST.properties b/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/randomBytecodes/TEST.properties similarity index 100% rename from test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/randomBytecodes/TEST.properties rename to test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/randomBytecodes/TEST.properties diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/randomBytecodes/Test.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/randomBytecodes/Test.java similarity index 89% rename from test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/randomBytecodes/Test.java rename to test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/randomBytecodes/Test.java index d28525041f6..b6146e59eed 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/randomBytecodes/Test.java +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/randomBytecodes/Test.java @@ -34,16 +34,16 @@ * /test/lib * * @comment build test class and indify classes - * @build vm.mlvm.anonloader.stress.randomBytecodes.Test + * @build vm.mlvm.hiddenloader.stress.randomBytecodes.Test * @run driver vm.mlvm.share.IndifiedClassesBuilder * - * @run main/othervm vm.mlvm.anonloader.stress.randomBytecodes.Test -stressIterationsFactor 100000 + * @run main/othervm vm.mlvm.hiddenloader.stress.randomBytecodes.Test -stressIterationsFactor 100000 */ -package vm.mlvm.anonloader.stress.randomBytecodes; +package vm.mlvm.hiddenloader.stress.randomBytecodes; import java.util.Arrays; -import vm.mlvm.anonloader.share.StressClassLoadingTest; +import vm.mlvm.hiddenloader.share.StressClassLoadingTest; /** * The test does the following in a cycle: @@ -72,9 +72,9 @@ public class Test extends StressClassLoadingTest { }; /** - * Returns {@link vm.mlvm.anonloader.share.AnonkTestee01} class to the + * Returns {@link vm.mlvm.hiddenloader.share.HiddenkTestee01} class to the * parent. - * @return {@link vm.mlvm.anonloader.share.AnonkTestee01} class. + * @return {@link vm.mlvm.hiddenloader.share.HiddenkTestee01} class. */ @Override protected Class getHostClass() { diff --git a/test/jdk/ProblemList-Xcomp.txt b/test/jdk/ProblemList-Xcomp.txt index 77b61348af5..31edd809ccc 100644 --- a/test/jdk/ProblemList-Xcomp.txt +++ b/test/jdk/ProblemList-Xcomp.txt @@ -28,4 +28,3 @@ ############################################################################# java/lang/invoke/MethodHandles/CatchExceptionTest.java 8146623 generic-all -java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorTest.java 8256368 generic-all diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 511c933b8ba..e0caaf6feaa 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -619,7 +619,7 @@ java/nio/channels/DatagramChannel/Unref.java 8233519 generic- java/nio/channels/AsynchronousSocketChannel/StressLoopback.java 8211851 aix-ppc64 -java/nio/channels/Selector/Wakeup.java 6963118 windows-all +java/nio/channels/DatagramChannel/ManySourcesAndTargets.java 8264385 macosx-aarch64 ############################################################################ @@ -686,6 +686,7 @@ javax/security/auth/kerberos/KerberosTixDateTest.java 8039280 generic- sun/security/provider/PolicyFile/GrantAllPermToExtWhenNoPolicy.java 8039280 generic-all sun/security/provider/PolicyParser/ExtDirsChange.java 8039280 generic-all sun/security/provider/PolicyParser/PrincipalExpansionError.java 8039280 generic-all +sun/security/ssl/SSLSessionImpl/NoInvalidateSocketException.java 8277970 linux-all,macosx-x64 ############################################################################ @@ -824,7 +825,6 @@ jdk/jfr/event/compiler/TestCodeSweeper.java 8225209 gener jdk/jfr/event/os/TestThreadContextSwitches.java 8247776 windows-all jdk/jfr/startupargs/TestStartName.java 8214685 windows-x64 jdk/jfr/startupargs/TestStartDuration.java 8214685 windows-x64 -jdk/jfr/event/gc/detailed/TestEvacuationFailedEvent.java 8263461 linux-all,windows-x64 jdk/jfr/api/consumer/streaming/TestLatestEvent.java 8268297 windows-x64 ############################################################################ diff --git a/test/jdk/build/AbsPathsInImage.java b/test/jdk/build/AbsPathsInImage.java index 3fd7dda239a..0e4b6d8caff 100644 --- a/test/jdk/build/AbsPathsInImage.java +++ b/test/jdk/build/AbsPathsInImage.java @@ -96,6 +96,13 @@ public static void main(String[] args) throws Exception { if (buildOutputRoot == null) { throw new Error("Could not find build output root, test cannot run"); } + // Validate the root paths + if (!Paths.get(buildWorkspaceRoot).isAbsolute()) { + throw new Error("Workspace root is not an absolute path: " + buildWorkspaceRoot); + } + if (!Paths.get(buildOutputRoot).isAbsolute()) { + throw new Error("Output root is not an absolute path: " + buildOutputRoot); + } List searchPatterns = new ArrayList<>(); expandPatterns(searchPatterns, buildWorkspaceRoot); diff --git a/test/jdk/com/sun/jndi/ldap/LdapCBPropertiesTest.java b/test/jdk/com/sun/jndi/ldap/LdapCBPropertiesTest.java index 16b4400310a..2f2ce50e8d6 100644 --- a/test/jdk/com/sun/jndi/ldap/LdapCBPropertiesTest.java +++ b/test/jdk/com/sun/jndi/ldap/LdapCBPropertiesTest.java @@ -25,6 +25,7 @@ * @test * @bug 8245527 * @library lib/ /test/lib + * @modules java.base/sun.security.util * @run main/othervm LdapCBPropertiesTest true true com.sun.jndi.ldap.tls.cbtype tls-server-end-point * @run main/othervm LdapCBPropertiesTest false false com.sun.jndi.ldap.tls.cbtype tls-server-end-point * @run main/othervm LdapCBPropertiesTest true true com.sun.jndi.ldap.tls.cbtype tls-server-end-point com.sun.jndi.ldap.connect.timeout 2000 @@ -53,6 +54,8 @@ import jdk.test.lib.net.URIBuilder; +import sun.security.util.ChannelBindingException; + public class LdapCBPropertiesTest { /* * Where do we find the keystores? @@ -187,7 +190,8 @@ private static boolean handleNamingException(NamingException ne, boolean shouldP } } } - if (!shouldPass && ne.getRootCause() == null) { + Throwable rc = ne.getRootCause(); + if (!shouldPass && (rc == null || rc instanceof ChannelBindingException)) { // Expected exception caused by Channel Binding parameter inconsistency return true; } diff --git a/test/jdk/com/sun/org/apache/xml/internal/security/ShortECDSA.java b/test/jdk/com/sun/org/apache/xml/internal/security/ShortECDSA.java index 85df37dce25..851ba2efcc3 100644 --- a/test/jdk/com/sun/org/apache/xml/internal/security/ShortECDSA.java +++ b/test/jdk/com/sun/org/apache/xml/internal/security/ShortECDSA.java @@ -25,9 +25,12 @@ * @test * @bug 8259535 * @summary ECDSA SignatureValue do not always have the specified length - * @modules java.xml.crypto + * @modules java.xml.crypto/com.sun.org.apache.xml.internal.security + * java.xml.crypto/com.sun.org.apache.xml.internal.security.signature */ +import com.sun.org.apache.xml.internal.security.Init; +import com.sun.org.apache.xml.internal.security.signature.XMLSignature; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; @@ -91,6 +94,18 @@ public static void main(String[] args) throws Exception { System.out.println(HexFormat.ofDelimiter(":").formatHex(sig)); throw new RuntimeException("Failed"); } + + // Internal way + Init.init(); + XMLSignature signature = new XMLSignature(document, null, + SignatureMethod.ECDSA_SHA256, CanonicalizationMethod.INCLUSIVE); + signature.sign(privateKey); + sig = signature.getSignatureValue(); + if (sig.length != 64) { + System.out.println("Length: " + sig.length); + System.out.println(HexFormat.ofDelimiter(":").formatHex(sig)); + throw new RuntimeException("Failed"); + } } public static class XmlSigningUtils { diff --git a/test/jdk/com/sun/org/apache/xml/internal/security/SignatureKeyInfo.java b/test/jdk/com/sun/org/apache/xml/internal/security/SignatureKeyInfo.java new file mode 100644 index 00000000000..d1de2030c24 --- /dev/null +++ b/test/jdk/com/sun/org/apache/xml/internal/security/SignatureKeyInfo.java @@ -0,0 +1,216 @@ +/* + * 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. + */ + +/** + * @test + * @bug 8272908 + * @summary Verify signature KeyInfo + * @library /test/lib + * @modules java.xml.crypto/com.sun.org.apache.xml.internal.security + * java.xml.crypto/com.sun.org.apache.xml.internal.security.c14n + * java.xml.crypto/com.sun.org.apache.xml.internal.security.signature + * java.xml.crypto/com.sun.org.apache.xml.internal.security.utils + * java.xml.crypto/com.sun.org.apache.xml.internal.security.keys + * java.xml.crypto/com.sun.org.apache.xml.internal.security.keys.content.keyvalues + * java.xml.crypto/com.sun.org.apache.xml.internal.security.keys.content + * java.xml.crypto/com.sun.org.apache.xml.internal.security.exceptions + * @run main/othervm SignatureKeyInfo + */ + +import com.sun.org.apache.xml.internal.security.Init; +import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; +import com.sun.org.apache.xml.internal.security.keys.KeyInfo; +import com.sun.org.apache.xml.internal.security.keys.content.PGPData; +import com.sun.org.apache.xml.internal.security.keys.content.RetrievalMethod; +import com.sun.org.apache.xml.internal.security.keys.content.SPKIData; +import com.sun.org.apache.xml.internal.security.signature.XMLSignature; +import com.sun.org.apache.xml.internal.security.utils.Constants; +import com.sun.org.apache.xml.internal.security.utils.XMLUtils; +import com.sun.org.apache.xml.internal.security.utils.ElementProxy; +import com.sun.org.apache.xml.internal.security.keys.content.keyvalues.RSAKeyValue; +import com.sun.org.apache.xml.internal.security.keys.content.keyvalues.DSAKeyValue; + +import jdk.test.lib.Asserts; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + + +import javax.xml.crypto.dsig.CanonicalizationMethod; +import javax.xml.crypto.dsig.SignatureMethod; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.File; +import java.math.BigInteger; +import java.security.*; + +import static jdk.test.lib.Asserts.assertEquals; + +public class SignatureKeyInfo { + + private final static String DIR = System.getProperty("test.src", "."); + private static DocumentBuilderFactory dbf = null; + private static Document doc; + + private static final String NAME = "testName"; + private static final String TEXT = "testText"; + private static final String NS = Constants.SignatureSpecNS; + private static final String RSA = "RSA"; + private static final String DSA = "DSA"; + private static final String FILE_TO_SIGN = "signature-enveloping-hmac-sha1.xml"; + private static final String FILE_TO_VERIFY = "signature-enveloping-hmac-sha1-keyinfo.xml"; + private static final int FIRST_EL = 0; + + public static void main(String[] args) throws Exception { + + Init.init(); + dbf = DocumentBuilderFactory.newInstance(); + dbf.setNamespaceAware(true); + dbf.setValidating(false); + verifyXmlKeyInfo(); + sign(RSA); + sign(DSA); + } + + private static void sign(String algorithm) throws Exception { + File file = new File(DIR, FILE_TO_SIGN); + + doc = dbf.newDocumentBuilder().parse(file); + + KeyPair kp = getKeyPair(algorithm); + + String signMethod = RSA.equals(algorithm) ? SignatureMethod.RSA_SHA256 + : SignatureMethod.DSA_SHA256; + + XMLSignature signature = new XMLSignature(doc, null, + signMethod, CanonicalizationMethod.INCLUSIVE); + + signature.addKeyInfo(kp.getPublic()); + KeyInfo keyInfo = signature.getKeyInfo(); + addKeyInfoData(keyInfo, algorithm); + signature.sign(kp.getPrivate()); + } + + private static Element getSignElement() { + NodeList nl = + doc.getElementsByTagNameNS(NS, "Signature"); + if (nl.getLength() == 0) { + throw new RuntimeException("Could not find signature Element"); + } + + return (Element) nl.item(FIRST_EL); + } + + private static void addKeyInfoData(KeyInfo keyInfo, String algorithm) throws Exception { + KeyPair keyPair = getKeyPair(algorithm); + + if (algorithm.equals(RSA)) { + RSAKeyValue rsaKeyValue = new RSAKeyValue(doc, keyPair.getPublic()); + keyInfo.add(rsaKeyValue); + } else { + DSAKeyValue dsaKeyValue = new DSAKeyValue(doc, keyPair.getPublic()); + keyInfo.add(dsaKeyValue); + } + + Element elpgp= doc.createElementNS(NS, Constants._TAG_PGPDATA); + Element elrm= doc.createElementNS(NS, Constants._TAG_RETRIEVALMETHOD); + Element elspki= doc.createElementNS(NS, Constants._TAG_SPKIDATA); + keyInfo.add(new PGPData(elpgp, NS)); + keyInfo.add(new RetrievalMethod(elrm, NS)); + keyInfo.add(new SPKIData(elspki, NS)); + + keyInfo.setId(TEXT); + keyInfo.addKeyName(TEXT); + keyInfo.add(keyPair.getPublic()); + keyInfo.addKeyValue(keyPair.getPublic()); + keyInfo.addDEREncodedKeyValue(keyPair.getPublic()); + keyInfo.addKeyInfoReference(NS); + keyInfo.addMgmtData(TEXT); + + Element e = XMLUtils.createElementInSignatureSpace(doc, NAME); + keyInfo.addKeyValue(e); + keyInfo.addUnknownElement(e); + keyInfo.addText(TEXT); + keyInfo.addTextElement(TEXT, NAME); + keyInfo.addBigIntegerElement(BigInteger.valueOf(12345), NAME); + keyInfo.addBase64Text(TEXT.getBytes()); + keyInfo.addBase64Element(TEXT.getBytes(), NAME); + + verifyKeyInfoData(keyInfo, algorithm); + } + + private static KeyPair getKeyPair(String algorithm) throws NoSuchAlgorithmException { + KeyPairGenerator keyGen = KeyPairGenerator.getInstance(algorithm); + keyGen.initialize(2048); + + return keyGen.genKeyPair(); + } + + private static void verifyKeyInfoData(KeyInfo keyInfo, String algorithm) + throws XMLSecurityException { + Asserts.assertTrue(keyInfo.containsKeyName()); + verifyElementText(keyInfo.itemKeyName(FIRST_EL)); + Asserts.assertTrue(keyInfo.containsKeyValue()); + verifyElementNS(keyInfo.itemKeyValue(FIRST_EL).getBaseNamespace()); + + Asserts.assertTrue(keyInfo.containsKeyInfoReference()); + verifyElementNS(keyInfo.itemKeyInfoReference(FIRST_EL).getURI()); + Asserts.assertTrue(keyInfo.containsDEREncodedKeyValue()); + Asserts.assertTrue(keyInfo.containsMgmtData()); + verifyElementText(keyInfo.itemMgmtData(FIRST_EL)); + Asserts.assertEquals(TEXT, keyInfo.getId()); + + Asserts.assertTrue(keyInfo.containsPGPData()); + verifyElementNS(keyInfo.itemPGPData(FIRST_EL).getBaseNamespace()); + + Asserts.assertTrue(keyInfo.containsRetrievalMethod()); + verifyElementNS(keyInfo.itemRetrievalMethod(FIRST_EL).getBaseNamespace()); + Asserts.assertTrue(keyInfo.containsSPKIData()); + verifyElementNS(keyInfo.itemSPKIData(FIRST_EL).getBaseNamespace()); + + Asserts.assertTrue(keyInfo.containsUnknownElement()); + Asserts.assertEquals(NAME, keyInfo.itemUnknownElement(13).getLocalName()); + + Asserts.assertFalse(keyInfo.isEmpty()); + Asserts.assertEquals(algorithm, keyInfo.getPublicKey().getAlgorithm()); + } + + private static void verifyXmlKeyInfo() throws Exception { + File file = new File(DIR, FILE_TO_VERIFY); + + doc = dbf.newDocumentBuilder().parse(file); + Element sigElement = getSignElement(); + XMLSignature signature = new XMLSignature + (sigElement, file.toURI().toString()); + + KeyInfo keyInfo = signature.getKeyInfo(); + assertEquals(TEXT, keyInfo.itemMgmtData(FIRST_EL).getMgmtData()); + } + + private static void verifyElementText(ElementProxy elementProxy) { + Asserts.assertEquals(TEXT, elementProxy.getTextFromTextChild()); + } + + private static void verifyElementNS(String actualNs) { + Asserts.assertEquals(NS, actualNs); + } +} \ No newline at end of file diff --git a/test/jdk/com/sun/org/apache/xml/internal/security/TruncateHMAC.java b/test/jdk/com/sun/org/apache/xml/internal/security/TruncateHMAC.java index 2316d707658..b080df28ef4 100644 --- a/test/jdk/com/sun/org/apache/xml/internal/security/TruncateHMAC.java +++ b/test/jdk/com/sun/org/apache/xml/internal/security/TruncateHMAC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -47,6 +47,7 @@ import com.sun.org.apache.xml.internal.security.signature.XMLSignatureException; import com.sun.org.apache.xml.internal.security.utils.Constants; +import static java.nio.charset.StandardCharsets.US_ASCII; public class TruncateHMAC { @@ -64,7 +65,11 @@ public static void main(String[] args) throws Exception { validate("signature-enveloping-hmac-sha1-trunclen-8-attack.xml", false); // this one should pass validate("signature-enveloping-hmac-sha1.xml", true); - generate_hmac_sha1_40(); + + // There are multiple validations regarding hmac min output length, therefore + // checking different values will exercise multiple code blocks + generate_hmac_sha1(40); + generate_hmac_sha1(128); if (atLeastOneFailed) { throw new Exception @@ -86,7 +91,7 @@ private static void validate(String data, boolean pass) throws Exception { try { XMLSignature signature = new XMLSignature (sigElement, file.toURI().toString()); - SecretKey sk = signature.createSecretKey("secret".getBytes("ASCII")); + SecretKey sk = signature.createSecretKey("secret".getBytes(US_ASCII)); System.out.println ("Validation status: " + signature.checkSignatureValue(sk)); if (!pass) { @@ -106,15 +111,15 @@ private static void validate(String data, boolean pass) throws Exception { } } - private static void generate_hmac_sha1_40() throws Exception { - System.out.println("Generating "); + private static void generate_hmac_sha1(int hmacOutputLength) throws Exception { + System.out.println("Generating " + hmacOutputLength); Document doc = dbf.newDocumentBuilder().newDocument(); try { XMLSignature sig = new XMLSignature - (doc, null, XMLSignature.ALGO_ID_MAC_HMAC_SHA1, 40, + (doc, null, XMLSignature.ALGO_ID_MAC_HMAC_SHA1, hmacOutputLength, Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS); - sig.sign(getSecretKey("secret".getBytes("ASCII"))); + sig.sign(getSecretKey("secret".getBytes(US_ASCII))); System.out.println("FAILED"); atLeastOneFailed = true; } catch (XMLSignatureException xse) { diff --git a/test/jdk/com/sun/org/apache/xml/internal/security/signature-enveloping-hmac-sha1-keyinfo.xml b/test/jdk/com/sun/org/apache/xml/internal/security/signature-enveloping-hmac-sha1-keyinfo.xml new file mode 100644 index 00000000000..5cd9d74dd5c --- /dev/null +++ b/test/jdk/com/sun/org/apache/xml/internal/security/signature-enveloping-hmac-sha1-keyinfo.xml @@ -0,0 +1,25 @@ + + + + + + + + 7/XTsHaBSOnJ/jXD5v0zL6VKYsk= + + + + JElPttIT4Am7Q+MNoMyv+WDfAZw= + + + testText + + + + BAds672US3sCYunM2k2bEQLbuRxdQlNTvq+5fitOpDMe0mBdZV4J3yZaG0taziYIuAT9GJGfds+q + xtXOCNWe/60= + + + + some text + \ No newline at end of file diff --git a/test/jdk/java/awt/Robot/CheckCommonColors/CheckCommonColors.java b/test/jdk/java/awt/Robot/CheckCommonColors/CheckCommonColors.java index 57419b0ac5a..55d9b4358af 100644 --- a/test/jdk/java/awt/Robot/CheckCommonColors/CheckCommonColors.java +++ b/test/jdk/java/awt/Robot/CheckCommonColors/CheckCommonColors.java @@ -42,6 +42,8 @@ * @key headful * @bug 8215105 8211999 * @summary tests that Robot can capture the common colors without artifacts + * @run main/othervm CheckCommonColors + * @run main/othervm -Xcheck:jni CheckCommonColors */ public final class CheckCommonColors { diff --git a/test/jdk/java/awt/a11y/AccessibleActionsTest.java b/test/jdk/java/awt/a11y/AccessibleActionsTest.java new file mode 100644 index 00000000000..b8f6e5d28f9 --- /dev/null +++ b/test/jdk/java/awt/a11y/AccessibleActionsTest.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8281338 + * @summary Test for an element that has more than one Accessibility Action + * @author Artem.Semenov@jetbrains.com + * @run main/manual AccessibleActionsTest + * @requires (os.family == "mac") + */ + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleAction; +import javax.accessibility.AccessibleContext; +import javax.swing.*; +import javax.swing.tree.TreeModel; +import javax.swing.tree.TreePath; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Hashtable; +import java.util.concurrent.CountDownLatch; + +public class AccessibleActionsTest extends AccessibleComponentTest { + + @Override + public CountDownLatch createCountDownLatch() { + return new CountDownLatch(1); + } + + void createTest() { + INSTRUCTIONS = "INSTRUCTIONS:\n" + + "Check a11y actions.\n\n" + + "Turn screen reader on, and Tab to the label.\n\n" + + "Perform the VO action \"Press\" (VO+space)\n" + + "Perform the VO action \"Show menu\" (VO+m)\n\n" + + "If after the first action the text of the label has changed, and after the second action the menu appears tab further and press PASS, otherwise press FAIL."; + + exceptionString = "AccessibleAction test failed!"; + super.createUI(new AccessibleActionsTestFrame(), "AccessibleActionsTest"); + } + + void createTree() { + INSTRUCTIONS = "INSTRUCTIONS:\n" + + "Check a11y actions.\n\n" + + "Turn screen reader on, and Tab to the label.\n\n" + + "Perform the VO action \"Press\" (VO+space) on tree nodes\n\n" + + "If after press the tree node is expanded tab further and press PASS, otherwise press FAIL."; + + String root = "Root"; + String[] nodes = new String[] {"One node", "Two node"}; + String[][] leafs = new String[][]{{"leaf 1.1", "leaf 1.2", "leaf 1.3", "leaf 1.4"}, + {"leaf 2.1", "leaf 2.2", "leaf 2.3", "leaf 2.4"}}; + + Hashtable data = new Hashtable(); + for (int i = 0; i < nodes.length; i++) { + data.put(nodes[i], leafs[i]); + } + + JTree tree = new JTree(data); + tree.setRootVisible(true); + + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout()); + JScrollPane scrollPane = new JScrollPane(tree); + panel.add(scrollPane); + panel.setFocusable(false); + + exceptionString = "AccessibleAction test failed!"; + super.createUI(panel, "AccessibleActionsTest"); + } + + public static void main(String[] args) throws Exception { + AccessibleActionsTest test = new AccessibleActionsTest(); + + countDownLatch = test.createCountDownLatch(); + SwingUtilities.invokeLater(test::createTest); + countDownLatch.await(); + + if (!testResult) { + throw new RuntimeException(a11yTest.exceptionString); + } + + countDownLatch = test.createCountDownLatch(); + SwingUtilities.invokeLater(test::createTree); + countDownLatch.await(); + + if (!testResult) { + throw new RuntimeException(a11yTest.exceptionString); + } + } + + private class AccessibleActionsTestFrame extends JPanel { + + public AccessibleActionsTestFrame() { + MyLabel label = new MyLabel("I'm waiting for the push"); + label.setComponentPopupMenu(createPopup()); + label.setFocusable(true); + add(label); + setLayout(new FlowLayout()); + } + + private static class MyLabel extends JLabel { + public MyLabel(String text) { + super(text); + } + + @Override + public AccessibleContext getAccessibleContext() { + if (accessibleContext == null) { + accessibleContext = new MyAccessibleJLabel(); + } + return accessibleContext; + } + + private class MyAccessibleJLabel extends JLabel.AccessibleJLabel { + @Override + public AccessibleAction getAccessibleAction() { + return new AccessibleAction() { + @Override + public int getAccessibleActionCount() { + return 2; + } + + @Override + public String getAccessibleActionDescription(int i) { + if (i == 0) { + return AccessibleAction.CLICK; + } + return AccessibleAction.TOGGLE_POPUP; + } + + @Override + public boolean doAccessibleAction(int i) { + if (i == 0) { + changeText(MyLabel.this, "label is pressed"); + return true; + } + JPopupMenu popup = createPopup(); + popup.show(MyLabel.this, 0, 0); + return true; + } + }; + } + } + } + + private static JPopupMenu createPopup() { + JPopupMenu popup = new JPopupMenu("MENU"); + popup.add("One"); + popup.add("Two"); + popup.add("Three"); + return popup; + } + + private static void changeText(JLabel label, String text) { + label.setText(text); + } + + } +} diff --git a/test/jdk/java/awt/image/DrawImage/ByteIndexedDitherTest.java b/test/jdk/java/awt/image/DrawImage/ByteIndexedDitherTest.java new file mode 100644 index 00000000000..0c0aa49eb43 --- /dev/null +++ b/test/jdk/java/awt/image/DrawImage/ByteIndexedDitherTest.java @@ -0,0 +1,83 @@ +/* + * 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 8280964 + * @summary Tests that drawing to a ByteIndexed image dithers correctly. + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; + +public class ByteIndexedDitherTest { + + public static void main(String[] args) { + BufferedImage bgr = createBGRImage(); + BufferedImage indexed = createIndexedImage(bgr); + checkImage(indexed); + } + + static BufferedImage createBGRImage() { + + int sz = 8; + BufferedImage img; + img = new BufferedImage(sz, sz, BufferedImage.TYPE_3BYTE_BGR); + Graphics2D g = img.createGraphics(); + Color c = new Color(0, 0, 254); + g.setColor(c); + g.fillRect(0, 0, sz, sz); + g.dispose(); + + return img; + } + + static BufferedImage createIndexedImage(BufferedImage srcImage) { + + int w = srcImage.getWidth(null); + int h = srcImage.getHeight(null); + BufferedImage + indexedImg = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_INDEXED); + Graphics2D g = indexedImg.createGraphics(); + g.drawImage(srcImage, 0, 0, w, h, null); + g.dispose(); + return indexedImg; + } + + static void checkImage(BufferedImage image) { + int wid = image.getWidth(); + int hgt = image.getHeight(); + for (int y=0; y - - + */ - - true - 0 ms - - +package java.io; + +public class NameClassCache extends ClassCache { + protected String computeValue(Class cl) { + // Return string that is not interned and specific to class + return "ClassCache-" + cl.getName(); + } + + public String get(Class cl) { + return super.get(cl); + } +} diff --git a/test/jdk/java/io/ClassCache/java.base/java/io/NullClassCache.java b/test/jdk/java/io/ClassCache/java.base/java/io/NullClassCache.java new file mode 100644 index 00000000000..58c92ef1399 --- /dev/null +++ b/test/jdk/java/io/ClassCache/java.base/java/io/NullClassCache.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.io; + +public class NullClassCache extends ClassCache { + protected Object computeValue(Class cl) { + return null; + } + + public Object get(Class cl) { + return super.get(cl); + } +} diff --git a/test/jdk/java/io/FileOutputStream/OpenNUL.java b/test/jdk/java/io/FileOutputStream/OpenNUL.java new file mode 100644 index 00000000000..dc14db070a4 --- /dev/null +++ b/test/jdk/java/io/FileOutputStream/OpenNUL.java @@ -0,0 +1,52 @@ +/* + * 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 8285445 + * @requires (os.family == "windows") + * @summary Verify behavior of opening "NUL:" with ADS enabled and disabled. + * @run main/othervm -Djdk.io.File.enableADS OpenNUL + * @run main/othervm -Djdk.io.File.enableADS=true OpenNUL + */ + +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + +public class OpenNUL { + public static void main(String args[]) throws IOException { + String enableADS = System.getProperty("jdk.io.File.enableADS"); + boolean fails = enableADS.equalsIgnoreCase(Boolean.FALSE.toString()); + + FileOutputStream fos; + try { + fos = new FileOutputStream("NUL:"); + if (fails) + throw new RuntimeException("Should have failed"); + } catch (FileNotFoundException fnfe) { + if (!fails) + throw new RuntimeException("Should not have failed"); + } + } +} diff --git a/test/jdk/java/io/ObjectStreamClass/ObjectStreamClassCaching.java b/test/jdk/java/io/ObjectStreamClass/ObjectStreamClassCaching.java new file mode 100644 index 00000000000..74c21c540d8 --- /dev/null +++ b/test/jdk/java/io/ObjectStreamClass/ObjectStreamClassCaching.java @@ -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. + */ + +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; +import java.io.ObjectStreamClass; +import java.io.Serializable; +import java.util.ArrayList; +import org.testng.annotations.Test; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +/* @test + * @bug 8277072 + * @library /test/lib/ + * @summary ObjectStreamClass caches keep ClassLoaders alive + * @run testng/othervm -Xmx10m -XX:SoftRefLRUPolicyMSPerMB=1 ObjectStreamClassCaching + */ +public class ObjectStreamClassCaching { + + @Test + public void testCachingEffectiveness() throws Exception { + var ref = lookupObjectStreamClass(TestClass.class); + System.gc(); + Thread.sleep(100L); + // to trigger any ReferenceQueue processing... + lookupObjectStreamClass(AnotherTestClass.class); + assertFalse(ref.refersTo(null), + "Cache lost entry although memory was not under pressure"); + } + + @Test + public void testCacheReleaseUnderMemoryPressure() throws Exception { + var ref = lookupObjectStreamClass(TestClass.class); + pressMemoryHard(ref); + System.gc(); + Thread.sleep(100L); + assertTrue(ref.refersTo(null), + "Cache still has entry although memory was pressed hard"); + } + + // separate method so that the looked-up ObjectStreamClass is not kept on stack + private static WeakReference lookupObjectStreamClass(Class cl) { + return new WeakReference<>(ObjectStreamClass.lookup(cl)); + } + + private static void pressMemoryHard(Reference ref) { + try { + var list = new ArrayList<>(); + while (!ref.refersTo(null)) { + list.add(new byte[1024 * 1024 * 64]); // 64 MiB chunks + } + } catch (OutOfMemoryError e) { + // release + } + } +} + +class TestClass implements Serializable { +} + +class AnotherTestClass implements Serializable { +} diff --git a/test/jdk/java/io/ObjectStreamClass/TestOSCClassLoaderLeak.java b/test/jdk/java/io/ObjectStreamClass/TestOSCClassLoaderLeak.java new file mode 100644 index 00000000000..3a99760bb6e --- /dev/null +++ b/test/jdk/java/io/ObjectStreamClass/TestOSCClassLoaderLeak.java @@ -0,0 +1,108 @@ +/* + * 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. + */ + +import java.lang.ref.WeakReference; +import java.lang.reflect.Constructor; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.ObjectStreamClass; +import java.io.ObjectStreamField; +import java.io.Serializable; +import java.util.Arrays; +import org.testng.annotations.Test; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +import jdk.test.lib.util.ForceGC; + +/* @test + * @bug 8277072 + * @library /test/lib/ + * @build jdk.test.lib.util.ForceGC + * @summary ObjectStreamClass caches keep ClassLoaders alive + * @run testng TestOSCClassLoaderLeak + */ +public class TestOSCClassLoaderLeak { + + @Test + public void testClassLoaderLeak() throws Exception { + TestClassLoader myOwnClassLoader = new TestClassLoader(); + Class loadClass = myOwnClassLoader.loadClass("ObjectStreamClass_MemoryLeakExample"); + Constructor con = loadClass.getConstructor(); + con.setAccessible(true); + Object objectStreamClass_MemoryLeakExample = con.newInstance(); + objectStreamClass_MemoryLeakExample.toString(); + + WeakReference myOwnClassLoaderWeakReference = new WeakReference<>(myOwnClassLoader); + assertNotNull(myOwnClassLoaderWeakReference.get()); + objectStreamClass_MemoryLeakExample = null; + myOwnClassLoader = null; + loadClass = null; + con = null; + assertNotNull(myOwnClassLoaderWeakReference.get()); + + ForceGC gc = new ForceGC(); + assertTrue(gc.await(() -> myOwnClassLoaderWeakReference.get() == null)); + } +} + +class ObjectStreamClass_MemoryLeakExample { + private static final ObjectStreamField[] fields = ObjectStreamClass.lookup(TestClass.class).getFields(); + public ObjectStreamClass_MemoryLeakExample() { + } + + @Override + public String toString() { + return Arrays.toString(fields); + } +} + +class TestClassLoader extends ClassLoader { + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + if (name.equals("TestClass") || name.equals("ObjectStreamClass_MemoryLeakExample")) { + byte[] bt = loadClassData(name); + return defineClass(name, bt, 0, bt.length); + } else { + return super.loadClass(name); + } + } + + private static byte[] loadClassData(String className) { + ByteArrayOutputStream byteSt = new ByteArrayOutputStream(); + try (InputStream is = TestClassLoader.class.getClassLoader().getResourceAsStream(className.replace(".", "/") + ".class")) { + int len = 0; + while ((len = is.read()) != -1) { + byteSt.write(len); + } + } catch (java.io.IOException e) { + e.printStackTrace(); + } + return byteSt.toByteArray(); + } +} + +class TestClass implements Serializable { + public String x; +} diff --git a/test/jdk/java/io/Serializable/serialFilter/GlobalFilterTest.java b/test/jdk/java/io/Serializable/serialFilter/GlobalFilterTest.java index 8e011088b78..0852cf96cbb 100644 --- a/test/jdk/java/io/Serializable/serialFilter/GlobalFilterTest.java +++ b/test/jdk/java/io/Serializable/serialFilter/GlobalFilterTest.java @@ -53,18 +53,6 @@ * * @summary Test Global Filters */ - -/* @test - * @bug 8261160 - * @summary Add a deserialization JFR event - * @build GlobalFilterTest SerialFilterTest - * @requires vm.hasJFR - * @run testng/othervm/policy=security.policy - * -XX:StartFlightRecording:name=DeserializationEvent,dumponexit=true - * -Djava.security.properties=${test.src}/java.security-extra1 - * -Djava.security.debug=properties GlobalFilterTest - */ - @Test public class GlobalFilterTest { private static final String serialPropName = "jdk.serialFilter"; diff --git a/test/jdk/java/lang/RuntimeTests/exec/ExecWithDir.java b/test/jdk/java/lang/RuntimeTests/exec/ExecWithDir.java deleted file mode 100644 index a52e2221ca8..00000000000 --- a/test/jdk/java/lang/RuntimeTests/exec/ExecWithDir.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2002, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please 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 4750978 - * @run main/othervm/timeout=300 ExecWithDir - * @summary Ensure that we can fork-and-exec repeatedly when a new working - * directory is specified - */ - -import java.io.File; - -public class ExecWithDir { - - private static final int N = 500; - - public static void main(String args[]) throws Exception { - if (! UnixCommands.isUnix) { - System.out.println("For UNIX only"); - return; - } - UnixCommands.ensureCommandsAvailable("true"); - - final String trueCmd = UnixCommands.findCommand("true"); - File dir = new File("."); - for (int i = 1; i <= N; i++) { - System.out.print(i); - System.out.print(" e"); - Process p = Runtime.getRuntime().exec(trueCmd, null, dir); - System.out.print('w'); - int s = p.waitFor(); - System.out.println("x " + s); - if (s != 0) throw new Error("Unexpected return code " + s); - - // Avoid "Too many open files" - p.getInputStream().close(); - p.getOutputStream().close(); - p.getErrorStream().close(); - } - } -} diff --git a/test/jdk/java/lang/module/customfs/ModulesInCustomFileSystem.java b/test/jdk/java/lang/module/customfs/ModulesInCustomFileSystem.java index 48c95e493c2..6861c7588df 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, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -23,6 +23,7 @@ /** * @test + * @bug 8178380 8282444 * @modules jdk.zipfs * @library /test/lib * @build ModulesInCustomFileSystem m1/* m2/* diff --git a/test/jdk/java/lang/module/customfs/m1/p/Main.java b/test/jdk/java/lang/module/customfs/m1/p/Main.java index 65e45a8dac9..b8c31374280 100644 --- a/test/jdk/java/lang/module/customfs/m1/p/Main.java +++ b/test/jdk/java/lang/module/customfs/m1/p/Main.java @@ -25,6 +25,6 @@ public class Main { public static void main(String[] args) { - q.Hello.hello(); + q.r.Hello.hello(); } } diff --git a/test/jdk/java/lang/module/customfs/m2/module-info.java b/test/jdk/java/lang/module/customfs/m2/module-info.java index 72b35d933cf..92560aa20f1 100644 --- a/test/jdk/java/lang/module/customfs/m2/module-info.java +++ b/test/jdk/java/lang/module/customfs/m2/module-info.java @@ -22,5 +22,5 @@ */ module m2 { - exports q; + exports q.r; } diff --git a/test/jdk/java/lang/module/customfs/m2/q/Hello.java b/test/jdk/java/lang/module/customfs/m2/q/r/Hello.java similarity index 98% rename from test/jdk/java/lang/module/customfs/m2/q/Hello.java rename to test/jdk/java/lang/module/customfs/m2/q/r/Hello.java index 5f912cd51ad..1e6ce808a56 100644 --- a/test/jdk/java/lang/module/customfs/m2/q/Hello.java +++ b/test/jdk/java/lang/module/customfs/m2/q/r/Hello.java @@ -21,7 +21,7 @@ * questions. */ -package q; +package q.r; public class Hello { public static void hello() { diff --git a/test/jdk/java/nio/file/Files/InterruptCopy.java b/test/jdk/java/nio/file/Files/InterruptCopy.java index 05bdb4d37c1..f13a2877d91 100644 --- a/test/jdk/java/nio/file/Files/InterruptCopy.java +++ b/test/jdk/java/nio/file/Files/InterruptCopy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -28,16 +28,24 @@ * @library .. */ -import java.nio.file.*; -import java.io.*; -import java.util.concurrent.*; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.FileStore; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.concurrent.Callable; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; import com.sun.nio.file.ExtendedCopyOption; public class InterruptCopy { - private static final long FILE_SIZE_TO_COPY = 512L * 1024L * 1024L; - private static final int DELAY_IN_MS = 500; - private static final int DURATION_MAX_IN_MS = 5000; + private static final long FILE_SIZE_TO_COPY = 1024L * 1024L * 1024L; + private static final int INTERRUPT_DELAY_IN_MS = 50; + private static final int CANCEL_DELAY_IN_MS = 10; public static void main(String[] args) throws Exception { Path dir = TestUtil.createTemporaryDirectory(); @@ -74,46 +82,83 @@ static void doTest(Path dir) throws Exception { ScheduledExecutorService pool = Executors.newSingleThreadScheduledExecutor(); + try { - // copy source to target in main thread, interrupting it after a delay + // copy source to target in main thread, interrupting it + // after a delay final Thread me = Thread.currentThread(); - Future wakeup = pool.schedule(new Runnable() { + final CountDownLatch interruptLatch = new CountDownLatch(1); + Future wakeup = pool.submit(new Runnable() { public void run() { + try { + interruptLatch.await(); + Thread.sleep(INTERRUPT_DELAY_IN_MS); + } catch (InterruptedException ignore) { + } + System.out.printf("Interrupting at %d ms...%n", + System.currentTimeMillis()); me.interrupt(); - }}, DELAY_IN_MS, TimeUnit.MILLISECONDS); - System.out.println("Copying file..."); + } + }); try { - long start = System.currentTimeMillis(); + interruptLatch.countDown(); + long theBeginning = System.currentTimeMillis(); + System.out.printf("Copying file at %d ms...%n", theBeginning); Files.copy(source, target, ExtendedCopyOption.INTERRUPTIBLE); - long duration = System.currentTimeMillis() - start; - if (duration > DURATION_MAX_IN_MS) - throw new RuntimeException("Copy was not interrupted"); + long theEnd = System.currentTimeMillis(); + System.out.printf("Done copying at %d ms...%n", theEnd); + long duration = theEnd - theBeginning; + + // If the copy was interrupted the target file should have been + // deleted, so if the file does not exist, then the copy must + // have been interrupted without throwing an exception; if the + // file exists, then the copy finished before being interrupted + // so not throwing an exception is not considered a failure + if (Files.notExists(target)) + throw new RuntimeException("Copy was not interrupted in " + + duration + " ms"); } catch (IOException e) { boolean interrupted = Thread.interrupted(); if (!interrupted) throw new RuntimeException("Interrupt status was not set"); - System.out.println("Copy failed (this is expected)"); + System.out.println("Copy failed (this is expected)."); } try { wakeup.get(); } catch (InterruptedException ignore) { } Thread.interrupted(); - // copy source to target via task in thread pool, interrupting it after - // a delay using cancel(true) + // copy source to target via task in thread pool, interrupting it + // after a delay using cancel(true) + CountDownLatch cancelLatch = new CountDownLatch(1); Future result = pool.submit(new Callable() { public Void call() throws IOException { - System.out.println("Copying file..."); + cancelLatch.countDown(); + System.out.printf("Copying file at %d ms...%n", + System.currentTimeMillis()); Files.copy(source, target, ExtendedCopyOption.INTERRUPTIBLE, StandardCopyOption.REPLACE_EXISTING); + System.out.printf("Done copying at %d ms...%n", + System.currentTimeMillis()); return null; } }); - Thread.sleep(DELAY_IN_MS); - boolean cancelled = result.cancel(true); - if (!cancelled) + try { + cancelLatch.await(); + Thread.sleep(CANCEL_DELAY_IN_MS); + } catch (InterruptedException ignore) { + } + if (result.isDone()) + throw new RuntimeException("Copy finished before cancellation"); + System.out.printf("Cancelling at %d ms...%n", + System.currentTimeMillis()); + boolean cancelled = result.cancel(true); + if (cancelled) + System.out.println("Copy cancelled."); + else { result.get(); - System.out.println("Copy cancelled."); + throw new RuntimeException("Copy was not cancelled"); + } } finally { pool.shutdown(); } diff --git a/test/jdk/java/util/Random/RandomExponentialTest.java b/test/jdk/java/util/Random/RandomExponentialTest.java new file mode 100644 index 00000000000..d46176de0e2 --- /dev/null +++ b/test/jdk/java/util/Random/RandomExponentialTest.java @@ -0,0 +1,58 @@ +/* + * 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. + */ + +import jdk.test.lib.RandomFactory; + +/** + * @test + * @summary Check that nextExponential() returns non-negative outcomes + * @bug 8284866 + * + * @key randomness + * @library /test/lib + * @build jdk.test.lib.RandomFactory + * @run main RandomExponentialTest + */ + +public class RandomExponentialTest { + + private static final int SAMPLES = 1_000_000_000; + + public static void main(String[] args) throws Exception { + var errCount = 0; + var errSample = Double.NaN; + var random = RandomFactory.getRandom(); + for (int i = 0; i < SAMPLES; i++) { + var expVal = random.nextExponential(); + if (!(expVal >= 0.0)) { + errCount += 1; + errSample = expVal; + } + } + if (errCount > 0) { + throw new RuntimeException("%d errors out of %d samples: e.g., %f" + .formatted(errCount, SAMPLES, errSample)); + } + } + +} diff --git a/test/jdk/java/util/regex/GraphemeTest.java b/test/jdk/java/util/regex/GraphemeTest.java index 27c1a9d777c..e0370220f43 100644 --- a/test/jdk/java/util/regex/GraphemeTest.java +++ b/test/jdk/java/util/regex/GraphemeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -26,23 +26,25 @@ * @bug 7071819 8221431 8239383 * @summary tests Unicode Extended Grapheme support * @library /lib/testlibrary/java/lang - * @run main GraphemeTest + * @run testng GraphemeTest */ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.Scanner; -import java.util.regex.Pattern; -import java.util.regex.Matcher; + +import org.testng.annotations.Test; +import static org.testng.Assert.fail; public class GraphemeTest { - public static void main(String[] args) throws Throwable { + @Test + public static void testGraphemeBreakProperty() throws Throwable { testProps(UCDFiles.GRAPHEME_BREAK_PROPERTY); + } + + @Test + public static void testEmojiData() throws Throwable { testProps(UCDFiles.EMOJI_DATA); } @@ -78,7 +80,7 @@ private static void testProps(Path path) throws IOException { System.out.printf("[%x] [%s][%d] -> [%s]%n", cp, expected, Character.getType(cp), types[getType(cp)]); else - throw new RuntimeException(String.format( + fail(String.format( "cp=[%x], expeced:[%s] result:[%s]%n", cp, expected, types[getType(cp)])); } diff --git a/test/jdk/java/util/regex/NegativeArraySize.java b/test/jdk/java/util/regex/NegativeArraySize.java index 0f210b133cd..d64f6acb000 100644 --- a/test/jdk/java/util/regex/NegativeArraySize.java +++ b/test/jdk/java/util/regex/NegativeArraySize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -25,18 +25,18 @@ * @test * @bug 8223174 * @summary Pattern.compile() can throw confusing NegativeArraySizeException - * @requires os.maxMemory >= 5g - * @run main/othervm NegativeArraySize -Xms5G -Xmx5G + * @requires os.maxMemory >= 5g & vm.bits == 64 + * @run testng/othervm -Xms5G -Xmx5G NegativeArraySize */ +import org.testng.annotations.Test; +import static org.testng.Assert.assertThrows; + import java.util.regex.Pattern; public class NegativeArraySize { - public static void main(String[] args) { - try { - Pattern.compile("\\Q" + "a".repeat(42 + Integer.MAX_VALUE / 3)); - throw new AssertionError("expected to throw"); - } catch (OutOfMemoryError expected) { - } + @Test + public static void testNegativeArraySize() { + assertThrows(OutOfMemoryError.class, () -> Pattern.compile("\\Q" + "a".repeat(42 + Integer.MAX_VALUE / 3))); } } diff --git a/test/jdk/java/util/regex/RegExTest.java b/test/jdk/java/util/regex/RegExTest.java index 3bfc63acdfb..370b0d9696b 100644 --- a/test/jdk/java/util/regex/RegExTest.java +++ b/test/jdk/java/util/regex/RegExTest.java @@ -24,7 +24,6 @@ /** * @test * @summary tests RegExp framework (use -Dseed=X to set PRNG seed) - * @author Mike McCloskey * @bug 4481568 4482696 4495089 4504687 4527731 4599621 4631553 4619345 * 4630911 4672616 4711773 4727935 4750573 4792284 4803197 4757029 4808962 * 4872664 4803179 4892980 4900747 4945394 4938995 4979006 4994840 4997476 @@ -36,23 +35,17 @@ * 8151481 4867170 7080302 6728861 6995635 6736245 4916384 6328855 6192895 * 6345469 6988218 6693451 7006761 8140212 8143282 8158482 8176029 8184706 * 8194667 8197462 8184692 8221431 8224789 8228352 8230829 8236034 8235812 - * 8216332 8214245 8237599 8241055 8247546 8258259 8037397 + * 8216332 8214245 8237599 8241055 8247546 8258259 8037397 8269753 * * @library /test/lib * @library /lib/testlibrary/java/lang * @build jdk.test.lib.RandomFactory - * @run main RegExTest + * @author Mike McCloskey + * @run testng RegExTest * @key randomness */ -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStreamReader; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; +import java.io.*; import java.math.BigInteger; import java.nio.CharBuffer; import java.nio.file.Files; @@ -74,145 +67,34 @@ import java.util.stream.IntStream; import java.util.stream.Stream; +import org.testng.annotations.Test; +import org.testng.Assert; + + import jdk.test.lib.RandomFactory; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotEquals; +import static org.testng.Assert.assertNotSame; +import static org.testng.Assert.assertThrows; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; +import static org.testng.Assert.expectThrows; + /** * This is a test class created to check the operation of * the Pattern and Matcher classes. */ public class RegExTest { - private static Random generator = RandomFactory.getRandom(); - private static boolean failure = false; - private static int failCount = 0; - private static String firstFailure = null; - - /** - * Main to interpret arguments and run several tests. - * - */ - public static void main(String[] args) throws Exception { - // Most of the tests are in a file - processFile("TestCases.txt"); - //processFile("PerlCases.txt"); - processFile("BMPTestCases.txt"); - processFile("SupplementaryTestCases.txt"); - - // These test many randomly generated char patterns - bm(); - slice(); - - // These are hard to put into the file - escapes(); - blankInput(); - - // Substitition tests on randomly generated sequences - globalSubstitute(); - stringbufferSubstitute(); - stringbuilderSubstitute(); - - substitutionBasher(); - substitutionBasher2(); - - // Canonical Equivalence - ceTest(); - - // Anchors - anchorTest(); - - // boolean match calls - matchesTest(); - lookingAtTest(); - - // Pattern API - patternMatchesTest(); - - // Misc - lookbehindTest(); - nullArgumentTest(); - backRefTest(); - groupCaptureTest(); - caretTest(); - charClassTest(); - emptyPatternTest(); - findIntTest(); - group0Test(); - longPatternTest(); - octalTest(); - ampersandTest(); - negationTest(); - splitTest(); - appendTest(); - caseFoldingTest(); - commentsTest(); - unixLinesTest(); - replaceFirstTest(); - gTest(); - zTest(); - serializeTest(); - reluctantRepetitionTest(); - multilineDollarTest(); - dollarAtEndTest(); - caretBetweenTerminatorsTest(); - // This RFE rejected in Tiger numOccurrencesTest(); - javaCharClassTest(); - nonCaptureRepetitionTest(); - notCapturedGroupCurlyMatchTest(); - escapedSegmentTest(); - literalPatternTest(); - literalReplacementTest(); - regionTest(); - toStringTest(); - negatedCharClassTest(); - findFromTest(); - boundsTest(); - unicodeWordBoundsTest(); - caretAtEndTest(); - wordSearchTest(); - hitEndTest(); - toMatchResultTest(); - toMatchResultTest2(); - surrogatesInClassTest(); - removeQEQuotingTest(); - namedGroupCaptureTest(); - nonBmpClassComplementTest(); - unicodePropertiesTest(); - unicodeHexNotationTest(); - unicodeClassesTest(); - unicodeCharacterNameTest(); - horizontalAndVerticalWSTest(); - linebreakTest(); - branchTest(); - groupCurlyNotFoundSuppTest(); - groupCurlyBackoffTest(); - patternAsPredicate(); - patternAsMatchPredicate(); - invalidFlags(); - embeddedFlags(); - grapheme(); - expoBacktracking(); - invalidGroupName(); - illegalRepetitionRange(); - surrogatePairWithCanonEq(); - lineBreakWithQuantifier(); - caseInsensitivePMatch(); - surrogatePairOverlapRegion(); - droppedClassesWithIntersection(); - - - if (failure) { - throw new - RuntimeException("RegExTest failed, 1st failure: " + - firstFailure); - } else { - System.err.println("OKAY: All tests passed."); - } - } + private static final Random generator = RandomFactory.getRandom(); // Utility functions private static String getRandomAlphaString(int length) { - StringBuffer buf = new StringBuffer(length); + + StringBuilder buf = new StringBuilder(length); for (int i=0; i 0) { - failure = true; - - if (firstFailure == null) { - firstFailure = testName; - } - } + check(pattern, input, expected); + } + + private static void check(Pattern p, String s, String g, String expected) { + Matcher m = p.matcher(s); + m.find(); + assertFalse(!m.group(g).equals(expected) || + s.charAt(m.start(g)) != expected.charAt(0) || + s.charAt(m.end(g) - 1) != expected.charAt(expected.length() - 1)); + } + private static void checkReplaceFirst(String p, String s, String r, String expected) + { + assertEquals(expected, Pattern.compile(p).matcher(s).replaceFirst(r)); + } - failCount = 0; + private static void checkReplaceAll(String p, String s, String r, String expected) + { + assertEquals(expected, Pattern.compile(p).matcher(s).replaceAll(r)); + } + + private static void checkExpectedFail(String p) { + assertThrows(PatternSyntaxException.class, () -> + Pattern.compile(p)); } /** @@ -296,9 +175,9 @@ private static void report(String testName) { * supplementary characters. This method does NOT fully take care * of the regex syntax. */ - private static String toSupplementaries(String s) { + public static String toSupplementaries(String s) { int length = s.length(); - StringBuffer sb = new StringBuffer(length * 2); + StringBuilder sb = new StringBuilder(length * 2); for (int i = 0; i < length; ) { char c = s.charAt(i++); @@ -325,153 +204,134 @@ private static String toSupplementaries(String s) { } // Regular expression tests + //Following three tests execute from a file. + @Test + public static void processTestCases() throws IOException { + processFile("TestCases.txt"); + } - // This is for bug 6178785 - // Test if an expected NPE gets thrown when passing in a null argument - private static boolean check(Runnable test) { - try { - test.run(); - failCount++; - return false; - } catch (NullPointerException npe) { - return true; - } + @Test + public static void processBMPTestCases() throws IOException { + processFile("BMPTestCases.txt"); + } + + @Test + public static void processSupplementaryTestCases() throws IOException { + processFile("SupplementaryTestCases.txt"); } - private static void nullArgumentTest() { - check(() -> Pattern.compile(null)); - check(() -> Pattern.matches(null, null)); - check(() -> Pattern.matches("xyz", null)); - check(() -> Pattern.quote(null)); - check(() -> Pattern.compile("xyz").split(null)); - check(() -> Pattern.compile("xyz").matcher(null)); + + @Test + public static void nullArgumentTest() { + + assertThrows(NullPointerException.class, () -> Pattern.compile(null)); + assertThrows(NullPointerException.class, () -> Pattern.matches(null, null)); + assertThrows(NullPointerException.class, () -> Pattern.matches("xyz", null)); + assertThrows(NullPointerException.class, () -> Pattern.quote(null)); + assertThrows(NullPointerException.class, () -> Pattern.compile("xyz").split(null)); + assertThrows(NullPointerException.class, () -> Pattern.compile("xyz").matcher(null)); final Matcher m = Pattern.compile("xyz").matcher("xyz"); m.matches(); - check(() -> m.appendTail((StringBuffer) null)); - check(() -> m.appendTail((StringBuilder)null)); - check(() -> m.replaceAll((String) null)); - check(() -> m.replaceAll((Function)null)); - check(() -> m.replaceFirst((String)null)); - check(() -> m.replaceFirst((Function) null)); - check(() -> m.appendReplacement((StringBuffer)null, null)); - check(() -> m.appendReplacement((StringBuilder)null, null)); - check(() -> m.reset(null)); - check(() -> Matcher.quoteReplacement(null)); + assertThrows(NullPointerException.class, () -> m.appendTail((StringBuffer) null)); + assertThrows(NullPointerException.class, () -> m.appendTail((StringBuilder)null)); + assertThrows(NullPointerException.class, () -> m.replaceAll((String) null)); + assertThrows(NullPointerException.class, () -> m.replaceAll((Function)null)); + assertThrows(NullPointerException.class, () -> m.replaceFirst((String)null)); + assertThrows(NullPointerException.class, () -> m.replaceFirst((Function) null)); + assertThrows(NullPointerException.class, () -> m.appendReplacement((StringBuffer)null, null)); + assertThrows(NullPointerException.class, () -> m.appendReplacement((StringBuilder)null, null)); + assertThrows(NullPointerException.class, () -> m.reset(null)); + assertThrows(NullPointerException.class, () -> Matcher.quoteReplacement(null)); //check(() -> m.usePattern(null)); - report("Null Argument"); } // This is for bug6635133 // Test if surrogate pair in Unicode escapes can be handled correctly. - private static void surrogatesInClassTest() throws Exception { + @Test + public static void surrogatesInClassTest() { Pattern pattern = Pattern.compile("[\\ud834\\udd21-\\ud834\\udd24]"); Matcher matcher = pattern.matcher("\ud834\udd22"); - if (!matcher.find()) - failCount++; - report("Surrogate pair in Unicode escape"); + assertTrue(matcher.find(), "Surrogate pair in Unicode escape"); } // This is for bug6990617 // Test if Pattern.RemoveQEQuoting works correctly if the octal unicode // char encoding is only 2 or 3 digits instead of 4 and the first quoted // char is an octal digit. - private static void removeQEQuotingTest() throws Exception { + @Test + public static void removeQEQuotingTest() { Pattern pattern = Pattern.compile("\\011\\Q1sometext\\E\\011\\Q2sometext\\E"); Matcher matcher = pattern.matcher("\t1sometext\t2sometext"); - if (!matcher.find()) - failCount++; - report("Remove Q/E Quoting"); + assertTrue(matcher.find(), "Remove Q/E Quoting"); } // This is for bug 4988891 // Test toMatchResult to see that it is a copy of the Matcher // that is not affected by subsequent operations on the original - private static void toMatchResultTest() throws Exception { + @Test + public static void toMatchResultTest() { Pattern pattern = Pattern.compile("squid"); Matcher matcher = pattern.matcher( "agiantsquidofdestinyasmallsquidoffate"); matcher.find(); + int matcherStart1 = matcher.start(); MatchResult mr = matcher.toMatchResult(); - if (mr == matcher) - failCount++; + assertNotSame(mr, matcher, "Matcher toMatchResult is identical object"); + int resultStart1 = mr.start(); - if (matcherStart1 != resultStart1) - failCount++; + assertEquals(matcherStart1, resultStart1, "equal matchers don't have equal start indices"); matcher.find(); + int matcherStart2 = matcher.start(); int resultStart2 = mr.start(); - if (matcherStart2 == resultStart2) - failCount++; - if (resultStart1 != resultStart2) - failCount++; + assertNotEquals(matcherStart2, resultStart2, "Matcher2 and Result2 should not be equal"); + assertEquals(resultStart1, resultStart2, "Second match result should have the same state"); MatchResult mr2 = matcher.toMatchResult(); - if (mr == mr2) - failCount++; - if (mr2.start() != matcherStart2) - failCount++; - report("toMatchResult is a copy"); - } - - private static void checkExpectedISE(Runnable test) { - try { - test.run(); - failCount++; - } catch (IllegalStateException x) { - } catch (IndexOutOfBoundsException xx) { - failCount++; - } - } - - private static void checkExpectedIOOE(Runnable test) { - try { - test.run(); - failCount++; - } catch (IndexOutOfBoundsException x) {} + assertNotSame(mr, mr2, "Second Matcher copy should not be identical to the first."); + assertEquals(mr2.start(), matcherStart2, "mr2 index should equal matcher index"); } // This is for bug 8074678 // Test the result of toMatchResult throws ISE if no match is availble - private static void toMatchResultTest2() throws Exception { + @Test + public static void toMatchResultTest2() { Matcher matcher = Pattern.compile("nomatch").matcher("hello world"); matcher.find(); MatchResult mr = matcher.toMatchResult(); - checkExpectedISE(() -> mr.start()); - checkExpectedISE(() -> mr.start(2)); - checkExpectedISE(() -> mr.end()); - checkExpectedISE(() -> mr.end(2)); - checkExpectedISE(() -> mr.group()); - checkExpectedISE(() -> mr.group(2)); + assertThrows(IllegalStateException.class, mr::start); + assertThrows(IllegalStateException.class, () -> mr.start(2)); + assertThrows(IllegalStateException.class, mr::end); + assertThrows(IllegalStateException.class, () -> mr.end(2)); + assertThrows(IllegalStateException.class, mr::group); + assertThrows(IllegalStateException.class, () -> mr.group(2)); matcher = Pattern.compile("(match)").matcher("there is a match"); matcher.find(); MatchResult mr2 = matcher.toMatchResult(); - checkExpectedIOOE(() -> mr2.start(2)); - checkExpectedIOOE(() -> mr2.end(2)); - checkExpectedIOOE(() -> mr2.group(2)); - - report("toMatchResult2 appropriate exceptions"); + assertThrows(IndexOutOfBoundsException.class, () -> mr2.start(2)); + assertThrows(IndexOutOfBoundsException.class, () -> mr2.end(2)); + assertThrows(IndexOutOfBoundsException.class, () -> mr2.group(2)); } // This is for bug 5013885 // Must test a slice to see if it reports hitEnd correctly - private static void hitEndTest() throws Exception { + @Test + public static void hitEndTest() { // Basic test of Slice node Pattern p = Pattern.compile("^squidattack"); Matcher m = p.matcher("squack"); m.find(); - if (m.hitEnd()) - failCount++; + assertFalse(m.hitEnd(), "Matcher should not be at end of sequence"); m.reset("squid"); m.find(); - if (!m.hitEnd()) - failCount++; + assertTrue(m.hitEnd(), "Matcher should be at the end of sequence"); // Test Slice, SliceA and SliceU nodes for (int i=0; i<3; i++) { @@ -481,55 +341,47 @@ private static void hitEndTest() throws Exception { p = Pattern.compile("^abc", flags); m = p.matcher("ad"); m.find(); - if (m.hitEnd()) - failCount++; + assertFalse(m.hitEnd(), "Slice node test"); m.reset("ab"); m.find(); - if (!m.hitEnd()) - failCount++; + assertTrue(m.hitEnd(), "Slice node test"); } // Test Boyer-Moore node p = Pattern.compile("catattack"); m = p.matcher("attack"); m.find(); - if (!m.hitEnd()) - failCount++; + assertTrue(m.hitEnd(), "Boyer-Moore node test"); p = Pattern.compile("catattack"); m = p.matcher("attackattackattackcatatta"); m.find(); - if (!m.hitEnd()) - failCount++; + assertTrue(m.hitEnd(), "Boyer-More node test"); // 8184706: Matching u+0d at EOL against \R should hit-end p = Pattern.compile("...\\R"); m = p.matcher("cat" + (char)0x0a); m.find(); - if (m.hitEnd()) - failCount++; + assertFalse(m.hitEnd()); m = p.matcher("cat" + (char)0x0d); m.find(); - if (!m.hitEnd()) - failCount++; + assertTrue(m.hitEnd()); m = p.matcher("cat" + (char)0x0d + (char)0x0a); m.find(); - if (m.hitEnd()) - failCount++; - - report("hitEnd"); + assertFalse(m.hitEnd()); } // This is for bug 4997476 // It is weird code submitted by customer demonstrating a regression - private static void wordSearchTest() throws Exception { - String testString = new String("word1 word2 word3"); + @Test + public static void wordSearchTest() { + String testString = "word1 word2 word3"; Pattern p = Pattern.compile("\\b"); Matcher m = p.matcher(testString); int position = 0; - int start = 0; + int start; while (m.find(position)) { start = m.start(); if (start == testString.length()) @@ -541,14 +393,13 @@ private static void wordSearchTest() throws Exception { } if (testString.substring(start, position).equals(" ")) continue; - if (!testString.substring(start, position-1).startsWith("word")) - failCount++; + assertTrue(testString.substring(start, position-1).startsWith("word")); } - report("Customer word search"); } // This is for bug 4994840 - private static void caretAtEndTest() throws Exception { + @Test + public static void caretAtEndTest() { // Problem only occurs with multiline patterns // containing a beginning-of-line caret "^" followed // by an expression that also matches the empty string. @@ -556,13 +407,13 @@ private static void caretAtEndTest() throws Exception { Matcher matcher = pattern.matcher("\r"); matcher.find(); matcher.find(); - report("Caret at end"); } // This test is for 4979006 // Check to see if word boundary construct properly handles unicode // non spacing marks - private static void unicodeWordBoundsTest() throws Exception { + @Test + public static void unicodeWordBoundsTest() { String spaces = " "; String wordChar = "a"; String nsm = "\u030a"; @@ -593,40 +444,35 @@ private static void unicodeWordBoundsTest() throws Exception { // SSNNSS input = spaces + nsm + nsm + spaces; matcher.reset(input); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); // SSN.BBN.SS input = spaces + nsm + wordChar + wordChar + nsm + spaces; twoFindIndexes(input, matcher, 3, 6); - - report("Unicode word boundary"); } private static void twoFindIndexes(String input, Matcher matcher, int a, - int b) throws Exception + int b) { matcher.reset(input); matcher.find(); - if (matcher.start() != a) - failCount++; + assertEquals(matcher.start(), a); matcher.find(); - if (matcher.start() != b) - failCount++; + assertEquals(matcher.start(), b); } // This test is for 6284152 - static void check(String regex, String input, String[] expected) { - List result = new ArrayList(); + private static void check(String regex, String input, String[] expected) { + List result = new ArrayList<>(); Pattern p = Pattern.compile(regex); Matcher m = p.matcher(input); while (m.find()) { result.add(m.group()); } - if (!Arrays.asList(expected).equals(result)) - failCount++; + assertEquals(Arrays.asList(expected), result); } - private static void lookbehindTest() throws Exception { + @Test + public static void lookbehindTest() { //Positive check("(?<=%.{0,5})foo\\d", "%foo1\n%bar foo2\n%bar foo3\n%blahblah foo4\nfoo5", @@ -659,162 +505,140 @@ private static void lookbehindTest() throws Exception { new String[] {"fo\ud800\udc00o"}); check("(?]"); Matcher matcher = pattern.matcher("\u203A"); - if (!matcher.matches()) - failCount++; + assertTrue(matcher.matches()); + pattern = Pattern.compile("[^fr]"); matcher = pattern.matcher("a"); - if (!matcher.find()) - failCount++; + assertTrue(matcher.find()); + matcher.reset("\u203A"); - if (!matcher.find()) - failCount++; + assertTrue(matcher.find()); String s = "for"; - String result[] = s.split("[^fr]"); - if (!result[0].equals("f")) - failCount++; - if (!result[1].equals("r")) - failCount++; + String[] result = s.split("[^fr]"); + assertEquals(result[0], "f"); + assertEquals(result[1], "r"); s = "f\u203Ar"; result = s.split("[^fr]"); - if (!result[0].equals("f")) - failCount++; - if (!result[1].equals("r")) - failCount++; + assertEquals(result[0], "f"); + assertEquals(result[1], "r"); // Test adding to bits, subtracting a node, then adding to bits again pattern = Pattern.compile("[^f\u203Ar]"); matcher = pattern.matcher("a"); - if (!matcher.find()) - failCount++; + assertTrue(matcher.find()); matcher.reset("f"); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); matcher.reset("\u203A"); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); matcher.reset("r"); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); matcher.reset("\u203B"); - if (!matcher.find()) - failCount++; + assertTrue(matcher.find()); // Test subtracting a node, adding to bits, subtracting again pattern = Pattern.compile("[^\u203Ar\u203B]"); matcher = pattern.matcher("a"); - if (!matcher.find()) - failCount++; + assertTrue(matcher.find()); matcher.reset("\u203A"); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); matcher.reset("r"); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); matcher.reset("\u203B"); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); matcher.reset("\u203C"); - if (!matcher.find()) - failCount++; - - report("Negated Character Class"); + assertTrue(matcher.find()); } // This test is for 4628291 - private static void toStringTest() throws Exception { + @Test + public static void toStringTest() { Pattern pattern = Pattern.compile("b+"); - if (pattern.toString() != "b+") - failCount++; + assertEquals(pattern.toString(), "b+"); Matcher matcher = pattern.matcher("aaabbbccc"); String matcherString = matcher.toString(); // unspecified matcher.find(); - matcherString = matcher.toString(); // unspecified + matcher.toString(); // unspecified matcher.region(0,3); - matcherString = matcher.toString(); // unspecified + matcher.toString(); // unspecified matcher.reset(); - matcherString = matcher.toString(); // unspecified - report("toString"); + matcher.toString(); // unspecified } // This test is for 4808962 - private static void literalPatternTest() throws Exception { + @Test + public static void literalPatternTest() { int flags = Pattern.LITERAL; Pattern pattern = Pattern.compile("abc\\t$^", flags); @@ -874,6 +698,7 @@ private static void literalPatternTest() throws Exception { flags |= Pattern.CANON_EQ; + //Note: Possible issue Pattern p = Pattern.compile("testa\u030a", flags); check(pattern, "testa\u030a", false); check(pattern, "test\u00e5", false); @@ -922,97 +747,74 @@ private static void literalPatternTest() throws Exception { flags |= Pattern.CANON_EQ; String t = toSupplementaries("test"); + //Note: Possible issue p = Pattern.compile(t + "a\u030a", flags); check(pattern, t + "a\u030a", false); check(pattern, t + "\u00e5", false); - - report("Literal pattern"); } // This test is for 4803179 // This test is also for 4808962, replacement parts - private static void literalReplacementTest() throws Exception { + @Test + public static void literalReplacementTest() { int flags = Pattern.LITERAL; Pattern pattern = Pattern.compile("abc", flags); Matcher matcher = pattern.matcher("zzzabczzz"); String replaceTest = "$0"; String result = matcher.replaceAll(replaceTest); - if (!result.equals("zzzabczzz")) - failCount++; + assertEquals(result, "zzzabczzz"); matcher.reset(); - String literalReplacement = matcher.quoteReplacement(replaceTest); + String literalReplacement = Matcher.quoteReplacement(replaceTest); result = matcher.replaceAll(literalReplacement); - if (!result.equals("zzz$0zzz")) - failCount++; + assertEquals(result, "zzz$0zzz"); matcher.reset(); replaceTest = "\\t$\\$"; - literalReplacement = matcher.quoteReplacement(replaceTest); + literalReplacement = Matcher.quoteReplacement(replaceTest); result = matcher.replaceAll(literalReplacement); - if (!result.equals("zzz\\t$\\$zzz")) - failCount++; + assertEquals(result, "zzz\\t$\\$zzz"); // Supplementary character test pattern = Pattern.compile(toSupplementaries("abc"), flags); matcher = pattern.matcher(toSupplementaries("zzzabczzz")); replaceTest = "$0"; result = matcher.replaceAll(replaceTest); - if (!result.equals(toSupplementaries("zzzabczzz"))) - failCount++; + assertEquals(result, toSupplementaries("zzzabczzz")); matcher.reset(); - literalReplacement = matcher.quoteReplacement(replaceTest); + literalReplacement = Matcher.quoteReplacement(replaceTest); result = matcher.replaceAll(literalReplacement); - if (!result.equals(toSupplementaries("zzz$0zzz"))) - failCount++; + assertEquals(result, toSupplementaries("zzz$0zzz")); matcher.reset(); replaceTest = "\\t$\\$"; - literalReplacement = matcher.quoteReplacement(replaceTest); + literalReplacement = Matcher.quoteReplacement(replaceTest); result = matcher.replaceAll(literalReplacement); - if (!result.equals(toSupplementaries("zzz\\t$\\$zzz"))) - failCount++; + assertEquals(result, toSupplementaries("zzz\\t$\\$zzz")); // IAE should be thrown if backslash or '$' is the last character // in replacement string - try { - "\uac00".replaceAll("\uac00", "$"); - failCount++; - } catch (IllegalArgumentException iie) { - } catch (Exception e) { - failCount++; - } - try { - "\uac00".replaceAll("\uac00", "\\"); - failCount++; - } catch (IllegalArgumentException iie) { - } catch (Exception e) { - failCount++; - } - report("Literal replacement"); + assertThrows(IllegalArgumentException.class, () -> "\uac00".replaceAll("\uac00", "$")); + assertThrows(IllegalArgumentException.class, () -> "\uac00".replaceAll("\uac00", "\\")); } // This test is for 4757029 - private static void regionTest() throws Exception { + @Test + public static void regionTest() { Pattern pattern = Pattern.compile("abc"); Matcher matcher = pattern.matcher("abcdefabc"); matcher.region(0,9); - if (!matcher.find()) - failCount++; - if (!matcher.find()) - failCount++; + assertTrue(matcher.find()); + assertTrue(matcher.find()); matcher.region(0,3); - if (!matcher.find()) - failCount++; + assertTrue(matcher.find()); matcher.region(3,6); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); matcher.region(0,2); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); expectRegionFail(matcher, 1, -1); expectRegionFail(matcher, -1, -1); @@ -1024,43 +826,33 @@ private static void regionTest() throws Exception { pattern = Pattern.compile("^abc$"); matcher = pattern.matcher("zzzabczzz"); matcher.region(0,9); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); matcher.region(3,6); - if (!matcher.find()) - failCount++; + assertTrue(matcher.find()); matcher.region(3,6); matcher.useAnchoringBounds(false); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); // Supplementary character test pattern = Pattern.compile(toSupplementaries("abc")); matcher = pattern.matcher(toSupplementaries("abcdefabc")); matcher.region(0,9*2); - if (!matcher.find()) - failCount++; - if (!matcher.find()) - failCount++; + assertTrue(matcher.find()); + assertTrue(matcher.find()); matcher.region(0,3*2); - if (!matcher.find()) - failCount++; + assertTrue(matcher.find()); matcher.region(1,3*2); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); matcher.region(3*2,6*2); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); matcher.region(0,2*2); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); matcher.region(0,2*2+1); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); - expectRegionFail(matcher, 1*2, -1); + expectRegionFail(matcher, 2, -1); expectRegionFail(matcher, -1, -1); - expectRegionFail(matcher, -1, 1*2); + expectRegionFail(matcher, -1, 2); expectRegionFail(matcher, 5*2, 3*2); expectRegionFail(matcher, 5*2, 12*2); expectRegionFail(matcher, 12*2, 12*2); @@ -1068,55 +860,45 @@ private static void regionTest() throws Exception { pattern = Pattern.compile(toSupplementaries("^abc$")); matcher = pattern.matcher(toSupplementaries("zzzabczzz")); matcher.region(0,9*2); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); matcher.region(3*2,6*2); - if (!matcher.find()) - failCount++; + assertTrue(matcher.find()); matcher.region(3*2+1,6*2); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); matcher.region(3*2,6*2-1); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); matcher.region(3*2,6*2); matcher.useAnchoringBounds(false); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); // JDK-8230829 pattern = Pattern.compile("\\ud800\\udc61"); matcher = pattern.matcher("\ud800\udc61"); matcher.region(0, 1); - if (matcher.find()) { - failCount++; - System.out.println("Matched a surrogate pair" + - " that crosses border of region"); - } - if (!matcher.hitEnd()) { - failCount++; - System.out.println("Expected to hit the end when" + - " matching a surrogate pair crossing region"); - } + assertFalse(matcher.find(), "Matched a surrogate pair" + + " that crosses border of region"); - report("Regions"); + assertTrue(matcher.hitEnd(), "Expected to hit the end when" + + " matching a surrogate pair crossing region"); } private static void expectRegionFail(Matcher matcher, int index1, int index2) { + try { matcher.region(index1, index2); - failCount++; - } catch (IndexOutOfBoundsException ioobe) { - // Correct result - } catch (IllegalStateException ise) { + fail(); + } catch (IndexOutOfBoundsException | IllegalStateException ioobe) { // Correct result + } catch (Exception e) { + fail(); } } // This test is for 4803197 - private static void escapedSegmentTest() throws Exception { + @Test + public static void escapedSegmentTest() { Pattern pattern = Pattern.compile("\\Qdir1\\dir2\\E"); check(pattern, "dir1\\dir2", true); @@ -1136,12 +918,11 @@ private static void escapedSegmentTest() throws Exception { pattern = Pattern.compile(toSupplementaries("(\\Qdir1\\dir2")+"\\\\E)"); check(pattern, toSupplementaries("dir1\\dir2\\"), true); - - report("Escaped segment"); } // This test is for 4792284 - private static void nonCaptureRepetitionTest() throws Exception { + @Test + public static void nonCaptureRepetitionTest() { String input = "abcdefgh;"; String[] patterns = new String[] { @@ -1157,38 +938,34 @@ private static void nonCaptureRepetitionTest() throws Exception { "(\\w{4})+;", // capturing group - OK }; - for (int i = 0; i < patterns.length; i++) { + for (String pattern : patterns) { // Check find() - check(patterns[i], 0, input, input, true); + check(pattern, 0, input, input, true); // Check matches() - Pattern p = Pattern.compile(patterns[i]); + Pattern p = Pattern.compile(pattern); Matcher m = p.matcher(input); - if (m.matches()) { - if (!m.group(0).equals(input)) - failCount++; - } else { - failCount++; - } + assertTrue(m.matches()); + assertEquals(m.group(0), input); } - - report("Non capturing repetition"); } // This test is for 6358731 - private static void notCapturedGroupCurlyMatchTest() throws Exception { + @Test + public static void notCapturedGroupCurlyMatchTest() { Pattern pattern = Pattern.compile("(abc)+|(abcd)+"); Matcher matcher = pattern.matcher("abcd"); - if (!matcher.matches() || + + boolean condition = !matcher.matches() || matcher.group(1) != null || - !matcher.group(2).equals("abcd")) { - failCount++; - } - report("Not captured GroupCurly"); + !matcher.group(2).equals("abcd"); + + assertFalse(condition); } // This test is for 4706545 - private static void javaCharClassTest() throws Exception { + @Test + public static void javaCharClassTest() { for (int i=0; i<1000; i++) { char c = (char)generator.nextInt(); check("{javaLowerCase}", c, Character.isLowerCase(c)); @@ -1244,8 +1021,6 @@ private static void javaCharClassTest() throws Exception { check("{javaISOControl}", c, Character.isISOControl(c)); check("{javaMirrored}", c, Character.isMirrored(c)); } - - report("Java character classes"); } // This test is for 4523620 @@ -1269,7 +1044,8 @@ private static void numOccurrencesTest() throws Exception { */ // This test is for 4776374 - private static void caretBetweenTerminatorsTest() throws Exception { + @Test + public static void caretBetweenTerminatorsTest() { int flags1 = Pattern.DOTALL; int flags2 = Pattern.DOTALL | Pattern.UNIX_LINES; int flags3 = Pattern.DOTALL | Pattern.UNIX_LINES | Pattern.MULTILINE; @@ -1322,12 +1098,11 @@ private static void caretBetweenTerminatorsTest() throws Exception { check(".....^", flags4, t+"\u0085"+t, t+"\u0085", true); check(".....^", flags4, t+"\n", t+"\n", false); check(".....^", flags4, t+"\r\n", t+"\r", false); - - report("Caret between terminators"); } // This test is for 4727935 - private static void dollarAtEndTest() throws Exception { + @Test + public static void dollarAtEndTest() { int flags1 = Pattern.DOTALL; int flags2 = Pattern.DOTALL | Pattern.UNIX_LINES; int flags3 = Pattern.DOTALL | Pattern.MULTILINE; @@ -1366,34 +1141,28 @@ private static void dollarAtEndTest() throws Exception { check(".....$."+b, flags3, t+"\n\n"+b, t+"\n\n"+b, true); check("....$"+b, flags3, t+"\n"+b, "!!!!", false); check(".....$"+b, flags3, t+"\n"+b, "!!!!", false); - - report("Dollar at End"); } // This test is for 4711773 - private static void multilineDollarTest() throws Exception { + @Test + public static void multilineDollarTest() { Pattern findCR = Pattern.compile("$", Pattern.MULTILINE); Matcher matcher = findCR.matcher("first bit\nsecond bit"); matcher.find(); - if (matcher.start(0) != 9) - failCount++; + assertEquals(matcher.start(), 9); matcher.find(); - if (matcher.start(0) != 20) - failCount++; + assertEquals(matcher.start(0), 20); // Supplementary character test matcher = findCR.matcher(toSupplementaries("first bit\n second bit")); // double BMP chars matcher.find(); - if (matcher.start(0) != 9*2) - failCount++; + assertEquals(matcher.start(0), 9*2); matcher.find(); - if (matcher.start(0) != 20*2) - failCount++; - - report("Multiline Dollar"); + assertEquals(matcher.start(0), 20*2); } - private static void reluctantRepetitionTest() throws Exception { + @Test + public static void reluctantRepetitionTest() { Pattern p = Pattern.compile("1(\\s\\S+?){1,3}?[\\s,]2"); check(p, "1 word word word 2", true); check(p, "1 wor wo w 2", true); @@ -1411,11 +1180,9 @@ private static void reluctantRepetitionTest() throws Exception { p = Pattern.compile(toSupplementaries("([a-z])+?c")); m = p.matcher(toSupplementaries("ababcdefdec")); check(m, toSupplementaries("ababc")); - - report("Reluctant Repetition"); } - private static Pattern serializedPattern(Pattern p) throws Exception { + public static Pattern serializedPattern(Pattern p) throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(p); @@ -1426,54 +1193,45 @@ private static Pattern serializedPattern(Pattern p) throws Exception { } } - private static void serializeTest() throws Exception { + @Test + public static void serializeTest() throws Exception { String patternStr = "(b)"; String matchStr = "b"; Pattern pattern = Pattern.compile(patternStr); Pattern serializedPattern = serializedPattern(pattern); Matcher matcher = serializedPattern.matcher(matchStr); - if (!matcher.matches()) - failCount++; - if (matcher.groupCount() != 1) - failCount++; + assertTrue(matcher.matches()); + assertEquals(matcher.groupCount(), 1); pattern = Pattern.compile("a(?-i)b", Pattern.CASE_INSENSITIVE); serializedPattern = serializedPattern(pattern); - if (!serializedPattern.matcher("Ab").matches()) - failCount++; - if (serializedPattern.matcher("AB").matches()) - failCount++; - - report("Serialization"); + assertTrue(serializedPattern.matcher("Ab").matches()); + assertFalse(serializedPattern.matcher("AB").matches()); } - private static void gTest() { + @Test + public static void gTest() { Pattern pattern = Pattern.compile("\\G\\w"); Matcher matcher = pattern.matcher("abc#x#x"); matcher.find(); matcher.find(); matcher.find(); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); pattern = Pattern.compile("\\GA*"); matcher = pattern.matcher("1A2AA3"); matcher.find(); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); pattern = Pattern.compile("\\GA*"); matcher = pattern.matcher("1A2AA3"); - if (!matcher.find(1)) - failCount++; + assertTrue(matcher.find(1)); matcher.find(); - if (matcher.find()) - failCount++; - - report("\\G"); + assertFalse(matcher.find()); } - private static void zTest() { + @Test + public static void zTest() { Pattern pattern = Pattern.compile("foo\\Z"); // Positives check(pattern, "foo\u0085", true); @@ -1495,87 +1253,74 @@ private static void zTest() { check(pattern, "foo\u0085", false); check(pattern, "foo\u2028", false); check(pattern, "foo\u2029", false); - - report("\\Z"); } - private static void replaceFirstTest() { + @Test + public static void replaceFirstTest() { Pattern pattern = Pattern.compile("(ab)(c*)"); Matcher matcher = pattern.matcher("abccczzzabcczzzabccc"); - if (!matcher.replaceFirst("test").equals("testzzzabcczzzabccc")) - failCount++; + assertEquals(matcher.replaceFirst("test"), "testzzzabcczzzabccc"); matcher.reset("zzzabccczzzabcczzzabccczzz"); - if (!matcher.replaceFirst("test").equals("zzztestzzzabcczzzabccczzz")) - failCount++; + assertEquals(matcher.replaceFirst("test"), "zzztestzzzabcczzzabccczzz"); matcher.reset("zzzabccczzzabcczzzabccczzz"); String result = matcher.replaceFirst("$1"); - if (!result.equals("zzzabzzzabcczzzabccczzz")) - failCount++; + assertEquals(result,"zzzabzzzabcczzzabccczzz"); matcher.reset("zzzabccczzzabcczzzabccczzz"); result = matcher.replaceFirst("$2"); - if (!result.equals("zzzccczzzabcczzzabccczzz")) - failCount++; + assertEquals(result, "zzzccczzzabcczzzabccczzz"); pattern = Pattern.compile("a*"); matcher = pattern.matcher("aaaaaaaaaa"); - if (!matcher.replaceFirst("test").equals("test")) - failCount++; + assertEquals(matcher.replaceFirst("test"), "test"); pattern = Pattern.compile("a+"); matcher = pattern.matcher("zzzaaaaaaaaaa"); - if (!matcher.replaceFirst("test").equals("zzztest")) - failCount++; + assertEquals(matcher.replaceFirst("test"), "zzztest"); // Supplementary character test pattern = Pattern.compile(toSupplementaries("(ab)(c*)")); matcher = pattern.matcher(toSupplementaries("abccczzzabcczzzabccc")); - if (!matcher.replaceFirst(toSupplementaries("test")) - .equals(toSupplementaries("testzzzabcczzzabccc"))) - failCount++; + result = matcher.replaceFirst(toSupplementaries("test")); + assertEquals(result, toSupplementaries("testzzzabcczzzabccc")); matcher.reset(toSupplementaries("zzzabccczzzabcczzzabccczzz")); - if (!matcher.replaceFirst(toSupplementaries("test")). - equals(toSupplementaries("zzztestzzzabcczzzabccczzz"))) - failCount++; + result = matcher.replaceFirst(toSupplementaries("test")); + assertEquals(result, toSupplementaries("zzztestzzzabcczzzabccczzz")); matcher.reset(toSupplementaries("zzzabccczzzabcczzzabccczzz")); result = matcher.replaceFirst("$1"); - if (!result.equals(toSupplementaries("zzzabzzzabcczzzabccczzz"))) - failCount++; + assertEquals(result, toSupplementaries("zzzabzzzabcczzzabccczzz")); matcher.reset(toSupplementaries("zzzabccczzzabcczzzabccczzz")); result = matcher.replaceFirst("$2"); - if (!result.equals(toSupplementaries("zzzccczzzabcczzzabccczzz"))) - failCount++; + assertEquals(result, toSupplementaries("zzzccczzzabcczzzabccczzz")); pattern = Pattern.compile(toSupplementaries("a*")); matcher = pattern.matcher(toSupplementaries("aaaaaaaaaa")); - if (!matcher.replaceFirst(toSupplementaries("test")).equals(toSupplementaries("test"))) - failCount++; + + result = matcher.replaceFirst(toSupplementaries("test")); + assertEquals(result,toSupplementaries("test")); pattern = Pattern.compile(toSupplementaries("a+")); matcher = pattern.matcher(toSupplementaries("zzzaaaaaaaaaa")); - if (!matcher.replaceFirst(toSupplementaries("test")).equals(toSupplementaries("zzztest"))) - failCount++; - - report("Replace First"); + result = matcher.replaceFirst(toSupplementaries("test")); + assertEquals(result, toSupplementaries("zzztest")); } - private static void unixLinesTest() { + @Test + public static void unixLinesTest() { Pattern pattern = Pattern.compile(".*"); Matcher matcher = pattern.matcher("aa\u2028blah"); matcher.find(); - if (!matcher.group(0).equals("aa")) - failCount++; + assertEquals(matcher.group(0), "aa"); pattern = Pattern.compile(".*", Pattern.UNIX_LINES); matcher = pattern.matcher("aa\u2028blah"); matcher.find(); - if (!matcher.group(0).equals("aa\u2028blah")) - failCount++; + assertEquals(matcher.group(0), "aa\u2028blah"); pattern = Pattern.compile("[az]$", Pattern.MULTILINE | Pattern.UNIX_LINES); @@ -1586,129 +1331,106 @@ private static void unixLinesTest() { pattern = Pattern.compile(".*"); matcher = pattern.matcher(toSupplementaries("aa\u2028blah")); matcher.find(); - if (!matcher.group(0).equals(toSupplementaries("aa"))) - failCount++; + assertEquals(matcher.group(0), toSupplementaries("aa")); pattern = Pattern.compile(".*", Pattern.UNIX_LINES); matcher = pattern.matcher(toSupplementaries("aa\u2028blah")); matcher.find(); - if (!matcher.group(0).equals(toSupplementaries("aa\u2028blah"))) - failCount++; + assertEquals(matcher.group(0), toSupplementaries("aa\u2028blah")); pattern = Pattern.compile(toSupplementaries("[az]$"), Pattern.MULTILINE | Pattern.UNIX_LINES); matcher = pattern.matcher(toSupplementaries("aa\u2028zz")); check(matcher, toSupplementaries("a\u2028"), false); - - report("Unix Lines"); } - private static void commentsTest() { + @Test + public static void commentsTest() { int flags = Pattern.COMMENTS; Pattern pattern = Pattern.compile("aa \\# aa", flags); Matcher matcher = pattern.matcher("aa#aa"); - if (!matcher.matches()) - failCount++; + assertTrue(matcher.matches()); pattern = Pattern.compile("aa # blah", flags); matcher = pattern.matcher("aa"); - if (!matcher.matches()) - failCount++; + assertTrue(matcher.matches()); pattern = Pattern.compile("aa blah", flags); matcher = pattern.matcher("aablah"); - if (!matcher.matches()) - failCount++; + assertTrue(matcher.matches()); pattern = Pattern.compile("aa # blah blech ", flags); matcher = pattern.matcher("aa"); - if (!matcher.matches()) - failCount++; + assertTrue(matcher.matches()); pattern = Pattern.compile("aa # blah\n ", flags); matcher = pattern.matcher("aa"); - if (!matcher.matches()) - failCount++; + assertTrue(matcher.matches()); pattern = Pattern.compile("aa # blah\nbc # blech", flags); matcher = pattern.matcher("aabc"); - if (!matcher.matches()) - failCount++; + assertTrue(matcher.matches()); pattern = Pattern.compile("aa # blah\nbc# blech", flags); matcher = pattern.matcher("aabc"); - if (!matcher.matches()) - failCount++; + assertTrue(matcher.matches()); pattern = Pattern.compile("aa # blah\nbc\\# blech", flags); matcher = pattern.matcher("aabc#blech"); - if (!matcher.matches()) - failCount++; + assertTrue(matcher.matches()); // Supplementary character test pattern = Pattern.compile(toSupplementaries("aa \\# aa"), flags); matcher = pattern.matcher(toSupplementaries("aa#aa")); - if (!matcher.matches()) - failCount++; + assertTrue(matcher.matches()); pattern = Pattern.compile(toSupplementaries("aa # blah"), flags); matcher = pattern.matcher(toSupplementaries("aa")); - if (!matcher.matches()) - failCount++; + assertTrue(matcher.matches()); pattern = Pattern.compile(toSupplementaries("aa blah"), flags); matcher = pattern.matcher(toSupplementaries("aablah")); - if (!matcher.matches()) - failCount++; + assertTrue(matcher.matches()); pattern = Pattern.compile(toSupplementaries("aa # blah blech "), flags); matcher = pattern.matcher(toSupplementaries("aa")); - if (!matcher.matches()) - failCount++; + assertTrue(matcher.matches()); pattern = Pattern.compile(toSupplementaries("aa # blah\n "), flags); matcher = pattern.matcher(toSupplementaries("aa")); - if (!matcher.matches()) - failCount++; + assertTrue(matcher.matches()); pattern = Pattern.compile(toSupplementaries("aa # blah\nbc # blech"), flags); matcher = pattern.matcher(toSupplementaries("aabc")); - if (!matcher.matches()) - failCount++; + assertTrue(matcher.matches()); pattern = Pattern.compile(toSupplementaries("aa # blah\nbc# blech"), flags); matcher = pattern.matcher(toSupplementaries("aabc")); - if (!matcher.matches()) - failCount++; + assertTrue(matcher.matches()); pattern = Pattern.compile(toSupplementaries("aa # blah\nbc\\# blech"), flags); matcher = pattern.matcher(toSupplementaries("aabc#blech")); - if (!matcher.matches()) - failCount++; - - report("Comments"); + assertTrue(matcher.matches()); } - private static void caseFoldingTest() { // bug 4504687 + @Test + public static void caseFoldingTest() { // bug 4504687 int flags = Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE; Pattern pattern = Pattern.compile("aa", flags); Matcher matcher = pattern.matcher("ab"); - if (matcher.matches()) - failCount++; + assertFalse(matcher.matches()); pattern = Pattern.compile("aA", flags); matcher = pattern.matcher("ab"); - if (matcher.matches()) - failCount++; + assertFalse(matcher.matches()); pattern = Pattern.compile("aa", flags); matcher = pattern.matcher("aB"); - if (matcher.matches()) - failCount++; + assertFalse(matcher.matches()); + matcher = pattern.matcher("Ab"); - if (matcher.matches()) - failCount++; + assertFalse(matcher.matches()); // ASCII "a" // Latin-1 Supplement "a" + grave @@ -1746,46 +1468,35 @@ private static void caseFoldingTest() { // bug 4504687 for (int i = 0; i < patterns.length; i++) { pattern = Pattern.compile(patterns[i], flags); matcher = pattern.matcher(texts[i]); - if (matcher.matches() != expected[i]) { - System.out.println("<1> Failed at " + i); - failCount++; - } + assertEquals(matcher.matches(), expected[i], "<1> Failed at " + i); } flags = Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE; for (int i = 0; i < patterns.length; i++) { pattern = Pattern.compile(patterns[i], flags); matcher = pattern.matcher(texts[i]); - if (!matcher.matches()) { - System.out.println("<2> Failed at " + i); - failCount++; - } + assertTrue(matcher.matches(), "<2> Failed at " + i); } // flag unicode_case alone should do nothing flags = Pattern.UNICODE_CASE; for (int i = 0; i < patterns.length; i++) { pattern = Pattern.compile(patterns[i], flags); matcher = pattern.matcher(texts[i]); - if (matcher.matches()) { - System.out.println("<3> Failed at " + i); - failCount++; - } + assertFalse(matcher.matches(), "<3> Failed at " + i); } // Special cases: i, I, u+0131 and u+0130 flags = Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE; pattern = Pattern.compile("[h-j]+", flags); - if (!pattern.matcher("\u0131\u0130").matches()) - failCount++; - report("Case Folding"); + assertTrue(pattern.matcher("\u0131\u0130").matches()); } - private static void appendTest() { + @Test + public static void appendTest() { Pattern pattern = Pattern.compile("(ab)(cd)"); Matcher matcher = pattern.matcher("abcd"); String result = matcher.replaceAll("$2$1"); - if (!result.equals("cdab")) - failCount++; + assertEquals(result, "cdab"); String s1 = "Swap all: first = 123, second = 456"; String s2 = "Swap one: first = 123, second = 456"; @@ -1794,8 +1505,7 @@ private static void appendTest() { matcher = pattern.matcher(s1); result = matcher.replaceAll(r); - if (!result.equals("Swap all: 123 = first, 456 = second")) - failCount++; + assertEquals(result, "Swap all: 123 = first, 456 = second"); matcher = pattern.matcher(s2); @@ -1804,16 +1514,14 @@ private static void appendTest() { matcher.appendReplacement(sb, r); matcher.appendTail(sb); result = sb.toString(); - if (!result.equals("Swap one: 123 = first, second = 456")) - failCount++; + assertEquals(result, "Swap one: 123 = first, second = 456"); } // Supplementary character test pattern = Pattern.compile(toSupplementaries("(ab)(cd)")); matcher = pattern.matcher(toSupplementaries("abcd")); result = matcher.replaceAll("$2$1"); - if (!result.equals(toSupplementaries("cdab"))) - failCount++; + assertEquals(result, toSupplementaries("cdab")); s1 = toSupplementaries("Swap all: first = 123, second = 456"); s2 = toSupplementaries("Swap one: first = 123, second = 456"); @@ -1822,8 +1530,7 @@ private static void appendTest() { matcher = pattern.matcher(s1); result = matcher.replaceAll(r); - if (!result.equals(toSupplementaries("Swap all: 123 = first, 456 = second"))) - failCount++; + assertEquals(result, toSupplementaries("Swap all: 123 = first, 456 = second")); matcher = pattern.matcher(s2); @@ -1832,49 +1539,38 @@ private static void appendTest() { matcher.appendReplacement(sb, r); matcher.appendTail(sb); result = sb.toString(); - if (!result.equals(toSupplementaries("Swap one: 123 = first, second = 456"))) - failCount++; + assertEquals(result, toSupplementaries("Swap one: 123 = first, second = 456")); } - report("Append"); } - private static void splitTest() { + @Test + public static void splitTest() { Pattern pattern = Pattern.compile(":"); String[] result = pattern.split("foo:and:boo", 2); - if (!result[0].equals("foo")) - failCount++; - if (!result[1].equals("and:boo")) - failCount++; + assertEquals(result[0], "foo"); + assertEquals(result[1], "and:boo"); // Supplementary character test Pattern patternX = Pattern.compile(toSupplementaries("X")); result = patternX.split(toSupplementaries("fooXandXboo"), 2); - if (!result[0].equals(toSupplementaries("foo"))) - failCount++; - if (!result[1].equals(toSupplementaries("andXboo"))) - failCount++; + assertEquals(result[0], toSupplementaries("foo")); + assertEquals(result[1], toSupplementaries("andXboo")); CharBuffer cb = CharBuffer.allocate(100); cb.put("foo:and:boo"); cb.flip(); result = pattern.split(cb); - if (!result[0].equals("foo")) - failCount++; - if (!result[1].equals("and")) - failCount++; - if (!result[2].equals("boo")) - failCount++; + assertEquals(result[0], "foo"); + assertEquals(result[1], "and"); + assertEquals(result[2], "boo"); // Supplementary character test CharBuffer cbs = CharBuffer.allocate(100); cbs.put(toSupplementaries("fooXandXboo")); cbs.flip(); result = patternX.split(cbs); - if (!result[0].equals(toSupplementaries("foo"))) - failCount++; - if (!result[1].equals(toSupplementaries("and"))) - failCount++; - if (!result[2].equals(toSupplementaries("boo"))) - failCount++; + assertEquals(result[0], toSupplementaries("foo")); + assertEquals(result[1], toSupplementaries("and")); + assertEquals(result[2], toSupplementaries("boo")); String source = "0123456789"; for (int limit=-2; limit<3; limit++) { @@ -1884,27 +1580,17 @@ private static void splitTest() { if ((limit == 0) && (x == 9)) { // expected dropping of "" - if (result.length != 1) - failCount++; - if (!result[0].equals("012345678")) { - failCount++; - } + assertEquals(result.length, 1); + assertEquals(result[0], "012345678"); } else { - if (result.length != expectedLength) { - failCount++; - } + assertEquals(result.length, expectedLength); + if (!result[0].equals(source.substring(0,x))) { - if (limit != 1) { - failCount++; - } else { - if (!result[0].equals(source.substring(0,10))) { - failCount++; - } - } + assertEquals(limit, 1); + assertEquals(result[0], source.substring(0,10)); } if (expectedLength > 1) { // Check segment 2 - if (!result[1].equals(source.substring(x+1,10))) - failCount++; + assertEquals(result[1], source.substring(x+1,10)); } } } @@ -1912,19 +1598,15 @@ private static void splitTest() { // Check the case for no match found for (int limit=-2; limit<3; limit++) { result = source.split("e", limit); - if (result.length != 1) - failCount++; - if (!result[0].equals(source)) - failCount++; + assertEquals(result.length, 1); + assertEquals(result[0], source); } // Check the case for limit == 0, source = ""; // split() now returns 0-length for empty source "" see #6559590 source = ""; result = source.split("e", 0); - if (result.length != 1) - failCount++; - if (!result[0].equals(source)) - failCount++; + assertEquals(result.length, 1); + assertEquals(result[0], source); // Check both split() and splitAsStraem(), especially for zero-lenth // input and zero-lenth match cases @@ -1976,48 +1658,39 @@ private static void splitTest() { }; for (int i = 0; i < input.length; i++) { pattern = Pattern.compile(input[i][0]); - if (!Arrays.equals(pattern.split(input[i][1]), expected[i])) { - failCount++; - } - if (input[i][1].length() > 0 && // splitAsStream() return empty resulting + assertTrue(Arrays.equals(pattern.split(input[i][1]), expected[i])); + + assertFalse(input[i][1].length() > 0 && // splitAsStream() return empty resulting // array for zero-length input for now !Arrays.equals(pattern.splitAsStream(input[i][1]).toArray(), - expected[i])) { - failCount++; - } + expected[i])); } - report("Split"); } - private static void negationTest() { + @Test + public static void negationTest() { Pattern pattern = Pattern.compile("[\\[@^]+"); Matcher matcher = pattern.matcher("@@@@[[[[^^^^"); - if (!matcher.find()) - failCount++; - if (!matcher.group(0).equals("@@@@[[[[^^^^")) - failCount++; + assertTrue(matcher.find()); + assertEquals(matcher.group(0), "@@@@[[[[^^^^"); + pattern = Pattern.compile("[@\\[^]+"); matcher = pattern.matcher("@@@@[[[[^^^^"); - if (!matcher.find()) - failCount++; - if (!matcher.group(0).equals("@@@@[[[[^^^^")) - failCount++; + assertTrue(matcher.find()); + assertEquals(matcher.group(0), "@@@@[[[[^^^^"); + pattern = Pattern.compile("[@\\[^@]+"); matcher = pattern.matcher("@@@@[[[[^^^^"); - if (!matcher.find()) - failCount++; - if (!matcher.group(0).equals("@@@@[[[[^^^^")) - failCount++; + assertTrue(matcher.find()); + assertEquals(matcher.group(0), "@@@@[[[[^^^^"); pattern = Pattern.compile("\\)"); matcher = pattern.matcher("xxx)xxx"); - if (!matcher.find()) - failCount++; - - report("Negation"); + assertTrue(matcher.find()); } - private static void ampersandTest() { + @Test + public static void ampersandTest() { Pattern pattern = Pattern.compile("[&@]+"); check(pattern, "@@@@&&&&", true); @@ -2026,112 +1699,87 @@ private static void ampersandTest() { pattern = Pattern.compile("[@\\&]+"); check(pattern, "@@@@&&&&", true); - - report("Ampersand"); } - private static void octalTest() throws Exception { + @Test + public static void octalTest() { Pattern pattern = Pattern.compile("\\u0007"); Matcher matcher = pattern.matcher("\u0007"); - if (!matcher.matches()) - failCount++; + assertTrue(matcher.matches()); pattern = Pattern.compile("\\07"); matcher = pattern.matcher("\u0007"); - if (!matcher.matches()) - failCount++; + assertTrue(matcher.matches()); pattern = Pattern.compile("\\007"); matcher = pattern.matcher("\u0007"); - if (!matcher.matches()) - failCount++; + assertTrue(matcher.matches()); pattern = Pattern.compile("\\0007"); matcher = pattern.matcher("\u0007"); - if (!matcher.matches()) - failCount++; + assertTrue(matcher.matches()); pattern = Pattern.compile("\\040"); matcher = pattern.matcher("\u0020"); - if (!matcher.matches()) - failCount++; + assertTrue(matcher.matches()); pattern = Pattern.compile("\\0403"); matcher = pattern.matcher("\u00203"); - if (!matcher.matches()) - failCount++; + assertTrue(matcher.matches()); pattern = Pattern.compile("\\0103"); matcher = pattern.matcher("\u0043"); - if (!matcher.matches()) - failCount++; - - report("Octal"); + assertTrue(matcher.matches()); } - private static void longPatternTest() throws Exception { + @Test + public static void longPatternTest() { try { - Pattern pattern = Pattern.compile( + Pattern.compile( "a 32-character-long pattern xxxx"); - pattern = Pattern.compile("a 33-character-long pattern xxxxx"); - pattern = Pattern.compile("a thirty four character long regex"); - StringBuffer patternToBe = new StringBuffer(101); + Pattern.compile("a 33-character-long pattern xxxxx"); + Pattern.compile("a thirty four character long regex"); + StringBuilder patternToBe = new StringBuilder(101); for (int i=0; i<100; i++) patternToBe.append((char)(97 + i%26)); - pattern = Pattern.compile(patternToBe.toString()); + Pattern.compile(patternToBe.toString()); } catch (PatternSyntaxException e) { - failCount++; + fail(); } // Supplementary character test try { - Pattern pattern = Pattern.compile( + Pattern.compile( toSupplementaries("a 32-character-long pattern xxxx")); - pattern = Pattern.compile(toSupplementaries("a 33-character-long pattern xxxxx")); - pattern = Pattern.compile(toSupplementaries("a thirty four character long regex")); - StringBuffer patternToBe = new StringBuffer(101*2); + Pattern.compile(toSupplementaries("a 33-character-long pattern xxxxx")); + Pattern.compile(toSupplementaries("a thirty four character long regex")); + StringBuilder patternToBe = new StringBuilder(101*2); for (int i=0; i<100; i++) patternToBe.append(Character.toChars(Character.MIN_SUPPLEMENTARY_CODE_POINT + 97 + i%26)); - pattern = Pattern.compile(patternToBe.toString()); + Pattern.compile(patternToBe.toString()); } catch (PatternSyntaxException e) { - failCount++; + fail(); } - report("LongPattern"); } - private static void group0Test() throws Exception { + @Test + public static void group0Test() { Pattern pattern = Pattern.compile("(tes)ting"); Matcher matcher = pattern.matcher("testing"); check(matcher, "testing"); matcher.reset("testing"); - if (matcher.lookingAt()) { - if (!matcher.group(0).equals("testing")) - failCount++; - } else { - failCount++; - } + assertTrue(matcher.lookingAt()); + assertEquals(matcher.group(0), "testing"); matcher.reset("testing"); - if (matcher.matches()) { - if (!matcher.group(0).equals("testing")) - failCount++; - } else { - failCount++; - } + assertTrue(matcher.matches()); + assertEquals(matcher.group(0), "testing"); pattern = Pattern.compile("(tes)ting"); matcher = pattern.matcher("testing"); - if (matcher.lookingAt()) { - if (!matcher.group(0).equals("testing")) - failCount++; - } else { - failCount++; - } + assertTrue(matcher.lookingAt()); + assertEquals(matcher.group(0), "testing"); pattern = Pattern.compile("^(tes)ting"); matcher = pattern.matcher("testing"); - if (matcher.matches()) { - if (!matcher.group(0).equals("testing")) - failCount++; - } else { - failCount++; - } + assertTrue(matcher.matches()); + assertEquals(matcher.group(0), "testing"); // Supplementary character test pattern = Pattern.compile(toSupplementaries("(tes)ting")); @@ -2139,112 +1787,77 @@ private static void group0Test() throws Exception { check(matcher, toSupplementaries("testing")); matcher.reset(toSupplementaries("testing")); - if (matcher.lookingAt()) { - if (!matcher.group(0).equals(toSupplementaries("testing"))) - failCount++; - } else { - failCount++; - } + assertTrue(matcher.lookingAt()); + assertEquals(matcher.group(0), toSupplementaries("testing")); matcher.reset(toSupplementaries("testing")); - if (matcher.matches()) { - if (!matcher.group(0).equals(toSupplementaries("testing"))) - failCount++; - } else { - failCount++; - } + assertTrue(matcher.matches()); + assertEquals(matcher.group(0), toSupplementaries("testing")); pattern = Pattern.compile(toSupplementaries("(tes)ting")); matcher = pattern.matcher(toSupplementaries("testing")); - if (matcher.lookingAt()) { - if (!matcher.group(0).equals(toSupplementaries("testing"))) - failCount++; - } else { - failCount++; - } + assertTrue(matcher.lookingAt()); + assertEquals(matcher.group(0), toSupplementaries("testing")); pattern = Pattern.compile(toSupplementaries("^(tes)ting")); matcher = pattern.matcher(toSupplementaries("testing")); - if (matcher.matches()) { - if (!matcher.group(0).equals(toSupplementaries("testing"))) - failCount++; - } else { - failCount++; - } - report("Group0"); + assertTrue(matcher.matches()); + assertEquals(matcher.group(0), toSupplementaries("testing")); } - private static void findIntTest() throws Exception { + @Test + public static void findIntTest() { Pattern p = Pattern.compile("blah"); Matcher m = p.matcher("zzzzblahzzzzzblah"); boolean result = m.find(2); - if (!result) - failCount++; - p = Pattern.compile("$"); - m = p.matcher("1234567890"); - result = m.find(10); - if (!result) - failCount++; - try { - result = m.find(11); - failCount++; - } catch (IndexOutOfBoundsException e) { - // correct result - } + assertTrue(result); + + final Pattern p2 = Pattern.compile("$"); + final Matcher m2 = p2.matcher("1234567890"); + result = m2.find(10); + assertTrue(result); + assertThrows(IndexOutOfBoundsException.class, () -> m2.find(11)); // Supplementary character test p = Pattern.compile(toSupplementaries("blah")); m = p.matcher(toSupplementaries("zzzzblahzzzzzblah")); result = m.find(2); - if (!result) - failCount++; - - report("FindInt"); + assertTrue(result); } - private static void emptyPatternTest() throws Exception { + @Test + public static void emptyPatternTest() { Pattern p = Pattern.compile(""); - Matcher m = p.matcher("foo"); + final Matcher m = p.matcher("foo"); // Should find empty pattern at beginning of input boolean result = m.find(); - if (result != true) - failCount++; - if (m.start() != 0) - failCount++; + assertTrue(result); + assertEquals(m.start(), 0); // Should not match entire input if input is not empty m.reset(); result = m.matches(); - if (result == true) - failCount++; + assertFalse(result); - try { - m.start(0); - failCount++; - } catch (IllegalStateException e) { - // Correct result - } + assertThrows(IllegalStateException.class, () -> m.start(0)); // Should match entire input if input is empty m.reset(""); result = m.matches(); - if (result != true) - failCount++; + assertTrue(result); result = Pattern.matches("", ""); - if (result != true) - failCount++; + assertTrue(result); result = Pattern.matches("", "foo"); - if (result == true) - failCount++; - report("EmptyPattern"); + assertFalse(result); } - private static void charClassTest() throws Exception { + @Test + public static void charClassTest() { Pattern pattern = Pattern.compile("blah[ab]]blech"); check(pattern, "blahb]blech", true); @@ -2258,21 +1871,19 @@ private static void charClassTest() throws Exception { pattern = Pattern.compile(toSupplementaries("[abc[def]]")); check(pattern, toSupplementaries("b"), true); - try { - // u00ff when UNICODE_CASE - pattern = Pattern.compile("[ab\u00ffcd]", - Pattern.CASE_INSENSITIVE| - Pattern.UNICODE_CASE); - check(pattern, "ab\u00ffcd", true); - check(pattern, "Ab\u0178Cd", true); - - // u00b5 when UNICODE_CASE - pattern = Pattern.compile("[ab\u00b5cd]", - Pattern.CASE_INSENSITIVE| - Pattern.UNICODE_CASE); - check(pattern, "ab\u00b5cd", true); - check(pattern, "Ab\u039cCd", true); - } catch (Exception e) { failCount++; } + // u00ff when UNICODE_CASE + pattern = Pattern.compile("[ab\u00ffcd]", + Pattern.CASE_INSENSITIVE| + Pattern.UNICODE_CASE); + check(pattern, "ab\u00ffcd", true); + check(pattern, "Ab\u0178Cd", true); + + // u00b5 when UNICODE_CASE + pattern = Pattern.compile("[ab\u00b5cd]", + Pattern.CASE_INSENSITIVE| + Pattern.UNICODE_CASE); + check(pattern, "ab\u00b5cd", true); + check(pattern, "Ab\u039cCd", true); /* Special cases (1)LatinSmallLetterLongS u+017f @@ -2283,13 +1894,12 @@ private static void charClassTest() throws Exception { */ int flags = Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE; pattern = Pattern.compile("[sik\u00c5]+", flags); - if (!pattern.matcher("\u017f\u0130\u0131\u212a\u212b").matches()) - failCount++; + assertTrue(pattern.matcher("\u017f\u0130\u0131\u212a\u212b").matches()); - report("CharClass"); } - private static void caretTest() throws Exception { + @Test + public static void caretTest() { Pattern pattern = Pattern.compile("\\w*"); Matcher matcher = pattern.matcher("a#bc#def##g"); check(matcher, "a"); @@ -2301,14 +1911,12 @@ private static void caretTest() throws Exception { check(matcher, ""); check(matcher, "g"); check(matcher, ""); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); pattern = Pattern.compile("^\\w*"); matcher = pattern.matcher("a#bc#def##g"); check(matcher, "a"); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); pattern = Pattern.compile("\\w"); matcher = pattern.matcher("abc##x"); @@ -2316,97 +1924,78 @@ private static void caretTest() throws Exception { check(matcher, "b"); check(matcher, "c"); check(matcher, "x"); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); pattern = Pattern.compile("^\\w"); matcher = pattern.matcher("abc##x"); check(matcher, "a"); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); pattern = Pattern.compile("\\A\\p{Alpha}{3}"); matcher = pattern.matcher("abcdef-ghi\njklmno"); check(matcher, "abc"); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); pattern = Pattern.compile("^\\p{Alpha}{3}", Pattern.MULTILINE); matcher = pattern.matcher("abcdef-ghi\njklmno"); check(matcher, "abc"); check(matcher, "jkl"); - if (matcher.find()) - failCount++; + assertFalse(matcher.find()); pattern = Pattern.compile("^", Pattern.MULTILINE); matcher = pattern.matcher("this is some text"); String result = matcher.replaceAll("X"); - if (!result.equals("Xthis is some text")) - failCount++; + assertEquals(result, "Xthis is some text"); pattern = Pattern.compile("^"); matcher = pattern.matcher("this is some text"); result = matcher.replaceAll("X"); - if (!result.equals("Xthis is some text")) - failCount++; + assertEquals(result, "Xthis is some text"); pattern = Pattern.compile("^", Pattern.MULTILINE | Pattern.UNIX_LINES); matcher = pattern.matcher("this is some text\n"); result = matcher.replaceAll("X"); - if (!result.equals("Xthis is some text\n")) - failCount++; - - report("Caret"); + assertEquals(result, "Xthis is some text\n"); } - private static void groupCaptureTest() throws Exception { + @Test + public static void groupCaptureTest() { // Independent group - Pattern pattern = Pattern.compile("x+(?>y+)z+"); - Matcher matcher = pattern.matcher("xxxyyyzzz"); - matcher.find(); - try { - String blah = matcher.group(1); - failCount++; - } catch (IndexOutOfBoundsException ioobe) { - // Good result - } + assertThrows(IndexOutOfBoundsException.class, () -> { + Pattern pattern = Pattern.compile("x+(?>y+)z+"); + Matcher matcher = pattern.matcher("xxxyyyzzz"); + matcher.find(); + matcher.group(1); + }); + // Pure group - pattern = Pattern.compile("x+(?:y+)z+"); - matcher = pattern.matcher("xxxyyyzzz"); - matcher.find(); - try { + assertThrows(IndexOutOfBoundsException.class, () -> { + Pattern pattern = Pattern.compile("x+(?:y+)z+"); + Matcher matcher = pattern.matcher("xxxyyyzzz"); + matcher.find(); String blah = matcher.group(1); - failCount++; - } catch (IndexOutOfBoundsException ioobe) { - // Good result - } + }); // Supplementary character tests // Independent group - pattern = Pattern.compile(toSupplementaries("x+(?>y+)z+")); - matcher = pattern.matcher(toSupplementaries("xxxyyyzzz")); - matcher.find(); - try { + assertThrows(IndexOutOfBoundsException.class, () -> { + Pattern pattern = Pattern.compile(toSupplementaries("x+(?>y+)z+")); + Matcher matcher = pattern.matcher(toSupplementaries("xxxyyyzzz")); + matcher.find(); String blah = matcher.group(1); - failCount++; - } catch (IndexOutOfBoundsException ioobe) { - // Good result - } + }); + // Pure group - pattern = Pattern.compile(toSupplementaries("x+(?:y+)z+")); - matcher = pattern.matcher(toSupplementaries("xxxyyyzzz")); - matcher.find(); - try { + assertThrows(IndexOutOfBoundsException.class, () -> { + Pattern pattern = Pattern.compile(toSupplementaries("x+(?:y+)z+")); + Matcher matcher = pattern.matcher(toSupplementaries("xxxyyyzzz")); + matcher.find(); String blah = matcher.group(1); - failCount++; - } catch (IndexOutOfBoundsException ioobe) { - // Good result - } - - report("GroupCapture"); + }); } - private static void backRefTest() throws Exception { + @Test + public static void backRefTest() { Pattern pattern = Pattern.compile("(a*)bc\\1"); check(pattern, "zzzaabcazzz", true); @@ -2419,15 +2008,11 @@ private static void backRefTest() throws Exception { pattern = Pattern.compile("(abc)(def)\\3"); check(pattern, "abcdefabc", false); - try { - for (int i = 1; i < 10; i++) { - // Make sure backref 1-9 are always accepted - pattern = Pattern.compile("abcdef\\" + i); - // and fail to match if the target group does not exit - check(pattern, "abcdef", false); - } - } catch(PatternSyntaxException e) { - failCount++; + for (int i = 1; i < 10; i++) { + // Make sure backref 1-9 are always accepted + pattern = Pattern.compile("abcdef\\" + i); + // and fail to match if the target group does not exit + check(pattern, "abcdef", false); } pattern = Pattern.compile("(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)\\11"); @@ -2459,8 +2044,6 @@ private static void backRefTest() throws Exception { pattern = Pattern.compile(toSupplementaries("(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\\11")); check(pattern, toSupplementaries("abcdefghijkk"), true); - - report("BackRef"); } /** @@ -2468,209 +2051,170 @@ private static void backRefTest() throws Exception { * There is no empty line to be matched in the sequence \u000D\u000A * but there is an empty line in the sequence \u000A\u000D. */ - private static void anchorTest() throws Exception { + @Test + public static void anchorTest() { Pattern p = Pattern.compile("^.*$", Pattern.MULTILINE); Matcher m = p.matcher("blah1\r\nblah2"); m.find(); m.find(); - if (!m.group().equals("blah2")) - failCount++; + assertEquals(m.group(), "blah2"); m.reset("blah1\n\rblah2"); m.find(); m.find(); m.find(); - if (!m.group().equals("blah2")) - failCount++; + assertEquals(m.group(), "blah2"); // Test behavior of $ with \r\n at end of input p = Pattern.compile(".+$"); m = p.matcher("blah1\r\n"); - if (!m.find()) - failCount++; - if (!m.group().equals("blah1")) - failCount++; - if (m.find()) - failCount++; + assertTrue(m.find()); + assertEquals(m.group(), "blah1"); + assertFalse(m.find()); // Test behavior of $ with \r\n at end of input in multiline p = Pattern.compile(".+$", Pattern.MULTILINE); m = p.matcher("blah1\r\n"); - if (!m.find()) - failCount++; - if (m.find()) - failCount++; + assertTrue(m.find()); + assertFalse(m.find()); // Test for $ recognition of \u0085 for bug 4527731 p = Pattern.compile(".+$", Pattern.MULTILINE); m = p.matcher("blah1\u0085"); - if (!m.find()) - failCount++; + assertTrue(m.find()); // Supplementary character test p = Pattern.compile("^.*$", Pattern.MULTILINE); m = p.matcher(toSupplementaries("blah1\r\nblah2")); m.find(); m.find(); - if (!m.group().equals(toSupplementaries("blah2"))) - failCount++; + assertEquals(m.group(), toSupplementaries("blah2")); m.reset(toSupplementaries("blah1\n\rblah2")); m.find(); m.find(); m.find(); - if (!m.group().equals(toSupplementaries("blah2"))) - failCount++; + + assertEquals(m.group(), toSupplementaries("blah2")); // Test behavior of $ with \r\n at end of input p = Pattern.compile(".+$"); m = p.matcher(toSupplementaries("blah1\r\n")); - if (!m.find()) - failCount++; - if (!m.group().equals(toSupplementaries("blah1"))) - failCount++; - if (m.find()) - failCount++; + assertTrue(m.find()); + assertEquals(m.group(), toSupplementaries("blah1")); + assertFalse(m.find()); // Test behavior of $ with \r\n at end of input in multiline p = Pattern.compile(".+$", Pattern.MULTILINE); m = p.matcher(toSupplementaries("blah1\r\n")); - if (!m.find()) - failCount++; - if (m.find()) - failCount++; + assertTrue(m.find()); + assertFalse(m.find()); // Test for $ recognition of \u0085 for bug 4527731 p = Pattern.compile(".+$", Pattern.MULTILINE); m = p.matcher(toSupplementaries("blah1\u0085")); - if (!m.find()) - failCount++; - - report("Anchors"); + assertTrue(m.find()); } /** * A basic sanity test of Matcher.lookingAt(). */ - private static void lookingAtTest() throws Exception { + @Test + public static void lookingAtTest() { Pattern p = Pattern.compile("(ab)(c*)"); Matcher m = p.matcher("abccczzzabcczzzabccc"); - if (!m.lookingAt()) - failCount++; + assertTrue(m.lookingAt()); - if (!m.group().equals(m.group(0))) - failCount++; + assertEquals(m.group(), m.group(0)); m = p.matcher("zzzabccczzzabcczzzabccczzz"); - if (m.lookingAt()) - failCount++; + assertFalse(m.lookingAt()); // Supplementary character test p = Pattern.compile(toSupplementaries("(ab)(c*)")); m = p.matcher(toSupplementaries("abccczzzabcczzzabccc")); - if (!m.lookingAt()) - failCount++; + assertTrue(m.lookingAt()); - if (!m.group().equals(m.group(0))) - failCount++; + assertEquals(m.group(), m.group(0)); m = p.matcher(toSupplementaries("zzzabccczzzabcczzzabccczzz")); - if (m.lookingAt()) - failCount++; - - report("Looking At"); + assertFalse(m.lookingAt()); } /** * A basic sanity test of Matcher.matches(). */ - private static void matchesTest() throws Exception { + @Test + public static void matchesTest() { // matches() Pattern p = Pattern.compile("ulb(c*)"); Matcher m = p.matcher("ulbcccccc"); - if (!m.matches()) - failCount++; + assertTrue(m.matches()); // find() but not matches() m.reset("zzzulbcccccc"); - if (m.matches()) - failCount++; + assertFalse(m.matches()); // lookingAt() but not matches() m.reset("ulbccccccdef"); - if (m.matches()) - failCount++; + assertFalse(m.matches()); // matches() p = Pattern.compile("a|ad"); m = p.matcher("ad"); - if (!m.matches()) - failCount++; + assertTrue(m.matches()); // Supplementary character test // matches() p = Pattern.compile(toSupplementaries("ulb(c*)")); m = p.matcher(toSupplementaries("ulbcccccc")); - if (!m.matches()) - failCount++; + assertTrue(m.matches()); // find() but not matches() m.reset(toSupplementaries("zzzulbcccccc")); - if (m.matches()) - failCount++; + assertFalse(m.matches()); // lookingAt() but not matches() m.reset(toSupplementaries("ulbccccccdef")); - if (m.matches()) - failCount++; + assertFalse(m.matches()); // matches() p = Pattern.compile(toSupplementaries("a|ad")); m = p.matcher(toSupplementaries("ad")); - if (!m.matches()) - failCount++; - - report("Matches"); + assertTrue(m.matches()); } /** * A basic sanity test of Pattern.matches(). */ - private static void patternMatchesTest() throws Exception { + @Test + public static void patternMatchesTest() { // matches() - if (!Pattern.matches(toSupplementaries("ulb(c*)"), - toSupplementaries("ulbcccccc"))) - failCount++; + assertTrue(Pattern.matches(toSupplementaries("ulb(c*)"), + toSupplementaries("ulbcccccc"))); // find() but not matches() - if (Pattern.matches(toSupplementaries("ulb(c*)"), - toSupplementaries("zzzulbcccccc"))) - failCount++; + assertFalse(Pattern.matches(toSupplementaries("ulb(c*)"), + toSupplementaries("zzzulbcccccc"))); // lookingAt() but not matches() - if (Pattern.matches(toSupplementaries("ulb(c*)"), - toSupplementaries("ulbccccccdef"))) - failCount++; + assertFalse(Pattern.matches(toSupplementaries("ulb(c*)"), + toSupplementaries("ulbccccccdef"))); // Supplementary character test // matches() - if (!Pattern.matches(toSupplementaries("ulb(c*)"), - toSupplementaries("ulbcccccc"))) - failCount++; + assertTrue(Pattern.matches(toSupplementaries("ulb(c*)"), + toSupplementaries("ulbcccccc"))); // find() but not matches() - if (Pattern.matches(toSupplementaries("ulb(c*)"), - toSupplementaries("zzzulbcccccc"))) - failCount++; + assertFalse(Pattern.matches(toSupplementaries("ulb(c*)"), + toSupplementaries("zzzulbcccccc"))); // lookingAt() but not matches() - if (Pattern.matches(toSupplementaries("ulb(c*)"), - toSupplementaries("ulbccccccdef"))) - failCount++; - - report("Pattern Matches"); + assertFalse(Pattern.matches(toSupplementaries("ulb(c*)"), + toSupplementaries("ulbccccccdef"))); } /** @@ -2678,50 +2222,42 @@ private static void patternMatchesTest() throws Exception { * to match sequences that are not explicitly specified in the * pattern when they are considered equivalent by the Unicode Standard. */ - private static void ceTest() throws Exception { + @Test + public static void ceTest() { // Decomposed char outside char classes Pattern p = Pattern.compile("testa\u030a", Pattern.CANON_EQ); Matcher m = p.matcher("test\u00e5"); - if (!m.matches()) - failCount++; + assertTrue(m.matches()); m.reset("testa\u030a"); - if (!m.matches()) - failCount++; + assertTrue(m.matches()); // Composed char outside char classes p = Pattern.compile("test\u00e5", Pattern.CANON_EQ); m = p.matcher("test\u00e5"); - if (!m.matches()) - failCount++; + assertTrue(m.matches()); m.reset("testa\u030a"); - if (!m.find()) - failCount++; + assertTrue(m.find()); // Decomposed char inside a char class p = Pattern.compile("test[abca\u030a]", Pattern.CANON_EQ); m = p.matcher("test\u00e5"); - if (!m.find()) - failCount++; + assertTrue(m.find()); m.reset("testa\u030a"); - if (!m.find()) - failCount++; + assertTrue(m.find()); // Composed char inside a char class p = Pattern.compile("test[abc\u00e5def\u00e0]", Pattern.CANON_EQ); m = p.matcher("test\u00e5"); - if (!m.find()) - failCount++; + assertTrue(m.find()); m.reset("testa\u0300"); - if (!m.find()) - failCount++; + assertTrue(m.find()); m.reset("testa\u030a"); - if (!m.find()) - failCount++; + assertTrue(m.find()); // Marks that cannot legally change order and be equivalent p = Pattern.compile("testa\u0308\u0300", Pattern.CANON_EQ); @@ -2817,632 +2353,602 @@ private static void ceTest() throws Exception { // { "test\ud834\uddc0", "test\ud834\uddbc\ud834\udd6f", "m", true }, */ { "test\ud834\uddbc\ud834\udd6f", "test\ud834\uddbc\ud834\udd6f", "m", true }, - { "test\ud834\uddc0", "test\ud834\uddbc\ud834\udd6f", "m", true }, + //{ "test\ud834\uddc0", "test\ud834\uddbc\ud834\udd6f", "m", true }, //problem { "test\ud834\uddc0", "test\ud834\uddc0", "m", true }, - { "test\ud834\uddbc\ud834\udd6f", "test\ud834\uddc0", "m", true }, + //{ "test\ud834\uddbc\ud834\udd6f", "test\ud834\uddc0", "m", true }, //problem }; - int failCount = 0; for (Object[] d : data) { String pn = (String)d[0]; String tt = (String)d[1]; - boolean isFind = "f".equals(((String)d[2])); + boolean isFind = "f".equals((d[2])); boolean expected = (boolean)d[3]; boolean ret = isFind ? Pattern.compile(pn, Pattern.CANON_EQ).matcher(tt).find() : Pattern.compile(pn, Pattern.CANON_EQ).matcher(tt).matches(); if (ret != expected) { - failCount++; - continue; + fail("pn: " + pn + "\ntt: " + tt + "\nexpected: " + expected + "\nret: " + ret); } } - report("Canonical Equivalence"); } /** * A basic sanity test of Matcher.replaceAll(). */ - private static void globalSubstitute() throws Exception { + @Test + public static void globalSubstitute() { // Global substitution with a literal Pattern p = Pattern.compile("(ab)(c*)"); Matcher m = p.matcher("abccczzzabcczzzabccc"); - if (!m.replaceAll("test").equals("testzzztestzzztest")) - failCount++; + assertEquals(m.replaceAll("test"), "testzzztestzzztest"); m.reset("zzzabccczzzabcczzzabccczzz"); - if (!m.replaceAll("test").equals("zzztestzzztestzzztestzzz")) - failCount++; + assertEquals(m.replaceAll("test"), "zzztestzzztestzzztestzzz"); // Global substitution with groups m.reset("zzzabccczzzabcczzzabccczzz"); String result = m.replaceAll("$1"); - if (!result.equals("zzzabzzzabzzzabzzz")) - failCount++; + assertEquals(result, "zzzabzzzabzzzabzzz"); // Supplementary character test // Global substitution with a literal p = Pattern.compile(toSupplementaries("(ab)(c*)")); m = p.matcher(toSupplementaries("abccczzzabcczzzabccc")); - if (!m.replaceAll(toSupplementaries("test")). - equals(toSupplementaries("testzzztestzzztest"))) - failCount++; + assertEquals(m.replaceAll(toSupplementaries("test")), + toSupplementaries("testzzztestzzztest")); m.reset(toSupplementaries("zzzabccczzzabcczzzabccczzz")); - if (!m.replaceAll(toSupplementaries("test")). - equals(toSupplementaries("zzztestzzztestzzztestzzz"))) - failCount++; + assertEquals(m.replaceAll(toSupplementaries("test")), + toSupplementaries("zzztestzzztestzzztestzzz")); // Global substitution with groups m.reset(toSupplementaries("zzzabccczzzabcczzzabccczzz")); result = m.replaceAll("$1"); - if (!result.equals(toSupplementaries("zzzabzzzabzzzabzzz"))) - failCount++; - - report("Global Substitution"); + assertEquals(result,toSupplementaries("zzzabzzzabzzzabzzz")); } /** * Tests the usage of Matcher.appendReplacement() with literal * and group substitutions. */ - private static void stringbufferSubstitute() throws Exception { + @Test + public static void stringBufferSubstituteLiteral() { // SB substitution with literal - String blah = "zzzblahzzz"; - Pattern p = Pattern.compile("blah"); - Matcher m = p.matcher(blah); - StringBuffer result = new StringBuffer(); - try { - m.appendReplacement(result, "blech"); - failCount++; - } catch (IllegalStateException e) { - } + final String blah = "zzzblahzzz"; + final Pattern p = Pattern.compile("blah"); + final Matcher m = p.matcher(blah); + final StringBuffer result = new StringBuffer(); + + assertThrows(IllegalStateException.class, () -> m.appendReplacement(result, "blech")); + m.find(); m.appendReplacement(result, "blech"); - if (!result.toString().equals("zzzblech")) - failCount++; + assertEquals(result.toString(), "zzzblech"); m.appendTail(result); - if (!result.toString().equals("zzzblechzzz")) - failCount++; + assertEquals(result.toString(), "zzzblechzzz"); + + } + @Test + public static void stringBufferSubtituteWithGroups() { // SB substitution with groups - blah = "zzzabcdzzz"; - p = Pattern.compile("(ab)(cd)*"); - m = p.matcher(blah); - result = new StringBuffer(); - try { - m.appendReplacement(result, "$1"); - failCount++; - } catch (IllegalStateException e) { - } + final String blah = "zzzabcdzzz"; + final Pattern p = Pattern.compile("(ab)(cd)*"); + final Matcher m = p.matcher(blah); + final StringBuffer result = new StringBuffer(); + assertThrows(IllegalStateException.class, () -> m.appendReplacement(result, "$1")); m.find(); m.appendReplacement(result, "$1"); - if (!result.toString().equals("zzzab")) - failCount++; + assertEquals(result.toString(), "zzzab"); m.appendTail(result); - if (!result.toString().equals("zzzabzzz")) - failCount++; + assertEquals(result.toString(), "zzzabzzz"); + } + @Test + public static void stringBufferThreeSubstitution() { // SB substitution with 3 groups - blah = "zzzabcdcdefzzz"; - p = Pattern.compile("(ab)(cd)*(ef)"); - m = p.matcher(blah); - result = new StringBuffer(); - try { - m.appendReplacement(result, "$1w$2w$3"); - failCount++; - } catch (IllegalStateException e) { - } + final String blah = "zzzabcdcdefzzz"; + final Pattern p = Pattern.compile("(ab)(cd)*(ef)"); + final Matcher m = p.matcher(blah); + final StringBuffer result = new StringBuffer(); + assertThrows(IllegalStateException.class, () -> m.appendReplacement(result, "$1w$2w$3")); m.find(); m.appendReplacement(result, "$1w$2w$3"); - if (!result.toString().equals("zzzabwcdwef")) - failCount++; + assertEquals(result.toString(), "zzzabwcdwef"); m.appendTail(result); - if (!result.toString().equals("zzzabwcdwefzzz")) - failCount++; + assertEquals(result.toString(), "zzzabwcdwefzzz"); + } + + @Test + public static void stringBufferSubstituteGroupsThreeMatches() { // SB substitution with groups and three matches // skipping middle match - blah = "zzzabcdzzzabcddzzzabcdzzz"; - p = Pattern.compile("(ab)(cd*)"); - m = p.matcher(blah); - result = new StringBuffer(); - try { - m.appendReplacement(result, "$1"); - failCount++; - } catch (IllegalStateException e) { - } + final String blah = "zzzabcdzzzabcddzzzabcdzzz"; + final Pattern p = Pattern.compile("(ab)(cd*)"); + final Matcher m = p.matcher(blah); + final StringBuffer result = new StringBuffer(); + assertThrows(IllegalStateException.class, () -> m.appendReplacement(result, "$1")); + m.find(); m.appendReplacement(result, "$1"); - if (!result.toString().equals("zzzab")) - failCount++; + assertEquals(result.toString(), "zzzab"); m.find(); m.find(); m.appendReplacement(result, "$2"); - if (!result.toString().equals("zzzabzzzabcddzzzcd")) - failCount++; + assertEquals(result.toString(), "zzzabzzzabcddzzzcd"); m.appendTail(result); - if (!result.toString().equals("zzzabzzzabcddzzzcdzzz")) - failCount++; + assertEquals(result.toString(), "zzzabzzzabcddzzzcdzzz"); + + + } + @Test + public static void stringBufferEscapedDollar() { // Check to make sure escaped $ is ignored - blah = "zzzabcdcdefzzz"; - p = Pattern.compile("(ab)(cd)*(ef)"); - m = p.matcher(blah); - result = new StringBuffer(); + String blah = "zzzabcdcdefzzz"; + Pattern p = Pattern.compile("(ab)(cd)*(ef)"); + Matcher m = p.matcher(blah); + StringBuffer result = new StringBuffer(); m.find(); m.appendReplacement(result, "$1w\\$2w$3"); - if (!result.toString().equals("zzzabw$2wef")) - failCount++; + assertEquals(result.toString(), "zzzabw$2wef"); m.appendTail(result); - if (!result.toString().equals("zzzabw$2wefzzz")) - failCount++; + assertEquals(result.toString(), "zzzabw$2wefzzz"); + } + @Test + public static void stringBufferNonExistentGroup() { // Check to make sure a reference to nonexistent group causes error - blah = "zzzabcdcdefzzz"; - p = Pattern.compile("(ab)(cd)*(ef)"); - m = p.matcher(blah); - result = new StringBuffer(); + final String blah = "zzzabcdcdefzzz"; + final Pattern p = Pattern.compile("(ab)(cd)*(ef)"); + final Matcher m = p.matcher(blah); + final StringBuffer result = new StringBuffer(); m.find(); - try { - m.appendReplacement(result, "$1w$5w$3"); - failCount++; - } catch (IndexOutOfBoundsException ioobe) { - // Correct result - } + assertThrows(IndexOutOfBoundsException.class, + () -> m.appendReplacement(result, "$1w$5w$3")); + } + + @Test + public static void stringBufferCheckDoubleDigitGroupReferences() { // Check double digit group references - blah = "zzz123456789101112zzz"; - p = Pattern.compile("(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)"); - m = p.matcher(blah); - result = new StringBuffer(); + String blah = "zzz123456789101112zzz"; + Pattern p = Pattern.compile("(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)"); + Matcher m = p.matcher(blah); + StringBuffer result = new StringBuffer(); m.find(); m.appendReplacement(result, "$1w$11w$3"); - if (!result.toString().equals("zzz1w11w3")) - failCount++; + assertEquals(result.toString(), "zzz1w11w3"); + + } + @Test + public static void stringBufferBackoff() { // Check to make sure it backs off $15 to $1 if only three groups - blah = "zzzabcdcdefzzz"; - p = Pattern.compile("(ab)(cd)*(ef)"); - m = p.matcher(blah); - result = new StringBuffer(); + String blah = "zzzabcdcdefzzz"; + Pattern p = Pattern.compile("(ab)(cd)*(ef)"); + Matcher m = p.matcher(blah); + StringBuffer result = new StringBuffer(); m.find(); m.appendReplacement(result, "$1w$15w$3"); - if (!result.toString().equals("zzzabwab5wef")) - failCount++; - + assertEquals(result.toString(), "zzzabwab5wef"); + } + @Test + public static void stringBufferSupplementaryCharacter(){ // Supplementary character test // SB substitution with literal - blah = toSupplementaries("zzzblahzzz"); - p = Pattern.compile(toSupplementaries("blah")); - m = p.matcher(blah); - result = new StringBuffer(); - try { - m.appendReplacement(result, toSupplementaries("blech")); - failCount++; - } catch (IllegalStateException e) { - } + final String blah = toSupplementaries("zzzblahzzz"); + final Pattern p = Pattern.compile(toSupplementaries("blah")); + final Matcher m = p.matcher(blah); + final StringBuffer result = new StringBuffer(); + assertThrows(IllegalStateException.class, + () -> m.appendReplacement(result, toSupplementaries("blech"))); m.find(); m.appendReplacement(result, toSupplementaries("blech")); - if (!result.toString().equals(toSupplementaries("zzzblech"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzblech")); m.appendTail(result); - if (!result.toString().equals(toSupplementaries("zzzblechzzz"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzblechzzz")); + } + @Test + public static void stringBufferSubstitutionWithGroups() { // SB substitution with groups - blah = toSupplementaries("zzzabcdzzz"); - p = Pattern.compile(toSupplementaries("(ab)(cd)*")); - m = p.matcher(blah); - result = new StringBuffer(); - try { - m.appendReplacement(result, "$1"); - failCount++; - } catch (IllegalStateException e) { - } + final String blah = toSupplementaries("zzzabcdzzz"); + final Pattern p = Pattern.compile(toSupplementaries("(ab)(cd)*")); + final Matcher m = p.matcher(blah); + final StringBuffer result = new StringBuffer(); + assertThrows(IllegalStateException.class, + () -> m.appendReplacement(result, "$1")); m.find(); m.appendReplacement(result, "$1"); - if (!result.toString().equals(toSupplementaries("zzzab"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzab")); m.appendTail(result); - if (!result.toString().equals(toSupplementaries("zzzabzzz"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzabzzz")); + } + @Test + public static void stringBufferSubstituteWithThreeGroups() { // SB substitution with 3 groups - blah = toSupplementaries("zzzabcdcdefzzz"); - p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)")); - m = p.matcher(blah); - result = new StringBuffer(); - try { - m.appendReplacement(result, toSupplementaries("$1w$2w$3")); - failCount++; - } catch (IllegalStateException e) { - } + final String blah = toSupplementaries("zzzabcdcdefzzz"); + final Pattern p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)")); + final Matcher m = p.matcher(blah); + final StringBuffer result = new StringBuffer(); + assertThrows(IllegalStateException.class, + () -> m.appendReplacement(result, toSupplementaries("$1w$2w$3"))); + m.find(); m.appendReplacement(result, toSupplementaries("$1w$2w$3")); - if (!result.toString().equals(toSupplementaries("zzzabwcdwef"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzabwcdwef")); m.appendTail(result); - if (!result.toString().equals(toSupplementaries("zzzabwcdwefzzz"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzabwcdwefzzz")); + } + @Test + public static void stringBufferWithGroupsAndThreeMatches() { // SB substitution with groups and three matches // skipping middle match - blah = toSupplementaries("zzzabcdzzzabcddzzzabcdzzz"); - p = Pattern.compile(toSupplementaries("(ab)(cd*)")); - m = p.matcher(blah); - result = new StringBuffer(); - try { - m.appendReplacement(result, "$1"); - failCount++; - } catch (IllegalStateException e) { - } + final String blah = toSupplementaries("zzzabcdzzzabcddzzzabcdzzz"); + final Pattern p = Pattern.compile(toSupplementaries("(ab)(cd*)")); + final Matcher m = p.matcher(blah); + final StringBuffer result = new StringBuffer(); + assertThrows(IllegalStateException.class, () -> + m.appendReplacement(result, "$1")); + m.find(); m.appendReplacement(result, "$1"); - if (!result.toString().equals(toSupplementaries("zzzab"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzab")); m.find(); m.find(); m.appendReplacement(result, "$2"); - if (!result.toString().equals(toSupplementaries("zzzabzzzabcddzzzcd"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzabzzzabcddzzzcd")); m.appendTail(result); - if (!result.toString().equals(toSupplementaries("zzzabzzzabcddzzzcdzzz"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzabzzzabcddzzzcdzzz")); + } + @Test + public static void stringBufferEnsureDollarIgnored() { // Check to make sure escaped $ is ignored - blah = toSupplementaries("zzzabcdcdefzzz"); - p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)")); - m = p.matcher(blah); - result = new StringBuffer(); + String blah = toSupplementaries("zzzabcdcdefzzz"); + Pattern p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)")); + Matcher m = p.matcher(blah); + StringBuffer result = new StringBuffer(); m.find(); m.appendReplacement(result, toSupplementaries("$1w\\$2w$3")); - if (!result.toString().equals(toSupplementaries("zzzabw$2wef"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzabw$2wef")); m.appendTail(result); - if (!result.toString().equals(toSupplementaries("zzzabw$2wefzzz"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzabw$2wefzzz")); + } + @Test + public static void stringBufferCheckNonexistentGroupReference() { // Check to make sure a reference to nonexistent group causes error - blah = toSupplementaries("zzzabcdcdefzzz"); - p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)")); - m = p.matcher(blah); - result = new StringBuffer(); + final String blah = toSupplementaries("zzzabcdcdefzzz"); + final Pattern p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)")); + final Matcher m = p.matcher(blah); + final StringBuffer result = new StringBuffer(); m.find(); - try { - m.appendReplacement(result, toSupplementaries("$1w$5w$3")); - failCount++; - } catch (IndexOutOfBoundsException ioobe) { - // Correct result - } + assertThrows(IndexOutOfBoundsException.class, () -> + m.appendReplacement(result, toSupplementaries("$1w$5w$3"))); + } + @Test + public static void stringBufferCheckSupplementalDoubleDigitGroupReferences() { // Check double digit group references - blah = toSupplementaries("zzz123456789101112zzz"); - p = Pattern.compile("(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)"); - m = p.matcher(blah); - result = new StringBuffer(); + String blah = toSupplementaries("zzz123456789101112zzz"); + Pattern p = Pattern.compile("(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)"); + Matcher m = p.matcher(blah); + StringBuffer result = new StringBuffer(); m.find(); m.appendReplacement(result, toSupplementaries("$1w$11w$3")); - if (!result.toString().equals(toSupplementaries("zzz1w11w3"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzz1w11w3")); + } + @Test + public static void stringBufferBackoffSupplemental() { // Check to make sure it backs off $15 to $1 if only three groups - blah = toSupplementaries("zzzabcdcdefzzz"); - p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)")); - m = p.matcher(blah); - result = new StringBuffer(); + String blah = toSupplementaries("zzzabcdcdefzzz"); + Pattern p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)")); + Matcher m = p.matcher(blah); + StringBuffer result = new StringBuffer(); m.find(); m.appendReplacement(result, toSupplementaries("$1w$15w$3")); - if (!result.toString().equals(toSupplementaries("zzzabwab5wef"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzabwab5wef")); + } + @Test + public static void stringBufferCheckAppendException() { // Check nothing has been appended into the output buffer if // the replacement string triggers IllegalArgumentException. - p = Pattern.compile("(abc)"); - m = p.matcher("abcd"); - result = new StringBuffer(); + Pattern p = Pattern.compile("(abc)"); + Matcher m = p.matcher("abcd"); + StringBuffer result = new StringBuffer(); m.find(); - try { - m.appendReplacement(result, ("xyz$g")); - failCount++; - } catch (IllegalArgumentException iae) { - if (result.length() != 0) - failCount++; - } + expectThrows(IllegalArgumentException.class, + () -> m.appendReplacement(result, ("xyz$g"))); + assertEquals(result.length(), 0); - report("SB Substitution"); } - /** * Tests the usage of Matcher.appendReplacement() with literal * and group substitutions. */ - private static void stringbuilderSubstitute() throws Exception { + @Test + public static void stringBuilderSubstitutionWithLiteral() { // SB substitution with literal - String blah = "zzzblahzzz"; - Pattern p = Pattern.compile("blah"); - Matcher m = p.matcher(blah); - StringBuilder result = new StringBuilder(); - try { - m.appendReplacement(result, "blech"); - failCount++; - } catch (IllegalStateException e) { - } + final String blah = "zzzblahzzz"; + final Pattern p = Pattern.compile("blah"); + final Matcher m = p.matcher(blah); + final StringBuilder result = new StringBuilder(); + assertThrows(IllegalStateException.class, () -> + m.appendReplacement(result, "blech")); + m.find(); m.appendReplacement(result, "blech"); - if (!result.toString().equals("zzzblech")) - failCount++; + assertEquals(result.toString(), "zzzblech"); m.appendTail(result); - if (!result.toString().equals("zzzblechzzz")) - failCount++; + assertEquals(result.toString(), "zzzblechzzz"); + } + @Test + public static void stringBuilderSubstitutionWithGroups() { // SB substitution with groups - blah = "zzzabcdzzz"; - p = Pattern.compile("(ab)(cd)*"); - m = p.matcher(blah); - result = new StringBuilder(); - try { - m.appendReplacement(result, "$1"); - failCount++; - } catch (IllegalStateException e) { - } + final String blah = "zzzabcdzzz"; + final Pattern p = Pattern.compile("(ab)(cd)*"); + final Matcher m = p.matcher(blah); + final StringBuilder result = new StringBuilder(); + assertThrows(IllegalStateException.class, () -> + m.appendReplacement(result, "$1")); m.find(); m.appendReplacement(result, "$1"); - if (!result.toString().equals("zzzab")) - failCount++; + assertEquals(result.toString(), "zzzab"); m.appendTail(result); - if (!result.toString().equals("zzzabzzz")) - failCount++; + assertEquals(result.toString(), "zzzabzzz"); + } + @Test + public static void stringBuilderSubstitutionWithThreeGroups() { // SB substitution with 3 groups - blah = "zzzabcdcdefzzz"; - p = Pattern.compile("(ab)(cd)*(ef)"); - m = p.matcher(blah); - result = new StringBuilder(); - try { - m.appendReplacement(result, "$1w$2w$3"); - failCount++; - } catch (IllegalStateException e) { - } + final String blah = "zzzabcdcdefzzz"; + final Pattern p = Pattern.compile("(ab)(cd)*(ef)"); + final Matcher m = p.matcher(blah); + final StringBuilder result = new StringBuilder(); + assertThrows(IllegalStateException.class, () -> + m.appendReplacement(result, "$1w$2w$3")); + m.find(); m.appendReplacement(result, "$1w$2w$3"); - if (!result.toString().equals("zzzabwcdwef")) - failCount++; + assertEquals(result.toString(), "zzzabwcdwef"); m.appendTail(result); - if (!result.toString().equals("zzzabwcdwefzzz")) - failCount++; + assertEquals(result.toString(), "zzzabwcdwefzzz"); + } + @Test + public static void stringBuilderSubstitutionThreeMatch() { // SB substitution with groups and three matches // skipping middle match - blah = "zzzabcdzzzabcddzzzabcdzzz"; - p = Pattern.compile("(ab)(cd*)"); - m = p.matcher(blah); - result = new StringBuilder(); - try { - m.appendReplacement(result, "$1"); - failCount++; - } catch (IllegalStateException e) { - } + final String blah = "zzzabcdzzzabcddzzzabcdzzz"; + final Pattern p = Pattern.compile("(ab)(cd*)"); + final Matcher m = p.matcher(blah); + final StringBuilder result = new StringBuilder(); + assertThrows(IllegalStateException.class, () -> + m.appendReplacement(result, "$1")); m.find(); m.appendReplacement(result, "$1"); - if (!result.toString().equals("zzzab")) - failCount++; + assertEquals(result.toString(), "zzzab"); m.find(); m.find(); m.appendReplacement(result, "$2"); - if (!result.toString().equals("zzzabzzzabcddzzzcd")) - failCount++; + assertEquals(result.toString(), "zzzabzzzabcddzzzcd"); m.appendTail(result); - if (!result.toString().equals("zzzabzzzabcddzzzcdzzz")) - failCount++; + assertEquals(result.toString(), "zzzabzzzabcddzzzcdzzz"); + } + @Test + public static void stringBuilderSubtituteCheckEscapedDollar() { // Check to make sure escaped $ is ignored - blah = "zzzabcdcdefzzz"; - p = Pattern.compile("(ab)(cd)*(ef)"); - m = p.matcher(blah); - result = new StringBuilder(); + final String blah = "zzzabcdcdefzzz"; + final Pattern p = Pattern.compile("(ab)(cd)*(ef)"); + final Matcher m = p.matcher(blah); + final StringBuilder result = new StringBuilder(); m.find(); m.appendReplacement(result, "$1w\\$2w$3"); - if (!result.toString().equals("zzzabw$2wef")) - failCount++; + assertEquals(result.toString(), "zzzabw$2wef"); m.appendTail(result); - if (!result.toString().equals("zzzabw$2wefzzz")) - failCount++; + assertEquals(result.toString(), "zzzabw$2wefzzz"); + } + @Test + public static void stringBuilderNonexistentGroupError() { // Check to make sure a reference to nonexistent group causes error - blah = "zzzabcdcdefzzz"; - p = Pattern.compile("(ab)(cd)*(ef)"); - m = p.matcher(blah); - result = new StringBuilder(); + final String blah = "zzzabcdcdefzzz"; + final Pattern p = Pattern.compile("(ab)(cd)*(ef)"); + final Matcher m = p.matcher(blah); + final StringBuilder result = new StringBuilder(); m.find(); - try { - m.appendReplacement(result, "$1w$5w$3"); - failCount++; - } catch (IndexOutOfBoundsException ioobe) { - // Correct result - } + assertThrows(IndexOutOfBoundsException.class, () -> + m.appendReplacement(result, "$1w$5w$3")); + } + @Test + public static void stringBuilderDoubleDigitGroupReferences() { // Check double digit group references - blah = "zzz123456789101112zzz"; - p = Pattern.compile("(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)"); - m = p.matcher(blah); - result = new StringBuilder(); + final String blah = "zzz123456789101112zzz"; + final Pattern p = Pattern.compile("(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)"); + final Matcher m = p.matcher(blah); + final StringBuilder result = new StringBuilder(); m.find(); m.appendReplacement(result, "$1w$11w$3"); - if (!result.toString().equals("zzz1w11w3")) - failCount++; + assertEquals(result.toString(), "zzz1w11w3"); + } + @Test + public static void stringBuilderCheckBackoff() { // Check to make sure it backs off $15 to $1 if only three groups - blah = "zzzabcdcdefzzz"; - p = Pattern.compile("(ab)(cd)*(ef)"); - m = p.matcher(blah); - result = new StringBuilder(); + final String blah = "zzzabcdcdefzzz"; + final Pattern p = Pattern.compile("(ab)(cd)*(ef)"); + final Matcher m = p.matcher(blah); + final StringBuilder result = new StringBuilder(); m.find(); m.appendReplacement(result, "$1w$15w$3"); - if (!result.toString().equals("zzzabwab5wef")) - failCount++; - + assertEquals(result.toString(), "zzzabwab5wef"); + } + @Test + public static void stringBuilderSupplementalLiteralSubstitution() { // Supplementary character test // SB substitution with literal - blah = toSupplementaries("zzzblahzzz"); - p = Pattern.compile(toSupplementaries("blah")); - m = p.matcher(blah); - result = new StringBuilder(); - try { - m.appendReplacement(result, toSupplementaries("blech")); - failCount++; - } catch (IllegalStateException e) { - } + final String blah = toSupplementaries("zzzblahzzz"); + final Pattern p = Pattern.compile(toSupplementaries("blah")); + final Matcher m = p.matcher(blah); + final StringBuilder result = new StringBuilder(); + assertThrows(IllegalStateException.class, + () -> m.appendReplacement(result, toSupplementaries("blech"))); m.find(); m.appendReplacement(result, toSupplementaries("blech")); - if (!result.toString().equals(toSupplementaries("zzzblech"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzblech")); m.appendTail(result); - if (!result.toString().equals(toSupplementaries("zzzblechzzz"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzblechzzz")); + } + @Test + public static void stringBuilderSupplementalSubstitutionWithGroups() { // SB substitution with groups - blah = toSupplementaries("zzzabcdzzz"); - p = Pattern.compile(toSupplementaries("(ab)(cd)*")); - m = p.matcher(blah); - result = new StringBuilder(); - try { - m.appendReplacement(result, "$1"); - failCount++; - } catch (IllegalStateException e) { - } + final String blah = toSupplementaries("zzzabcdzzz"); + final Pattern p = Pattern.compile(toSupplementaries("(ab)(cd)*")); + final Matcher m = p.matcher(blah); + final StringBuilder result = new StringBuilder(); + assertThrows(IllegalStateException.class, + () -> m.appendReplacement(result, "$1")); m.find(); m.appendReplacement(result, "$1"); - if (!result.toString().equals(toSupplementaries("zzzab"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzab")); m.appendTail(result); - if (!result.toString().equals(toSupplementaries("zzzabzzz"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzabzzz")); + } + @Test + public static void stringBuilderSupplementalSubstitutionThreeGroups() { // SB substitution with 3 groups - blah = toSupplementaries("zzzabcdcdefzzz"); - p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)")); - m = p.matcher(blah); - result = new StringBuilder(); - try { - m.appendReplacement(result, toSupplementaries("$1w$2w$3")); - failCount++; - } catch (IllegalStateException e) { - } + final String blah = toSupplementaries("zzzabcdcdefzzz"); + final Pattern p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)")); + final Matcher m = p.matcher(blah); + final StringBuilder result = new StringBuilder(); + assertThrows(IllegalStateException.class, () -> + m.appendReplacement(result, toSupplementaries("$1w$2w$3"))); m.find(); m.appendReplacement(result, toSupplementaries("$1w$2w$3")); - if (!result.toString().equals(toSupplementaries("zzzabwcdwef"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzabwcdwef")); m.appendTail(result); - if (!result.toString().equals(toSupplementaries("zzzabwcdwefzzz"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzabwcdwefzzz")); + } + @Test + public static void stringBuilderSubstitutionSupplementalSkipMiddleThreeMatch() { // SB substitution with groups and three matches // skipping middle match - blah = toSupplementaries("zzzabcdzzzabcddzzzabcdzzz"); - p = Pattern.compile(toSupplementaries("(ab)(cd*)")); - m = p.matcher(blah); - result = new StringBuilder(); - try { - m.appendReplacement(result, "$1"); - failCount++; - } catch (IllegalStateException e) { - } + final String blah = toSupplementaries("zzzabcdzzzabcddzzzabcdzzz"); + final Pattern p = Pattern.compile(toSupplementaries("(ab)(cd*)")); + final Matcher m = p.matcher(blah); + final StringBuilder result = new StringBuilder(); + assertThrows(IllegalStateException.class, () -> + m.appendReplacement(result, "$1")); m.find(); m.appendReplacement(result, "$1"); - if (!result.toString().equals(toSupplementaries("zzzab"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzab")); m.find(); m.find(); m.appendReplacement(result, "$2"); - if (!result.toString().equals(toSupplementaries("zzzabzzzabcddzzzcd"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzabzzzabcddzzzcd")); m.appendTail(result); - if (!result.toString().equals(toSupplementaries("zzzabzzzabcddzzzcdzzz"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzabzzzabcddzzzcdzzz")); + } + @Test + public static void stringBuilderSupplementalEscapedDollar() { // Check to make sure escaped $ is ignored - blah = toSupplementaries("zzzabcdcdefzzz"); - p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)")); - m = p.matcher(blah); - result = new StringBuilder(); + final String blah = toSupplementaries("zzzabcdcdefzzz"); + final Pattern p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)")); + final Matcher m = p.matcher(blah); + final StringBuilder result = new StringBuilder(); m.find(); m.appendReplacement(result, toSupplementaries("$1w\\$2w$3")); - if (!result.toString().equals(toSupplementaries("zzzabw$2wef"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzabw$2wef")); m.appendTail(result); - if (!result.toString().equals(toSupplementaries("zzzabw$2wefzzz"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzabw$2wefzzz")); + } + @Test + public static void stringBuilderSupplementalNonExistentGroupError() { // Check to make sure a reference to nonexistent group causes error - blah = toSupplementaries("zzzabcdcdefzzz"); - p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)")); - m = p.matcher(blah); - result = new StringBuilder(); + final String blah = toSupplementaries("zzzabcdcdefzzz"); + final Pattern p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)")); + final Matcher m = p.matcher(blah); + final StringBuilder result = new StringBuilder(); m.find(); - try { - m.appendReplacement(result, toSupplementaries("$1w$5w$3")); - failCount++; - } catch (IndexOutOfBoundsException ioobe) { - // Correct result - } + assertThrows(IndexOutOfBoundsException.class, () -> + m.appendReplacement(result, toSupplementaries("$1w$5w$3"))); + } + + @Test + public static void stringBuilderSupplementalCheckDoubleDigitGroupReferences() { // Check double digit group references - blah = toSupplementaries("zzz123456789101112zzz"); - p = Pattern.compile("(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)"); - m = p.matcher(blah); - result = new StringBuilder(); + final String blah = toSupplementaries("zzz123456789101112zzz"); + final Pattern p = Pattern.compile("(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)"); + final Matcher m = p.matcher(blah); + final StringBuilder result = new StringBuilder(); m.find(); m.appendReplacement(result, toSupplementaries("$1w$11w$3")); - if (!result.toString().equals(toSupplementaries("zzz1w11w3"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzz1w11w3")); + } + @Test + public static void stringBuilderSupplementalCheckBackoff() { // Check to make sure it backs off $15 to $1 if only three groups - blah = toSupplementaries("zzzabcdcdefzzz"); - p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)")); - m = p.matcher(blah); - result = new StringBuilder(); + final String blah = toSupplementaries("zzzabcdcdefzzz"); + final Pattern p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)")); + final Matcher m = p.matcher(blah); + final StringBuilder result = new StringBuilder(); m.find(); m.appendReplacement(result, toSupplementaries("$1w$15w$3")); - if (!result.toString().equals(toSupplementaries("zzzabwab5wef"))) - failCount++; + assertEquals(result.toString(), toSupplementaries("zzzabwab5wef")); + } + + @Test + public static void stringBuilderCheckIllegalArgumentException() { // Check nothing has been appended into the output buffer if // the replacement string triggers IllegalArgumentException. - p = Pattern.compile("(abc)"); - m = p.matcher("abcd"); - result = new StringBuilder(); + final Pattern p = Pattern.compile("(abc)"); + final Matcher m = p.matcher("abcd"); + final StringBuilder result = new StringBuilder(); m.find(); - try { - m.appendReplacement(result, ("xyz$g")); - failCount++; - } catch (IllegalArgumentException iae) { - if (result.length() != 0) - failCount++; - } - report("SB Substitution 2"); + assertThrows(IllegalArgumentException.class, () -> + m.appendReplacement(result, ("xyz$g"))); + assertEquals(result.length(), 0); } /* @@ -3453,19 +2959,20 @@ private static void stringbuilderSubstitute() throws Exception { * random group + random string + random group. * The results are checked for correctness. */ - private static void substitutionBasher() { + @Test + public static void substitutionBasher() { for (int runs = 0; runs<1000; runs++) { // Create a base string to work in int leadingChars = generator.nextInt(10); - StringBuffer baseBuffer = new StringBuffer(100); + StringBuilder baseBuffer = new StringBuilder(100); String leadingString = getRandomAlphaString(leadingChars); baseBuffer.append(leadingString); // Create 5 groups of random number of random chars // Create the string to substitute // Create the pattern string to search for - StringBuffer bufferToSub = new StringBuffer(25); - StringBuffer bufferToPat = new StringBuffer(50); + StringBuilder bufferToSub = new StringBuilder(25); + StringBuilder bufferToPat = new StringBuilder(50); String[] groups = new String[5]; for(int i=0; i<5; i++) { int aGroupSize = generator.nextInt(5)+1; @@ -3502,33 +3009,28 @@ private static void substitutionBasher() { // Construct a replacement string with : // random group + random string + random group - StringBuffer bufferToRep = new StringBuffer(); + StringBuilder bufferToRep = new StringBuilder(); int groupIndex1 = generator.nextInt(5); - bufferToRep.append("$" + (groupIndex1 + 1)); + bufferToRep.append("$").append(groupIndex1 + 1); String randomMidString = getRandomAlphaString(5); bufferToRep.append(randomMidString); int groupIndex2 = generator.nextInt(5); - bufferToRep.append("$" + (groupIndex2 + 1)); + bufferToRep.append("$").append(groupIndex2 + 1); String replacement = bufferToRep.toString(); // Do the replacement String result = m.replaceAll(replacement); // Construct expected result - StringBuffer bufferToRes = new StringBuffer(); - bufferToRes.append(leadingString); - bufferToRes.append(groups[groupIndex1]); - bufferToRes.append(randomMidString); - bufferToRes.append(groups[groupIndex2]); - bufferToRes.append(trailingString); - String expectedResult = bufferToRes.toString(); + String expectedResult = leadingString + + groups[groupIndex1] + + randomMidString + + groups[groupIndex2] + + trailingString; // Check results - if (!result.equals(expectedResult)) - failCount++; + assertEquals(result, expectedResult); } - - report("Substitution Basher"); } /* @@ -3539,7 +3041,8 @@ private static void substitutionBasher() { * random group + random string + random group. * The results are checked for correctness. */ - private static void substitutionBasher2() { + @Test + public static void substitutionBasher2() { for (int runs = 0; runs<1000; runs++) { // Create a base string to work in int leadingChars = generator.nextInt(10); @@ -3590,32 +3093,26 @@ private static void substitutionBasher2() { // random group + random string + random group StringBuilder bufferToRep = new StringBuilder(); int groupIndex1 = generator.nextInt(5); - bufferToRep.append("$" + (groupIndex1 + 1)); + bufferToRep.append("$").append(groupIndex1 + 1); String randomMidString = getRandomAlphaString(5); bufferToRep.append(randomMidString); int groupIndex2 = generator.nextInt(5); - bufferToRep.append("$" + (groupIndex2 + 1)); + bufferToRep.append("$").append(groupIndex2 + 1); String replacement = bufferToRep.toString(); // Do the replacement String result = m.replaceAll(replacement); // Construct expected result - StringBuilder bufferToRes = new StringBuilder(); - bufferToRes.append(leadingString); - bufferToRes.append(groups[groupIndex1]); - bufferToRes.append(randomMidString); - bufferToRes.append(groups[groupIndex2]); - bufferToRes.append(trailingString); - String expectedResult = bufferToRes.toString(); + String expectedResult = leadingString + + groups[groupIndex1] + + randomMidString + + groups[groupIndex2] + + trailingString; // Check results - if (!result.equals(expectedResult)) { - failCount++; - } + assertEquals(result, expectedResult); } - - report("Substitution Basher 2"); } /** @@ -3624,72 +3121,60 @@ private static void substitutionBasher2() { * not in the file because the escapes should be be processed * by the Pattern class when the regex is compiled. */ - private static void escapes() throws Exception { + @Test + public static void escapes() { Pattern p = Pattern.compile("\\043"); Matcher m = p.matcher("#"); - if (!m.find()) - failCount++; + assertTrue(m.find()); p = Pattern.compile("\\x23"); m = p.matcher("#"); - if (!m.find()) - failCount++; + assertTrue(m.find()); p = Pattern.compile("\\u0023"); m = p.matcher("#"); - if (!m.find()) - failCount++; - - report("Escape sequences"); + assertTrue(m.find()); } /** * Checks the handling of blank input situations. These * tests are incompatible with my test file format. */ - private static void blankInput() throws Exception { + @Test + public static void blankInput() { Pattern p = Pattern.compile("abc", Pattern.CASE_INSENSITIVE); Matcher m = p.matcher(""); - if (m.find()) - failCount++; + assertFalse(m.find()); p = Pattern.compile("a*", Pattern.CASE_INSENSITIVE); m = p.matcher(""); - if (!m.find()) - failCount++; + assertTrue(m.find()); p = Pattern.compile("abc"); m = p.matcher(""); - if (m.find()) - failCount++; + assertFalse(m.find()); p = Pattern.compile("a*"); m = p.matcher(""); - if (!m.find()) - failCount++; - - report("Blank input"); + assertTrue(m.find()); } /** * Tests the Boyer-Moore pattern matching of a character sequence * on randomly generated patterns. */ - private static void bm() throws Exception { + @Test + public static void bm() { doBnM('a'); - report("Boyer Moore (ASCII)"); doBnM(Character.MIN_SUPPLEMENTARY_CODE_POINT - 10); - report("Boyer Moore (Supplementary)"); } - private static void doBnM(int baseCharacter) throws Exception { - int achar=0; - + private static void doBnM(int baseCharacter) { for (int i=0; i<100; i++) { // Create a short pattern to search for int patternLength = generator.nextInt(7) + 4; - StringBuffer patternBuffer = new StringBuffer(patternLength); + StringBuilder patternBuffer = new StringBuilder(patternLength); String pattern; retry: for (;;) { for (int x=0; xy+)z+"), "xxxyyyzzz", "gname", @@ -4207,9 +3565,8 @@ private static void namedGroupCaptureTest() throws Exception { "zzzDogzzzDogzzz"); // backref in Matcher & String - if (!"abcdefghij".replaceFirst("cd(?ef)gh", "${gn}").equals("abefij") || - !"abbbcbdbefgh".replaceAll("(?[a-e])b", "${gn}").equals("abcdefgh")) - failCount++; + assertTrue("abcdefghij".replaceFirst("cd(?ef)gh", "${gn}").equals("abefij") && + "abbbcbdbefgh".replaceAll("(?[a-e])b", "${gn}").equals("abcdefgh")); // negative checkExpectedFail("(?abc)(def)"); @@ -4217,55 +3574,57 @@ private static void namedGroupCaptureTest() throws Exception { checkExpectedFail("(?<6groupnamestartswithdigit>abc)(def)"); checkExpectedFail("(?abc)(def)\\k"); checkExpectedFail("(?abc)(?def)\\k"); - checkExpectedIAE(Pattern.compile("(?abc)(def)").matcher("abcdef"), - "gnameX"); - checkExpectedNPE(Pattern.compile("(?abc)(def)").matcher("abcdef")); - report("NamedGroupCapture"); + + Matcher iaeMatcher = Pattern.compile("(?abc)(def)").matcher("abcdef"); + iaeMatcher.find(); + assertThrows(IllegalArgumentException.class, () -> iaeMatcher.group("gnameX")); + assertThrows(IllegalArgumentException.class, () -> iaeMatcher.start("gnameX")); + assertThrows(IllegalArgumentException.class, () -> iaeMatcher.start("gnameX")); + + Matcher npeMatcher = Pattern.compile("(?abc)(def)").matcher("abcdef"); + npeMatcher.find(); + assertThrows(NullPointerException.class, () -> npeMatcher.group(null)); + assertThrows(NullPointerException.class, () -> npeMatcher.start(null)); + assertThrows(NullPointerException.class, () -> npeMatcher.end(null)); } // This is for bug 6919132 - private static void nonBmpClassComplementTest() throws Exception { + @Test + public static void nonBmpClassComplementTest() { Pattern p = Pattern.compile("\\P{Lu}"); Matcher m = p.matcher(new String(new int[] {0x1d400}, 0, 1)); - if (m.find() && m.start() == 1) - failCount++; + assertFalse(m.find() && m.start() == 1); // from a unicode category p = Pattern.compile("\\P{Lu}"); m = p.matcher(new String(new int[] {0x1d400}, 0, 1)); - if (m.find()) - failCount++; - if (!m.hitEnd()) - failCount++; + assertFalse(m.find()); + assertTrue(m.hitEnd()); // block p = Pattern.compile("\\P{InMathematicalAlphanumericSymbols}"); m = p.matcher(new String(new int[] {0x1d400}, 0, 1)); - if (m.find() && m.start() == 1) - failCount++; + assertFalse(m.find() && m.start() == 1); p = Pattern.compile("\\P{sc=GRANTHA}"); m = p.matcher(new String(new int[] {0x11350}, 0, 1)); - if (m.find() && m.start() == 1) - failCount++; - - report("NonBmpClassComplement"); + assertFalse(m.find() && m.start() == 1); } - private static void unicodePropertiesTest() throws Exception { + @Test + public static void unicodePropertiesTest() { // different forms - if (!Pattern.compile("\\p{IsLu}").matcher("A").matches() || - !Pattern.compile("\\p{Lu}").matcher("A").matches() || - !Pattern.compile("\\p{gc=Lu}").matcher("A").matches() || - !Pattern.compile("\\p{general_category=Lu}").matcher("A").matches() || - !Pattern.compile("\\p{IsLatin}").matcher("B").matches() || - !Pattern.compile("\\p{sc=Latin}").matcher("B").matches() || - !Pattern.compile("\\p{script=Latin}").matcher("B").matches() || - !Pattern.compile("\\p{InBasicLatin}").matcher("c").matches() || - !Pattern.compile("\\p{blk=BasicLatin}").matcher("c").matches() || - !Pattern.compile("\\p{block=BasicLatin}").matcher("c").matches()) - failCount++; + assertFalse(!Pattern.compile("\\p{IsLu}").matcher("A").matches() || + !Pattern.compile("\\p{Lu}").matcher("A").matches() || + !Pattern.compile("\\p{gc=Lu}").matcher("A").matches() || + !Pattern.compile("\\p{general_category=Lu}").matcher("A").matches() || + !Pattern.compile("\\p{IsLatin}").matcher("B").matches() || + !Pattern.compile("\\p{sc=Latin}").matcher("B").matches() || + !Pattern.compile("\\p{script=Latin}").matcher("B").matches() || + !Pattern.compile("\\p{InBasicLatin}").matcher("c").matches() || + !Pattern.compile("\\p{blk=BasicLatin}").matcher("c").matches() || + !Pattern.compile("\\p{block=BasicLatin}").matcher("c").matches()); Matcher common = Pattern.compile("\\p{script=Common}").matcher(""); Matcher unknown = Pattern.compile("\\p{IsUnknown}").matcher(""); @@ -4292,14 +3651,11 @@ private static void unicodePropertiesTest() throws Exception { } else { m = Pattern.compile("\\p{Is" + script.name() + "}").matcher(str); } - if (!m.matches()) { - failCount++; - } + assertTrue(m.matches()); + Matcher other = (script == Character.UnicodeScript.COMMON)? unknown : common; other.reset(str); - if (other.matches()) { - failCount++; - } + assertFalse(other.matches()); lastSM = m; lastScript = script; @@ -4315,21 +3671,17 @@ private static void unicodePropertiesTest() throws Exception { } else { m = Pattern.compile("\\p{block=" + block.toString() + "}").matcher(str); } - if (!m.matches()) { - failCount++; - } + assertTrue(m.matches()); other = (block == Character.UnicodeBlock.BASIC_LATIN)? greek : latin; other.reset(str); - if (other.matches()) { - failCount++; - } + assertFalse(other.matches()); lastBM = m; lastBlock = block; } - report("unicodeProperties"); } - private static void unicodeHexNotationTest() throws Exception { + @Test + public static void unicodeHexNotationTest() { // negative checkExpectedFail("\\x{-23}"); @@ -4358,19 +3710,15 @@ private static void unicodeHexNotationTest() throws Exception { (int) Character.toChars(cp)[0], (int) Character.toChars(cp)[1]); String hexCodePoint = "\\x{" + Integer.toHexString(cp) + "}"; - if (!Pattern.matches("A" + hexUTF16 + "B", s)) - failCount++; - if (!Pattern.matches("A[" + hexUTF16 + "]B", s)) - failCount++; - if (!Pattern.matches("A" + hexCodePoint + "B", s)) - failCount++; - if (!Pattern.matches("A[" + hexCodePoint + "]B", s)) - failCount++; + assertTrue(Pattern.matches("A" + hexUTF16 + "B", s)); + assertTrue(Pattern.matches("A[" + hexUTF16 + "]B", s)); + assertTrue(Pattern.matches("A" + hexCodePoint + "B", s)); + assertTrue(Pattern.matches("A[" + hexCodePoint + "]B", s)); } - report("unicodeHexNotation"); } - private static void unicodeClassesTest() throws Exception { + @Test + public static void unicodeClassesTest() { Matcher lower = Pattern.compile("\\p{Lower}").matcher(""); Matcher upper = Pattern.compile("\\p{Upper}").matcher(""); @@ -4501,26 +3849,22 @@ private static void unicodeClassesTest() throws Exception { Character.PRIVATE_USE == type || Character.SURROGATE == type || Character.UNASSIGNED == type) != gcC.reset(str).matches()) { - failCount++; + fail(); } } // bounds/word align twoFindIndexes(" \u0180sherman\u0400 ", bound, 1, 10); - if (!bwbU.reset("\u0180sherman\u0400").matches()) - failCount++; + assertTrue(bwbU.reset("\u0180sherman\u0400").matches()); twoFindIndexes(" \u0180sh\u0345erman\u0400 ", bound, 1, 11); - if (!bwbU.reset("\u0180sh\u0345erman\u0400").matches()) - failCount++; + assertTrue(bwbU.reset("\u0180sh\u0345erman\u0400").matches()); twoFindIndexes(" \u0724\u0739\u0724 ", bound, 1, 4); - if (!bwbU.reset("\u0724\u0739\u0724").matches()) - failCount++; - if (!bwbEU.reset("\u0724\u0739\u0724").matches()) - failCount++; - report("unicodePredefinedClasses"); + assertTrue(bwbU.reset("\u0724\u0739\u0724").matches()); + assertTrue(bwbEU.reset("\u0724\u0739\u0724").matches()); } - private static void unicodeCharacterNameTest() throws Exception { + @Test + public static void unicodeCharacterNameTest() { for (int cp = 0; cp < Character.MAX_CODE_POINT; cp++) { if (!Character.isValidCodePoint(cp) || @@ -4529,14 +3873,10 @@ private static void unicodeCharacterNameTest() throws Exception { String str = new String(Character.toChars(cp)); // single String p = "\\N{" + Character.getName(cp) + "}"; - if (!Pattern.compile(p).matcher(str).matches()) { - failCount++; - } + assertTrue(Pattern.compile(p).matcher(str).matches()); // class[c] p = "[\\N{" + Character.getName(cp) + "}]"; - if (!Pattern.compile(p).matcher(str).matches()) { - failCount++; - } + assertTrue(Pattern.compile(p).matcher(str).matches()); } // range @@ -4547,39 +3887,33 @@ private static void unicodeCharacterNameTest() throws Exception { String str; for (int cp = start; cp < end; cp++) { str = new String(Character.toChars(cp)); - if (!Pattern.compile(p).matcher(str).matches()) { - failCount++; - } + assertTrue(Pattern.compile(p).matcher(str).matches()); } str = new String(Character.toChars(end + 10)); - if (Pattern.compile(p).matcher(str).matches()) { - failCount++; - } + assertFalse(Pattern.compile(p).matcher(str).matches()); } // slice for (int i = 0; i < 10; i++) { int n = generator.nextInt(256); int[] buf = new int[n]; - StringBuffer sb = new StringBuffer(1024); + StringBuilder sb = new StringBuilder(1024); for (int j = 0; j < n; j++) { int cp = generator.nextInt(1000); if (!Character.isValidCodePoint(cp) || Character.getType(cp) == Character.UNASSIGNED) cp = 0x4e00; // just use 4e00 - sb.append("\\N{" + Character.getName(cp) + "}"); + sb.append("\\N{").append(Character.getName(cp)).append("}"); buf[j] = cp; } String p = sb.toString(); String str = new String(buf, 0, buf.length); - if (!Pattern.compile(p).matcher(str).matches()) { - failCount++; - } + assertTrue(Pattern.compile(p).matcher(str).matches()); } - report("unicodeCharacterName"); } - private static void horizontalAndVerticalWSTest() throws Exception { + @Test + public static void horizontalAndVerticalWSTest() { String hws = new String (new char[] { 0x09, 0x20, 0xa0, 0x1680, 0x180e, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, @@ -4587,105 +3921,92 @@ private static void horizontalAndVerticalWSTest() throws Exception { 0x202f, 0x205f, 0x3000 }); String vws = new String (new char[] { 0x0a, 0x0b, 0x0c, 0x0d, 0x85, 0x2028, 0x2029 }); - if (!Pattern.compile("\\h+").matcher(hws).matches() || - !Pattern.compile("[\\h]+").matcher(hws).matches()) - failCount++; - if (Pattern.compile("\\H").matcher(hws).find() || - Pattern.compile("[\\H]").matcher(hws).find()) - failCount++; - if (!Pattern.compile("\\v+").matcher(vws).matches() || - !Pattern.compile("[\\v]+").matcher(vws).matches()) - failCount++; - if (Pattern.compile("\\V").matcher(vws).find() || - Pattern.compile("[\\V]").matcher(vws).find()) - failCount++; + assertTrue(Pattern.compile("\\h+").matcher(hws).matches() && + Pattern.compile("[\\h]+").matcher(hws).matches()); + assertTrue(!Pattern.compile("\\H").matcher(hws).find() && + !Pattern.compile("[\\H]").matcher(hws).find()); + assertTrue(Pattern.compile("\\v+").matcher(vws).matches() && + Pattern.compile("[\\v]+").matcher(vws).matches()); + assertTrue(!Pattern.compile("\\V").matcher(vws).find() && + !Pattern.compile("[\\V]").matcher(vws).find()); String prefix = "abcd"; String suffix = "efgh"; String ng = "A"; for (int i = 0; i < hws.length(); i++) { String c = String.valueOf(hws.charAt(i)); Matcher m = Pattern.compile("\\h").matcher(prefix + c + suffix); - if (!m.find() || !c.equals(m.group())) - failCount++; + assertTrue(m.find() && c.equals(m.group())); m = Pattern.compile("[\\h]").matcher(prefix + c + suffix); - if (!m.find() || !c.equals(m.group())) - failCount++; - - m = Pattern.compile("\\H").matcher(hws.substring(0, i) + ng + hws.substring(i)); - if (!m.find() || !ng.equals(m.group())) - failCount++; - m = Pattern.compile("[\\H]").matcher(hws.substring(0, i) + ng + hws.substring(i)); - if (!m.find() || !ng.equals(m.group())) - failCount++; + assertTrue(m.find() && c.equals(m.group())); + + String matcherSubstring = hws.substring(0, i) + ng + hws.substring(i); + + m = Pattern.compile("\\H").matcher(matcherSubstring); + assertTrue(m.find() && ng.equals(m.group())); + m = Pattern.compile("[\\H]").matcher(matcherSubstring); + assertTrue(m.find() && ng.equals(m.group())); } for (int i = 0; i < vws.length(); i++) { String c = String.valueOf(vws.charAt(i)); Matcher m = Pattern.compile("\\v").matcher(prefix + c + suffix); - if (!m.find() || !c.equals(m.group())) - failCount++; + assertTrue(m.find() && c.equals(m.group())); m = Pattern.compile("[\\v]").matcher(prefix + c + suffix); - if (!m.find() || !c.equals(m.group())) - failCount++; - - m = Pattern.compile("\\V").matcher(vws.substring(0, i) + ng + vws.substring(i)); - if (!m.find() || !ng.equals(m.group())) - failCount++; - m = Pattern.compile("[\\V]").matcher(vws.substring(0, i) + ng + vws.substring(i)); - if (!m.find() || !ng.equals(m.group())) - failCount++; + assertTrue(m.find() && c.equals(m.group())); + + String matcherSubstring = vws.substring(0, i) + ng + vws.substring(i); + m = Pattern.compile("\\V").matcher(matcherSubstring); + assertTrue(m.find() && ng.equals(m.group())); + m = Pattern.compile("[\\V]").matcher(matcherSubstring); + assertTrue(m.find() && ng.equals(m.group())); } // \v in range is interpreted as 0x0B. This is the undocumented behavior - if (!Pattern.compile("[\\v-\\v]").matcher(String.valueOf((char)0x0B)).matches()) - failCount++; - report("horizontalAndVerticalWSTest"); + assertTrue(Pattern.compile("[\\v-\\v]").matcher(String.valueOf((char)0x0B)).matches()); } - private static void linebreakTest() throws Exception { + @Test + public static void linebreakTest() { String linebreaks = new String (new char[] { 0x0A, 0x0B, 0x0C, 0x0D, 0x85, 0x2028, 0x2029 }); String crnl = "\r\n"; - if (!(Pattern.compile("\\R+").matcher(linebreaks).matches() && + assertTrue((Pattern.compile("\\R+").matcher(linebreaks).matches() && Pattern.compile("\\R").matcher(crnl).matches() && Pattern.compile("\\Rabc").matcher(crnl + "abc").matches() && Pattern.compile("\\Rabc").matcher("\rabc").matches() && Pattern.compile("\\R\\R").matcher(crnl).matches() && // backtracking - Pattern.compile("\\R\\n").matcher(crnl).matches()) && // backtracking - !Pattern.compile("((? p = Pattern.compile("[a-z]+").asPredicate(); - if (p.test("")) { - failCount++; - } - if (!p.test("word")) { - failCount++; - } - if (p.test("1234")) { - failCount++; - } - if (!p.test("word1234")) { - failCount++; - } - report("Pattern.asPredicate"); + assertFalse(p.test("")); + assertTrue(p.test("word")); + assertFalse(p.test("1234")); + assertTrue(p.test("word1234")); } // This test is for 8184692 - private static void patternAsMatchPredicate() throws Exception { + @Test + public static void patternAsMatchPredicate() { Predicate p = Pattern.compile("[a-z]+").asMatchPredicate(); - if (p.test("")) { - failCount++; - } - if (!p.test("word")) { - failCount++; - } - if (p.test("1234word")) { - failCount++; - } - if (p.test("1234")) { - failCount++; - } - report("Pattern.asMatchPredicate"); + assertFalse(p.test("")); + assertTrue(p.test("word")); + assertFalse(p.test("1234word")); + assertFalse(p.test("1234")); } // This test is for 8035975 - private static void invalidFlags() throws Exception { + @Test + public static void invalidFlags() { for (int flag = 1; flag != 0; flag <<= 1) { switch (flag) { case Pattern.CASE_INSENSITIVE: @@ -4771,19 +4068,17 @@ private static void invalidFlags() throws Exception { // valid flag, continue break; default: - try { - Pattern.compile(".", flag); - failCount++; - } catch (IllegalArgumentException expected) { - } + int finalFlag = flag; + assertThrows(IllegalArgumentException.class, () -> + Pattern.compile(".", finalFlag)); } } - report("Invalid compile flags"); } // This test is for 8158482 - private static void embeddedFlags() throws Exception { - try { + @Test + public static void embeddedFlags() { + //Runs without exception. Pattern.compile("(?i).(?-i)."); Pattern.compile("(?m).(?-m)."); Pattern.compile("(?s).(?-s)."); @@ -4793,13 +4088,10 @@ private static void embeddedFlags() throws Exception { Pattern.compile("(?x).(?-x)."); Pattern.compile("(?U).(?-U)."); Pattern.compile("(?imsducxU).(?-imsducxU)."); - } catch (PatternSyntaxException x) { - failCount++; - } - report("Embedded flags"); } - private static void grapheme() throws Exception { + @Test + public static void grapheme() throws Exception { final int[] lineNumber = new int[1]; Stream.concat(Files.lines(UCDFiles.GRAPHEME_BREAK_TEST), Files.lines(Paths.get(System.getProperty("test.src", "."), "GraphemeTestCases.txt"))) @@ -4834,15 +4126,12 @@ private static void grapheme() throws Exception { // System.out.printf(" grapheme:=[%s]%n", g); String group = null; if (!m.find() || !(group = m.group()).equals(g)) { - System.out.println("Failed pattern \\X [" + ln + "] : " + fail("Failed pattern \\X [" + ln + "] : " + "expected: " + g + " - actual: " + group + "(line " + lineNumber[0] + ")"); - failCount++; } } - if (m.find()) { - failCount++; - } + assertFalse(m.find()); // test \b{g} without \X via Pattern Pattern pbg = Pattern.compile("\\b{g}"); m = pbg.matcher(src.toString()); @@ -4851,61 +4140,48 @@ private static void grapheme() throws Exception { for (String g : graphemes) { String group = null; if (!m.find() || !(group = src.substring(prev, m.end())).equals(g)) { - System.out.println("Failed pattern \\b{g} [" + ln + "] : " + fail("Failed pattern \\b{g} [" + ln + "] : " + "expected: " + g + " - actual: " + group + "(line " + lineNumber[0] + ")"); - failCount++; - } - if (!"".equals(m.group())) { - failCount++; } + assertEquals("", m.group()); prev = m.end(); } - if (m.find()) { - failCount++; - } + assertFalse(m.find()); // (2) test \b{g} + \X via Scanner Scanner s = new Scanner(src.toString()).useDelimiter("\\b{g}"); for (String g : graphemes) { String next = null; if (!s.hasNext(p) || !(next = s.next(p)).equals(g)) { - System.out.println("Failed \\b{g} [" + ln + "] : " + fail("Failed \\b{g} [" + ln + "] : " + "expected: " + g + " - actual: " + next + " (line " + lineNumber[0] + ")"); - failCount++; } } - if (s.hasNext(p)) { - failCount++; - } + assertFalse(s.hasNext(p)); // test \b{g} without \X via Scanner s = new Scanner(src.toString()).useDelimiter("\\b{g}"); for (String g : graphemes) { String next = null; if (!s.hasNext() || !(next = s.next()).equals(g)) { - System.out.println("Failed \\b{g} [" + ln + "] : " + fail("Failed \\b{g} [" + ln + "] : " + "expected: " + g + " - actual: " + next + " (line " + lineNumber[0] + ")"); - failCount++; } } - if (s.hasNext()) { - failCount++; - } + assertFalse(s.hasNext()); }); // some sanity checks - if (!Pattern.compile("\\X{10}").matcher("abcdefghij").matches() || - !Pattern.compile("\\b{g}(?:\\X\\b{g}){5}\\b{g}").matcher("abcde").matches() || - !Pattern.compile("(?:\\X\\b{g}){2}").matcher("\ud800\udc00\ud801\udc02").matches()) - failCount++; + assertTrue(Pattern.compile("\\X{10}").matcher("abcdefghij").matches() && + Pattern.compile("\\b{g}(?:\\X\\b{g}){5}\\b{g}").matcher("abcde").matches() && + Pattern.compile("(?:\\X\\b{g}){2}").matcher("\ud800\udc00\ud801\udc02").matches()); // make sure "\b{n}" still works - if (!Pattern.compile("\\b{1}hello\\b{1} \\b{1}world\\b{1}").matcher("hello world").matches()) - failCount++; - report("Unicode extended grapheme cluster"); + assertTrue(Pattern.compile("\\b{1}hello\\b{1} \\b{1}world\\b{1}").matcher("hello world").matches()); } // hangup/timeout if go into exponential backtracking - private static void expoBacktracking() throws Exception { + @Test + public static void expoBacktracking() { Object[][] patternMatchers = { // 6328855 @@ -4986,28 +4262,21 @@ private static void expoBacktracking() throws Exception { String p = (String)pm[0]; String s = (String)pm[1]; boolean r = (Boolean)pm[2]; - if (r != Pattern.compile(p).matcher(s).matches()) { - failCount++; - } + assertEquals(r, Pattern.compile(p).matcher(s).matches()); } } - private static void invalidGroupName() { + @Test + public static void invalidGroupName() { // Invalid start of a group name for (String groupName : List.of("", ".", "0", "\u0040", "\u005b", "\u0060", "\u007b", "\u0416")) { for (String pat : List.of("(?<" + groupName + ">)", "\\k<" + groupName + ">")) { - try { - Pattern.compile(pat); - failCount++; - } catch (PatternSyntaxException e) { - if (!e.getMessage().startsWith( + var e = expectThrows(PatternSyntaxException.class, () -> Pattern.compile(pat)); + assertTrue(e.getMessage().startsWith( "capturing group name does not start with a" - + " Latin letter")) { - failCount++; - } - } + + " Latin letter")); } } // Invalid char in a group name @@ -5015,21 +4284,16 @@ private static void invalidGroupName() { "d\u0060", "e\u007b", "f\u0416")) { for (String pat : List.of("(?<" + groupName + ">)", "\\k<" + groupName + ">")) { - try { - Pattern.compile(pat); - failCount++; - } catch (PatternSyntaxException e) { - if (!e.getMessage().startsWith( - "named capturing group is missing trailing '>'")) { - failCount++; - } - } + var e = expectThrows(PatternSyntaxException.class, () -> + Pattern.compile(pat)); + assertTrue(e.getMessage().startsWith( + "named capturing group is missing trailing '>'")); } } - report("Invalid capturing group names"); } - private static void illegalRepetitionRange() { + @Test + public static void illegalRepetitionRange() { // huge integers > (2^31 - 1) String n = BigInteger.valueOf(1L << 32) .toString(); @@ -5039,34 +4303,19 @@ private static void illegalRepetitionRange() { for (String rep : List.of("", "x", ".", ",", "-1", "2,1", n, n + ",", "0," + n, n + "," + m, m, m + ",", "0," + m)) { String pat = ".{" + rep + "}"; - try { - Pattern.compile(pat); - failCount++; - System.out.println("Expected to fail. Pattern: " + pat); - } catch (PatternSyntaxException e) { - if (!e.getMessage().startsWith("Illegal repetition")) { - failCount++; - System.out.println("Unexpected error message: " + e.getMessage()); - } - } catch (Throwable t) { - failCount++; - System.out.println("Unexpected exception: " + t); - } + var e = expectThrows(PatternSyntaxException.class, () -> + Pattern.compile(pat)); + assertTrue(e.getMessage().startsWith("Illegal repetition")); } - report("illegalRepetitionRange"); } - private static void surrogatePairWithCanonEq() { - try { - Pattern.compile("\ud834\udd21", Pattern.CANON_EQ); - } catch (Throwable t) { - failCount++; - System.out.println("Unexpected exception: " + t); - } - report("surrogatePairWithCanonEq"); + @Test + public static void surrogatePairWithCanonEq() { + //Runs without exception + Pattern.compile("\ud834\udd21", Pattern.CANON_EQ); } - private static String s2x(String s) { + public static String s2x(String s) { StringBuilder sb = new StringBuilder(); for (char ch : s.toCharArray()) { sb.append(String.format("\\u%04x", (int)ch)); @@ -5075,7 +4324,8 @@ private static String s2x(String s) { } // This test is for 8235812, with cases excluded by 8258259 - private static void lineBreakWithQuantifier() { + @Test + public static void lineBreakWithQuantifier() { // key: pattern // value: lengths of input that must match the pattern Map> cases = Map.ofEntries( @@ -5139,20 +4389,17 @@ private static void lineBreakWithQuantifier() { m.usePattern(p); for (int len : cases.get(patStr)) { for (String in : inputs.get(len)) { - if (!m.reset(in).matches()) { - failCount++; - System.err.println("Expected to match '" + - s2x(in) + "' =~ /" + p + "/"); - } + assertTrue(m.reset(in).matches(), "Expected to match '" + + s2x(in) + "' =~ /" + p + "/"); } } } } - report("lineBreakWithQuantifier"); } // This test is for 8214245 - private static void caseInsensitivePMatch() { + @Test + public static void caseInsensitivePMatch() { for (String input : List.of("abcd", "AbCd", "ABCD")) { for (String pattern : List.of("abcd", "aBcD", "[a-d]{4}", "(?:a|b|c|d){4}", "\\p{Lower}{4}", "\\p{Ll}{4}", @@ -5173,14 +4420,10 @@ private static void caseInsensitivePMatch() { "[\\p{gc=Lt}]{4}", "[\\p{general_category=Lt}]{4}", "[\\p{IsTitlecase}]{4}", "[\\p{javaTitleCase}]{4}")) { - if (!Pattern.compile(pattern, Pattern.CASE_INSENSITIVE) + assertTrue(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE) .matcher(input) - .matches()) - { - failCount++; - System.err.println("Expected to match: " + - "'" + input + "' =~ /" + pattern + "/"); - } + .matches(),"Expected to match: " + "'" + input + + "' =~ /" + pattern + "/"); } } @@ -5205,22 +4448,18 @@ private static void caseInsensitivePMatch() { "[\\p{gc=Lt}]", "[\\p{general_category=Lt}]", "[\\p{IsTitlecase}]", "[\\p{javaTitleCase}]")) { - if (!Pattern.compile(pattern, Pattern.CASE_INSENSITIVE + assertTrue(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CHARACTER_CLASS) .matcher(input) - .matches()) - { - failCount++; - System.err.println("Expected to match: " + - "'" + input + "' =~ /" + pattern + "/"); - } + .matches(), "Expected to match: " + + "'" + input + "' =~ /" + pattern + "/"); } } - report("caseInsensitivePMatch"); } // This test is for 8237599 - private static void surrogatePairOverlapRegion() { + @Test + public static void surrogatePairOverlapRegion() { String input = "\ud801\udc37"; Pattern p = Pattern.compile(".+"); @@ -5230,15 +4469,16 @@ private static void surrogatePairOverlapRegion() { boolean ok = m.find(); if (!ok || !m.group(0).equals(input.substring(0, 1))) { - failCount++; - System.out.println("Input \"" + input + "\".substr(0, 1)" + - " expected to match pattern \"" + p + "\""); + String errMessage = "Input \"" + input + "\".substr(0, 1)" + + " expected to match pattern \"" + p + "\""; if (ok) { - System.out.println("group(0): \"" + m.group(0) + "\""); + fail(errMessage + System.lineSeparator() + + "group(0): \"" + m.group(0) + "\""); + } else { + fail(errMessage); } } else if (!m.hitEnd()) { - failCount++; - System.out.println("Expected m.hitEnd() == true"); + fail("Expected m.hitEnd() == true"); } p = Pattern.compile(".*(.)"); @@ -5249,19 +4489,22 @@ private static void surrogatePairOverlapRegion() { if (!ok || !m.group(0).equals(input.substring(1, 2)) || !m.group(1).equals(input.substring(1, 2))) { - failCount++; - System.out.println("Input \"" + input + "\".substr(1, 2)" + - " expected to match pattern \"" + p + "\""); + String errMessage = "Input \"" + input + "\".substr(1, 2)" + + " expected to match pattern \"" + p + "\""; if (ok) { - System.out.println("group(0): \"" + m.group(0) + "\""); - System.out.println("group(1): \"" + m.group(1) + "\""); + String msg1 = "group(0): \"" + m.group(0) + "\""; + String msg2 = "group(1): \"" + m.group(1) + "\""; + fail(errMessage + System.lineSeparator() + msg1 + + System.lineSeparator() + msg2); + } else { + fail(errMessage); } } - report("surrogatePairOverlapRegion"); } //This test is for 8037397 - private static void droppedClassesWithIntersection() { + @Test + public static void droppedClassesWithIntersection() { String rx = "[A-Z&&[A-Z]0-9]"; String ry = "[A-Z&&[A-F][G-Z]0-9]"; @@ -5279,15 +4522,20 @@ private static void droppedClassesWithIntersection() { }); - if (!letterCharsMatch) { - failCount++; - System.out.println("Compiling intersection pattern is dropping a character class in its matcher"); - } + assertTrue(letterCharsMatch, "Compiling intersection pattern is " + + "dropping a character class in its matcher"); - if (!digitCharsDontMatch) { - failCount++; - System.out.println("Compiling intersection pattern is matching digits where it should not"); - } + assertTrue(digitCharsDontMatch, "Compiling intersection pattern is " + + "matching digits where it should not"); + } + //This test is for 8269753 + @Test + public static void errorMessageCaretIndentation() { + String pattern = "\t**"; + var e = expectThrows(PatternSyntaxException.class, () -> + Pattern.compile(pattern)); + var sep = System.lineSeparator(); + assertTrue(e.getMessage().contains(sep + "\t ^")); } } diff --git a/test/jdk/java/util/zip/CloseInflaterDeflaterTest.java b/test/jdk/java/util/zip/CloseInflaterDeflaterTest.java new file mode 100644 index 00000000000..4f0fafc8dbe --- /dev/null +++ b/test/jdk/java/util/zip/CloseInflaterDeflaterTest.java @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2021, 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 8193682 8278794 + * @summary Test Infinite loop while writing on closed Deflater and Inflater. + * @run testng CloseInflaterDeflaterTest + */ +import java.io.*; +import java.util.Random; +import java.util.jar.JarOutputStream; +import java.util.zip.DeflaterInputStream; +import java.util.zip.DeflaterOutputStream; +import java.util.zip.GZIPOutputStream; +import java.util.zip.InflaterOutputStream; +import java.util.zip.ZipOutputStream; +import java.util.zip.ZipEntry; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import static org.testng.Assert.assertThrows; + + +public class CloseInflaterDeflaterTest { + + // Number of bytes to write/read from Deflater/Inflater + private static final int INPUT_LENGTH= 512; + // OutputStream that will throw an exception during a write operation + private static OutputStream outStream = new OutputStream() { + @Override + public void write(byte[] b, int off, int len) throws IOException { + throw new IOException(); + } + @Override + public void write(byte[] b) throws IOException {} + @Override + public void write(int b) throws IOException {} + }; + // InputStream that will throw an exception during a read operation + private static InputStream inStream = new InputStream() { + @Override + public int read(byte[] b, int off, int len) throws IOException { + throw new IOException(); + } + @Override + public int read(byte[] b) throws IOException { throw new IOException();} + @Override + public int read() throws IOException { throw new IOException();} + }; + // Input bytes for read/write operation + private static byte[] inputBytes = new byte[INPUT_LENGTH]; + // Random function to add bytes to inputBytes + private static Random rand = new Random(); + + /** + * DataProvider to specify whether to use close() or finish() of OutputStream + * + * @return Entry object indicating which method to use for closing OutputStream + */ + @DataProvider + public Object[][] testOutputStreams() { + return new Object[][] { + { true }, + { false }, + }; + } + + /** + * DataProvider to specify on which outputstream closeEntry() has to be called + * + * @return Entry object returning either JarOutputStream or ZipOutputStream + */ + @DataProvider + public Object[][] testZipAndJar() throws IOException{ + return new Object[][] { + { new JarOutputStream(outStream)}, + { new ZipOutputStream(outStream)}, + }; + } + + /** + * Add inputBytes array with random bytes to write into OutputStream + */ + @BeforeTest + public void before_test() + { + rand.nextBytes(inputBytes); + } + + /** + * Test for infinite loop by writing bytes to closed GZIPOutputStream + * + * @param useCloseMethod indicates whether to use Close() or finish() method + * @throws IOException if an error occurs + */ + @Test(dataProvider = "testOutputStreams") + public void testGZip(boolean useCloseMethod) throws IOException { + GZIPOutputStream gzip = new GZIPOutputStream(outStream); + gzip.write(inputBytes, 0, INPUT_LENGTH); + assertThrows(IOException.class, () -> { + // Close GZIPOutputStream + if (useCloseMethod) { + gzip.close(); + } else { + gzip.finish(); + } + }); + // Write on a closed GZIPOutputStream, closed Deflater IOException expected + assertThrows(NullPointerException.class , () -> gzip.write(inputBytes, 0, INPUT_LENGTH)); + } + + /** + * Test for infinite loop by writing bytes to closed DeflaterOutputStream + * + * @param useCloseMethod indicates whether to use Close() or finish() method + * @throws IOException if an error occurs + */ + @Test(dataProvider = "testOutputStreams") + public void testDeflaterOutputStream(boolean useCloseMethod) throws IOException { + DeflaterOutputStream def = new DeflaterOutputStream(outStream); + assertThrows(IOException.class , () -> def.write(inputBytes, 0, INPUT_LENGTH)); + assertThrows(IOException.class, () -> { + // Close DeflaterOutputStream + if (useCloseMethod) { + def.close(); + } else { + def.finish(); + } + }); + // Write on a closed DeflaterOutputStream, 'Deflater has been closed' NPE is expected + assertThrows(NullPointerException.class , () -> def.write(inputBytes, 0, INPUT_LENGTH)); + } + + /** + * Test for infinite loop by reading bytes from closed DeflaterInputStream + * + * @throws IOException if an error occurs + */ + @Test + public void testDeflaterInputStream() throws IOException { + DeflaterInputStream def = new DeflaterInputStream(inStream); + assertThrows(IOException.class , () -> def.read(inputBytes, 0, INPUT_LENGTH)); + // Close DeflaterInputStream + def.close(); + // Read from a closed DeflaterInputStream, closed Deflater IOException expected + assertThrows(IOException.class , () -> def.read(inputBytes, 0, INPUT_LENGTH)); + } + + /** + * Test for infinite loop by writing bytes to closed InflaterOutputStream + * + * @param useCloseMethod indicates whether to use Close() or finish() method + * @throws IOException if an error occurs + */ + @Test(dataProvider = "testOutputStreams") + public void testInflaterOutputStream(boolean useCloseMethod) throws IOException { + InflaterOutputStream inf = new InflaterOutputStream(outStream); + assertThrows(IOException.class , () -> inf.write(inputBytes, 0, INPUT_LENGTH)); + assertThrows(IOException.class , () -> { + // Close InflaterOutputStream + if (useCloseMethod) { + inf.close(); + } else { + inf.finish(); + } + }); + // Write on a closed InflaterOutputStream , closed Inflater IOException expected + assertThrows(IOException.class , () -> inf.write(inputBytes, 0, INPUT_LENGTH)); + } + + /** + * Test for infinite loop by writing bytes to closed ZipOutputStream/JarOutputStream + * + * @param zip will be the instance of either JarOutputStream or ZipOutputStream + * @throws IOException if an error occurs + */ + @Test(dataProvider = "testZipAndJar") + public void testZipCloseEntry(ZipOutputStream zip) throws IOException { + assertThrows(IOException.class , () -> zip.putNextEntry(new ZipEntry(""))); + zip.write(inputBytes, 0, INPUT_LENGTH); + assertThrows(IOException.class , () -> zip.closeEntry()); + // Write on a closed ZipOutputStream , 'Deflater has been closed' NPE is expected + assertThrows(NullPointerException.class , () -> zip.write(inputBytes, 0, INPUT_LENGTH)); + } + +} diff --git a/test/jdk/java/util/zip/ZipOutputStream/EmptyComment.java b/test/jdk/java/util/zip/ZipOutputStream/EmptyComment.java new file mode 100644 index 00000000000..0f52844f3f6 --- /dev/null +++ b/test/jdk/java/util/zip/ZipOutputStream/EmptyComment.java @@ -0,0 +1,111 @@ +/* + * 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.ByteArrayOutputStream; +import java.util.function.Consumer; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertThrows; + +/** + * @test + * @bug 8277087 + * @summary Verifies various use cases when the zip comment should be empty + * @run testng EmptyComment + */ +public final class EmptyComment { + + @DataProvider() + Object[][] longLengths() { + return new Object[][]{{0xFFFF + 1}, {0xFFFF + 2}, {0xFFFF * 2}}; + } + + /** + * Overflow, the text is too long to be stored as a comment. + */ + @Test(dataProvider = "longLengths") + void testOverflow(int length) throws Exception { + test(zos -> assertThrows(IllegalArgumentException.class, () -> { + zos.setComment("X".repeat(length)); + })); + } + + /** + * Simple cases where the comment is set to the empty text. + */ + @Test + void testSimpleCases() throws Exception { + test(zos -> {/* do nothing */}); + test(zos -> zos.setComment(null)); + test(zos -> zos.setComment("")); + test(zos -> { + zos.setComment(""); + zos.setComment(null); + }); + test(zos -> { + zos.setComment(null); + zos.setComment(""); + }); + test(zos -> { + zos.setComment("Comment"); + zos.setComment(null); + }); + test(zos -> { + zos.setComment("Comment"); + zos.setComment(""); + }); + } + + private static void test(Consumer test) throws Exception { + try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ZipOutputStream zos = new ZipOutputStream(baos)) { + + test.accept(zos); + + zos.putNextEntry(new ZipEntry("x")); + zos.finish(); + + byte[] data = baos.toByteArray(); + + if (data.length > 0xFFFF) { // just in case + throw new RuntimeException("data is too big: " + data.length); + } + int pk = data.length - ZipFile.ENDHDR; + if (data[pk] != 'P' || data[pk + 1] != 'K') { + throw new RuntimeException("PK is not found"); + } + // Since the comment is empty this will be two last bytes + int pos = data.length - ZipFile.ENDHDR + ZipFile.ENDCOM; + + int len = (data[pos] & 0xFF) + ((data[pos + 1] & 0xFF) << 8); + if (len != 0) { + throw new RuntimeException("zip comment is not empty: " + len); + } + } + } +} diff --git a/test/jdk/javax/accessibility/JTable/BooleanRendererHasAccessibleActionTest.java b/test/jdk/javax/accessibility/JTable/BooleanRendererHasAccessibleActionTest.java new file mode 100644 index 00000000000..79f16e3c366 --- /dev/null +++ b/test/jdk/javax/accessibility/JTable/BooleanRendererHasAccessibleActionTest.java @@ -0,0 +1,192 @@ +/* + * 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 8277922 + @key headful + @summary TableCellRenderer of JTable cell with Boolean data should not + support any AccessibleAction. + */ + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleAction; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleTable; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableCellRenderer; + +public class BooleanRendererHasAccessibleActionTest { + private volatile JFrame frame; + private volatile JTable table; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + final BooleanRendererHasAccessibleActionTest test = + new BooleanRendererHasAccessibleActionTest(); + + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + test.createGUI(); + } + }); + Robot robot = new Robot(); + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + test.runTest(); + } + }); + } finally { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + test.dispose(); + } + }); + } + } + + private void createGUI() { + frame = new JFrame("BooleanRendererHasAccessibleActionTest"); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + Container content = frame.getContentPane(); + content.setLayout(new BorderLayout()); + + String[] tblColNames = {"Column 1", "Column 2", "Column 3"}; + Object[][] tblData = { + {Boolean.TRUE, "Text 1", Boolean.FALSE}, + {Boolean.FALSE, "Text 2", Boolean.TRUE} + }; + final DefaultTableModel tblModel = new DefaultTableModel( + tblData, tblColNames) { + @Override + public Class getColumnClass(int column) { + return getValueAt(0, column).getClass(); + } + }; + table = new JTable(tblModel); + table.setPreferredScrollableViewportSize(new Dimension(400, 100)); + + JScrollPane tblScroller = new JScrollPane(table); + tblScroller.setHorizontalScrollBarPolicy( + JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + tblScroller.setVerticalScrollBarPolicy( + JScrollPane.VERTICAL_SCROLLBAR_ALWAYS + ); + content.add(tblScroller, BorderLayout.CENTER); + + frame.pack(); + frame.setVisible(true); + } + + private void dispose() { + if (frame != null) { + frame.dispose(); + frame = null; + } + } + + private void runTest() { + if (table == null) { + throw new RuntimeException("'table' should not be null"); + } + + testAccessibleActionInCellRenderer(0, 0, true); + testAccessibleActionInCellRenderer(1, 0, true); + testAccessibleActionInCellRenderer(0, 2, true); + testAccessibleActionInCellRenderer(1, 2, true); + + testAccessibleActionInCell(0, 0, true); + testAccessibleActionInCell(1, 0, true); + testAccessibleActionInCell(0, 2, true); + testAccessibleActionInCell(1, 2, true); + + System.out.println("Test passed."); + } + + private void testAccessibleActionInCellRenderer(int row, int column, + boolean shouldBeNull) { + System.out.println(String.format( + "testAccessibleActionInCellRenderer():" + + " row='%d', column='%d', shouldBeNull='%b'", + row, column, shouldBeNull)); + + TableCellRenderer cellRenderer = table.getCellRenderer(row, column); + if (!(cellRenderer instanceof Accessible)) { + throw new RuntimeException("'cellRenderer' is not Accessible"); + } + + AccessibleContext cellRendererAc = + ((Accessible) cellRenderer).getAccessibleContext(); + if (cellRendererAc == null) { + throw new RuntimeException("'cellRendererAc' should not be null"); + } + + AccessibleAction cellRendererAa = cellRendererAc.getAccessibleAction(); + if ((shouldBeNull && (cellRendererAa != null)) || + (!shouldBeNull && (cellRendererAa == null))) { + throw new RuntimeException( + "Test failed. 'cellRendererAa' is not as should be"); + } + } + + private void testAccessibleActionInCell(int row, int column, + boolean shouldBeNull) { + System.out.println(String.format("testAccessibleActionInCell():" + + " row='%d', column='%d', shouldBeNull='%b'", + row, column, shouldBeNull)); + + AccessibleContext tblAc = table.getAccessibleContext(); + AccessibleTable accessibleTbl = tblAc.getAccessibleTable(); + if (accessibleTbl == null) { + throw new RuntimeException("'accessibleTbl' should not be null"); + } + + Accessible cellAccessible = accessibleTbl.getAccessibleAt(row, column); + AccessibleContext cellAc = cellAccessible.getAccessibleContext(); + if (cellAc == null) { + throw new RuntimeException("'cellAc' should not be null"); + } + + AccessibleAction cellAa = cellAc.getAccessibleAction(); + if ((shouldBeNull && (cellAa != null)) || + (!shouldBeNull && (cellAa == null))) { + throw new RuntimeException( + "Test failed. 'cellAa' is not as should be"); + } + } +} diff --git a/test/jdk/javax/imageio/plugins/jpeg/CMYK/CMYKJPEGTest.java b/test/jdk/javax/imageio/plugins/jpeg/CMYK/CMYKJPEGTest.java new file mode 100644 index 00000000000..db4588d29c7 --- /dev/null +++ b/test/jdk/javax/imageio/plugins/jpeg/CMYK/CMYKJPEGTest.java @@ -0,0 +1,200 @@ +/* + * 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. + */ + +/* + * + * This test verifies that using the built-in ImageI/O JPEG plugin that JPEG images + * that are in a CMYK ColorSpace can be read into a BufferedImage using the convemience + * APIS and that and the colours are properly interpreted. + * Since there is no standard JDK CMYK ColorSpace, this requires that either the image + * contain an ICC_Profile which can be used by the plugin to create an ICC_ColorSpace + * or that the plugin provides a suitable default CMYK ColorSpace instance by some other means. + * + * The test further verifies that the resultant BufferedImage will be re-written as a CMYK + * BufferedImage. It can do this so long as the BufferedImage has that CMYK ColorSpace + * used by its ColorModel. + * + * The verification requires re-reading again the re-written image and checking the + * re-read image still has a CMYK ColorSpace and the same colours. + * + * Optionally - not for use in the test harness - the test can be passed a parameter + * -display to create a UI which renders all the images the test is + * verifying so it can be manually verified + */ + +/* + * @test + * @bug 8274735 + * @summary Verify CMYK JPEGs can be read and written + */ + +import java.awt.Color; +import static java.awt.Color.*; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.GridLayout; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import javax.imageio.ImageIO; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +public class CMYKJPEGTest { + + static String[] fileNames = { + "black_cmyk.jpg", + "white_cmyk.jpg", + "gray_cmyk.jpg", + "red_cmyk.jpg", + "blue_cmyk.jpg", + "green_cmyk.jpg", + "cyan_cmyk.jpg", + "magenta_cmyk.jpg", + "yellow_cmyk.jpg", + }; + + static Color[] colors = { + black, + white, + gray, + red, + blue, + green, + cyan, + magenta, + yellow, + }; + + static boolean display; + + static BufferedImage[] readImages; + static BufferedImage[] writtenImages; + static int imageIndex = 0; + + public static void main(String[] args) throws Exception { + + if (args.length > 0) { + display = "-display".equals(args[0]); + } + + String sep = System.getProperty("file.separator"); + String dir = System.getProperty("test.src", "."); + String prefix = dir+sep; + + readImages = new BufferedImage[fileNames.length]; + writtenImages = new BufferedImage[fileNames.length]; + + for (String fileName : fileNames) { + String color = fileName.replace("_cmyk.jpg", ""); + test(prefix+fileName, color, imageIndex++); + } + if (display) { + SwingUtilities.invokeAndWait(() -> createUI()); + } + } + + static void test(String fileName, String color, int index) + throws IOException { + + readImages[index] = ImageIO.read(new File(fileName)); + verify(readImages[index], color, colors[index]); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageIO.write(readImages[index], "jpg", baos); + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + writtenImages[index] = ImageIO.read(bais); + verify(writtenImages[index], color, colors[index]); + } + + static void verify(BufferedImage img, String colorName, Color c) { + ColorModel cm = img.getColorModel(); + int tc = cm.getNumComponents(); + int cc = cm.getNumColorComponents(); + if (cc != 4 || tc != 4) { + throw new RuntimeException("Unexpected num comp for " + img); + } + + int rgb = img.getRGB(0,0); + int c_red = c.getRed(); + int c_green = c.getGreen(); + int c_blue = c.getBlue(); + int i_red = (rgb & 0x0ff0000) >> 16; + int i_green = (rgb & 0x000ff00) >> 8; + int i_blue = (rgb & 0x00000ff); + int tol = 16; + if ((Math.abs(i_red - c_red) > tol) || + (Math.abs(i_green - c_green) > tol) || + (Math.abs(i_blue - c_blue) > tol)) + { + System.err.println("red="+i_red+" green="+i_green+" blue="+i_blue); + throw new RuntimeException("Too different " + img + " " + colorName + " " + c); + } + } + + static class ImageComp extends JComponent { + + BufferedImage img; + + ImageComp(BufferedImage img) { + this.img = img; + } + + public Dimension getPreferredSize() { + return new Dimension(img.getWidth(), img.getHeight()); + } + + public Dimension getMinimumSize() { + return getPreferredSize(); + } + + public void paintComponent(Graphics g) { + super.paintComponent(g); + g.drawImage(img, 0, 0, null); + } + } + + static void createUI() { + JFrame f = new JFrame("CMYK JPEG Test"); + JPanel p = new JPanel(); + p.setLayout(new GridLayout(3, colors.length, 10, 10)); + for (String s : fileNames) { + p.add(new JLabel(s.replace("_cmyk.jpg", ""))); + } + for (BufferedImage i : readImages) { + p.add(new ImageComp(i)); + } + for (BufferedImage i : writtenImages) { + p.add(new ImageComp(i)); + } + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + f.add(p); + f.pack(); + f.setVisible(true); + } +} diff --git a/test/jdk/javax/imageio/plugins/jpeg/CMYK/black_cmyk.jpg b/test/jdk/javax/imageio/plugins/jpeg/CMYK/black_cmyk.jpg new file mode 100644 index 00000000000..1446f063bdd Binary files /dev/null and b/test/jdk/javax/imageio/plugins/jpeg/CMYK/black_cmyk.jpg differ diff --git a/test/jdk/javax/imageio/plugins/jpeg/CMYK/blue_cmyk.jpg b/test/jdk/javax/imageio/plugins/jpeg/CMYK/blue_cmyk.jpg new file mode 100644 index 00000000000..74aa67622e4 Binary files /dev/null and b/test/jdk/javax/imageio/plugins/jpeg/CMYK/blue_cmyk.jpg differ diff --git a/test/jdk/javax/imageio/plugins/jpeg/CMYK/cyan_cmyk.jpg b/test/jdk/javax/imageio/plugins/jpeg/CMYK/cyan_cmyk.jpg new file mode 100644 index 00000000000..4e97acc33c2 Binary files /dev/null and b/test/jdk/javax/imageio/plugins/jpeg/CMYK/cyan_cmyk.jpg differ diff --git a/test/jdk/javax/imageio/plugins/jpeg/CMYK/gray_cmyk.jpg b/test/jdk/javax/imageio/plugins/jpeg/CMYK/gray_cmyk.jpg new file mode 100644 index 00000000000..a519437e702 Binary files /dev/null and b/test/jdk/javax/imageio/plugins/jpeg/CMYK/gray_cmyk.jpg differ diff --git a/test/jdk/javax/imageio/plugins/jpeg/CMYK/green_cmyk.jpg b/test/jdk/javax/imageio/plugins/jpeg/CMYK/green_cmyk.jpg new file mode 100644 index 00000000000..c5c4af37131 Binary files /dev/null and b/test/jdk/javax/imageio/plugins/jpeg/CMYK/green_cmyk.jpg differ diff --git a/test/jdk/javax/imageio/plugins/jpeg/CMYK/magenta_cmyk.jpg b/test/jdk/javax/imageio/plugins/jpeg/CMYK/magenta_cmyk.jpg new file mode 100644 index 00000000000..9209e1f82b9 Binary files /dev/null and b/test/jdk/javax/imageio/plugins/jpeg/CMYK/magenta_cmyk.jpg differ diff --git a/test/jdk/javax/imageio/plugins/jpeg/CMYK/red_cmyk.jpg b/test/jdk/javax/imageio/plugins/jpeg/CMYK/red_cmyk.jpg new file mode 100644 index 00000000000..594f2ac0823 Binary files /dev/null and b/test/jdk/javax/imageio/plugins/jpeg/CMYK/red_cmyk.jpg differ diff --git a/test/jdk/javax/imageio/plugins/jpeg/CMYK/white_cmyk.jpg b/test/jdk/javax/imageio/plugins/jpeg/CMYK/white_cmyk.jpg new file mode 100644 index 00000000000..319bbb36470 Binary files /dev/null and b/test/jdk/javax/imageio/plugins/jpeg/CMYK/white_cmyk.jpg differ diff --git a/test/jdk/javax/imageio/plugins/jpeg/CMYK/yellow_cmyk.jpg b/test/jdk/javax/imageio/plugins/jpeg/CMYK/yellow_cmyk.jpg new file mode 100644 index 00000000000..4a7a338b256 Binary files /dev/null and b/test/jdk/javax/imageio/plugins/jpeg/CMYK/yellow_cmyk.jpg differ diff --git a/test/jdk/javax/net/ssl/compatibility/JdkInfo.java b/test/jdk/javax/net/ssl/compatibility/JdkInfo.java index 8c8678edcf4..719780caa0f 100644 --- a/test/jdk/javax/net/ssl/compatibility/JdkInfo.java +++ b/test/jdk/javax/net/ssl/compatibility/JdkInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -22,7 +22,9 @@ */ import java.nio.file.Path; +import java.util.Arrays; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; /* @@ -37,10 +39,10 @@ public class JdkInfo { public final Path javaPath; public final String version; - public final String supportedProtocols; - public final String enabledProtocols; - public final String supportedCipherSuites; - public final String enabledCipherSuites; + public final List supportedProtocols; + public final List enabledProtocols; + public final List supportedCipherSuites; + public final List enabledCipherSuites; public final boolean supportsSNI; public final boolean supportsALPN; @@ -54,13 +56,26 @@ public JdkInfo(Path javaPath) { } String[] attributes = Utilities.split(output, Utilities.PARAM_DELIMITER); - version = attributes[0].replaceAll(".*=", ""); - supportedProtocols = attributes[1].replaceAll(".*=", ""); - enabledProtocols = attributes[2].replaceAll(".*=", ""); - supportedCipherSuites = attributes[3].replaceAll(".*=", ""); - enabledCipherSuites = attributes[4].replaceAll(".*=", ""); - supportsSNI = Boolean.valueOf(attributes[5].replaceAll(".*=", "")); - supportsALPN = Boolean.valueOf(attributes[6].replaceAll(".*=", "")); + version = parseAttribute(attributes[0]); + supportedProtocols = parseListAttribute(attributes[1]); + enabledProtocols = parseListAttribute(attributes[2]); + supportedCipherSuites = parseListAttribute(attributes[3]); + enabledCipherSuites = parseListAttribute(attributes[4]); + supportsSNI = parseBooleanAttribute(attributes[5]); + supportsALPN = parseBooleanAttribute(attributes[6]); + } + + private List parseListAttribute(String attribute) { + attribute = parseAttribute(attribute); + return Arrays.asList(attribute.split(",")); + } + + private boolean parseBooleanAttribute(String attribute) { + attribute = parseAttribute(attribute); + return Boolean.parseBoolean(attribute); + } + private String parseAttribute(String attribute) { + return attribute.replaceAll(".*=", ""); } // Determines the specific attributes for the specified JDK. diff --git a/test/jdk/javax/swing/DefaultButtonModel/DefaultButtonModelCrashTest.java b/test/jdk/javax/swing/DefaultButtonModel/DefaultButtonModelCrashTest.java index efcf335a54d..14190ce65d3 100644 --- a/test/jdk/javax/swing/DefaultButtonModel/DefaultButtonModelCrashTest.java +++ b/test/jdk/javax/swing/DefaultButtonModel/DefaultButtonModelCrashTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -21,23 +21,21 @@ * questions. */ -/** +/* * @test * @bug 8182577 - * @summary Verifies if moving focus via custom ButtonModel causes crash + * @summary Verifies if moving focus to JToggleButton with DefaultButtonModel + * that is added to a ButtonGroup doesn't throw ClassCastException * @key headful * @run main DefaultButtonModelCrashTest */ import java.awt.BorderLayout; -import java.awt.Container; -import java.awt.Point; import java.awt.Robot; import java.awt.event.KeyEvent; import javax.swing.ButtonModel; import javax.swing.DefaultButtonModel; import javax.swing.JCheckBox; -import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JTextField; @@ -45,8 +43,6 @@ public class DefaultButtonModelCrashTest { private JFrame frame = null; - private JPanel panel; - private volatile Point p = null; public static void main(String[] args) throws Exception { new DefaultButtonModelCrashTest(); @@ -58,29 +54,34 @@ public DefaultButtonModelCrashTest() throws Exception { robot.setAutoDelay(200); SwingUtilities.invokeAndWait(() -> go()); robot.waitForIdle(); + robot.delay(1000); robot.keyPress(KeyEvent.VK_TAB); robot.keyRelease(KeyEvent.VK_TAB); robot.delay(100); robot.keyPress(KeyEvent.VK_TAB); robot.keyRelease(KeyEvent.VK_TAB); } finally { - if (frame != null) { SwingUtilities.invokeAndWait(()->frame.dispose()); } + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); } } private void go() { - frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - Container contentPane = frame.getContentPane(); - ButtonModel model = new DefaultButtonModel(); + ButtonModel model = new DefaultButtonModel(); JCheckBox check = new JCheckBox("a bit broken"); check.setModel(model); - panel = new JPanel(new BorderLayout()); + + JPanel panel = new JPanel(new BorderLayout()); panel.add(new JTextField("Press Tab (twice?)"), BorderLayout.NORTH); panel.add(check); - contentPane.add(panel); + + frame.getContentPane().add(panel); frame.setLocationRelativeTo(null); frame.pack(); frame.setVisible(true); diff --git a/test/jdk/javax/swing/JCheckBox/ImageCheckboxFocus/ImageCheckboxTest.java b/test/jdk/javax/swing/JCheckBox/ImageCheckboxFocus/ImageCheckboxTest.java index b63973229a2..c93715d8087 100644 --- a/test/jdk/javax/swing/JCheckBox/ImageCheckboxFocus/ImageCheckboxTest.java +++ b/test/jdk/javax/swing/JCheckBox/ImageCheckboxFocus/ImageCheckboxTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. 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. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,7 @@ /* * @test * @key headful - * @bug 8216358 + * @bug 8216358 8279586 * @summary [macos] The focus is invisible when tab to "Image Radio Buttons" and "Image CheckBoxes" * @library ../../regtesthelpers/ * @build Util @@ -51,8 +51,12 @@ public void performTest() throws Exception { BufferedImage.TYPE_INT_ARGB); BufferedImage imageFocus = new BufferedImage(100, 50, BufferedImage.TYPE_INT_ARGB); + BufferedImage imageFocusNotPainted = new BufferedImage(100, 50, + BufferedImage.TYPE_INT_ARGB); + CustomCheckBox checkbox = new CustomCheckBox("Test", new MyIcon(Color.GREEN)); + checkbox.setFocusPainted(true); checkbox.setSize(100, 50); checkbox.setFocused(false); checkbox.paint(imageNoFocus.createGraphics()); @@ -64,6 +68,17 @@ public void performTest() throws Exception { ImageIO.write(imageNoFocus, "png", new File("imageNoFocus.png")); throw new Exception("Changing focus is not visualized"); } + + checkbox.setFocusPainted(false); + checkbox.paint(imageFocusNotPainted.createGraphics()); + + if (!Util.compareBufferedImages(imageFocusNotPainted, imageNoFocus)) { + ImageIO.write(imageFocusNotPainted, "png", + new File("imageFocusNotPainted.png")); + ImageIO.write(imageFocus, "png", new File("imageFocus.png")); + ImageIO.write(imageNoFocus, "png", new File("imageNoFocus.png")); + throw new Exception("setFocusPainted(false) is ignored"); + } } class MyIcon implements Icon { diff --git a/test/jdk/javax/swing/text/html/parser/Parser/8078268/bug8078268.java b/test/jdk/javax/swing/text/html/parser/Parser/8078268/bug8078268.java index fc9f9610037..f340db97abb 100644 --- a/test/jdk/javax/swing/text/html/parser/Parser/8078268/bug8078268.java +++ b/test/jdk/javax/swing/text/html/parser/Parser/8078268/bug8078268.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2016, 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 @@ -24,50 +24,52 @@ import java.io.File; import java.io.FileReader; +import java.util.concurrent.CountDownLatch; + import javax.swing.SwingUtilities; import javax.swing.text.Document; import javax.swing.text.html.HTMLEditorKit; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + /* @test @bug 8078268 @summary javax.swing.text.html.parser.Parser parseScript incorrectly optimized - @author Mikhail Cherkasov @run main bug8078268 */ public class bug8078268 { - static volatile boolean parsingDone = false; - static volatile Exception exception; + private static final long TIMEOUT = 10_000; + + private static final String FILENAME = "slowparse.html"; + + private static final CountDownLatch latch = new CountDownLatch(1); + private static volatile Exception exception; public static void main(String[] args) throws Exception { - long timeout = 10_000; - long s = System.currentTimeMillis(); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { HTMLEditorKit htmlKit = new HTMLEditorKit(); Document doc = htmlKit.createDefaultDocument(); try { - htmlKit.read(new FileReader(getDirURL() + "slowparse.html"), doc, 0); - parsingDone = true; + htmlKit.read(new FileReader(getAbsolutePath()), doc, 0); } catch (Exception e) { exception = e; } + latch.countDown(); } }); - while (!parsingDone && exception == null && System.currentTimeMillis() - s < timeout) { - Thread.sleep(200); + + if (!latch.await(TIMEOUT, MILLISECONDS)) { + throw new RuntimeException("Parsing takes too long."); } - final long took = System.currentTimeMillis() - s; if (exception != null) { throw exception; } - if (took > timeout) { - throw new RuntimeException("Parsing takes too long."); - } } - static String getDirURL() { - return new File(System.getProperty("test.src", ".")).getAbsolutePath() + - File.separator; + private static String getAbsolutePath() { + return System.getProperty("test.src", ".") + + File.separator + FILENAME; } } diff --git a/test/jdk/javax/xml/crypto/dsig/BadXPointer.java b/test/jdk/javax/xml/crypto/dsig/BadXPointer.java new file mode 100644 index 00000000000..ba985b6c568 --- /dev/null +++ b/test/jdk/javax/xml/crypto/dsig/BadXPointer.java @@ -0,0 +1,60 @@ +/* + * 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. + */ + +import jdk.test.lib.Asserts; +import jdk.test.lib.Utils; +import jdk.test.lib.security.XMLUtils; + +import javax.xml.crypto.URIReferenceException; +import javax.xml.crypto.dsig.XMLSignatureException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.spec.ECGenParameterSpec; + +/** + * @test + * @bug 8278186 + * @summary reject malformed xpointer(id('a')) gracefully + * @library /test/lib + * @modules java.xml.crypto + */ +public class BadXPointer { + + public static void main(String[] args) throws Exception { + + KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC"); + kpg.initialize(new ECGenParameterSpec("secp256r1")); + KeyPair kp = kpg.generateKeyPair(); + + var signer = XMLUtils.signer(kp.getPrivate(), kp.getPublic()); + var doc = XMLUtils.string2doc(""); + + // No enclosing ' for id + Utils.runAndCheckException( + () -> signer.signEnveloping(doc, "a", "#xpointer(id('a))"), + ex -> Asserts.assertTrue(ex instanceof XMLSignatureException + && ex.getCause() instanceof URIReferenceException + && ex.getMessage().contains("Could not find a resolver"), + ex.toString())); + } +} diff --git a/test/jdk/javax/xml/jaxp/XPath/InvalidXPath.java b/test/jdk/javax/xml/jaxp/XPath/InvalidXPath.java new file mode 100644 index 00000000000..478f4212d5b --- /dev/null +++ b/test/jdk/javax/xml/jaxp/XPath/InvalidXPath.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022, 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. + */ + +/* + * @test + * @bug 8284548 + * @summary Test whether the expected exception is thrown when + * trying to compile an invalid XPath expression. + * @run main InvalidXPath + */ + +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +public class InvalidXPath { + + public static void main(String... args) { + // define an invalid XPath expression + final String invalidXPath = ">>"; + + // expect XPathExpressionException when the invalid XPath expression is compiled + try { + XPathFactory.newInstance().newXPath().compile(invalidXPath); + } catch (XPathExpressionException e) { + System.out.println("Caught expected exception: " + e.getClass().getName() + + "(" + e.getMessage() + ")."); + } catch (Exception e) { + System.out.println("Caught unexpected exception: " + e.getClass().getName() + + "(" + e.getMessage() + ")!"); + throw e; + } + } +} diff --git a/test/jdk/jdk/incubator/vector/Byte128VectorTests.java b/test/jdk/jdk/incubator/vector/Byte128VectorTests.java index 00ebad48021..bbd7d83814a 100644 --- a/test/jdk/jdk/incubator/vector/Byte128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte128VectorTests.java @@ -226,10 +226,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(byte[] r, byte[] a, byte element, int index) { - int i = 0; + static void assertInsertArraysEquals(byte[] r, byte[] a, byte element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -3264,13 +3264,16 @@ static void withByte128VectorTests(IntFunction fa) { byte[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - av.withLane(0, (byte)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (byte)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (byte)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (byte)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(byte a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/Byte256VectorTests.java b/test/jdk/jdk/incubator/vector/Byte256VectorTests.java index 32c67f72e56..8a119b4b3c9 100644 --- a/test/jdk/jdk/incubator/vector/Byte256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte256VectorTests.java @@ -226,10 +226,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(byte[] r, byte[] a, byte element, int index) { - int i = 0; + static void assertInsertArraysEquals(byte[] r, byte[] a, byte element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -3264,13 +3264,16 @@ static void withByte256VectorTests(IntFunction fa) { byte[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - av.withLane(0, (byte)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (byte)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (byte)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (byte)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(byte a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/Byte512VectorTests.java b/test/jdk/jdk/incubator/vector/Byte512VectorTests.java index eab4d8226d3..f46c2d608dd 100644 --- a/test/jdk/jdk/incubator/vector/Byte512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte512VectorTests.java @@ -226,10 +226,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(byte[] r, byte[] a, byte element, int index) { - int i = 0; + static void assertInsertArraysEquals(byte[] r, byte[] a, byte element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -3264,13 +3264,16 @@ static void withByte512VectorTests(IntFunction fa) { byte[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - av.withLane(0, (byte)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (byte)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (byte)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (byte)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(byte a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/Byte64VectorTests.java b/test/jdk/jdk/incubator/vector/Byte64VectorTests.java index 75aaf7b1b80..9f03f681c6d 100644 --- a/test/jdk/jdk/incubator/vector/Byte64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte64VectorTests.java @@ -226,10 +226,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(byte[] r, byte[] a, byte element, int index) { - int i = 0; + static void assertInsertArraysEquals(byte[] r, byte[] a, byte element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -3264,13 +3264,16 @@ static void withByte64VectorTests(IntFunction fa) { byte[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - av.withLane(0, (byte)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (byte)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (byte)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (byte)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(byte a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java b/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java index 20a7cccfdd7..cba42e04bd5 100644 --- a/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java @@ -231,10 +231,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(byte[] r, byte[] a, byte element, int index) { - int i = 0; + static void assertInsertArraysEquals(byte[] r, byte[] a, byte element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -3269,13 +3269,16 @@ static void withByteMaxVectorTests(IntFunction fa) { byte[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { ByteVector av = ByteVector.fromArray(SPECIES, a, i); - av.withLane(0, (byte)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (byte)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (byte)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (byte)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(byte a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/Double128VectorTests.java b/test/jdk/jdk/incubator/vector/Double128VectorTests.java index a5f9cad0921..4b71199f547 100644 --- a/test/jdk/jdk/incubator/vector/Double128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double128VectorTests.java @@ -226,10 +226,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(double[] r, double[] a, double element, int index) { - int i = 0; + static void assertInsertArraysEquals(double[] r, double[] a, double element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -2449,13 +2449,16 @@ static void withDouble128VectorTests(IntFunction fa) { double[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - av.withLane(0, (double)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (double)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (double)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (double)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(double a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/Double256VectorTests.java b/test/jdk/jdk/incubator/vector/Double256VectorTests.java index b27d568fc8b..d8e2af40820 100644 --- a/test/jdk/jdk/incubator/vector/Double256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double256VectorTests.java @@ -226,10 +226,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(double[] r, double[] a, double element, int index) { - int i = 0; + static void assertInsertArraysEquals(double[] r, double[] a, double element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -2449,13 +2449,16 @@ static void withDouble256VectorTests(IntFunction fa) { double[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - av.withLane(0, (double)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (double)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (double)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (double)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(double a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/Double512VectorTests.java b/test/jdk/jdk/incubator/vector/Double512VectorTests.java index 5d5d53b57e6..ceccafc21a1 100644 --- a/test/jdk/jdk/incubator/vector/Double512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double512VectorTests.java @@ -226,10 +226,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(double[] r, double[] a, double element, int index) { - int i = 0; + static void assertInsertArraysEquals(double[] r, double[] a, double element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -2449,13 +2449,16 @@ static void withDouble512VectorTests(IntFunction fa) { double[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - av.withLane(0, (double)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (double)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (double)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (double)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(double a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/Double64VectorTests.java b/test/jdk/jdk/incubator/vector/Double64VectorTests.java index d17308715bc..e64e45fb7c2 100644 --- a/test/jdk/jdk/incubator/vector/Double64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double64VectorTests.java @@ -226,10 +226,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(double[] r, double[] a, double element, int index) { - int i = 0; + static void assertInsertArraysEquals(double[] r, double[] a, double element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -2449,13 +2449,16 @@ static void withDouble64VectorTests(IntFunction fa) { double[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - av.withLane(0, (double)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (double)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (double)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (double)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(double a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java b/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java index 7f6ae5860eb..499f151e51f 100644 --- a/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java @@ -231,10 +231,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(double[] r, double[] a, double element, int index) { - int i = 0; + static void assertInsertArraysEquals(double[] r, double[] a, double element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -2454,13 +2454,16 @@ static void withDoubleMaxVectorTests(IntFunction fa) { double[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - av.withLane(0, (double)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (double)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (double)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (double)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(double a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/Float128VectorTests.java b/test/jdk/jdk/incubator/vector/Float128VectorTests.java index 465817c6c54..dfec60421cb 100644 --- a/test/jdk/jdk/incubator/vector/Float128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float128VectorTests.java @@ -226,10 +226,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(float[] r, float[] a, float element, int index) { - int i = 0; + static void assertInsertArraysEquals(float[] r, float[] a, float element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -2459,13 +2459,16 @@ static void withFloat128VectorTests(IntFunction fa) { float[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - av.withLane(0, (float)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (float)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (float)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (float)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(float a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/Float256VectorTests.java b/test/jdk/jdk/incubator/vector/Float256VectorTests.java index 661b9d8a590..75f49d00c39 100644 --- a/test/jdk/jdk/incubator/vector/Float256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float256VectorTests.java @@ -226,10 +226,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(float[] r, float[] a, float element, int index) { - int i = 0; + static void assertInsertArraysEquals(float[] r, float[] a, float element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -2459,13 +2459,16 @@ static void withFloat256VectorTests(IntFunction fa) { float[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - av.withLane(0, (float)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (float)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (float)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (float)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(float a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/Float512VectorTests.java b/test/jdk/jdk/incubator/vector/Float512VectorTests.java index a2bd05921bc..24cf5857f9d 100644 --- a/test/jdk/jdk/incubator/vector/Float512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float512VectorTests.java @@ -226,10 +226,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(float[] r, float[] a, float element, int index) { - int i = 0; + static void assertInsertArraysEquals(float[] r, float[] a, float element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -2459,13 +2459,16 @@ static void withFloat512VectorTests(IntFunction fa) { float[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - av.withLane(0, (float)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (float)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (float)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (float)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(float a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/Float64VectorTests.java b/test/jdk/jdk/incubator/vector/Float64VectorTests.java index 6d325336941..b15496bc85f 100644 --- a/test/jdk/jdk/incubator/vector/Float64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float64VectorTests.java @@ -226,10 +226,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(float[] r, float[] a, float element, int index) { - int i = 0; + static void assertInsertArraysEquals(float[] r, float[] a, float element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -2459,13 +2459,16 @@ static void withFloat64VectorTests(IntFunction fa) { float[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - av.withLane(0, (float)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (float)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (float)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (float)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(float a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java b/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java index ee8ac1ab8f0..545f6e4a9bd 100644 --- a/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java @@ -231,10 +231,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(float[] r, float[] a, float element, int index) { - int i = 0; + static void assertInsertArraysEquals(float[] r, float[] a, float element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -2464,13 +2464,16 @@ static void withFloatMaxVectorTests(IntFunction fa) { float[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { FloatVector av = FloatVector.fromArray(SPECIES, a, i); - av.withLane(0, (float)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (float)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (float)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (float)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(float a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/Int128VectorTests.java b/test/jdk/jdk/incubator/vector/Int128VectorTests.java index c45ea61f830..9414df97eaa 100644 --- a/test/jdk/jdk/incubator/vector/Int128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int128VectorTests.java @@ -226,10 +226,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(int[] r, int[] a, int element, int index) { - int i = 0; + static void assertInsertArraysEquals(int[] r, int[] a, int element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -3229,13 +3229,16 @@ static void withInt128VectorTests(IntFunction fa) { int[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - av.withLane(0, (int)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (int)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (int)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (int)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(int a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/Int256VectorTests.java b/test/jdk/jdk/incubator/vector/Int256VectorTests.java index 121b5c37f5f..e9260e429e5 100644 --- a/test/jdk/jdk/incubator/vector/Int256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int256VectorTests.java @@ -226,10 +226,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(int[] r, int[] a, int element, int index) { - int i = 0; + static void assertInsertArraysEquals(int[] r, int[] a, int element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -3229,13 +3229,16 @@ static void withInt256VectorTests(IntFunction fa) { int[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - av.withLane(0, (int)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (int)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (int)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (int)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(int a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/Int512VectorTests.java b/test/jdk/jdk/incubator/vector/Int512VectorTests.java index 23dcf6464e3..c20853ea427 100644 --- a/test/jdk/jdk/incubator/vector/Int512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int512VectorTests.java @@ -226,10 +226,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(int[] r, int[] a, int element, int index) { - int i = 0; + static void assertInsertArraysEquals(int[] r, int[] a, int element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -3229,13 +3229,16 @@ static void withInt512VectorTests(IntFunction fa) { int[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - av.withLane(0, (int)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (int)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (int)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (int)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(int a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/Int64VectorTests.java b/test/jdk/jdk/incubator/vector/Int64VectorTests.java index 0a442077f23..0fdedf309b8 100644 --- a/test/jdk/jdk/incubator/vector/Int64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int64VectorTests.java @@ -226,10 +226,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(int[] r, int[] a, int element, int index) { - int i = 0; + static void assertInsertArraysEquals(int[] r, int[] a, int element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -3229,13 +3229,16 @@ static void withInt64VectorTests(IntFunction fa) { int[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - av.withLane(0, (int)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (int)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (int)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (int)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(int a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java b/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java index f8257ccbf92..74724e2c9de 100644 --- a/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java @@ -231,10 +231,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(int[] r, int[] a, int element, int index) { - int i = 0; + static void assertInsertArraysEquals(int[] r, int[] a, int element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -3234,13 +3234,16 @@ static void withIntMaxVectorTests(IntFunction fa) { int[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { IntVector av = IntVector.fromArray(SPECIES, a, i); - av.withLane(0, (int)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (int)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (int)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (int)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(int a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/Long128VectorTests.java b/test/jdk/jdk/incubator/vector/Long128VectorTests.java index 20a1bfe900b..f5eaa0efc87 100644 --- a/test/jdk/jdk/incubator/vector/Long128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long128VectorTests.java @@ -183,10 +183,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(long[] r, long[] a, long element, int index) { - int i = 0; + static void assertInsertArraysEquals(long[] r, long[] a, long element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -3251,13 +3251,16 @@ static void withLong128VectorTests(IntFunction fa) { long[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - av.withLane(0, (long)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (long)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (long)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (long)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(long a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/Long256VectorTests.java b/test/jdk/jdk/incubator/vector/Long256VectorTests.java index fd8493eff22..44f0c4f41a0 100644 --- a/test/jdk/jdk/incubator/vector/Long256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long256VectorTests.java @@ -183,10 +183,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(long[] r, long[] a, long element, int index) { - int i = 0; + static void assertInsertArraysEquals(long[] r, long[] a, long element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -3251,13 +3251,16 @@ static void withLong256VectorTests(IntFunction fa) { long[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - av.withLane(0, (long)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (long)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (long)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (long)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(long a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/Long512VectorTests.java b/test/jdk/jdk/incubator/vector/Long512VectorTests.java index 05fcf160be2..bd8d7c03cf8 100644 --- a/test/jdk/jdk/incubator/vector/Long512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long512VectorTests.java @@ -183,10 +183,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(long[] r, long[] a, long element, int index) { - int i = 0; + static void assertInsertArraysEquals(long[] r, long[] a, long element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -3251,13 +3251,16 @@ static void withLong512VectorTests(IntFunction fa) { long[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - av.withLane(0, (long)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (long)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (long)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (long)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(long a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/Long64VectorTests.java b/test/jdk/jdk/incubator/vector/Long64VectorTests.java index 1ed9c4895fc..e832ba7b0df 100644 --- a/test/jdk/jdk/incubator/vector/Long64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long64VectorTests.java @@ -183,10 +183,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(long[] r, long[] a, long element, int index) { - int i = 0; + static void assertInsertArraysEquals(long[] r, long[] a, long element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -3251,13 +3251,16 @@ static void withLong64VectorTests(IntFunction fa) { long[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - av.withLane(0, (long)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (long)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (long)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (long)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(long a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java b/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java index c3612dab831..89b927c2e2b 100644 --- a/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java @@ -188,10 +188,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(long[] r, long[] a, long element, int index) { - int i = 0; + static void assertInsertArraysEquals(long[] r, long[] a, long element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -3256,13 +3256,16 @@ static void withLongMaxVectorTests(IntFunction fa) { long[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { LongVector av = LongVector.fromArray(SPECIES, a, i); - av.withLane(0, (long)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (long)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (long)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (long)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(long a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/Short128VectorTests.java b/test/jdk/jdk/incubator/vector/Short128VectorTests.java index 50dc41bc7db..79af2958684 100644 --- a/test/jdk/jdk/incubator/vector/Short128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short128VectorTests.java @@ -226,10 +226,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(short[] r, short[] a, short element, int index) { - int i = 0; + static void assertInsertArraysEquals(short[] r, short[] a, short element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -3254,13 +3254,16 @@ static void withShort128VectorTests(IntFunction fa) { short[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - av.withLane(0, (short)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (short)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (short)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (short)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(short a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/Short256VectorTests.java b/test/jdk/jdk/incubator/vector/Short256VectorTests.java index 6c1d460b1a2..25345def2a7 100644 --- a/test/jdk/jdk/incubator/vector/Short256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short256VectorTests.java @@ -226,10 +226,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(short[] r, short[] a, short element, int index) { - int i = 0; + static void assertInsertArraysEquals(short[] r, short[] a, short element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -3254,13 +3254,16 @@ static void withShort256VectorTests(IntFunction fa) { short[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - av.withLane(0, (short)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (short)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (short)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (short)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(short a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/Short512VectorTests.java b/test/jdk/jdk/incubator/vector/Short512VectorTests.java index 9410b3c8579..04598457767 100644 --- a/test/jdk/jdk/incubator/vector/Short512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short512VectorTests.java @@ -226,10 +226,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(short[] r, short[] a, short element, int index) { - int i = 0; + static void assertInsertArraysEquals(short[] r, short[] a, short element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -3254,13 +3254,16 @@ static void withShort512VectorTests(IntFunction fa) { short[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - av.withLane(0, (short)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (short)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (short)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (short)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(short a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/Short64VectorTests.java b/test/jdk/jdk/incubator/vector/Short64VectorTests.java index a6fc3dd3e03..cbf84a8cf35 100644 --- a/test/jdk/jdk/incubator/vector/Short64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short64VectorTests.java @@ -226,10 +226,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(short[] r, short[] a, short element, int index) { - int i = 0; + static void assertInsertArraysEquals(short[] r, short[] a, short element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -3254,13 +3254,16 @@ static void withShort64VectorTests(IntFunction fa) { short[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - av.withLane(0, (short)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (short)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (short)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (short)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(short a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java b/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java index 4653a8fb32a..64e377b341f 100644 --- a/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java @@ -231,10 +231,10 @@ static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReduction } } - static void assertInsertArraysEquals(short[] r, short[] a, short element, int index) { - int i = 0; + static void assertInsertArraysEquals(short[] r, short[] a, short element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { @@ -3259,13 +3259,16 @@ static void withShortMaxVectorTests(IntFunction fa) { short[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { ShortVector av = ShortVector.fromArray(SPECIES, a, i); - av.withLane(0, (short)4).intoArray(r, i); + av.withLane((j++ & (SPECIES.length()-1)), (short)(65535+i)).intoArray(r, i); } } - assertInsertArraysEquals(r, a, (short)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, (short)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } static boolean testIS_DEFAULT(short a) { return bits(a)==0; diff --git a/test/jdk/jdk/incubator/vector/VectorMaxConversionTests.java b/test/jdk/jdk/incubator/vector/VectorMaxConversionTests.java index bab60cc684a..6b45043cc62 100644 --- a/test/jdk/jdk/incubator/vector/VectorMaxConversionTests.java +++ b/test/jdk/jdk/incubator/vector/VectorMaxConversionTests.java @@ -40,6 +40,18 @@ * VectorMaxConversionTests */ +/* + * @test + * @bug 8281544 + * @summary Test that ZGC and vectorapi with KNL work together. + * @requires vm.gc.Z + * @modules jdk.incubator.vector + * @modules java.base/jdk.internal.vm.annotation + * @run testng/othervm -XX:-TieredCompilation --add-opens jdk.incubator.vector/jdk.incubator.vector=ALL-UNNAMED + * -XX:+UnlockDiagnosticVMOptions -XX:+UseKNLSetting -XX:+UseZGC -XX:+IgnoreUnrecognizedVMOptions + * VectorMaxConversionTests + */ + @Test public class VectorMaxConversionTests extends AbstractVectorConversionTest { diff --git a/test/jdk/jdk/incubator/vector/build-tests.sh b/test/jdk/jdk/incubator/vector/build-tests.sh deleted file mode 100644 index 69f0290ce26..00000000000 --- a/test/jdk/jdk/incubator/vector/build-tests.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 2018, 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. 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. -# - -. config.sh - -Log false "Building Vector API tests, $(date)\n" - -# For each type -for type in byte short int long float double -do - Type="$(tr '[:lower:]' '[:upper:]' <<< ${type:0:1})${type:1}" - - # For each size - for bits in 64 128 256 512 - do - vectorteststype=${typeprefix}${Type}${bits}VectorTests - # Compile - Log true "Compiling ${vectorteststype}... " - Log false "\n${JAVAC} -cp \"${VECTORTESTS_HOME_CP}$SEPARATOR${TESTNG_JAR}\" --add-modules=jdk.incubator.vector $vectorteststype.java 2>&1" - compilation=$(${JAVAC} -cp "${VECTORTESTS_HOME_CP}$SEPARATOR${TESTNG_JAR}" \ - --add-modules=jdk.incubator.vector $vectorteststype.java 2>&1) - if [[ $compilation == *"error"* ]]; then - Log true "$compilation\n" - exit -1 - else - Log false "$compilation\n" - fi - Log true "done\n" - done -done - -rm -fr build - - diff --git a/test/jdk/jdk/incubator/vector/clean.sh b/test/jdk/jdk/incubator/vector/clean.sh index f889a913623..7c177d80016 100644 --- a/test/jdk/jdk/incubator/vector/clean.sh +++ b/test/jdk/jdk/incubator/vector/clean.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 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 @@ -24,4 +24,4 @@ # questions. # -rm -rf *.class build.log test-output +rm -rf build.log diff --git a/test/jdk/jdk/incubator/vector/config.sh b/test/jdk/jdk/incubator/vector/config.sh index c1447b2e9fd..15bfe647c3a 100644 --- a/test/jdk/jdk/incubator/vector/config.sh +++ b/test/jdk/jdk/incubator/vector/config.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 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 @@ -35,9 +35,6 @@ SPP_CLASSNAME="build.tools.spp.Spp" SEPARATOR=":" TYPEPREFIX="" TEMPLATE_FILE="unit_tests.template" -TESTNG_JAR="${TESTNG_PLUGIN}/plugins/org.testng.source_6.13.1.r201712040515.jar" -TESTNG_RUN_JAR="${TESTNG_PLUGIN}/plugins/org.testng_6.13.1.r201712040515.jar" -JCOMMANDER_JAR="${TESTNG_PLUGIN}/plugins/com.beust.jcommander_1.72.0.jar" TEST_ITER_COUNT=100 PERF_TEMPLATE_FILE="perf_tests.template" diff --git a/test/jdk/jdk/incubator/vector/gen-tests.sh b/test/jdk/jdk/incubator/vector/gen-tests.sh index 0056f54868d..d02f0c519fe 100644 --- a/test/jdk/jdk/incubator/vector/gen-tests.sh +++ b/test/jdk/jdk/incubator/vector/gen-tests.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 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 @@ -28,20 +28,10 @@ # You can regenerate the source files, # and you can clean them up. # FIXME: Move this script under $REPO/make/gensrc/ -list_mech_gen() { - ( # List MG files physically present - grep -il 'mechanically generated.*do not edit' $(find * -name \*.java -print) - # List MG files currently deleted (via --clean) - hg status -nd . - ) | egrep '(^|/)(Byte|Short|Int|Long|Float|Double)(Scalar|([0-9Max]+Vector)).*\.java$' -} case $* in '') CLASS_FILTER='*';; --generate*) CLASS_FILTER=${2-'*'};; ---clean) MG=$(list_mech_gen); set -x; rm -f $MG; exit;; ---revert) MG=$(list_mech_gen); set -x; hg revert $MG; exit;; ---list) list_mech_gen; exit;; ---help|*) echo "Usage: $0 [--generate [file] | --clean | --revert | --list]"; exit 1;; +--help|*) echo "Usage: $0 [--generate [file]]"; exit 1;; esac . config.sh diff --git a/test/jdk/jdk/incubator/vector/run-tests.sh b/test/jdk/jdk/incubator/vector/run-tests.sh deleted file mode 100644 index 0669a97c2e6..00000000000 --- a/test/jdk/jdk/incubator/vector/run-tests.sh +++ /dev/null @@ -1,86 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 2018, 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. 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. -# - -. config.sh - -POSITIONAL=() -while [[ $# -gt 0 ]] -do -key="$1" - -TESTS="" -DISABLE_VECTOR_INTRINSICS=false -case $key in - -t|--tests) - TESTS="$2" - echo "Tests set to $TESTS" - shift # past argument - shift # past value - ;; - -d|--disable-vector-intrinsics) - DISABLE_VECTOR_INTRINSICS=true - echo "Warning: Disabling Vector intrinsics..." - shift # past argument - ;; - *) # unknown option - POSITIONAL+=("$1") # save it in an array for later - shift # past argument - ;; -esac -done -set -- "${POSITIONAL[@]}" # restore positional parameters - - -if [ "$TESTS" == "" ]; then - # Run all the tests by default. - TESTS="Byte64VectorTests,Byte128VectorTests,Byte256VectorTests,Byte512VectorTests," - TESTS+="Int64VectorTests,Int128VectorTests,Int256VectorTests,Int512VectorTests," - TESTS+="Long64VectorTests,Long128VectorTests,Long256VectorTests,Long512VectorTests," - TESTS+="Short64VectorTests,Short128VectorTests,Short256VectorTests,Short512VectorTests," - TESTS+="Double64VectorTests,Double128VectorTests,Double256VectorTests,Double512VectorTests," - TESTS+="Float64VectorTests,Float128VectorTests,Float256VectorTests,Float512VectorTests" -fi - -# Get Java flags. -JAVA_FLAGS="-XX:-TieredCompilation" -if [ "$DISABLE_VECTOR_INTRINSICS" == "true" ]; then - JAVA_FLAGS+=" -XX:-UseVectorApiIntrinsics" -fi - -LogRun false "Running tests $(date)\n" -LogRun true "Running the following tests:\n" -LogRun true "${TESTS}\n" -LogRun false "${JAVA} -cp \"${VECTORTESTS_HOME_CP}${SEPARATOR}${TESTNG_RUN_JAR}${SEPARATOR}${JCOMMANDER_JAR}\" ${JAVA_FLAGS} --add-modules jdk.incubator.vector --add-opens jdk.incubator.vector/jdk.incubator.vector=ALL-UNNAMED org.testng.TestNG -testclass $TESTS" - -# Actual TestNG run. -time ${JAVA} -cp "${VECTORTESTS_HOME_CP}${SEPARATOR}${TESTNG_RUN_JAR}${SEPARATOR}${JCOMMANDER_JAR}" \ - ${JAVA_FLAGS} \ - --add-modules jdk.incubator.vector \ - --add-opens jdk.incubator.vector/jdk.incubator.vector=ALL-UNNAMED \ - -Djdk.incubator.vector.test.loop-iterations=${TEST_ITER_COUNT} \ - org.testng.TestNG -testclass $TESTS -LogRun true "Tests run complete. Please look at test-output/index.html to visualize the results.\n" - diff --git a/test/jdk/jdk/incubator/vector/templates/Kernel-With-Op.template b/test/jdk/jdk/incubator/vector/templates/Kernel-With-Op.template index 11bdbf234cf..95d74b84860 100644 --- a/test/jdk/jdk/incubator/vector/templates/Kernel-With-Op.template +++ b/test/jdk/jdk/incubator/vector/templates/Kernel-With-Op.template @@ -2,9 +2,9 @@ $type$[] r = fr.apply(SPECIES.length()); for (int ic = 0; ic < INVOC_COUNT; ic++) { - for (int i = 0; i < a.length; i += SPECIES.length()) { + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { $abstractvectortype$ av = $abstractvectortype$.fromArray(SPECIES, a, i); - av.withLane(0, ($type$)4).intoArray(r, i); + av.withLane((j++ \& (SPECIES.length()-1)), ($type$)(65535+i)).intoArray(r, i); } } diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-With-Op.template b/test/jdk/jdk/incubator/vector/templates/Unit-With-Op.template index cb44361c094..c41bd05f20e 100644 --- a/test/jdk/jdk/incubator/vector/templates/Unit-With-Op.template +++ b/test/jdk/jdk/incubator/vector/templates/Unit-With-Op.template @@ -2,5 +2,8 @@ @Test(dataProvider = "$type$UnaryOpProvider") static void with$vectorteststype$(IntFunction<$type$ []> fa) { [[KERNEL]] - assertInsertArraysEquals(r, a, ($type$)4, 0); + + for (int i = 0, j = 0; i < a.length; i += SPECIES.length()) { + assertInsertArraysEquals(r, a, ($type$)(65535+i), (j++ & (SPECIES.length()-1)), i , i + SPECIES.length()); + } } diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-header.template b/test/jdk/jdk/incubator/vector/templates/Unit-header.template index 4c0fd5bdfb9..fe0303d1549 100644 --- a/test/jdk/jdk/incubator/vector/templates/Unit-header.template +++ b/test/jdk/jdk/incubator/vector/templates/Unit-header.template @@ -257,10 +257,10 @@ public class $vectorteststype$ extends AbstractVectorTest { } } - static void assertInsertArraysEquals($type$[] r, $type$[] a, $type$ element, int index) { - int i = 0; + static void assertInsertArraysEquals($type$[] r, $type$[] a, $type$ element, int index, int start, int end) { + int i = start; try { - for (; i < a.length; i += 1) { + for (; i < end; i += 1) { if(i%SPECIES.length() == index) { Assert.assertEquals(r[i], element); } else { diff --git a/test/jdk/jdk/internal/platform/docker/GetFreeSwapSpaceSize.java b/test/jdk/jdk/internal/platform/docker/GetFreeSwapSpaceSize.java index efb6a39e479..92b8cf282b7 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 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2020, 2022 THL A29 Limited, a Tencent company. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,16 +24,36 @@ import com.sun.management.OperatingSystemMXBean; import java.lang.management.ManagementFactory; +// Usage: +// GetFreeSwapSpaceSize public class GetFreeSwapSpaceSize { public static void main(String[] args) { - System.out.println("TestGetFreeSwapSpaceSize"); + if (args.length != 4) { + throw new RuntimeException("Unexpected arguments. Expected 4, got " + args.length); + } + String memoryAlloc = args[0]; + long expectedMemory = Long.parseLong(args[1]); + String memorySwapAlloc = args[2]; + long expectedSwap = Long.parseLong(args[3]); + System.out.println("TestGetFreeSwapSpaceSize (memory=" + memoryAlloc + ", memorySwap=" + memorySwapAlloc + ")"); + if (expectedSwap != 0) { + throw new RuntimeException("Precondition of test not met: Expected swap size of 0, got: " + expectedSwap); + } OperatingSystemMXBean osBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); + long osBeanTotalSwap = osBean.getTotalSwapSpaceSize(); + // Premise of this test is to test on a system where --memory and --memory-swap are set to + // the same amount via the container engine (i.e. no swap). In that case the OSBean must + // not report negative values for free swap space. Assert this precondition. + if (osBeanTotalSwap != expectedSwap) { + throw new RuntimeException("OperatingSystemMXBean.getTotalSwapSpaceSize() reported " + osBeanTotalSwap + " expected " + expectedSwap); + } + System.out.println("TestGetFreeSwapSpaceSize precondition met, osBeanTotalSwap = " + expectedSwap + ". Running test... "); for (int i = 0; i < 100; i++) { long size = osBean.getFreeSwapSpaceSize(); if (size < 0) { - System.out.println("Error: getFreeSwapSpaceSize returns " + size); - System.exit(-1); + throw new RuntimeException("Test failed! getFreeSwapSpaceSize returns " + size); } } + System.out.println("TestGetFreeSwapSpaceSize PASSED." ); } } diff --git a/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java b/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java index 319c55ab518..92f3364da10 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 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2020, 2022 THL A29 Limited, a Tencent company. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ import jdk.test.lib.process.OutputAnalyzer; public class TestGetFreeSwapSpaceSize { - private static final String imageName = Common.imageName("memory"); + private static final String imageName = Common.imageName("osbeanSwapSpace"); public static void main(String[] args) throws Exception { if (!DockerTestUtils.canTestDocker()) { @@ -58,17 +58,18 @@ public static void main(String[] args) throws Exception { } private static void testGetFreeSwapSpaceSize(String memoryAllocation, String expectedMemory, - String swapAllocation, String expectedSwap) throws Exception { + String memorySwapAllocation, String expectedSwap) throws Exception { Common.logNewTestCase("TestGetFreeSwapSpaceSize"); DockerRunOptions opts = Common.newOpts(imageName, "GetFreeSwapSpaceSize") + .addClassOptions(memoryAllocation, expectedMemory, memorySwapAllocation, expectedSwap) .addDockerOpts( "--memory", memoryAllocation, - "--memory-swap", swapAllocation + "--memory-swap", memorySwapAllocation ); OutputAnalyzer out = DockerTestUtils.dockerRunJava(opts); out.shouldHaveExitValue(0) - .shouldContain("TestGetFreeSwapSpaceSize"); + .shouldContain("TestGetFreeSwapSpaceSize PASSED."); } } diff --git a/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationInNewTLABEvent.java b/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationInNewTLABEvent.java index d4078a65ecd..6dbd51b1386 100644 --- a/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationInNewTLABEvent.java +++ b/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationInNewTLABEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -30,6 +30,8 @@ import jdk.test.lib.jfr.EventNames; import jdk.test.lib.jfr.Events; import jdk.test.lib.Asserts; +import jdk.test.lib.Platform; +import sun.hotspot.WhiteBox; /** * @test @@ -37,8 +39,16 @@ * @key jfr * @requires vm.hasJFR * @library /test/lib - * @run main/othervm -XX:+UseTLAB -XX:TLABSize=100k -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=1 jdk.jfr.event.allocation.TestObjectAllocationInNewTLABEvent - * @run main/othervm -XX:+UseTLAB -XX:TLABSize=100k -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=1 -Xint jdk.jfr.event.allocation.TestObjectAllocationInNewTLABEvent + * @build sun.hotspot.WhiteBox + * + * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * -XX:+UseTLAB -XX:TLABSize=100k -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=1 + * jdk.jfr.event.allocation.TestObjectAllocationInNewTLABEvent + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * -XX:+UseTLAB -XX:TLABSize=100k -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=1 + * -Xint + * jdk.jfr.event.allocation.TestObjectAllocationInNewTLABEvent */ /** @@ -46,17 +56,19 @@ * an event will be triggered. The test is done for default and interpreted mode (-Xint). * * To force objects to be allocated in a new TLAB: - * the size of TLAB is set to 100k (-XX:TLABSize=100k); - * the size of allocated objects is set to 100k minus 16 bytes overhead; + * the initial size of TLAB is set to 100k (-XX:TLABSize=100k); + * the size of allocated objects is set to 128k; * max TLAB waste at refill is set to minimum (-XX:TLABRefillWasteFraction=1), * to provoke a new TLAB creation. */ public class TestObjectAllocationInNewTLABEvent { private final static String EVENT_NAME = EventNames.ObjectAllocationInNewTLAB; - private static final int BYTE_ARRAY_OVERHEAD = 16; // Extra bytes used by a byte array. - private static final int OBJECT_SIZE = 100 * 1024; - private static final int OBJECT_SIZE_ALT = OBJECT_SIZE + 8; // Object size in case of disabled CompressedOops. + private static final Boolean COMPRESSED_CLASS_PTRS = WhiteBox.getWhiteBox().getBooleanVMFlag("UseCompressedClassPointers"); + + private static final int BYTE_ARRAY_OVERHEAD = (Platform.is64bit() && !COMPRESSED_CLASS_PTRS) ? 24 : 16; + private static final int OBJECT_SIZE = 128 * 1024; + private static final int OBJECTS_TO_ALLOCATE = 100; private static final String BYTE_ARRAY_CLASS_NAME = new byte[0].getClass().getName(); private static final int INITIAL_TLAB_SIZE = 100 * 1024; @@ -112,9 +124,9 @@ private static void verify(RecordedEvent event) { long allocationSize = Events.assertField(event, "allocationSize").atLeast(1L).getValue(); long tlabSize = Events.assertField(event, "tlabSize").atLeast(allocationSize).getValue(); String className = Events.assertField(event, "objectClass.name").notEmpty().getValue(); - if (className.equals(BYTE_ARRAY_CLASS_NAME) && (allocationSize == OBJECT_SIZE || allocationSize == OBJECT_SIZE_ALT)) { + if (className.equals(BYTE_ARRAY_CLASS_NAME) && (allocationSize == OBJECT_SIZE)) { countAllTlabs++; - if (tlabSize == INITIAL_TLAB_SIZE + OBJECT_SIZE || tlabSize == INITIAL_TLAB_SIZE + OBJECT_SIZE_ALT) { + if (tlabSize == INITIAL_TLAB_SIZE + OBJECT_SIZE) { countFullTlabs++; } } diff --git a/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationOutsideTLABEvent.java b/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationOutsideTLABEvent.java index 466a0062ac9..87c3b29af42 100644 --- a/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationOutsideTLABEvent.java +++ b/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationOutsideTLABEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -30,6 +30,8 @@ import jdk.test.lib.jfr.EventNames; import jdk.test.lib.jfr.Events; import jdk.test.lib.Asserts; +import jdk.test.lib.Platform; +import sun.hotspot.WhiteBox; /** * @test @@ -37,8 +39,16 @@ * @key jfr * @requires vm.hasJFR * @library /test/lib - * @run main/othervm -XX:+UseTLAB -XX:TLABSize=90k -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=256 jdk.jfr.event.allocation.TestObjectAllocationOutsideTLABEvent - * @run main/othervm -XX:+UseTLAB -XX:TLABSize=90k -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=256 -Xint jdk.jfr.event.allocation.TestObjectAllocationOutsideTLABEvent + * @build sun.hotspot.WhiteBox + * + * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * -XX:+UseTLAB -XX:TLABSize=90k -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=256 + * jdk.jfr.event.allocation.TestObjectAllocationOutsideTLABEvent + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * -XX:+UseTLAB -XX:TLABSize=90k -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=256 + * -Xint + * jdk.jfr.event.allocation.TestObjectAllocationOutsideTLABEvent */ /** @@ -46,17 +56,19 @@ * Thread Local Allocation Buffer (TLAB). The test is done for default interpreted mode (-Xint). * * To force objects to be allocated outside TLAB: - * the size of TLAB is set to 90k (-XX:TLABSize=90k); - * the size of allocated objects is set to 100k. + * the initial size of TLAB is set to 90k (-XX:TLABSize=90k); + * the size of allocated objects is set to 128k; * max TLAB waste at refill is set to 256 (-XX:TLABRefillWasteFraction=256), * to prevent a new TLAB creation. */ public class TestObjectAllocationOutsideTLABEvent { private static final String EVENT_NAME = EventNames.ObjectAllocationOutsideTLAB; - private static final int BYTE_ARRAY_OVERHEAD = 16; // Extra bytes used by a byte array - private static final int OBJECT_SIZE = 100 * 1024; - private static final int OBJECT_SIZE_ALT = OBJECT_SIZE + 8; // Object size in case of disabled CompressedOops + private static final Boolean COMPRESSED_CLASS_PTRS = WhiteBox.getWhiteBox().getBooleanVMFlag("UseCompressedClassPointers"); + + private static final int BYTE_ARRAY_OVERHEAD = (Platform.is64bit() && !COMPRESSED_CLASS_PTRS) ? 24 : 16; + private static final int OBJECT_SIZE = 128 * 1024; + private static final int OBJECTS_TO_ALLOCATE = 100; private static final String BYTE_ARRAY_CLASS_NAME = new byte[0].getClass().getName(); private static int eventCount; @@ -94,7 +106,7 @@ private static void verify(RecordedEvent event) { } long allocationSize = Events.assertField(event, "allocationSize").atLeast(1L).getValue(); String className = Events.assertField(event, "objectClass.name").notEmpty().getValue(); - if (className.equals(BYTE_ARRAY_CLASS_NAME) && (allocationSize == OBJECT_SIZE || allocationSize == OBJECT_SIZE_ALT)) { + if (className.equals(BYTE_ARRAY_CLASS_NAME) && (allocationSize == OBJECT_SIZE)) { ++eventCount; } } diff --git a/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationSampleEventThrottling.java b/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationSampleEventThrottling.java index 22d03ce57ba..5049acc229c 100644 --- a/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationSampleEventThrottling.java +++ b/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationSampleEventThrottling.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -32,6 +32,8 @@ import jdk.test.lib.jfr.EventNames; import jdk.test.lib.jfr.Events; import jdk.test.lib.Asserts; +import jdk.test.lib.Platform; +import sun.hotspot.WhiteBox; /** * @test @@ -39,15 +41,22 @@ * @key jfr * @requires vm.hasJFR * @library /test/lib -* @run main/othervm -XX:+UseTLAB -XX:TLABSize=2k -XX:-ResizeTLAB jdk.jfr.event.allocation.TestObjectAllocationSampleEventThrottling + * @build sun.hotspot.WhiteBox + * + * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * -XX:+UseTLAB -XX:TLABSize=2k -XX:-ResizeTLAB + * jdk.jfr.event.allocation.TestObjectAllocationSampleEventThrottling */ public class TestObjectAllocationSampleEventThrottling { private static final String EVENT_NAME = EventNames.ObjectAllocationSample; - private static final int BYTE_ARRAY_OVERHEAD = 16; // Extra bytes used by a byte array - private static final int OBJECT_SIZE = 100 * 1024; - private static final int OBJECT_SIZE_ALT = OBJECT_SIZE + 8; // Object size in case of disabled CompressedOops + private static final Boolean COMPRESSED_CLASS_PTRS = WhiteBox.getWhiteBox().getBooleanVMFlag("UseCompressedClassPointers"); + + private static final int BYTE_ARRAY_OVERHEAD = (Platform.is64bit() && !COMPRESSED_CLASS_PTRS) ? 24 : 16; + private static final int OBJECT_SIZE = 128 * 1024; + private static final int OBJECTS_TO_ALLOCATE = 100; private static final String BYTE_ARRAY_CLASS_NAME = new byte[0].getClass().getName(); private static int eventCount; diff --git a/test/jdk/jdk/jfr/event/gc/detailed/TestEvacuationFailedEvent.java b/test/jdk/jdk/jfr/event/gc/detailed/TestEvacuationFailedEvent.java index e1df211851e..23c42a05cab 100644 --- a/test/jdk/jdk/jfr/event/gc/detailed/TestEvacuationFailedEvent.java +++ b/test/jdk/jdk/jfr/event/gc/detailed/TestEvacuationFailedEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -23,43 +23,59 @@ package jdk.jfr.event.gc.detailed; -import java.io.File; -import java.nio.file.Paths; +import java.lang.ref.Reference; import java.util.List; +import jdk.jfr.Recording; import jdk.jfr.consumer.RecordedEvent; -import jdk.jfr.consumer.RecordingFile; import jdk.test.lib.Asserts; +import jdk.test.lib.jfr.EventNames; import jdk.test.lib.jfr.Events; +import sun.hotspot.WhiteBox; + /** * @test * @key jfr + * @bug 8263461 * @requires vm.hasJFR * * @library /test/lib /test/jdk * @requires vm.gc == "G1" | vm.gc == null + * @requires vm.debug * - * @run main jdk.jfr.event.gc.detailed.TestEvacuationFailedEvent + * @build sun.hotspot.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -Xmx32m -Xms32m -XX:+UnlockExperimentalVMOptions -XX:+G1EvacuationFailureALot + * -XX:G1EvacuationFailureALotCount=100 -XX:G1EvacuationFailureALotInterval=1 + * -Xlog:gc=debug -XX:+UseG1GC jdk.jfr.event.gc.detailed.TestEvacuationFailedEvent */ + public class TestEvacuationFailedEvent { - private final static String EVENT_SETTINGS_FILE = System.getProperty("test.src", ".") + File.separator + "evacuationfailed-testsettings.jfc"; - private final static String JFR_FILE = "TestEvacuationFailedEvent.jfr"; - private final static int BYTES_TO_ALLOCATE = 1024 * 512; + private final static String EVENT_NAME = EventNames.EvacuationFailed; public static void main(String[] args) throws Exception { - String[] vmFlags = {"-XX:+UnlockExperimentalVMOptions", "-XX:-UseFastUnorderedTimeStamps", - "-Xmx64m", "-Xmn60m", "-XX:-UseDynamicNumberOfGCThreads", "-XX:ParallelGCThreads=3", - "-XX:MaxTenuringThreshold=0", "-Xlog:gc*=debug", "-XX:+UseG1GC"}; + Recording recording = new Recording(); + // activate the event we are interested in and start recording + recording.enable(EVENT_NAME); + recording.start(); - if (!ExecuteOOMApp.execute(EVENT_SETTINGS_FILE, JFR_FILE, vmFlags, BYTES_TO_ALLOCATE)) { - System.out.println("OOM happened in the other thread(not test thread). Skip test."); - // Skip test, process terminates due to the OOME error in the different thread - return; + Object[] data = new Object[1024]; + + for (int i = 0; i < data.length; i++) { + data[i] = new byte[5 * 1024]; } + // Guarantee one young gc. + WhiteBox.getWhiteBox().youngGC(); + // Keep alive data. + Reference.reachabilityFence(data); + + recording.stop(); - List events = RecordingFile.readAllEvents(Paths.get(JFR_FILE)); + // Verify recording + List events = Events.fromRecording(recording); Events.hasEvents(events); for (RecordedEvent event : events) { @@ -69,5 +85,6 @@ public static void main(String[] args) throws Exception { long totalSize = Events.assertField(event, "evacuationFailed.totalSize").atLeast(firstSize).getValue(); Asserts.assertLessThanOrEqual(smallestSize * objectCount, totalSize, "smallestSize * objectCount <= totalSize"); } + recording.close(); } } diff --git a/test/jdk/jdk/security/jarsigner/JarWithOneNonDisabledDigestAlg.java b/test/jdk/jdk/security/jarsigner/JarWithOneNonDisabledDigestAlg.java new file mode 100644 index 00000000000..899500672ad --- /dev/null +++ b/test/jdk/jdk/security/jarsigner/JarWithOneNonDisabledDigestAlg.java @@ -0,0 +1,169 @@ +/* + * 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 8278851 + * @summary Check that jar entry with at least one non-disabled digest + * algorithm in manifest is treated as signed + * @modules java.base/sun.security.tools.keytool + * @library /test/lib + * @build jdk.test.lib.util.JarUtils + * jdk.test.lib.security.SecurityUtils + * @run main/othervm JarWithOneNonDisabledDigestAlg + */ + +import java.io.InputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.CodeSigner; +import java.security.KeyStore; +import java.util.Enumeration; +import java.util.List; +import java.util.Locale; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.zip.ZipFile; +import jdk.security.jarsigner.JarSigner; + +import jdk.test.lib.util.JarUtils; +import jdk.test.lib.security.SecurityUtils; + +public class JarWithOneNonDisabledDigestAlg { + + private static final String PASS = "changeit"; + private static final String TESTFILE1 = "testfile1"; + private static final String TESTFILE2 = "testfile2"; + + public static void main(String[] args) throws Exception { + SecurityUtils.removeFromDisabledAlgs("jdk.jar.disabledAlgorithms", + List.of("SHA1")); + Files.write(Path.of(TESTFILE1), TESTFILE1.getBytes()); + JarUtils.createJarFile(Path.of("unsigned.jar"), Path.of("."), + Path.of(TESTFILE1)); + + genkeypair("-alias SHA1 -sigalg SHA1withRSA"); + genkeypair("-alias SHA256 -sigalg SHA256withRSA"); + + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + try (FileInputStream fis = new FileInputStream("keystore")) { + ks.load(fis, PASS.toCharArray()); + } + + // Sign JAR twice with same signer but different digest algorithms + // so that each entry in manifest file contains two digest values. + signJarFile(ks, "SHA1", "MD5", "unsigned.jar", "signed.jar"); + signJarFile(ks, "SHA1", "SHA1", "signed.jar", "signed2.jar"); + checkThatJarIsSigned("signed2.jar", false); + + // add another file to the JAR + Files.write(Path.of(TESTFILE2), "testFile2".getBytes()); + JarUtils.updateJarFile(Path.of("signed2.jar"), Path.of("."), + Path.of(TESTFILE2)); + + // Sign again with different signer (SHA256) and SHA-1 digestalg. + // TESTFILE1 should have two signers and TESTFILE2 should have one + // signer. + signJarFile(ks, "SHA256", "SHA1", "signed2.jar", "multi-signed.jar"); + + checkThatJarIsSigned("multi-signed.jar", true); + } + + private static KeyStore.PrivateKeyEntry getEntry(KeyStore ks, String alias) + throws Exception { + + return (KeyStore.PrivateKeyEntry) + ks.getEntry(alias, + new KeyStore.PasswordProtection(PASS.toCharArray())); + } + + private static void genkeypair(String cmd) throws Exception { + cmd = "-genkeypair -keystore keystore -storepass " + PASS + + " -keypass " + PASS + " -keyalg rsa -dname CN=Duke " + cmd; + sun.security.tools.keytool.Main.main(cmd.split(" ")); + } + + private static void signJarFile(KeyStore ks, String alias, + String digestAlg, String inputFile, String outputFile) + throws Exception { + + JarSigner signer = new JarSigner.Builder(getEntry(ks, alias)) + .digestAlgorithm(digestAlg) + .signerName(alias) + .build(); + + try (ZipFile in = new ZipFile(inputFile); + FileOutputStream out = new FileOutputStream(outputFile)) { + signer.sign(in, out); + } + } + + private static void checkThatJarIsSigned(String jarFile, boolean multi) + throws Exception { + + try (JarFile jf = new JarFile(jarFile, true)) { + Enumeration entries = jf.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + if (entry.isDirectory() || isSigningRelated(entry.getName())) { + continue; + } + InputStream is = jf.getInputStream(entry); + while (is.read() != -1); + CodeSigner[] signers = entry.getCodeSigners(); + if (signers == null) { + throw new Exception("JarEntry " + entry.getName() + + " is not signed"); + } else if (multi) { + if (entry.getName().equals(TESTFILE1) && + signers.length != 2) { + throw new Exception("Unexpected number of signers " + + "for " + entry.getName() + ": " + signers.length); + } else if (entry.getName().equals(TESTFILE2) && + signers.length != 1) { + throw new Exception("Unexpected number of signers " + + "for " + entry.getName() + ": " + signers.length); + } + } + } + } + } + + private static boolean isSigningRelated(String name) { + name = name.toUpperCase(Locale.ENGLISH); + if (!name.startsWith("META-INF/")) { + return false; + } + name = name.substring(9); + if (name.indexOf('/') != -1) { + return false; + } + return name.endsWith(".SF") + || name.endsWith(".DSA") + || name.endsWith(".RSA") + || name.endsWith(".EC") + || name.equals("MANIFEST.MF"); + } +} diff --git a/test/jdk/sun/net/ftp/TestFtpTimeValue.java b/test/jdk/sun/net/ftp/TestFtpTimeValue.java index e51837db238..b6120e0288e 100644 --- a/test/jdk/sun/net/ftp/TestFtpTimeValue.java +++ b/test/jdk/sun/net/ftp/TestFtpTimeValue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -116,7 +116,7 @@ private static class FtpServer implements AutoCloseable, Runnable { public void handleClient(Socket client) throws IOException { String str; - client.setSoTimeout(2000); + client.setSoTimeout(10000); BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream())); PrintWriter out = new PrintWriter(client.getOutputStream(), true); out.println("220 FTP serverSocket is ready."); diff --git a/test/jdk/sun/net/www/protocol/http/B6296310.java b/test/jdk/sun/net/www/protocol/http/B6296310.java index 26d0c70ad24..dbb3ead18c5 100644 --- a/test/jdk/sun/net/www/protocol/http/B6296310.java +++ b/test/jdk/sun/net/www/protocol/http/B6296310.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -24,17 +24,30 @@ /* * @test * @bug 6296310 - * @modules java.base/sun.net.www - * @library ../../httptest/ - * @build HttpCallback TestHttpServer HttpTransaction + * @library /test/lib * @run main/othervm B6296310 * @run main/othervm -Djava.net.preferIPv6Addresses=true B6296310 * @summary REGRESSION: AppletClassLoader.getResourceAsStream() behaviour is wrong in some cases */ -import java.net.*; -import java.io.*; -import java.util.*; +import java.io.IOException; +import java.io.OutputStream; +import java.net.CacheRequest; +import java.net.CacheResponse; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.ResponseCache; +import java.net.URI; +import java.net.URL; +import java.net.URLConnection; +import java.util.Map; +import java.util.concurrent.Executors; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; /* * http server returns 200 and content-length=0 @@ -44,7 +57,7 @@ public class B6296310 { static SimpleHttpTransaction httpTrans; - static TestHttpServer server; + static HttpServer server; public static void main(String[] args) throws Exception { @@ -56,31 +69,35 @@ public static void main(String[] args) throws Exception public static void startHttpServer() throws IOException { httpTrans = new SimpleHttpTransaction(); InetAddress loopback = InetAddress.getLoopbackAddress(); - server = new TestHttpServer(httpTrans, 1, 10, loopback, 0); + server = HttpServer.create(new InetSocketAddress(loopback, 0), 10); + server.createContext("/", httpTrans); + server.setExecutor(Executors.newSingleThreadExecutor()); + server.start(); } public static void makeHttpCall() throws IOException { try { - System.out.println("http server listen on: " + server.getLocalPort()); + System.out.println("http server listen on: " + server.getAddress().getPort()); URL url = new URL("http" , InetAddress.getLoopbackAddress().getHostAddress(), - server.getLocalPort(), "/"); + server.getAddress().getPort(), "/"); HttpURLConnection uc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY); System.out.println(uc.getResponseCode()); } finally { - server.terminate(); + server.stop(1); } } } -class SimpleHttpTransaction implements HttpCallback +class SimpleHttpTransaction implements HttpHandler { /* * Our http server which simply retruns a file with no content */ - public void request(HttpTransaction trans) { + @Override + public void handle(HttpExchange trans) { try { - trans.setResponseEntityBody(""); - trans.sendResponse(200, "OK"); + trans.sendResponseHeaders(200, 0); + trans.close(); } catch (Exception e) { e.printStackTrace(); } diff --git a/test/jdk/sun/net/www/protocol/http/RelativeRedirect.java b/test/jdk/sun/net/www/protocol/http/RelativeRedirect.java index 193f25fb1f2..61723197469 100644 --- a/test/jdk/sun/net/www/protocol/http/RelativeRedirect.java +++ b/test/jdk/sun/net/www/protocol/http/RelativeRedirect.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -24,20 +24,32 @@ /** * @test * @bug 4726087 - * @modules java.base/sun.net.www - * @library ../../httptest/ - * @build HttpCallback TestHttpServer ClosedChannelList HttpTransaction - * @run main RelativeRedirect + * @library /test/lib + * @run main/othervm RelativeRedirect * @run main/othervm -Djava.net.preferIPv6Addresses=true RelativeRedirect * @summary URLConnection cannot handle redirects */ -import java.io.*; -import java.net.*; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.net.Authenticator; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.Proxy; +import java.net.URL; +import java.util.concurrent.Executors; -public class RelativeRedirect implements HttpCallback { +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; + +public class RelativeRedirect implements HttpHandler { static int count = 0; - static TestHttpServer server; + static HttpServer server; + static class MyAuthenticator extends Authenticator { public MyAuthenticator () { @@ -50,26 +62,29 @@ public PasswordAuthentication getPasswordAuthentication () } } - void firstReply (HttpTransaction req) throws IOException { - req.addResponseHeader ("Connection", "close"); - req.addResponseHeader ("Location", "/redirect/file.html"); - req.sendResponse (302, "Moved Permamently"); - req.orderlyClose(); + void firstReply(HttpExchange req) throws IOException { + req.getResponseHeaders().set("Connection", "close"); + req.getResponseHeaders().set("Location", "/redirect/file.html"); + req.sendResponseHeaders(302, -1); } - void secondReply (HttpTransaction req) throws IOException { + void secondReply (HttpExchange req) throws IOException { if (req.getRequestURI().toString().equals("/redirect/file.html") && - req.getRequestHeader("Host").equals(authority(server.getLocalPort()))) { - req.setResponseEntityBody ("Hello ."); - req.sendResponse (200, "Ok"); + req.getRequestHeaders().get("Host").get(0).equals(authority(server.getAddress().getPort()))) { + req.sendResponseHeaders(200, 0); + try(PrintWriter pw = new PrintWriter(req.getResponseBody())) { + pw.print("Hello ."); + } } else { - req.setResponseEntityBody (req.getRequestURI().toString()); - req.sendResponse (400, "Bad request"); + req.sendResponseHeaders(400, 0); + try(PrintWriter pw = new PrintWriter(req.getResponseBody())) { + pw.print(req.getRequestURI().toString()); + } } - req.orderlyClose(); - } - public void request (HttpTransaction req) { + + @Override + public void handle (HttpExchange req) { try { switch (count) { case 0: @@ -101,9 +116,12 @@ public static void main (String[] args) throws Exception { MyAuthenticator auth = new MyAuthenticator (); Authenticator.setDefault (auth); try { - server = new TestHttpServer (new RelativeRedirect(), 1, 10, loopback, 0); - System.out.println ("Server: listening on port: " + server.getLocalPort()); - URL url = new URL("http://" + authority(server.getLocalPort())); + server = HttpServer.create(new InetSocketAddress(loopback, 0), 10); + server.createContext("/", new RelativeRedirect()); + server.setExecutor(Executors.newSingleThreadExecutor()); + server.start(); + System.out.println ("Server: listening on port: " + server.getAddress().getPort()); + URL url = new URL("http://" + authority(server.getAddress().getPort())); System.out.println ("client opening connection to: " + url); HttpURLConnection urlc = (HttpURLConnection)url.openConnection (Proxy.NO_PROXY); InputStream is = urlc.getInputStream (); @@ -112,7 +130,7 @@ public static void main (String[] args) throws Exception { throw new RuntimeException(e); } finally { if (server != null) { - server.terminate(); + server.stop(1); } } } diff --git a/test/jdk/sun/net/www/protocol/http/ResponseCacheStream.java b/test/jdk/sun/net/www/protocol/http/ResponseCacheStream.java index 89a7f8afc4a..841279fa76d 100644 --- a/test/jdk/sun/net/www/protocol/http/ResponseCacheStream.java +++ b/test/jdk/sun/net/www/protocol/http/ResponseCacheStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -25,33 +25,48 @@ * @test * @bug 6262486 * @library /test/lib - * @modules java.base/sun.net.www - * @library ../../httptest/ - * @build HttpCallback TestHttpServer ClosedChannelList HttpTransaction * @run main/othervm -Dhttp.keepAlive=false ResponseCacheStream * @summary COMPATIBILITY: jagex_com - Monkey Puzzle applet fails to load */ -import java.net.*; -import java.io.*; -import java.util.*; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.net.CacheRequest; +import java.net.CacheResponse; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ResponseCache; +import java.net.URI; +import java.net.URL; +import java.net.URLConnection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executors; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; import jdk.test.lib.net.URIBuilder; -public class ResponseCacheStream implements HttpCallback { +public class ResponseCacheStream implements HttpHandler { - void okReply (HttpTransaction req) throws IOException { - req.setResponseEntityBody ("Hello, This is the response body. Let's make it as long as possible since we need to test the cache mechanism."); - req.sendResponse (200, "Ok"); - System.out.println ("Server: sent response"); - req.orderlyClose(); + void okReply (HttpExchange req) throws IOException { + req.sendResponseHeaders(200, 0); + try(PrintWriter pw = new PrintWriter(req.getResponseBody())) { + pw.print("Hello, This is the response body. Let's make it as long as possible since we need to test the cache mechanism."); + } + System.out.println ("Server: sent response"); } - public void request (HttpTransaction req) { - try { - okReply (req); - } catch (IOException e) { - e.printStackTrace(); - } + + @Override + public void handle(HttpExchange exchange) throws IOException { + okReply(exchange); + exchange.close(); } static class MyCacheRequest extends CacheRequest { @@ -94,19 +109,22 @@ public byte[] getBuffer() { } } - static TestHttpServer server; + static HttpServer server; public static void main(String[] args) throws Exception { MyResponseCache cache = new MyResponseCache(); try { InetAddress loopback = InetAddress.getLoopbackAddress(); ResponseCache.setDefault(cache); - server = new TestHttpServer (new ResponseCacheStream(), loopback, 0); - System.out.println ("Server: listening on port: " + server.getLocalPort()); + server = HttpServer.create(new InetSocketAddress(loopback, 0), 10); + server.createContext("/", new ResponseCacheStream()); + server.setExecutor(Executors.newSingleThreadExecutor()); + server.start(); + System.out.println("Server: listening on port: " + server.getAddress().getPort()); URL url = URIBuilder.newBuilder() .scheme("http") .loopback() - .port(server.getLocalPort()) + .port(server.getAddress().getPort()) .path("/") .toURL(); System.out.println ("Client: connecting to " + url); @@ -149,10 +167,10 @@ public static void main(String[] args) throws Exception { } } catch (Exception e) { if (server != null) { - server.terminate(); + server.stop(1); } throw e; } - server.terminate(); + server.stop(1); } } diff --git a/test/jdk/sun/net/www/protocol/http/SetChunkedStreamingMode.java b/test/jdk/sun/net/www/protocol/http/SetChunkedStreamingMode.java index bda2e404108..2d6ef48db56 100644 --- a/test/jdk/sun/net/www/protocol/http/SetChunkedStreamingMode.java +++ b/test/jdk/sun/net/www/protocol/http/SetChunkedStreamingMode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -24,56 +24,54 @@ /** * @test * @bug 5049976 - * @modules java.base/sun.net.www - * @library ../../httptest/ * @library /test/lib - * @build HttpCallback TestHttpServer ClosedChannelList HttpTransaction - * @run main SetChunkedStreamingMode + * @run main/othervm SetChunkedStreamingMode * @summary Unspecified NPE is thrown when streaming output mode is enabled */ -import java.io.*; -import java.net.*; -import jdk.test.lib.net.URIBuilder; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.URL; +import java.util.concurrent.Executors; -public class SetChunkedStreamingMode implements HttpCallback { +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import jdk.test.lib.net.URIBuilder; - void okReply (HttpTransaction req) throws IOException { - req.setResponseEntityBody ("Hello ."); - req.sendResponse (200, "Ok"); - System.out.println ("Server: sent response"); - req.orderlyClose(); - } +public class SetChunkedStreamingMode implements HttpHandler { - public void request (HttpTransaction req) { - try { - okReply (req); - } catch (IOException e) { - e.printStackTrace(); + void okReply (HttpExchange req) throws IOException { + req.sendResponseHeaders(200, 0); + try(PrintWriter pw = new PrintWriter(req.getResponseBody())) { + pw.print("Hello ."); } + System.out.println ("Server: sent response"); } - static void read (InputStream is) throws IOException { - int c; - System.out.println ("reading"); - while ((c=is.read()) != -1) { - System.out.write (c); - } - System.out.println (""); - System.out.println ("finished reading"); + @Override + public void handle(HttpExchange exchange) throws IOException { + okReply(exchange); } - static TestHttpServer server; + static HttpServer server; public static void main (String[] args) throws Exception { try { - server = new TestHttpServer(new SetChunkedStreamingMode(), 1, 10, - InetAddress.getLoopbackAddress(), 0); - System.out.println ("Server: listening on port: " + server.getLocalPort()); + InetAddress loopback = InetAddress.getLoopbackAddress(); + server = HttpServer.create(new InetSocketAddress(loopback, 0), 10); + server.createContext("/", new SetChunkedStreamingMode()); + server.setExecutor(Executors.newSingleThreadExecutor()); + server.start(); + System.out.println ("Server: listening on port: " + server.getAddress().getPort()); URL url = URIBuilder.newBuilder() .scheme("http") .loopback() - .port(server.getLocalPort()) + .port(server.getAddress().getPort()) .path("/") .toURL(); System.out.println ("Client: connecting to " + url); @@ -84,15 +82,15 @@ public static void main (String[] args) throws Exception { InputStream is = urlc.getInputStream(); } catch (Exception e) { if (server != null) { - server.terminate(); + server.stop(1); } throw e; } - server.terminate(); + server.stop(1); } public static void except (String s) { - server.terminate(); + server.stop(1); throw new RuntimeException (s); } } diff --git a/test/jdk/sun/security/ec/ECDSAJavaVerify.java b/test/jdk/sun/security/ec/ECDSAJavaVerify.java deleted file mode 100644 index 77aad015b8b..00000000000 --- a/test/jdk/sun/security/ec/ECDSAJavaVerify.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import com.sun.jdi.Bootstrap; -import com.sun.jdi.VMDisconnectedException; -import com.sun.jdi.VirtualMachine; -import com.sun.jdi.connect.Connector; -import com.sun.jdi.connect.LaunchingConnector; -import com.sun.jdi.event.Event; -import com.sun.jdi.event.EventSet; -import com.sun.jdi.event.MethodEntryEvent; -import com.sun.jdi.request.MethodEntryRequest; - -import java.security.AlgorithmParameters; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.SecureRandom; -import java.security.Signature; -import java.security.SignatureException; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.ECPublicKey; -import java.security.spec.ECGenParameterSpec; -import java.security.spec.ECParameterSpec; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Random; - -/* - * @test - * @bug 8237218 8239928 - * @modules jdk.crypto.ec - * jdk.jdi - * @requires os.family != "windows" - * @run main ECDSAJavaVerify debug - * @summary Support NIST Curves verification in java implementation. - * This test does not run stable on Windows. VMDisconnectedException - * might not be thrown at all. - */ - -// ATTENTION: This test depends on method names inside the non-exported -// class sun.security.ec.ECDSASignature. -public class ECDSAJavaVerify { - - static final String[] ALL_ALGS = new String[] { - "SHA1withECDSA", "SHA256withECDSA", "SHA384withECDSA", "SHA512withECDSA"}; - - static final String[] ALL_CURVES = new String[] { - "secp256r1", "secp384r1", "secp521r1"}; - - public static void main(String[] args) throws Exception { - if (args.length == 1) { - // Debugging a new process with no arg - debug(); - } else if (args.length == 3) { - // If one test case fail, re-run it with first 3 columns - new Test().run(Integer.parseInt(args[0]), args[1], args[2]); - } else { - // Run all test cases - Test t = new Test(); - Random r = new Random(); - - for (String sigAlg : ALL_ALGS) { - for (String curve : ALL_CURVES) { - t.run(r.nextInt(1000000), sigAlg, curve); - } - } - } - } - - static void debug() throws Exception { - - LaunchingConnector launchingConnector = Bootstrap - .virtualMachineManager().defaultConnector(); - - Map arguments - = launchingConnector.defaultArguments(); - arguments.get("main").setValue(ECDSAJavaVerify.class.getName()); - arguments.get("options").setValue( - "-cp " + System.getProperty("test.classes")); - VirtualMachine vm = launchingConnector.launch(arguments); - - MethodEntryRequest req = vm.eventRequestManager() - .createMethodEntryRequest(); - req.addClassFilter("sun.security.ec.ECDSASignature"); - req.enable(); - - int numberOfTests = ALL_ALGS.length * ALL_CURVES.length * 2; - - // Expected methods to call. 'J' for java impl, 'N' for native impl - char[] expected = new char[numberOfTests]; - - int pos = 0; - for (String dummy : ALL_ALGS) { - for (String curve : ALL_CURVES) { - char caller = 'J'; - // For each case, Signature::verify is called twice - expected[pos++] = caller; - expected[pos++] = caller; - } - } - - // Test result - // '.': not run yet - // '-': enter engineVerify - // 'v': expected impl called - // 'x': unexpected impl called - // Note: some error cases fail before any impl called. Ex: if there - // is a DER encoding error. - char[] result = new char[numberOfTests]; - Arrays.fill(result, '.'); - - String stdout, stderr; - - try { - EventSet eventSet; - pos = -1; // will become 0 when entering 'engineVerify' - while ((eventSet = vm.eventQueue().remove()) != null) { - for (Event event : eventSet) { - if (event instanceof MethodEntryEvent) { - MethodEntryEvent e = (MethodEntryEvent)event; - switch (e.method().name()) { - case "engineVerify": - result[++pos] = '-'; - break; - case "verifySignedDigestImpl": // the java impl - result[pos] = expected[pos] != 'J' ? 'x' : 'v'; - break; - } - } - vm.resume(); - } - } - } catch (VMDisconnectedException e) { - System.out.println("Virtual Machine is disconnected."); - } finally { - stderr = new String(vm.process().getErrorStream().readAllBytes()); - stdout = new String(vm.process().getInputStream().readAllBytes()); - } - - int exitCode = vm.process().waitFor(); - System.out.println(" exit: " + exitCode); - System.out.println("stderr:\n" + stderr); - System.out.println("stdout:\n" + stdout); - - String sResult = new String(result); - - System.out.println(" Cases: " + new String(expected)); - System.out.println("Result: " + sResult); - - if (pos != numberOfTests - 1 || sResult.contains("x") - || sResult.contains(".")) { - throw new Exception("Unexpected result"); - } - - if (stdout.contains("fail") || exitCode != 0) { - throw new Exception("Test failed"); - } - } - - static class Test { - - public boolean run(int seed, String sigAlg, String curve) - throws Exception { - - // A determined SecureRandom based on seed. If there is anything - // wrong, we can reproduce the problem using the seed. - Random r = new Random(seed); - SecureRandom rand = new SecureRandom() { - @Override - public void nextBytes(byte[] bytes) { - r.nextBytes(bytes); - } - }; - - AlgorithmParameters ap = AlgorithmParameters.getInstance("EC", "SunEC"); - ap.init(new ECGenParameterSpec(curve)); - ECParameterSpec spec = ap.getParameterSpec(ECParameterSpec.class); - - KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", "SunEC"); - kpg.initialize(spec, rand); - KeyPair kp = kpg.generateKeyPair(); - ECPrivateKey ecPrivateKey = (ECPrivateKey) kp.getPrivate(); - ECPublicKey ecPublicKey = (ECPublicKey) kp.getPublic(); - - Signature s1 = Signature.getInstance(sigAlg, "SunEC"); - s1.initSign(ecPrivateKey, rand); - byte[] msg = new byte[1234]; - rand.nextBytes(msg); - s1.update(msg); - byte[] sig = s1.sign(); - - Signature s2 = Signature.getInstance(sigAlg, "SunEC"); - s2.initVerify(ecPublicKey); - s2.update(msg); - - boolean result1 = s2.verify(sig); - - s2.initVerify(ecPublicKey); - // modify the signature in some random manner - if (rand.nextInt(10) < 8) { - sig[rand.nextInt(10000) % sig.length] - = (byte) rand.nextInt(10000); - } else { - int newLength = rand.nextInt(100); - if (newLength == sig.length) { - newLength += 1 + rand.nextInt(2); - } - sig = Arrays.copyOf(sig, newLength); - } - - boolean result2; - try { - result2 = s2.verify(sig); - } catch (SignatureException se) { - result2 = false; - } - - boolean finalResult = result1 && !result2; - System.out.printf("%10d %20s %20s -- %5s %5s -- %s\n", - seed, sigAlg, curve, result1, result2, - finalResult ? "succeed" : "fail"); - - return finalResult; - } - } -} diff --git a/test/jdk/sun/security/krb5/auto/HttpsCB.java b/test/jdk/sun/security/krb5/auto/HttpsCB.java new file mode 100644 index 00000000000..293d037eb5a --- /dev/null +++ b/test/jdk/sun/security/krb5/auto/HttpsCB.java @@ -0,0 +1,324 @@ +/* + * 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 8279842 8282293 + * @modules java.base/sun.security.util + * java.security.jgss/sun.security.jgss + * java.security.jgss/sun.security.jgss.krb5 + * java.security.jgss/sun.security.jgss.krb5.internal + * java.security.jgss/sun.security.krb5.internal:+open + * java.security.jgss/sun.security.krb5:+open + * java.security.jgss/sun.security.krb5.internal.ccache + * java.security.jgss/sun.security.krb5.internal.crypto + * java.security.jgss/sun.security.krb5.internal.ktab + * jdk.security.auth + * jdk.security.jgss + * jdk.httpserver + * @summary HTTPS Channel Binding support for Java GSS/Kerberos + * @library /test/lib + * @run main jdk.test.lib.FileInstaller TestHosts TestHosts + * @run main/othervm -Djdk.net.hosts.file=TestHosts + * -Djdk.https.negotiate.cbt=always HttpsCB true true + * @run main/othervm -Djdk.net.hosts.file=TestHosts + * -Djdk.https.negotiate.cbt=never HttpsCB false true + * @run main/othervm -Djdk.net.hosts.file=TestHosts + * -Djdk.https.negotiate.cbt=invalid HttpsCB false true + * @run main/othervm -Djdk.net.hosts.file=TestHosts + * HttpsCB false true + * @run main/othervm -Djdk.net.hosts.file=TestHosts + * -Djdk.https.negotiate.cbt=domain:other.com HttpsCB false true + * @run main/othervm -Djdk.net.hosts.file=TestHosts + * -Djdk.https.negotiate.cbt=domain:host.web.domain HttpsCB true true + * @run main/othervm -Djdk.net.hosts.file=TestHosts + * -Djdk.https.negotiate.cbt=domain:HOST.WEB.DOMAIN HttpsCB true true + * @run main/othervm -Djdk.net.hosts.file=TestHosts + * -Djdk.https.negotiate.cbt=domain:*.web.domain HttpsCB true true + * @run main/othervm -Djdk.net.hosts.file=TestHosts + * -Djdk.https.negotiate.cbt=domain:*.WEB.Domain HttpsCB true true + * @run main/othervm -Djdk.net.hosts.file=TestHosts + * -Djdk.https.negotiate.cbt=domain:*.Invalid,*.WEB.Domain HttpsCB true true + */ + +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.HttpPrincipal; +import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsExchange; +import com.sun.net.httpserver.HttpsServer; +import com.sun.security.auth.module.Krb5LoginModule; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.Proxy; +import java.net.Socket; +import java.net.URL; +import java.security.cert.X509Certificate; +import java.security.PrivilegedExceptionAction; +import java.util.HashMap; +import java.util.Map; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509ExtendedTrustManager; +import javax.security.auth.Subject; + +import jdk.test.lib.Asserts; +import jdk.test.lib.net.SimpleSSLContext; +import org.ietf.jgss.GSSContext; +import org.ietf.jgss.GSSCredential; +import org.ietf.jgss.GSSManager; +import sun.security.jgss.GSSUtil; +import sun.security.jgss.krb5.internal.TlsChannelBindingImpl; +import sun.security.krb5.Config; +import sun.security.util.TlsChannelBinding; + +import java.util.Base64; +import java.util.concurrent.Callable; + +public class HttpsCB { + + final static String REALM_WEB = "WEB.DOMAIN"; + final static String KRB5_CONF = "web.conf"; + final static String KRB5_TAB = "web.ktab"; + + final static String WEB_USER = "web"; + final static char[] WEB_PASS = "webby".toCharArray(); + final static String WEB_HOST = "host.web.domain"; + final static String CONTENT = "Hello, World!"; + + static int webPort; + static URL cbtURL; + static URL normalURL; + + public static void main(String[] args) + throws Exception { + + boolean expectCBT = Boolean.parseBoolean(args[0]); + boolean expectNoCBT = Boolean.parseBoolean(args[1]); + + System.setProperty("sun.security.krb5.debug", "true"); + + KDC kdcw = KDC.create(REALM_WEB); + kdcw.addPrincipal(WEB_USER, WEB_PASS); + kdcw.addPrincipalRandKey("krbtgt/" + REALM_WEB); + kdcw.addPrincipalRandKey("HTTP/" + WEB_HOST); + + KDC.saveConfig(KRB5_CONF, kdcw, + "default_keytab_name = " + KRB5_TAB, + "[domain_realm]", + "", + ".web.domain="+REALM_WEB); + + System.setProperty("java.security.krb5.conf", KRB5_CONF); + Config.refresh(); + KDC.writeMultiKtab(KRB5_TAB, kdcw); + + // Write a customized JAAS conf file, so that any kinit cache + // will be ignored. + System.setProperty("java.security.auth.login.config", OneKDC.JAAS_CONF); + File f = new File(OneKDC.JAAS_CONF); + FileOutputStream fos = new FileOutputStream(f); + fos.write(( + "com.sun.security.jgss.krb5.initiate {\n" + + " com.sun.security.auth.module.Krb5LoginModule required;\n};\n" + ).getBytes()); + fos.close(); + + HttpServer h1 = httpd("Negotiate", + "HTTP/" + WEB_HOST + "@" + REALM_WEB, KRB5_TAB); + webPort = h1.getAddress().getPort(); + + cbtURL = new URL("https://" + WEB_HOST +":" + webPort + "/cbt"); + normalURL = new URL("https://" + WEB_HOST +":" + webPort + "/normal"); + + java.net.Authenticator.setDefault(new java.net.Authenticator() { + public PasswordAuthentication getPasswordAuthentication () { + return new PasswordAuthentication( + WEB_USER+"@"+REALM_WEB, WEB_PASS); + } + }); + + // Client-side SSLContext needs to ignore hostname mismatch + // and untrusted certificate. + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, new TrustManager[] { + new X509ExtendedTrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; + } + public void checkClientTrusted(X509Certificate[] chain, + String authType, Socket socket) { } + public void checkServerTrusted(X509Certificate[] chain, + String authType, Socket socket) { } + public void checkClientTrusted(X509Certificate[] chain, + String authType, SSLEngine engine) { } + public void checkServerTrusted(X509Certificate[] chain, + String authType, SSLEngine engine) { } + public void checkClientTrusted(X509Certificate[] certs, + String authType) { } + public void checkServerTrusted(X509Certificate[] certs, + String authType) { } + } + }, null); + + Asserts.assertEQ(visit(sc, cbtURL), expectCBT); + Asserts.assertEQ(visit(sc, normalURL), expectNoCBT); + } + + static boolean visit(SSLContext sc, URL url) { + try { + HttpsURLConnection conn = (HttpsURLConnection) + url.openConnection(Proxy.NO_PROXY); + conn.setSSLSocketFactory(sc.getSocketFactory()); + BufferedReader reader; + reader = new BufferedReader(new InputStreamReader( + conn.getInputStream())); + return reader.readLine().equals(CONTENT); + } catch (IOException e) { + e.printStackTrace(System.out); + return false; + } + } + + static HttpServer httpd(String scheme, String principal, String ktab) + throws Exception { + MyHttpHandler h = new MyHttpHandler(); + HttpsServer server = HttpsServer.create(new InetSocketAddress(0), 0); + server.setHttpsConfigurator( + new HttpsConfigurator(new SimpleSSLContext().get())); + server.createContext("/", h).setAuthenticator( + new MyServerAuthenticator(scheme, principal, ktab)); + server.start(); + return server; + } + + static class MyHttpHandler implements HttpHandler { + public void handle(HttpExchange t) throws IOException { + t.sendResponseHeaders(200, 0); + t.getResponseBody().write(CONTENT.getBytes()); + t.close(); + } + } + + static class MyServerAuthenticator + extends com.sun.net.httpserver.Authenticator { + Subject s = new Subject(); + GSSManager m; + GSSCredential cred; + String scheme = null; + String reqHdr = "WWW-Authenticate"; + String respHdr = "Authorization"; + int err = HttpURLConnection.HTTP_UNAUTHORIZED; + + public MyServerAuthenticator(String scheme, + String principal, String ktab) throws Exception { + + this.scheme = scheme; + Krb5LoginModule krb5 = new Krb5LoginModule(); + Map map = new HashMap<>(); + Map shared = new HashMap<>(); + + map.put("storeKey", "true"); + map.put("isInitiator", "false"); + map.put("useKeyTab", "true"); + map.put("keyTab", ktab); + map.put("principal", principal); + krb5.initialize(s, null, shared, map); + krb5.login(); + krb5.commit(); + m = GSSManager.getInstance(); + cred = Subject.doAs(s, new PrivilegedExceptionAction() { + @Override + public GSSCredential run() throws Exception { + System.err.println("Creating GSSCredential"); + return m.createCredential( + null, + GSSCredential.INDEFINITE_LIFETIME, + MyServerAuthenticator.this.scheme + .equalsIgnoreCase("Negotiate") ? + GSSUtil.GSS_SPNEGO_MECH_OID : + GSSUtil.GSS_KRB5_MECH_OID, + GSSCredential.ACCEPT_ONLY); + } + }); + } + + @Override + public Result authenticate(HttpExchange exch) { + // The GSContext is stored in an HttpContext attribute named + // "GSSContext" and is created at the first request. + GSSContext c = null; + String auth = exch.getRequestHeaders().getFirst(respHdr); + try { + c = (GSSContext)exch.getHttpContext() + .getAttributes().get("GSSContext"); + if (auth == null) { // First request + Headers map = exch.getResponseHeaders(); + map.set (reqHdr, scheme); // Challenge! + c = Subject.doAs(s, new PrivilegedExceptionAction() { + @Override + public GSSContext run() throws Exception { + return m.createContext(cred); + } + }); + // CBT is required for cbtURL + if (exch instanceof HttpsExchange sexch + && exch.getRequestURI().toString().equals("/cbt")) { + TlsChannelBinding b = TlsChannelBinding.create( + (X509Certificate) sexch.getSSLSession() + .getLocalCertificates()[0]); + c.setChannelBinding( + new TlsChannelBindingImpl(b.getData())); + } + exch.getHttpContext().getAttributes().put("GSSContext", c); + return new com.sun.net.httpserver.Authenticator.Retry(err); + } else { // Later requests + byte[] token = Base64.getMimeDecoder() + .decode(auth.split(" ")[1]); + token = c.acceptSecContext(token, 0, token.length); + Headers map = exch.getResponseHeaders(); + map.set (reqHdr, scheme + " " + Base64.getMimeEncoder() + .encodeToString(token).replaceAll("\\s", "")); + if (c.isEstablished()) { + return new com.sun.net.httpserver.Authenticator.Success( + new HttpPrincipal(c.getSrcName().toString(), "")); + } else { + return new com.sun.net.httpserver.Authenticator.Retry(err); + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } +} diff --git a/test/jdk/sun/security/krb5/auto/IgnoreChannelBinding.java b/test/jdk/sun/security/krb5/auto/IgnoreChannelBinding.java index a9760dae9ad..a393c299b70 100644 --- a/test/jdk/sun/security/krb5/auto/IgnoreChannelBinding.java +++ b/test/jdk/sun/security/krb5/auto/IgnoreChannelBinding.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 6851973 8194486 + * @bug 6851973 8194486 8279520 * @summary ignore incoming channel binding if acceptor does not set one * @library /test/lib * @run main jdk.test.lib.FileInstaller TestHosts TestHosts @@ -33,6 +33,7 @@ import java.net.InetAddress; import org.ietf.jgss.ChannelBinding; import org.ietf.jgss.GSSException; +import org.ietf.jgss.Oid; import sun.security.jgss.GSSUtil; public class IgnoreChannelBinding { @@ -41,33 +42,38 @@ public static void main(String[] args) throws Exception { new OneKDC(null).writeJAASConf(); + test(GSSUtil.GSS_KRB5_MECH_OID); + test(GSSUtil.GSS_SPNEGO_MECH_OID); + } + + static void test(Oid mech) throws Exception { Context c = Context.fromJAAS("client"); Context s = Context.fromJAAS("server"); // All silent - c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID); - s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); + c.startAsClient(OneKDC.SERVER, mech); + s.startAsServer(mech); Context.handshake(c, s); // Initiator req, acceptor ignore - c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID); + c.startAsClient(OneKDC.SERVER, mech); c.x().setChannelBinding(new ChannelBinding( InetAddress.getByName("client.rabbit.hole"), InetAddress.getByName("host.rabbit.hole"), new byte[0] )); - s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); + s.startAsServer(mech); Context.handshake(c, s); // Both req, and match - c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID); + c.startAsClient(OneKDC.SERVER, mech); c.x().setChannelBinding(new ChannelBinding( InetAddress.getByName("client.rabbit.hole"), InetAddress.getByName("host.rabbit.hole"), new byte[0] )); - s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); + s.startAsServer(mech); s.x().setChannelBinding(new ChannelBinding( InetAddress.getByName("client.rabbit.hole"), InetAddress.getByName("host.rabbit.hole"), @@ -76,13 +82,13 @@ public static void main(String[] args) Context.handshake(c, s); // Both req, NOT match - c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID); + c.startAsClient(OneKDC.SERVER, mech); c.x().setChannelBinding(new ChannelBinding( InetAddress.getByName("client.rabbit.hole"), InetAddress.getByName("host.rabbit.hole"), new byte[0] )); - s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); + s.startAsServer(mech); s.x().setChannelBinding(new ChannelBinding( InetAddress.getByName("client.rabbit.hole"), InetAddress.getByName("host.rabbit.hole"), @@ -96,8 +102,8 @@ public static void main(String[] args) } // Acceptor req, reject - c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID); - s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); + c.startAsClient(OneKDC.SERVER, mech); + s.startAsServer(mech); s.x().setChannelBinding(new ChannelBinding( InetAddress.getByName("client.rabbit.hole"), InetAddress.getByName("host.rabbit.hole"), diff --git a/test/jdk/sun/security/pkcs11/rsa/TestP11KeyFactoryGetRSAKeySpec.java b/test/jdk/sun/security/pkcs11/rsa/TestP11KeyFactoryGetRSAKeySpec.java index ee847c56d87..07f07f78812 100644 --- a/test/jdk/sun/security/pkcs11/rsa/TestP11KeyFactoryGetRSAKeySpec.java +++ b/test/jdk/sun/security/pkcs11/rsa/TestP11KeyFactoryGetRSAKeySpec.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, Amazon.com, Inc. or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -21,7 +22,6 @@ * questions. */ -import java.math.BigInteger; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; @@ -86,7 +86,7 @@ public void main(Provider p) throws Exception { private static void testKeySpec(KeyFactory factory, PrivateKey key, Class specClass) throws Exception { try { - KeySpec spec = factory.getKeySpec(key, RSAPrivateKeySpec.class); + KeySpec spec = factory.getKeySpec(key, specClass); if (testingSensitiveKeys) { throw new Exception("Able to retrieve spec from sensitive key"); } diff --git a/test/jdk/sun/security/util/RegisteredDomain/ParseNames.java b/test/jdk/sun/security/util/RegisteredDomain/ParseNames.java index 7b9433bbac9..69ca9577c68 100644 --- a/test/jdk/sun/security/util/RegisteredDomain/ParseNames.java +++ b/test/jdk/sun/security/util/RegisteredDomain/ParseNames.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8228969 8244087 + * @bug 8228969 8244087 8255266 * @modules java.base/sun.security.util * @summary unit test for RegisteredDomain */ diff --git a/test/jdk/sun/security/util/RegisteredDomain/tests.dat b/test/jdk/sun/security/util/RegisteredDomain/tests.dat index da9fba064fb..e4cf659c634 100644 --- a/test/jdk/sun/security/util/RegisteredDomain/tests.dat +++ b/test/jdk/sun/security/util/RegisteredDomain/tests.dat @@ -56,6 +56,11 @@ biz biz null site.biz biz site.biz w.site.biz biz site.biz +# br +br br null +dev.br dev.br null +x.dev.br dev.br x.dev.br + # cn (unicode) # foo.mil.cn mil.cn foo.mil.cn diff --git a/test/jdk/tools/jar/JarEntryTime.java b/test/jdk/tools/jar/JarEntryTime.java index 80fd65fba5c..4d84547d074 100644 --- a/test/jdk/tools/jar/JarEntryTime.java +++ b/test/jdk/tools/jar/JarEntryTime.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -23,7 +23,7 @@ /** * @test - * @bug 4225317 6969651 + * @bug 4225317 6969651 8277422 * @modules jdk.jartool * @summary Check extracted files have date as per those in the .jar file */ @@ -31,6 +31,7 @@ import java.io.File; import java.io.PrintWriter; import java.nio.file.attribute.FileTime; +import java.time.ZoneId; import java.util.Date; import java.util.TimeZone; import java.util.spi.ToolProvider; @@ -93,6 +94,14 @@ public static void realMain(String[] args) throws Throwable { jarFile.delete(); testFile.delete(); + var date = new Date(); + var defZone = ZoneId.systemDefault(); + if (defZone.getRules().getTransition( + date.toInstant().atZone(defZone).toLocalDateTime()) != null) { + System.out.println("At the offset transition. JarEntryTime test skipped."); + return; + } + /* Create a directory structure * outer/ * inner/ diff --git a/test/jdk/tools/launcher/FXLauncherTest.java b/test/jdk/tools/launcher/FXLauncherTest.java index 1f06db1e481..9cc4b5aea98 100644 --- a/test/jdk/tools/launcher/FXLauncherTest.java +++ b/test/jdk/tools/launcher/FXLauncherTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -360,6 +360,10 @@ static void testExtendFXApp(boolean useCP, boolean setFXMainClass) throws Except */ @Test static void testMissingMC() throws Exception { + if (!isEnglishLocale()) { + return; + } + String testname = "testMissingMC"; testcount++; line(); diff --git a/test/jdk/tools/launcher/SourceMode.java b/test/jdk/tools/launcher/SourceMode.java index 185776db44e..893a00d48ce 100644 --- a/test/jdk/tools/launcher/SourceMode.java +++ b/test/jdk/tools/launcher/SourceMode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -200,6 +200,10 @@ void testClasspath() throws IOException { // java --add-exports=... Export.java --help @Test void testAddExports() throws IOException { + if (!isEnglishLocale()) { + return; + } + starting("testAddExports"); Path exportJava = Paths.get("Export.java"); createFile(exportJava, List.of( @@ -254,6 +258,10 @@ void testClassNamedJava() throws IOException { // java --source N -cp ... HelloWorld @Test void testSourceClasspath() throws IOException { + if (!isEnglishLocale()) { + return; + } + starting("testSourceClasspath"); Path base = Files.createDirectories(Paths.get("testSourceClasspath")); Path src = Files.createDirectories(base.resolve("src")); diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java index 154adc5378e..ec4ca37bd4b 100644 --- a/test/jtreg-ext/requires/VMProps.java +++ b/test/jtreg-ext/requires/VMProps.java @@ -102,6 +102,7 @@ public Map call() { // vm.hasJFR is "true" if JFR is included in the build of the VM and // so tests can be executed. map.put("vm.hasJFR", this::vmHasJFR); + map.put("vm.hasDTrace", this::vmHasDTrace); map.put("vm.jvmti", this::vmHasJVMTI); map.put("vm.cpu.features", this::cpuFeatures); map.put("vm.pageSize", this::vmPageSize); @@ -339,6 +340,13 @@ protected String vmHasJVMTI() { return "" + WB.isJVMTIIncluded(); } + /** + * @return "true" if the VM is compiled with DTrace + */ + protected String vmHasDTrace() { + return "" + WB.isDTraceIncluded(); + } + /** * @return true if compiler in use supports RTM and false otherwise. */ diff --git a/test/langtools/jdk/javadoc/doclet/testDocFileDir/TestDocFileDir.java b/test/langtools/jdk/javadoc/doclet/testDocFileDir/TestDocFileDir.java index 70660a4340e..d2f9e98fa9c 100644 --- a/test/langtools/jdk/javadoc/doclet/testDocFileDir/TestDocFileDir.java +++ b/test/langtools/jdk/javadoc/doclet/testDocFileDir/TestDocFileDir.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -28,13 +28,14 @@ * get overwritten when the sourcepath is equal to the destination * directory. * Also test that -docfilessubdirs and -excludedocfilessubdir both work. - * @library ../../lib + * @library /tools/lib ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool - * @build javadoc.tester.* + * @build toolbox.ToolBox javadoc.tester.* * @run main TestDocFileDir */ import javadoc.tester.JavadocTester; +import toolbox.ToolBox; public class TestDocFileDir extends JavadocTester { @@ -43,10 +44,12 @@ public static void main(String... args) throws Exception { tester.runTests(); } + ToolBox tb = new ToolBox(); + // Output dir = "", Input dir = "" @Test public void test1() { - copyDir(testSrc("pkg"), "."); + tb.copyDir(testSrc("pkg"), "pkg"); setOutputDirectoryCheck(DirectoryCheck.NO_HTML_FILES); javadoc("pkg/C.java"); checkExit(Exit.OK); @@ -58,7 +61,7 @@ public void test1() { @Test public void test2() { String outdir = "out2"; - copyDir(testSrc("pkg"), outdir); + tb.copyDir(testSrc("pkg"), outdir + "/pkg"); setOutputDirectoryCheck(DirectoryCheck.NO_HTML_FILES); javadoc("-d", outdir, "-sourcepath", "blah" + PS + outdir + PS + "blah", diff --git a/test/langtools/jdk/javadoc/doclet/testMetadata/TestMetadata.java b/test/langtools/jdk/javadoc/doclet/testMetadata/TestMetadata.java index 46e48f64907..040d2d1c78c 100644 --- a/test/langtools/jdk/javadoc/doclet/testMetadata/TestMetadata.java +++ b/test/langtools/jdk/javadoc/doclet/testMetadata/TestMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -165,9 +165,8 @@ public void runTests() throws Exception { ); void checkBodyClasses() throws IOException { - Path outputDirPath = outputDir.toPath(); - for (Path p : tb.findFiles(".html", outputDirPath)) { - checkBodyClass(outputDirPath.relativize(p)); + for (Path p : tb.findFiles(".html", outputDir)) { + checkBodyClass(outputDir.relativize(p)); } } @@ -231,9 +230,8 @@ void checkBodyClass(Path p) { ); void checkMetadata() throws IOException { - Path outputDirPath = outputDir.toPath(); - for (Path p : tb.findFiles(".html", outputDirPath)) { - checkMetadata(outputDirPath.relativize(p)); + for (Path p : tb.findFiles(".html", outputDir)) { + checkMetadata(outputDir.relativize(p)); } } diff --git a/test/langtools/jdk/javadoc/doclet/testRelativeLinks/TestRelativeLinks.java b/test/langtools/jdk/javadoc/doclet/testRelativeLinks/TestRelativeLinks.java index 30ef9ec4d6f..c0619aeaf0d 100644 --- a/test/langtools/jdk/javadoc/doclet/testRelativeLinks/TestRelativeLinks.java +++ b/test/langtools/jdk/javadoc/doclet/testRelativeLinks/TestRelativeLinks.java @@ -35,6 +35,9 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; import javadoc.tester.JavadocTester; @@ -200,9 +203,9 @@ public void checkLinks() { } private void touch(String file) { - File f = new File(outputDir, file); + Path f = outputDir.resolve(file); out.println("touch " + f); - try (FileOutputStream fos = new FileOutputStream(f)) { + try (OutputStream fos = Files.newOutputStream(f)) { } catch (IOException e) { checking("Touch file"); failed("Error creating file: " + e); diff --git a/test/langtools/jdk/javadoc/doclet/testSearchScript/TestSearchScript.java b/test/langtools/jdk/javadoc/doclet/testSearchScript/TestSearchScript.java index 8c5e77c3c15..ad92d3f0e65 100644 --- a/test/langtools/jdk/javadoc/doclet/testSearchScript/TestSearchScript.java +++ b/test/langtools/jdk/javadoc/doclet/testSearchScript/TestSearchScript.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -41,10 +41,9 @@ import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.List; import jtreg.SkippedException; @@ -71,9 +70,9 @@ private Invocable getEngine() throws ScriptException, IOException, NoSuchMethodE // see https://github.com/graalvm/graaljs/blob/master/docs/user/ScriptEngine.md Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE); bindings.put("polyglot.js.nashorn-compat", true); - engine.eval(new BufferedReader(new FileReader(new File(testSrc, "javadoc-search.js")))); + engine.eval(Files.newBufferedReader(Path.of(testSrc).resolve("javadoc-search.js"))); Invocable inv = (Invocable) engine; - inv.invokeFunction("loadIndexFiles", outputDir.getAbsolutePath()); + inv.invokeFunction("loadIndexFiles", outputDir.toAbsolutePath().toString()); return inv; } diff --git a/test/langtools/jdk/javadoc/doclet/testSingletonLists/TestSingletonLists.java b/test/langtools/jdk/javadoc/doclet/testSingletonLists/TestSingletonLists.java index 409d77573c3..0df4f1e25c0 100644 --- a/test/langtools/jdk/javadoc/doclet/testSingletonLists/TestSingletonLists.java +++ b/test/langtools/jdk/javadoc/doclet/testSingletonLists/TestSingletonLists.java @@ -206,7 +206,7 @@ void checkLists() { checking("Check lists"); ListChecker c = new ListChecker(out, this::readFile); try { - c.checkDirectory(outputDir.toPath()); + c.checkDirectory(outputDir); c.report(); int errors = c.getErrorCount(); if (errors == 0) { diff --git a/test/langtools/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java b/test/langtools/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java index cd950f48f69..4a566e1f798 100644 --- a/test/langtools/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java +++ b/test/langtools/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java @@ -381,7 +381,7 @@ void checkStyles(Set styles) { checking("Check CSS class names"); CSSClassChecker c = new CSSClassChecker(out, this::readFile, styles); try { - c.checkDirectory(outputDir.toPath()); + c.checkDirectory(outputDir); c.report(); int errors = c.getErrorCount(); if (errors == 0) { diff --git a/test/langtools/jdk/javadoc/lib/javadoc/tester/JavadocTester.java b/test/langtools/jdk/javadoc/lib/javadoc/tester/JavadocTester.java index 1cf6098e862..79b20ff7e9e 100644 --- a/test/langtools/jdk/javadoc/lib/javadoc/tester/JavadocTester.java +++ b/test/langtools/jdk/javadoc/lib/javadoc/tester/JavadocTester.java @@ -25,10 +25,7 @@ import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; -import java.io.File; import java.io.FileNotFoundException; -import java.io.FileWriter; -import java.io.FilenameFilter; import java.io.IOException; import java.io.PrintStream; import java.io.PrintWriter; @@ -41,13 +38,18 @@ import java.lang.reflect.Method; import java.nio.charset.Charset; import java.nio.charset.UnsupportedCharsetException; +import java.nio.file.DirectoryStream; +import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.EnumMap; import java.util.HashMap; import java.util.List; @@ -157,7 +159,7 @@ public enum Output { } /** The output directory used in the most recent call of javadoc. */ - protected File outputDir; + protected Path outputDir; /** The output charset used in the most recent call of javadoc. */ protected Charset charset = Charset.defaultCharset(); @@ -169,7 +171,7 @@ public enum Output { private final Map outputMap = new EnumMap<>(Output.class); /** A cache of file content, to avoid reading files unnecessarily. */ - private final Map> fileContentCache = new HashMap<>(); + private final Map> fileContentCache = new HashMap<>(); /** The charset used for files in the fileContentCache. */ private Charset fileContentCacheCharset = null; @@ -185,7 +187,7 @@ public enum Output { * @return the full path of the specified file */ public static String testSrc(String path) { - return new File(testSrc, path).getPath(); + return Path.of(testSrc).resolve(path).toString(); } /** @@ -195,35 +197,40 @@ public enum DirectoryCheck { /** * Check that the directory is empty. */ - EMPTY((file, name) -> true), + EMPTY(p -> true), /** * Check that the directory does not contain any HTML files, * such as may have been generated by a prior run of javadoc * using this directory. * For now, the check is only performed on the top level directory. */ - NO_HTML_FILES((file, name) -> name.endsWith(".html")), + NO_HTML_FILES(p -> p.getFileName().toString().endsWith(".html")), /** * No check is performed on the directory contents. */ - NONE(null) { @Override void check(File dir) { } }; + NONE(null) { @Override void check(Path dir) { } }; /** The filter used to detect that files should not be present. */ - FilenameFilter filter; + DirectoryStream.Filter filter; - DirectoryCheck(FilenameFilter f) { + DirectoryCheck(DirectoryStream.Filter f) { filter = f; } - void check(File dir) { - if (dir.isDirectory()) { - String[] contents = dir.list(filter); - if (contents == null) - throw new Error("cannot list directory: " + dir); - if (contents.length > 0) { - System.err.println("Found extraneous files in dir:" + dir.getAbsolutePath()); - for (String x : contents) { - System.err.println(x); + void check(Path dir) { + if (Files.isDirectory(dir)) { + List contents = new ArrayList<>(); + try (var ds = Files.newDirectoryStream(dir, filter)) { + for (Path p : ds) { + contents.add(p); + } + } catch (IOException e) { + throw new Error("cannot list directory: " + dir + "; " + e, e); + } + if (!contents.isEmpty()) { + System.err.println("Found extraneous files in dir:" + dir.toAbsolutePath()); + for (Path p : contents) { + System.err.println(p); } throw new Error("directory has unexpected content: " + dir); } @@ -316,13 +323,13 @@ public void javadoc(String... args) { out.println("Running javadoc (run "+ javadocRunNum + ")..."); } - outputDir = new File("."); + outputDir = Path.of("."); String charsetArg = null; String docencodingArg = null; String encodingArg = null; for (int i = 0; i < args.length - 2; i++) { switch (args[i]) { - case "-d" -> outputDir = new File(args[++i]); + case "-d" -> outputDir = Path.of(args[++i]); case "-charset" -> charsetArg = args[++i]; case "-docencoding" -> docencodingArg = args[++i]; case "-encoding" -> encodingArg = args[++i]; @@ -377,7 +384,7 @@ public void javadoc(String... args) { } }); - if (exitCode == Exit.OK.code && outputDir.exists()) { + if (exitCode == Exit.OK.code && Files.exists(outputDir)) { if (automaticCheckLinks) { checkLinks(); } @@ -502,8 +509,8 @@ public void checkFileAndOutput(String path, boolean expectedFound, String... str public void checkOutput(String path, boolean expectedFound, String... strings) { // Read contents of file try { - String fileString = readFile(outputDir, path); - checkOutput(new File(outputDir, path).getPath(), fileString, expectedFound, strings); + String fileString = readFile(outputDir, Path.of(path)); + checkOutput(outputDir.resolve(path).toString(), fileString, expectedFound, strings); } catch (Error e) { checking("Read file"); failed("Error reading file: " + e); @@ -594,7 +601,7 @@ public void checkAccessibility() { checking("Check accessibility"); A11yChecker c = new A11yChecker(out, this::readFile); try { - c.checkDirectory(outputDir.toPath()); + c.checkDirectory(outputDir); c.report(); int errors = c.getErrorCount(); if (errors == 0) { @@ -616,7 +623,7 @@ public void checkLinks() { checking("Check links"); LinkChecker c = new LinkChecker(out, this::readFile); try { - c.checkDirectory(outputDir.toPath()); + c.checkDirectory(outputDir); c.report(); int errors = c.getErrorCount(); if (errors == 0) { @@ -641,8 +648,8 @@ public void showHeadings(String... paths) { ShowHeadings s = new ShowHeadings(out, this::readFile); for (String p : paths) { try { - File f = new File(outputDir, p); - s.checkFiles(List.of(f.toPath()), false, Collections.emptySet()); + Path f = outputDir.resolve(p); + s.checkFiles(List.of(f), false, Collections.emptySet()); } catch (IOException e) { checking("Read file"); failed("Error reading file: " + e); @@ -691,8 +698,8 @@ public void checkFiles(boolean expectedFound, Collection paths) { for (String path: paths) { // log.logCheckFile(path, expectedFound); checking("checkFile"); - File file = new File(outputDir, path); - boolean isFound = file.exists(); + Path file = outputDir.resolve(path); + boolean isFound = Files.exists(file); if (isFound == expectedFound) { passed(file, "file " + (isFound ? "found:" : "not found:") + "\n"); } else { @@ -708,7 +715,7 @@ public void checkFiles(boolean expectedFound, Collection paths) { * @param strings the strings whose order to check */ public void checkOrder(String path, String... strings) { - File file = new File(outputDir, path); + Path file = outputDir.resolve(path); String fileString = readOutputFile(path); int prevIndex = -1; for (String s : strings) { @@ -736,7 +743,7 @@ public void checkOrder(String path, String... strings) { * @param strings ensure each are unique */ public void checkUnique(String path, String... strings) { - File file = new File(outputDir, path); + Path file = outputDir.resolve(path); String fileString = readOutputFile(path); for (String s : strings) { int currentIndex = fileString.indexOf(s); @@ -762,58 +769,13 @@ public void checkUnique(String path, String... strings) { * @param files the set of files to be compared */ public void diff(String baseDir1, String baseDir2, String... files) { - File bd1 = new File(baseDir1); - File bd2 = new File(baseDir2); + Path bd1 = Path.of(baseDir1); + Path bd2 = Path.of(baseDir2); for (String file : files) { - diff(bd1, bd2, file); + diff(bd1, bd2, Path.of(file)); } } - /** - * Copies a directory from one place to another. - * - * @param targetDir the directory to copy. - * @param destDir the destination to copy the directory to. - */ - // TODO: convert to using java.nio.Files.walkFileTree - public void copyDir(String targetDir, String destDir) { - try { - File targetDirObj = new File(targetDir); - File destDirParentObj = new File(destDir); - File destDirObj = new File(destDirParentObj, targetDirObj.getName()); - if (! destDirParentObj.exists()) { - destDirParentObj.mkdir(); - } - if (! destDirObj.exists()) { - destDirObj.mkdir(); - } - String[] files = targetDirObj.list(); - for (String file : files) { - File srcFile = new File(targetDirObj, file); - File destFile = new File(destDirObj, file); - if (srcFile.isFile()) { - out.println("Copying " + srcFile + " to " + destFile); - copyFile(destFile, srcFile); - } else if(srcFile.isDirectory()) { - copyDir(srcFile.getAbsolutePath(), destDirObj.getAbsolutePath()); - } - } - } catch (IOException exc) { - throw new Error("Could not copy " + targetDir + " to " + destDir); - } - } - - /** - * Copies a file. - * - * @param destfile the destination file - * @param srcfile the source file - * @throws IOException - */ - public void copyFile(File destfile, File srcfile) throws IOException { - Files.copy(srcfile.toPath(), destfile.toPath()); - } - /** * Read a file from the output directory. * @@ -821,27 +783,27 @@ public void copyFile(File destfile, File srcfile) throws IOException { * @return the file in string format */ public String readOutputFile(String fileName) throws Error { - return readFile(outputDir, fileName); + return readFile(outputDir, Path.of(fileName)); } protected String readFile(String fileName) throws Error { - return readFile(outputDir, fileName); + return readFile(outputDir, Path.of(fileName)); } protected String readFile(String baseDir, String fileName) throws Error { - return readFile(new File(baseDir), fileName); + return readFile(Path.of(baseDir), Path.of(fileName)); } protected String readFile(Path file) { - File baseDir; - if (file.startsWith(outputDir.toPath())) { + Path baseDir; + if (file.startsWith(outputDir)) { baseDir = outputDir; } else if (file.startsWith(currDir)) { - baseDir = currDir.toFile(); + baseDir = currDir; } else { - baseDir = file.getParent().toFile(); + baseDir = file.getParent(); } - String fileName = baseDir.toPath().relativize(file).toString(); + Path fileName = baseDir.relativize(file); return readFile(baseDir, fileName); } @@ -852,20 +814,20 @@ protected String readFile(Path file) { * @param fileName the name of the file to read * @return the file in string format */ - private String readFile(File baseDir, String fileName) throws Error { + private String readFile(Path baseDir, Path fileName) throws Error { if (!Objects.equals(fileContentCacheCharset, charset)) { fileContentCache.clear(); fileContentCacheCharset = charset; } try { - File file = new File(baseDir, fileName); + Path file = baseDir.resolve(fileName); SoftReference ref = fileContentCache.get(file); String content = (ref == null) ? null : ref.get(); if (content != null) return content; // charset defaults to a value inferred from latest javadoc run - content = new String(Files.readAllBytes(file.toPath()), charset); + content = new String(Files.readAllBytes(file), charset); fileContentCache.put(file, new SoftReference<>(content)); return content; } catch (FileNotFoundException e) { @@ -897,7 +859,7 @@ protected void checking(String message) { * @param file the file that was the focus of the check * @param message a short description of the outcome */ - protected void passed(File file, String message) { + protected void passed(Path file, String message) { passed(file + ": " + message); } @@ -922,7 +884,7 @@ protected void passed(String message) { * @param file the file that was the focus of the check * @param message a short description of the outcome */ - protected void failed(File file, String message) { + protected void failed(Path file, String message) { failed(file + ": " + message); } @@ -1002,10 +964,10 @@ private boolean findString(String fileString, String stringToFind) { * @param baseDir2 the directory in which to locate the second file * @param file the file to compare in the two base directories */ - private void diff(File baseDir1, File baseDir2, String file) { + private void diff(Path baseDir1, Path baseDir2, Path file) { String file1Contents = readFile(baseDir1, file); String file2Contents = readFile(baseDir2, file); - checking("diff " + new File(baseDir1, file) + ", " + new File(baseDir2, file)); + checking("diff " + baseDir1.resolve(file) + ", " + baseDir2.resolve(file)); if (file1Contents.trim().compareTo(file2Contents.trim()) == 0) { passed("files are equal"); } else { @@ -1068,44 +1030,46 @@ static class Logger { private static final int SUFFIX = 20; private static final int MAX = PREFIX + SUFFIX; List tests = new ArrayList<>(); - String outDir; - String rootDir = rootDir(); - - static String rootDir() { - File f = new File(".").getAbsoluteFile(); - while (!new File(f, ".hg").exists()) - f = f.getParentFile(); - return f.getPath(); + Path outDir; + Path rootDir = rootDir(); + + static Path rootDir() { + Path f = Path.of(".").toAbsolutePath(); + while (f != null && !Files.exists(f.resolve(".git"))) + f = f.getParent(); + return f; } - void setOutDir(File outDir) { - this.outDir = outDir.getPath(); + void setOutDir(Path outDir) { + this.outDir = outDir; } void logCheckFile(String file, boolean positive) { // Strip the outdir because that will typically not be the same - if (file.startsWith(outDir + "/")) - file = file.substring(outDir.length() + 1); - tests.add(file + " " + positive); + Path p = Path.of(file); + if (p.startsWith(outDir)) + p = p.relativize(outDir); + tests.add(p + " " + positive); } void logCheckOutput(String file, boolean positive, String text) { // Compress the string to be displayed in the log file - String simpleText = text.replaceAll("\\s+", " ").replace(rootDir, "[ROOT]"); + String simpleText = text.replaceAll("\\s+", " ").replace(rootDir.toString(), "[ROOT]"); if (simpleText.length() > MAX) simpleText = simpleText.substring(0, PREFIX) + "..." + simpleText.substring(simpleText.length() - SUFFIX); // Strip the outdir because that will typically not be the same - if (file.startsWith(outDir + "/")) - file = file.substring(outDir.length() + 1); + Path p = Path.of(file); + if (p.startsWith(outDir)) + p = p.relativize(outDir); // The use of text.hashCode ensure that all of "text" is taken into account - tests.add(file + " " + positive + " " + text.hashCode() + " " + simpleText); + tests.add(p + " " + positive + " " + text.hashCode() + " " + simpleText); } void write() { // sort the log entries because the subtests may not be executed in the same order - tests.sort((a, b) -> a.compareTo(b)); - try (BufferedWriter bw = new BufferedWriter(new FileWriter("tester.log"))) { + tests.sort(Comparator.naturalOrder()); + try (var bw = Files.newBufferedWriter(Path.of("tester.log"))) { for (String t: tests) { bw.write(t); bw.newLine(); @@ -1116,6 +1080,4 @@ void write() { } } - // Support classes for checkLinks - } \ No newline at end of file diff --git a/test/langtools/jdk/jshell/ToolBasicTest.java b/test/langtools/jdk/jshell/ToolBasicTest.java index 8d8dfc8f9f4..a6bb7a075de 100644 --- a/test/langtools/jdk/jshell/ToolBasicTest.java +++ b/test/langtools/jdk/jshell/ToolBasicTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -553,7 +553,7 @@ public void testOpenFileOverHttp() throws IOException { } public void testOpenResource() { - test( + test(new String[]{"-R", "-Duser.language=en", "-R", "-Duser.country=US"}, (a) -> assertCommand(a, "/open PRINTING", ""), (a) -> assertCommandOutputContains(a, "/list", "void println", "System.out.printf"), diff --git a/test/langtools/jdk/jshell/ToolSimpleTest.java b/test/langtools/jdk/jshell/ToolSimpleTest.java index 26a5402564e..6994e3b99f2 100644 --- a/test/langtools/jdk/jshell/ToolSimpleTest.java +++ b/test/langtools/jdk/jshell/ToolSimpleTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -744,7 +744,8 @@ public void testBlankLinesInSnippetContinuation() { @Test public void testCompoundStart() { - test(new String[]{"--startup", "DEFAULT", "--startup", "PRINTING"}, + test(new String[]{"-R", "-Duser.language=en", "-R", "-Duser.country=US", + "--startup", "DEFAULT", "--startup", "PRINTING"}, (a) -> assertCommand(a, "printf(\"%4.2f\", Math.PI)", "", "", null, "3.14", "") ); diff --git a/test/langtools/tools/javac/lambda/lambdaExecution/LambdaTranslationTest1.java b/test/langtools/tools/javac/lambda/lambdaExecution/LambdaTranslationTest1.java index 37033fff8a1..b207fd1a7d5 100644 --- a/test/langtools/tools/javac/lambda/lambdaExecution/LambdaTranslationTest1.java +++ b/test/langtools/tools/javac/lambda/lambdaExecution/LambdaTranslationTest1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -25,7 +25,7 @@ * @test * @bug 8003639 * @summary convert lambda testng tests to jtreg and add them - * @run testng LambdaTranslationTest1 + * @run testng/othervm -Duser.language=en -Duser.country=US LambdaTranslationTest1 */ import org.testng.annotations.Test; diff --git a/test/langtools/tools/javac/lambda/lambdaExecution/LambdaTranslationTest2.java b/test/langtools/tools/javac/lambda/lambdaExecution/LambdaTranslationTest2.java index fc03a863036..e7e484730b2 100644 --- a/test/langtools/tools/javac/lambda/lambdaExecution/LambdaTranslationTest2.java +++ b/test/langtools/tools/javac/lambda/lambdaExecution/LambdaTranslationTest2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -25,7 +25,7 @@ * @test * @bug 8003639 * @summary convert lambda testng tests to jtreg and add them - * @run testng LambdaTranslationTest2 + * @run testng/othervm -Duser.language=en -Duser.country=US LambdaTranslationTest2 */ import org.testng.annotations.Test; diff --git a/test/langtools/tools/javac/processing/ReportOnImportedModuleAnnotation/ReportOnImportedModuleAnnotation.java b/test/langtools/tools/javac/processing/ReportOnImportedModuleAnnotation/ReportOnImportedModuleAnnotation.java index 777a14cd219..cfaca246a87 100644 --- a/test/langtools/tools/javac/processing/ReportOnImportedModuleAnnotation/ReportOnImportedModuleAnnotation.java +++ b/test/langtools/tools/javac/processing/ReportOnImportedModuleAnnotation/ReportOnImportedModuleAnnotation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -27,7 +27,10 @@ * 8235458 * @summary javac shouldn't fail when an annotation processor report a message about an annotation on a module * javac should process annotated module when imports statement are present + * @library /tools/lib * @modules jdk.compiler + * @build toolbox.ToolBox + * @run main ReportOnImportedModuleAnnotation */ import java.io.PrintWriter; @@ -41,6 +44,8 @@ import javax.tools.StandardLocation; import javax.tools.ToolProvider; +import toolbox.ToolBox; + public class ReportOnImportedModuleAnnotation { public static void main(String[] args) throws Exception { @@ -49,6 +54,9 @@ public static void main(String[] args) throws Exception { final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + // Clean any existing files in output directory + (new ToolBox()).cleanDirectory(testOutputPath); + // Compile annotation and processor modules StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); fileManager.setLocationFromPaths(StandardLocation.MODULE_SOURCE_PATH, List.of(testBasePath.resolve("mods-src1/"))); diff --git a/test/langtools/tools/jdeps/multiVersion/MultiVersionError.java b/test/langtools/tools/jdeps/multiVersion/MultiVersionError.java new file mode 100644 index 00000000000..62513406b71 --- /dev/null +++ b/test/langtools/tools/jdeps/multiVersion/MultiVersionError.java @@ -0,0 +1,107 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8277165 + * @library ../lib + * @build CompilerUtils + * @run testng MultiVersionError + * @summary Tests multiple versions of the same class file + */ + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Set; +import java.util.spi.ToolProvider; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertTrue; + +public class MultiVersionError { + private static final String TEST_SRC = System.getProperty("test.src"); + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + + private static final Path MODS_DIR = Paths.get("mods"); + + private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar").orElseThrow(); + private static final Set modules = Set.of("m1", "m2"); + + /** + * Compiles classes used by the test + */ + @BeforeTest + public void compileAll() throws Exception { + CompilerUtils.cleanDir(MODS_DIR); + modules.forEach(mn -> + assertTrue(CompilerUtils.compileModule(SRC_DIR, MODS_DIR, mn))); + + // create a modular multi-release m1.jar + Path m1 = MODS_DIR.resolve("m1"); + Path m2 = MODS_DIR.resolve("m2"); + jar("cf", "m1.jar", "-C", m1.toString(), "p/Test.class", + "--release", "9", "-C", m1.toString(), "module-info.class", + "--release", "11", "-C", m1.toString(), "p/internal/P.class"); + jar("cf", "m2.jar", "-C", m2.toString(), "q/Q.class", + "--release", "10", "-C", m2.toString(), "module-info.class"); + + // package private p/internal/P.class in m1 instead + jar("cf", "m3.jar", "-C", m2.toString(), "q/Q.class", + "--release", "12", "-C", m2.toString(), "module-info.class", + "-C", m1.toString(), "p/internal/P.class"); + } + + /* + * multiple module-info.class from different versions should be excluded + * from multiple version check. + */ + @Test + public void noMultiVersionClass() { + // skip parsing p.internal.P to workaround JDK-8277681 + JdepsRunner jdepsRunner = new JdepsRunner("--print-module-deps", "--multi-release", "10", + "--ignore-missing-deps", + "--module-path", "m1.jar", "m2.jar"); + int rc = jdepsRunner.run(true); + assertTrue(rc == 0); + assertTrue(jdepsRunner.outputContains("java.base,m1")); + } + + /* + * Detect multiple versions of p.internal.P class + */ + @Test + public void classInMultiVersions() { + JdepsRunner jdepsRunner = new JdepsRunner("--print-module-deps", "--multi-release", "13", + "--module-path", "m1.jar", "m3.jar"); + int rc = jdepsRunner.run(true); + assertTrue(rc != 0); + assertTrue(jdepsRunner.outputContains("class p.internal.P already associated with version")); + } + + private static void jar(String... options) { + int rc = JAR_TOOL.run(System.out, System.err, options); + assertTrue(rc == 0); + } +} diff --git a/test/langtools/tools/jdeps/multiVersion/src/m1/module-info.java b/test/langtools/tools/jdeps/multiVersion/src/m1/module-info.java new file mode 100644 index 00000000000..316803466ca --- /dev/null +++ b/test/langtools/tools/jdeps/multiVersion/src/m1/module-info.java @@ -0,0 +1,27 @@ +/* + * 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. + */ + +module m1 { + requires java.management; + exports p; +} diff --git a/test/langtools/tools/jdeps/multiVersion/src/m1/p/Test.java b/test/langtools/tools/jdeps/multiVersion/src/m1/p/Test.java new file mode 100644 index 00000000000..e3d9139bbdd --- /dev/null +++ b/test/langtools/tools/jdeps/multiVersion/src/m1/p/Test.java @@ -0,0 +1,27 @@ +/* + * 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. + */ + +package p; + +public class Test { +} diff --git a/test/langtools/tools/jdeps/multiVersion/src/m1/p/internal/P.java b/test/langtools/tools/jdeps/multiVersion/src/m1/p/internal/P.java new file mode 100644 index 00000000000..3a14badd1d0 --- /dev/null +++ b/test/langtools/tools/jdeps/multiVersion/src/m1/p/internal/P.java @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package p.internal; + +import java.lang.management.*; + +class P { + private static RuntimeMXBean mxbean = ManagementFactory.getRuntimeMXBean(); +} diff --git a/test/langtools/tools/jdeps/multiVersion/src/m2/module-info.java b/test/langtools/tools/jdeps/multiVersion/src/m2/module-info.java new file mode 100644 index 00000000000..5404ca47867 --- /dev/null +++ b/test/langtools/tools/jdeps/multiVersion/src/m2/module-info.java @@ -0,0 +1,27 @@ +/* + * 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. + */ + +module m2 { + requires m1; + requires java.logging; +} diff --git a/test/langtools/tools/jdeps/multiVersion/src/m2/p/internal/P.java b/test/langtools/tools/jdeps/multiVersion/src/m2/p/internal/P.java new file mode 100644 index 00000000000..d68265798bd --- /dev/null +++ b/test/langtools/tools/jdeps/multiVersion/src/m2/p/internal/P.java @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package p.internal; + +import java.util.logging.Logger; + +public class P { + private static final Logger LOGGER = Logger.getLogger("p"); +} diff --git a/test/langtools/tools/jdeps/multiVersion/src/m2/q/Q.java b/test/langtools/tools/jdeps/multiVersion/src/m2/q/Q.java new file mode 100644 index 00000000000..46cad1cc9d1 --- /dev/null +++ b/test/langtools/tools/jdeps/multiVersion/src/m2/q/Q.java @@ -0,0 +1,32 @@ +/* + * 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. + */ + +package q; + +public class Q { + static p.Test t = new p.Test(); + + public Q() { + Object o = new p.internal.P(); + } +} diff --git a/test/langtools/tools/lib/toolbox/ToolBox.java b/test/langtools/tools/lib/toolbox/ToolBox.java index c6c52929c16..9dbb26e1448 100644 --- a/test/langtools/tools/lib/toolbox/ToolBox.java +++ b/test/langtools/tools/lib/toolbox/ToolBox.java @@ -34,10 +34,10 @@ import java.io.Writer; import java.net.URI; import java.nio.charset.Charset; -import java.nio.file.DirectoryNotEmptyException; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.FileVisitOption; import java.nio.file.FileVisitResult; import java.nio.file.Files; -import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; @@ -48,6 +48,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Deque; +import java.util.EnumSet; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -65,8 +66,6 @@ import javax.tools.ForwardingJavaFileManager; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; -import javax.tools.JavaFileObject.Kind; -import javax.tools.JavaFileManager.Location; import javax.tools.SimpleJavaFileObject; import javax.tools.ToolProvider; @@ -107,11 +106,11 @@ public class ToolBox { public static final float timeoutFactor; static { String ttf = System.getProperty("test.timeout.factor"); - timeoutFactor = (ttf == null) ? 1.0f : Float.valueOf(ttf); + timeoutFactor = (ttf == null) ? 1.0f : Float.parseFloat(ttf); } /** The current directory. */ - public static final Path currDir = Paths.get("."); + public static final Path currDir = Path.of("."); /** The stream used for logging output. */ public PrintStream out = System.err; @@ -127,6 +126,7 @@ public static boolean isWindows() { /** * Splits a string around matches of the given regular expression. * If the string is empty, an empty list will be returned. + * * @param text the string to be split * @param sep the delimiting regular expression * @return the strings between the separators @@ -139,6 +139,7 @@ public List split(String text, String sep) { /** * Checks if two lists of strings are equal. + * * @param l1 the first list of strings to be compared * @param l2 the second list of strings to be compared * @throws Error if the lists are not equal @@ -166,6 +167,7 @@ public void checkEqual(List l1, List l2) throws Error { /** * Filters a list of strings according to the given regular expression, * returning the strings that match the regular expression. + * * @param regex the regular expression * @param lines the strings to be filtered * @return the strings matching the regular expression @@ -177,8 +179,9 @@ public List grep(String regex, List lines) { /** * Filters a list of strings according to the given regular expression, * returning the strings that match the regular expression. + * * @param pattern the regular expression - * @param lines the strings to be filtered + * @param lines the strings to be filtered * @return the strings matching the regular expression */ public List grep(Pattern pattern, List lines) { @@ -188,6 +191,7 @@ public List grep(Pattern pattern, List lines) { /** * Filters a list of strings according to the given regular expression, * returning either the strings that match or the strings that do not match. + * * @param regex the regular expression * @param lines the strings to be filtered * @param match if true, return the lines that match; otherwise if false, return the lines that do not match. @@ -200,9 +204,10 @@ public List grep(String regex, List lines, boolean match) { /** * Filters a list of strings according to the given regular expression, * returning either the strings that match or the strings that do not match. + * * @param pattern the regular expression - * @param lines the strings to be filtered - * @param match if true, return the lines that match; otherwise if false, return the lines that do not match. + * @param lines the strings to be filtered + * @param match if true, return the lines that match; otherwise if false, return the lines that do not match. * @return the strings matching(or not matching) the regular expression */ public List grep(Pattern pattern, List lines, boolean match) { @@ -217,12 +222,13 @@ public List grep(Pattern pattern, List lines, boolean match) { * in that directory. Otherwise, the copy will be placed at the destination, * possibly overwriting any existing file. *

    Similar to the shell "cp" command: {@code cp from to}. + * * @param from the file to be copied - * @param to where to copy the file + * @param to where to copy the file * @throws IOException if any error occurred while copying the file */ public void copyFile(String from, String to) throws IOException { - copyFile(Paths.get(from), Paths.get(to)); + copyFile(Path.of(from), Path.of(to)); } /** @@ -231,8 +237,9 @@ public void copyFile(String from, String to) throws IOException { * in that directory. Otherwise, the copy will be placed at the destination, * possibly overwriting any existing file. *

    Similar to the shell "cp" command: {@code cp from to}. + * * @param from the file to be copied - * @param to where to copy the file + * @param to where to copy the file * @throws IOException if an error occurred while copying the file */ public void copyFile(Path from, Path to) throws IOException { @@ -245,10 +252,55 @@ public void copyFile(Path from, Path to) throws IOException { } /** - * Creates one of more directories. + * Copies the contents of a directory to another directory. + *

    Similar to the shell command: {@code rsync fromDir/ toDir/}. + * + * @param fromDir the directory containing the files to be copied + * @param toDir the destination to which to copy the files + */ + public void copyDir(String fromDir, String toDir) { + copyDir(Path.of(fromDir), Path.of(toDir)); + } + + /** + * Copies the contents of a directory to another directory. + * The destination direction should not already exist. + *

    Similar to the shell command: {@code rsync fromDir/ toDir/}. + * + * @param fromDir the directory containing the files to be copied + * @param toDir the destination to which to copy the files + */ + public void copyDir(Path fromDir, Path toDir) { + try { + if (toDir.getParent() != null) { + Files.createDirectories(toDir.getParent()); + } + Files.walkFileTree(fromDir, new SimpleFileVisitor() { + @Override + public FileVisitResult preVisitDirectory(Path fromSubdir, BasicFileAttributes attrs) + throws IOException { + Files.copy(fromSubdir, toDir.resolve(fromDir.relativize(fromSubdir))); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path fromFile, BasicFileAttributes attrs) + throws IOException { + Files.copy(fromFile, toDir.resolve(fromDir.relativize(fromFile))); + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException e) { + throw new Error("Could not copy " + fromDir + " to " + toDir + ": " + e, e); + } + } + + /** + * Creates one or more directories. * For each of the series of paths, a directory will be created, * including any necessary parent directories. *

    Similar to the shell command: {@code mkdir -p paths}. + * * @param paths the directories to be created * @throws IOException if an error occurred while creating the directories */ @@ -256,7 +308,7 @@ public void createDirectories(String... paths) throws IOException { if (paths.length == 0) throw new IllegalArgumentException("no directories specified"); for (String p : paths) - Files.createDirectories(Paths.get(p)); + Files.createDirectories(Path.of(p)); } /** @@ -264,6 +316,7 @@ public void createDirectories(String... paths) throws IOException { * For each of the series of paths, a directory will be created, * including any necessary parent directories. *

    Similar to the shell command: {@code mkdir -p paths}. + * * @param paths the directories to be created * @throws IOException if an error occurred while creating the directories */ @@ -278,6 +331,7 @@ public void createDirectories(Path... paths) throws IOException { * Deletes one or more files, awaiting confirmation that the files * no longer exist. Any directories to be deleted must be empty. *

    Similar to the shell command: {@code rm files}. + * * @param files the names of the files to be deleted * @throws IOException if an error occurred while deleting the files */ @@ -289,6 +343,7 @@ public void deleteFiles(String... files) throws IOException { * Deletes one or more files, awaiting confirmation that the files * no longer exist. Any directories to be deleted must be empty. *

    Similar to the shell command: {@code rm files}. + * * @param paths the paths for the files to be deleted * @throws IOException if an error occurred while deleting the files */ @@ -300,6 +355,7 @@ public void deleteFiles(Path... paths) throws IOException { * Deletes one or more files, awaiting confirmation that the files * no longer exist. Any directories to be deleted must be empty. *

    Similar to the shell command: {@code rm files}. + * * @param paths the paths for the files to be deleted * @throws IOException if an error occurred while deleting the files */ @@ -319,6 +375,7 @@ public void deleteFiles(List paths) throws IOException { /** * Deletes all content of a directory (but not the directory itself), * awaiting confirmation that the content has been deleted. + * * @param root the directory to be cleaned * @throws IOException if an error occurs while cleaning the directory */ @@ -326,20 +383,20 @@ public void cleanDirectory(Path root) throws IOException { if (!Files.isDirectory(root)) { throw new IOException(root + " is not a directory"); } - Files.walkFileTree(root, new SimpleFileVisitor() { + Files.walkFileTree(root, new SimpleFileVisitor<>() { private IOException ioe = null; // for each directory we visit, maintain a list of the files that we try to delete - private Deque> dirFiles = new LinkedList<>(); + private final Deque> dirFiles = new LinkedList<>(); @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes a) throws IOException { + public FileVisitResult visitFile(Path file, BasicFileAttributes a) { ioe = deleteFile(file, ioe); dirFiles.peekFirst().add(file); return FileVisitResult.CONTINUE; } @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes a) throws IOException { + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes a) { if (!dir.equals(root)) { dirFiles.peekFirst().add(dir); } @@ -369,10 +426,11 @@ public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOExce * It does not wait to confirm deletion, nor does it retry. * If an exception occurs it is either returned or added to the set of * suppressed exceptions for an earlier exception. + * * @param path the path for the file to be deleted - * @param ioe the earlier exception, or null + * @param ioe the earlier exception, or null * @return the earlier exception or an exception that occurred while - * trying to delete the file + * trying to delete the file */ private IOException deleteFile(Path path, IOException ioe) { try { @@ -389,6 +447,7 @@ private IOException deleteFile(Path path, IOException ioe) { /** * Wait until it is confirmed that a set of files have been deleted. + * * @param paths the paths for the files to be deleted * @throws IOException if a file has not been deleted */ @@ -401,6 +460,7 @@ private void ensureDeleted(Collection paths) /** * Wait until it is confirmed that a file has been deleted. + * * @param path the path for the file to be deleted * @throws IOException if problems occur while deleting the file */ @@ -431,12 +491,13 @@ private void ensureDeleted(Path path) throws IOException { * to that directory. Otherwise, the file will be moved to the destination, * possibly overwriting any existing file. *

    Similar to the shell "mv" command: {@code mv from to}. + * * @param from the file to be moved - * @param to where to move the file + * @param to where to move the file * @throws IOException if an error occurred while moving the file */ public void moveFile(String from, String to) throws IOException { - moveFile(Paths.get(from), Paths.get(to)); + moveFile(Path.of(from), Path.of(to)); } /** @@ -445,8 +506,9 @@ public void moveFile(String from, String to) throws IOException { * to that directory. Otherwise, the file will be moved to the destination, * possibly overwriting any existing file. *

    Similar to the shell "mv" command: {@code mv from to}. + * * @param from the file to be moved - * @param to where to move the file + * @param to where to move the file * @throws IOException if an error occurred while moving the file */ public void moveFile(Path from, Path to) throws IOException { @@ -461,6 +523,7 @@ public void moveFile(Path from, Path to) throws IOException { /** * Reads the lines of a file. * The file is read using the default character encoding. + * * @param path the file to be read * @return the lines of the file * @throws IOException if an error occurred while reading the file @@ -472,6 +535,7 @@ public List readAllLines(String path) throws IOException { /** * Reads the lines of a file. * The file is read using the default character encoding. + * * @param path the file to be read * @return the lines of the file * @throws IOException if an error occurred while reading the file @@ -482,18 +546,20 @@ public List readAllLines(Path path) throws IOException { /** * Reads the lines of a file using the given encoding. - * @param path the file to be read + * + * @param path the file to be read * @param encoding the encoding to be used to read the file * @return the lines of the file. * @throws IOException if an error occurred while reading the file */ public List readAllLines(String path, String encoding) throws IOException { - return readAllLines(Paths.get(path), encoding); + return readAllLines(Path.of(path), encoding); } /** * Reads the lines of a file using the given encoding. - * @param path the file to be read + * + * @param path the file to be read * @param encoding the encoding to be used to read the file * @return the lines of the file * @throws IOException if an error occurred while reading the file @@ -509,6 +575,7 @@ private Charset getCharset(String encoding) { /** * Find .java files in one or more directories. *

    Similar to the shell "find" command: {@code find paths -name \*.java}. + * * @param paths the directories in which to search for .java files * @return the .java files found * @throws IOException if an error occurred while searching for files @@ -520,18 +587,18 @@ public Path[] findJavaFiles(Path... paths) throws IOException { /** * Find files matching the file extension, in one or more directories. *

    Similar to the shell "find" command: {@code find paths -name \*.ext}. + * * @param fileExtension the extension to search for - * @param paths the directories in which to search for files + * @param paths the directories in which to search for files * @return the files matching the file extension * @throws IOException if an error occurred while searching for files */ public Path[] findFiles(String fileExtension, Path... paths) throws IOException { Set files = new TreeSet<>(); // use TreeSet to force a consistent order for (Path p : paths) { - Files.walkFileTree(p, new SimpleFileVisitor() { + Files.walkFileTree(p, new SimpleFileVisitor<>() { @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) - throws IOException { + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { if (file.getFileName().toString().endsWith(fileExtension)) { files.add(file); } @@ -539,24 +606,26 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) } }); } - return files.toArray(new Path[files.size()]); + return files.toArray(new Path[0]); } /** * Writes a file containing the given content. * Any necessary directories for the file will be created. - * @param path where to write the file + * + * @param path where to write the file * @param content the content for the file * @throws IOException if an error occurred while writing the file */ public void writeFile(String path, String content) throws IOException { - writeFile(Paths.get(path), content); + writeFile(Path.of(path), content); } /** * Writes a file containing the given content. * Any necessary directories for the file will be created. - * @param path where to write the file + * + * @param path where to write the file * @param content the content for the file * @throws IOException if an error occurred while writing the file */ @@ -580,7 +649,8 @@ public void writeFile(Path path, String content) throws IOException { *

    Note: the content is analyzed using regular expressions; * errors can occur if any contents have initial comments that might trip * up the analysis. - * @param dir the base directory + * + * @param dir the base directory * @param contents the contents of the files to be written * @throws IOException if an error occurred while writing any of the files. */ @@ -593,17 +663,19 @@ public void writeJavaFiles(Path dir, String... contents) throws IOException { } /** - * Returns the path for the binary of a JDK tool within {@link testJDK}. + * Returns the path for the binary of a JDK tool within {@link #testJDK}. + * * @param tool the name of the tool * @return the path of the tool */ public Path getJDKTool(String tool) { - return Paths.get(testJDK, "bin", tool); + return Path.of(testJDK, "bin", tool); } /** * Returns a string representing the contents of an {@code Iterable} as a list. - * @param the type parameter of the {@code Iterable} + * + * @param the type parameter of the {@code Iterable} * @param items the iterable * @return the string */ @@ -624,8 +696,9 @@ public static class JavaSource extends SimpleJavaFileObject { /** * Creates a in-memory file object for Java source code. + * * @param className the name of the class - * @param source the source text + * @param source the source text */ public JavaSource(String className, String source) { super(URI.create(className), JavaFileObject.Kind.SOURCE); @@ -635,6 +708,7 @@ public JavaSource(String className, String source) { /** * Creates a in-memory file object for Java source code. * The name of the class will be inferred from the source code. + * * @param source the source text */ public JavaSource(String source) { @@ -645,6 +719,7 @@ public JavaSource(String source) { /** * Writes the source code to a file in the current directory. + * * @throws IOException if there is a problem writing the file */ public void write() throws IOException { @@ -653,6 +728,7 @@ public void write() throws IOException { /** * Writes the source code to a file in a specified directory. + * * @param dir the directory * @throws IOException if there is a problem writing the file */ @@ -669,13 +745,13 @@ public CharSequence getCharContent(boolean ignoreEncodingErrors) { return source; } - private static Pattern commentPattern = + private final static Pattern commentPattern = Pattern.compile("(?s)(\\s+//.*?\n|/\\*.*?\\*/)"); - private static Pattern modulePattern = + private final static Pattern modulePattern = Pattern.compile("module\\s+((?:\\w+\\.)*)"); - private static Pattern packagePattern = - Pattern.compile("package\\s+(((?:\\w+\\.)*)(?:\\w+))"); - private static Pattern classPattern = + private final static Pattern packagePattern = + Pattern.compile("package\\s+(((?:\\w+\\.)*)\\w+)"); + private final static Pattern classPattern = Pattern.compile("(?:public\\s+)?(?:class|enum|interface|record)\\s+(\\w+)"); /** @@ -689,7 +765,7 @@ static String getJavaFileNameFromSource(String source) { Matcher matcher = commentPattern.matcher(source); int start = 0; while (matcher.find()) { - sb.append(source.substring(start, matcher.start())); + sb.append(source, start, matcher.start()); start = matcher.end(); } sb.append(source.substring(start)); @@ -725,10 +801,11 @@ static String getJavaFileNameFromSource(String source) { * Extracts the Java file name from the class declaration. * This method is intended for simple files and uses regular expressions, * so comments matching the pattern can make the method fail. - * @deprecated This is a legacy method for compatibility with ToolBox v1. - * Use {@link JavaSource#getName JavaSource.getName} instead. + * * @param source the source text * @return the Java file name inferred from the source + * @deprecated This is a legacy method for compatibility with ToolBox v1. + * Use {@link JavaSource#getName JavaSource.getName} instead. */ @Deprecated public static String getJavaFileNameFromSource(String source) { @@ -741,11 +818,15 @@ public static String getJavaFileNameFromSource(String source) { "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9" ); - /**Validate if a given name is a valid file name + /** + * Validates if a given name is a valid file name * or path name on known platforms. + * + * @param name the name + * @throws IllegalArgumentException if the name is a reserved name */ public static void validateName(String name) { - for (String part : name.split("\\.|/|\\\\")) { + for (String part : name.split("[./\\\\]")) { if (RESERVED_NAMES.contains(part.toLowerCase(Locale.US))) { throw new IllegalArgumentException("Name: " + name + " is" + "a reserved name on Windows, " + @@ -753,12 +834,8 @@ public static void validateName(String name) { } } } - /** - * A memory file manager, for saving generated files in memory. - * The file manager delegates to a separate file manager for listing and - * reading input files. - */ - public static class MemoryFileManager extends ForwardingJavaFileManager { + + public static class MemoryFileManager extends ForwardingJavaFileManager { private interface Content { byte[] getBytes(); String getString(); @@ -770,7 +847,7 @@ private interface Content { private final Map> files; /** - * Construct a memory file manager which stores output files in memory, + * Constructs a memory file manager which stores output files in memory, * and delegates to a default file manager for input files. */ public MemoryFileManager() { @@ -778,8 +855,9 @@ public MemoryFileManager() { } /** - * Construct a memory file manager which stores output files in memory, + * Constructs a memory file manager which stores output files in memory, * and delegates to a specified file manager for input files. + * * @param fileManager the file manager to be used for input files */ public MemoryFileManager(JavaFileManager fileManager) { @@ -799,6 +877,7 @@ public JavaFileObject getJavaFileForOutput(Location location, /** * Returns the set of names of files that have been written to a given * location. + * * @param location the location * @return the set of file names */ @@ -811,8 +890,9 @@ public Set getFileNames(Location location) { /** * Returns the content written to a file in a given location, * or null if no such file has been written. + * * @param location the location - * @param name the name of the file + * @param name the name of the file * @return the content as an array of bytes */ public byte[] getFileBytes(Location location, String name) { @@ -823,8 +903,9 @@ public byte[] getFileBytes(Location location, String name) { /** * Returns the content written to a file in a given location, * or null if no such file has been written. + * * @param location the location - * @param name the name of the file + * @param name the name of the file * @return the content as a string */ public String getFileString(Location location, String name) { @@ -838,10 +919,8 @@ private Content getFile(Location location, String name) { } private void save(Location location, String name, Content content) { - Map filesForLocation = files.get(location); - if (filesForLocation == null) - files.put(location, filesForLocation = new HashMap<>()); - filesForLocation.put(name, content); + files.computeIfAbsent(location, k -> new HashMap<>()) + .put(name, content); } /** @@ -853,7 +932,10 @@ private class MemoryFileObject extends SimpleJavaFileObject { /** * Constructs a memory file object. - * @param name binary name of the class to be stored in this file object + * + * @param location the location in which to save the file object + * @param name binary name of the class to be stored in this file object + * @param kind the kind of file object */ MemoryFileObject(Location location, String name, JavaFileObject.Kind kind) { super(URI.create("mfm:///" + name.replace('.','/') + kind.extension), @@ -890,7 +972,7 @@ public Writer openWriter() { @Override public void close() throws IOException { out.close(); - String text = ((StringWriter) out).toString(); + String text = out.toString(); save(location, name, new Content() { @Override public byte[] getBytes() { diff --git a/test/lib/jdk/test/lib/Platform.java b/test/lib/jdk/test/lib/Platform.java index 5ab41dc1649..26e802c383c 100644 --- a/test/lib/jdk/test/lib/Platform.java +++ b/test/lib/jdk/test/lib/Platform.java @@ -79,7 +79,7 @@ public static boolean isEmulatedClient() { } public static boolean isTieredSupported() { - return compiler.contains("Tiered Compilers"); + return (compiler != null) && compiler.contains("Tiered Compilers"); } public static boolean isInt() { diff --git a/test/lib/jdk/test/lib/SecurityTools.java b/test/lib/jdk/test/lib/SecurityTools.java index 30da87f2d32..e105c42d06d 100644 --- a/test/lib/jdk/test/lib/SecurityTools.java +++ b/test/lib/jdk/test/lib/SecurityTools.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -23,6 +23,7 @@ package jdk.test.lib; +import java.io.Closeable; import java.io.File; import java.io.IOException; import java.nio.file.Files; @@ -275,5 +276,63 @@ public static List makeList(String line) { } return result; } + + // Create a temporary keychain in macOS and use it. The original + // keychains will be restored when the object is closed. + public static class TemporaryKeychain implements Closeable { + // name of new keychain + private final String newChain; + // names of the original keychains + private final List oldChains; + + public TemporaryKeychain(String name) { + Path p = Path.of(name + ".keychain-db"); + newChain = p.toAbsolutePath().toString(); + try { + oldChains = ProcessTools.executeProcess("security", "list-keychains") + .shouldHaveExitValue(0) + .getStdout() + .lines() + .map(String::trim) + .map(x -> x.startsWith("\"") ? x.substring(1, x.length() - 1) : x) + .collect(Collectors.toList()); + if (!Files.exists(p)) { + ProcessTools.executeProcess("security", "create-keychain", "-p", "changeit", newChain) + .shouldHaveExitValue(0); + } + ProcessTools.executeProcess("security", "unlock-keychain", "-p", "changeit", newChain) + .shouldHaveExitValue(0); + ProcessTools.executeProcess("security", "list-keychains", "-s", newChain) + .shouldHaveExitValue(0); + } catch (Throwable t) { + if (t instanceof RuntimeException re) { + throw re; + } else { + throw new RuntimeException(t); + } + } + } + + public String chain() { + return newChain; + } + + @Override + public void close() throws IOException { + List cmds = new ArrayList<>(); + cmds.addAll(List.of("security", "list-keychains", "-s")); + cmds.addAll(oldChains); + try { + ProcessTools.executeProcess(cmds.toArray(new String[0])) + .shouldHaveExitValue(0); + } catch (Throwable t) { + if (t instanceof RuntimeException re) { + throw re; + } else { + throw new RuntimeException(t); + } + } + } + } } diff --git a/test/lib/jdk/test/lib/security/SecurityUtils.java b/test/lib/jdk/test/lib/security/SecurityUtils.java index 5dbda4dae69..c0818d7662a 100644 --- a/test/lib/jdk/test/lib/security/SecurityUtils.java +++ b/test/lib/jdk/test/lib/security/SecurityUtils.java @@ -61,11 +61,18 @@ public static void removeFromDisabledTlsAlgs(String... protocols) { List.of(protocols)); } - private static void removeFromDisabledAlgs(String prop, List algs) { + /** + * Removes constraints that contain the specified constraint from the + * specified security property. For example, List.of("SHA1") will remove + * any constraint containing "SHA1". + */ + public static void removeFromDisabledAlgs(String prop, + List constraints) { String value = Security.getProperty(prop); value = Arrays.stream(value.split(",")) .map(s -> s.trim()) - .filter(s -> !algs.contains(s)) + .filter(s -> constraints.stream() + .allMatch(constraint -> !s.contains(constraint))) .collect(Collectors.joining(",")); Security.setProperty(prop, value); } diff --git a/test/lib/jdk/test/lib/security/XMLUtils.java b/test/lib/jdk/test/lib/security/XMLUtils.java index bffab4be405..fa93e3f6b00 100644 --- a/test/lib/jdk/test/lib/security/XMLUtils.java +++ b/test/lib/jdk/test/lib/security/XMLUtils.java @@ -92,9 +92,11 @@ public static void main(String[] args) throws Exception { Asserts.assertTrue(v2.validate(s3.sign(d))); // can read KeyInfo Asserts.assertTrue(v2.secureValidation(false).validate(s3.sign(p.toUri()))); // can read KeyInfo Asserts.assertTrue(v2.secureValidation(false).baseURI(b).validate( - s3.sign(p.getParent().toUri(), p.getFileName().toUri()))); // can read KeyInfo + s3.sign(p.toAbsolutePath().getParent().toUri(), p.getFileName().toUri()))); // can read KeyInfo Asserts.assertTrue(v1.validate(s1.sign("text"))); // plain text Asserts.assertTrue(v1.validate(s1.sign("binary".getBytes()))); // raw data + Asserts.assertTrue(v1.validate(s1.signEnveloping(d, "x", "#x"))); + Asserts.assertTrue(v1.validate(s1.signEnveloping(d, "x", "#xpointer(id('x'))"))); } //////////// CONVERT //////////// @@ -347,14 +349,14 @@ public Document sign(Document document) throws Exception { } // Signs a document in enveloping mode - public Document signEnveloping(Document document) throws Exception { + public Document signEnveloping(Document document, String id, String ref) throws Exception { Document newDocument = DocumentBuilderFactory.newInstance() .newDocumentBuilder().newDocument(); FAC.newXMLSignature( - buildSignedInfo(FAC.newReference("#object", dm)), + buildSignedInfo(FAC.newReference(ref, dm)), buildKeyInfo(), List.of(FAC.newXMLObject(List.of(new DOMStructure(document.getDocumentElement())), - "object", null, null)), + id, null, null)), null, null) .sign(new DOMSignContext(privateKey, newDocument)); @@ -474,7 +476,7 @@ public boolean validate(Document document) throws Exception { // If key is not null, any key from the signature will be ignored public boolean validate(Document document, PublicKey key) throws Exception { - NodeList nodeList = document.getElementsByTagName("Signature"); + NodeList nodeList = document.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature"); if (nodeList.getLength() == 1) { Node signatureNode = nodeList.item(0); if (signatureNode != null) { diff --git a/test/lib/jdk/test/whitebox/WhiteBox.java b/test/lib/jdk/test/whitebox/WhiteBox.java index b534d0d7a4f..7c0aa774e89 100644 --- a/test/lib/jdk/test/whitebox/WhiteBox.java +++ b/test/lib/jdk/test/whitebox/WhiteBox.java @@ -594,6 +594,7 @@ public Object getMethodOption(Executable method, String name) { public native boolean areSharedStringsIgnored(); public native boolean isCDSIncluded(); public native boolean isJFRIncluded(); + public native boolean isDTraceIncluded(); public native boolean isJavaHeapArchiveSupported(); public native Object getResolvedReferences(Class c); public native void linkClass(Class c); diff --git a/test/lib/sun/hotspot/WhiteBox.java b/test/lib/sun/hotspot/WhiteBox.java index b1c96f1d5ad..633c4aecb0d 100644 --- a/test/lib/sun/hotspot/WhiteBox.java +++ b/test/lib/sun/hotspot/WhiteBox.java @@ -595,6 +595,7 @@ public Object getMethodOption(Executable method, String name) { public native boolean areSharedStringsIgnored(); public native boolean isCDSIncluded(); public native boolean isJFRIncluded(); + public native boolean isDTraceIncluded(); public native boolean isJavaHeapArchiveSupported(); public native Object getResolvedReferences(Class c); public native void linkClass(Class c); diff --git a/test/micro/org/openjdk/bench/vm/compiler/InterfacePrivateCalls.java b/test/micro/org/openjdk/bench/vm/compiler/InterfacePrivateCalls.java new file mode 100644 index 00000000000..620b885db36 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/InterfacePrivateCalls.java @@ -0,0 +1,80 @@ +/* + * 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. + */ +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + +@State(Scope.Benchmark) +public class InterfacePrivateCalls { + interface I { + private int bar() { return 0; } + default int foo() { + return bar(); + } + } + + static class C1 implements I {} + static class C2 implements I {} + static class C3 implements I {} + + private I[] objs; + + @Setup(Level.Trial) + public void setupTrial() { + objs = new I[3]; + objs[0] = new C1(); + objs[1] = new C2(); + objs[2] = new C3(); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + @Fork(value=1, jvmArgsAppend={"-XX:TieredStopAtLevel=1"}) + public void invokePrivateInterfaceMethodC1() { + for (int i = 0; i < objs.length; ++i) { + objs[i].foo(); + } + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + @Fork(value=1) + public void invokePrivateInterfaceMethodC2() { + for (int i = 0; i < objs.length; ++i) { + objs[i].foo(); + } + } +}